aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorEnrico Tassi2018-04-20 10:13:36 +0200
committerEnrico Tassi2018-04-20 10:35:01 +0200
commit24a7fea1648991a77fc4ff86a972b0a3935678c8 (patch)
tree4d6043884fafaf062d33c15a266a7f4c92541f79 /docs
parent9352fc35ebe04b8b4e9002f3cf39ee1acbab8cd2 (diff)
move the webpage from gh-pages branch to docs/
Diffstat (limited to 'docs')
-rw-r--r--docs/README.md6
-rw-r--r--docs/htmldoc/Makefile32
-rwxr-xr-xdocs/htmldoc/buildlibgraph162
-rw-r--r--docs/htmldoc/js/cytoscape-dagre.js192
-rw-r--r--docs/htmldoc/js/cytoscape-panzoom.js550
-rw-r--r--docs/htmldoc/js/cytoscape-qtip.js362
-rw-r--r--docs/htmldoc/js/cytoscape.js24515
-rw-r--r--docs/htmldoc/js/cytoscape.js-panzoom.css203
-rw-r--r--docs/htmldoc/js/cytoscape.min.js26
-rw-r--r--docs/htmldoc/js/dagre.js16396
-rw-r--r--docs/htmldoc/js/dagre.min.js6
-rw-r--r--docs/htmldoc/js/jquery-2.0.3.js8829
-rw-r--r--docs/htmldoc/js/jquery-2.0.3.min.js6
-rw-r--r--docs/htmldoc/js/jquery.qtip.css623
-rw-r--r--docs/htmldoc/js/jquery.qtip.js3440
-rw-r--r--docs/htmldoc/js/jquery.qtip.min.css2
-rw-r--r--docs/htmldoc/js/jquery.qtip.min.js4
-rw-r--r--docs/htmldoc/libgraph.html245
-rw-r--r--docs/index.html106
-rw-r--r--docs/javascripts/scale.fix.js17
-rw-r--r--docs/logo-MS-Research-Inria-Joint-Centre.pngbin0 -> 16642 bytes
-rw-r--r--docs/oo.html88
-rw-r--r--docs/params.json1
-rw-r--r--docs/stylesheets/github-light.css116
-rw-r--r--docs/stylesheets/styles.css324
25 files changed, 56251 insertions, 0 deletions
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..55e55b0
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,6 @@
+This directory contains the website:
+ http://math-comp.github.io/math-comp/
+What is committed in here goes straight online.
+
+By running make in htmldoc one updates the html files
+generated by coqdoc and the library graph.
diff --git a/docs/htmldoc/Makefile b/docs/htmldoc/Makefile
new file mode 100644
index 0000000..d565125
--- /dev/null
+++ b/docs/htmldoc/Makefile
@@ -0,0 +1,32 @@
+H=@
+
+ifeq "$(COQBIN)" ""
+COQBIN=$(dir $(shell which coqtop))/
+endif
+
+SRC=$(shell cd ../mathcomp; ls */*.v | grep -v attic/)
+HEAD=$(shell git symbolic-ref HEAD)
+ifeq "$(HEAD)" "refs/heads/master"
+LAST=$(shell git tag -l --sort=v:refname "mathcomp-*" | tail -n 1)
+RELEASED=$(shell git show $(LAST):mathcomp/Make | grep 'v *$$' | cut -d / -f 2 | cut -d . -f 1)
+endif
+
+all:
+ $(H) git diff-index --quiet HEAD ||\
+ (echo error: uncommitted files; exit 1)
+ $(H) cd ../mathcomp;\
+ $(COQBIN)/coqdep -R . mathcomp $(SRC) 2>/dev/null |\
+ grep -v vio: > ../htmldoc/depend
+ $(H) cat depend | ./buildlibgraph cytoscape $(RELEASED) > depend.js
+ $(H) . ../etc/utils/builddoc_lib.sh; \
+ cd ../mathcomp; mangle_sources $(SRC)
+ $(H) make -C ../mathcomp clean
+ $(H) make -C ../mathcomp -j2
+ $(H) cd ../mathcomp; $(COQBIN)/coqdoc -t "Mathematical Components"\
+ -g --utf8 -R . mathcomp \
+ --parse-comments \
+ --multi-index $(SRC) -d ../htmldoc/
+ $(H) cp ../etc/artwork/coqdoc.css .
+ $(H) cd ../mathcomp; git checkout $(SRC)
+
+
diff --git a/docs/htmldoc/buildlibgraph b/docs/htmldoc/buildlibgraph
new file mode 100755
index 0000000..b7b91d0
--- /dev/null
+++ b/docs/htmldoc/buildlibgraph
@@ -0,0 +1,162 @@
+#!/usr/bin/lua5.1
+
+nodes = {}
+clusters = {}
+edges = {}
+args = {}
+
+function decompose(n)
+ return n:match("^([^/]+)/([^%.]+)")
+end
+
+for l in io.lines() do
+ local to, froms = l:match("^([^ :]+)[^:]*:(.*)")
+ local cluster, module = decompose(to)
+ clusters[cluster] = clusters[cluster] or {}
+ clusters[cluster][module] = true
+ nodes[module] = true
+ for from in froms:gmatch("[^ ]+") do
+ local cluster, module2 = decompose(from)
+ nodes[module2] = true
+ if module ~= module2 then
+ clusters[cluster] = clusters[cluster] or {}
+ clusters[cluster][module2] = true
+ edges[#edges+1] = { from = module; to = module2 }
+ end
+ end
+end
+
+-- transitive reduction
+--
+-- // reflexive reduction
+-- for (int i = 0; i < N; ++i)
+-- m[i][i] = false;
+--
+-- // transitive reduction
+-- for (int j = 0; j < N; ++j)
+-- for (int i = 0; i < N; ++i)
+-- if (m[i][j])
+-- for (int k = 0; k < N; ++k)
+-- if (m[j][k])
+-- m[i][k] = false;
+--
+function path_matrix(nodes,edges)
+ local m = {}
+ for j,_ in pairs(nodes) do
+ m[j] = {}
+ end
+ for _,e in ipairs(edges) do
+ m[e.from][e.to] = true
+ end
+ -- close
+ for j,_ in pairs(nodes) do
+ for i,_ in pairs(nodes) do
+ for k,_ in pairs(nodes) do
+ if m[i][j] == true and m[j][k] == true then m[i][k] = true end
+ end
+ end
+ end
+ return m
+end
+function tred(nodes,m)
+ -- reduce
+ for j,_ in pairs(nodes) do
+ for i,_ in pairs(nodes) do
+ if m[i][j] == true then
+ for k,_ in pairs(nodes) do
+ if m[j][k] then m[i][k] = false end
+ end
+ end
+ end
+ end
+end
+function matrix_to_list(nodes,m)
+ local edges = {}
+ for j,_ in pairs(nodes) do
+ for i,_ in pairs(nodes) do
+ if m[i][j] == true then
+ edges[#edges+1] = { from = i; to = j }
+ end
+ end
+ end
+ return edges
+end
+
+
+
+m = path_matrix(nodes,edges)
+tred(nodes,m)
+edges = matrix_to_list(nodes,m)
+
+meta_edges = {}
+for c1,nodes1 in pairs(clusters) do
+ for c2,nodes2 in pairs(clusters) do
+ if (c1 ~= c2) then
+ local connected = false
+ for n1,_ in pairs(nodes1) do
+ for n2,_ in pairs(nodes2) do
+ if m[n1][n2] == true then connected = true end
+ end
+ end
+ if connected then meta_edges[#meta_edges+1] = { from = c1; to = c2 } end
+ end
+ end
+end
+
+m = path_matrix(clusters,meta_edges)
+tred(clusters,m)
+meta_edges = matrix_to_list(clusters,m)
+
+function dot()
+ print[[
+ digraph mathcomp {
+ compound = true;
+ ]]
+ for c,nodes in pairs(clusters) do
+ print("subgraph cluster_" .. c .. " {")
+ for node,_ in pairs(nodes) do
+ print('"'..node..'";')
+ end
+ print("}")
+ end
+ for _,edge in ipairs(edges) do
+ print(string.format('"%s" -> "%s";',edge.from,edge.to))
+ end
+ print[[
+ }
+ ]]
+end
+
+function cytoscape()
+ print[[
+ var depends = [
+ ]]
+ for c,nodes in pairs(clusters) do
+ print(string.format('{ data: { id: "cluster_%s", name: "%s" } },', c, c))
+ print(string.format('{ data: { id: "cluster_%s_plus", name: "+", parent: "cluster_%s" } },', c, c))
+ for node,_ in pairs(nodes) do
+ local released = "no"
+ if args[node] then released = "yes" end
+ print(string.format('{ data: { id: "%s", name: "%s", parent: "cluster_%s", released: "%s" } },', node, node, c, released))
+ end
+ end
+ local i = 0
+ for _,edge in ipairs(edges) do
+ print(string.format('{ data: { id: "edge%d", source: "%s", target: "%s" } },', i, edge.from,edge.to))
+ i=i+1
+ end
+ for _,edge in ipairs(meta_edges) do
+ print(string.format('{ data: { id: "edge%d", source: "cluster_%s", target: "cluster_%s" } },', i, edge.from,edge.to))
+ i=i+1
+ end
+ print[[ ]; ]]
+end
+
+for i=2,#arg do
+ args[arg[i]] = true
+end
+_G[arg[1]]()
+
+-- $COQBIN/coqdep -R . mathcomp */*.v | grep -v vio: > depend
+-- cat depend | ./graph.lua dot | tee depend.dot | dot -T png -o depend.png
+-- cat depend | ./graph.lua cytoscape `git show release/1.6:mathcomp/Make | grep 'v *$' | cut -d / -f 2 | cut -d . -f 1` > depend.js
diff --git a/docs/htmldoc/js/cytoscape-dagre.js b/docs/htmldoc/js/cytoscape-dagre.js
new file mode 100644
index 0000000..c93288b
--- /dev/null
+++ b/docs/htmldoc/js/cytoscape-dagre.js
@@ -0,0 +1,192 @@
+;(function(){ 'use strict';
+
+ // registers the extension on a cytoscape lib ref
+ var register = function( cytoscape, dagre ){
+ if( !cytoscape || !dagre ){ return; } // can't register if cytoscape unspecified
+
+ var isFunction = function(o){ return typeof o === 'function'; };
+
+ // default layout options
+ var defaults = {
+ // dagre algo options, uses default value on undefined
+ nodeSep: undefined, // the separation between adjacent nodes in the same rank
+ edgeSep: undefined, // the separation between adjacent edges in the same rank
+ rankSep: undefined, // the separation between adjacent nodes in the same rank
+ rankDir: undefined, // 'TB' for top to bottom flow, 'LR' for left to right
+ minLen: function( edge ){ return 1; }, // number of ranks to keep between the source and target of the edge
+ edgeWeight: function( edge ){ return 1; }, // higher weight edges are generally made shorter and straighter than lower weight edges
+
+ // general layout options
+ fit: true, // whether to fit to viewport
+ padding: 30, // fit padding
+ animate: false, // whether to transition the node positions
+ animationDuration: 500, // duration of animation in ms if enabled
+ animationEasing: undefined, // easing of animation if enabled
+ boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
+ ready: function(){}, // on layoutready
+ stop: function(){} // on layoutstop
+ };
+
+ // constructor
+ // options : object containing layout options
+ function DagreLayout( options ){
+ var opts = this.options = {};
+ for( var i in defaults ){ opts[i] = defaults[i]; }
+ for( var i in options ){ opts[i] = options[i]; }
+ }
+
+ // runs the layout
+ DagreLayout.prototype.run = function(){
+ var options = this.options;
+ var layout = this;
+
+ var cy = options.cy; // cy is automatically populated for us in the constructor
+ var eles = options.eles;
+
+ var getVal = function( ele, val ){
+ return isFunction(val) ? val.apply( ele, [ ele ] ) : val;
+ };
+
+ var bb = options.boundingBox || { x1: 0, y1: 0, w: cy.width(), h: cy.height() };
+ if( bb.x2 === undefined ){ bb.x2 = bb.x1 + bb.w; }
+ if( bb.w === undefined ){ bb.w = bb.x2 - bb.x1; }
+ if( bb.y2 === undefined ){ bb.y2 = bb.y1 + bb.h; }
+ if( bb.h === undefined ){ bb.h = bb.y2 - bb.y1; }
+
+ var g = new dagre.graphlib.Graph({
+ multigraph: true,
+ compound: true
+ });
+
+ var gObj = {};
+ var setGObj = function( name, val ){
+ if( val != null ){
+ gObj[ name ] = val;
+ }
+ };
+
+ setGObj( 'nodesep', options.nodeSep );
+ setGObj( 'edgesep', options.edgeSep );
+ setGObj( 'ranksep', options.rankSep );
+ setGObj( 'rankdir', options.rankDir );
+
+ g.setGraph( gObj );
+
+ g.setDefaultEdgeLabel(function() { return {}; });
+ g.setDefaultNodeLabel(function() { return {}; });
+
+ // add nodes to dagre
+ var nodes = eles.nodes();
+ for( var i = 0; i < nodes.length; i++ ){
+ var node = nodes[i];
+ var nbb = node.boundingBox();
+
+ g.setNode( node.id(), {
+ width: nbb.w,
+ height: nbb.h,
+ name: node.id()
+ } );
+
+ // console.log( g.node(node.id()) );
+ }
+
+ // set compound parents
+ for( var i = 0; i < nodes.length; i++ ){
+ var node = nodes[i];
+
+ if( node.isChild() ){
+ g.setParent( node.id(), node.parent().id() );
+ }
+ }
+
+ // add edges to dagre
+ var edges = eles.edges().stdFilter(function( edge ){
+ return !edge.source().isParent() && !edge.target().isParent(); // dagre can't handle edges on compound nodes
+ });
+ for( var i = 0; i < edges.length; i++ ){
+ var edge = edges[i];
+
+ g.setEdge( edge.source().id(), edge.target().id(), {
+ minlen: getVal( edge, options.minLen ),
+ weight: getVal( edge, options.edgeWeight ),
+ name: edge.id()
+ }, edge.id() );
+
+ // console.log( g.edge(edge.source().id(), edge.target().id(), edge.id()) );
+ }
+
+ dagre.layout( g );
+
+ var gNodeIds = g.nodes();
+ for( var i = 0; i < gNodeIds.length; i++ ){
+ var id = gNodeIds[i];
+ var n = g.node( id );
+
+ cy.getElementById(id).scratch().dagre = n;
+ }
+
+ var dagreBB;
+
+ if( options.boundingBox ){
+ dagreBB = { x1: Infinity, x2: -Infinity, y1: Infinity, y2: -Infinity };
+ nodes.forEach(function( node ){
+ var dModel = node.scratch().dagre;
+
+ dagreBB.x1 = Math.min( dagreBB.x1, dModel.x );
+ dagreBB.x2 = Math.max( dagreBB.x2, dModel.x );
+
+ dagreBB.y1 = Math.min( dagreBB.y1, dModel.y );
+ dagreBB.y2 = Math.max( dagreBB.y2, dModel.y );
+ });
+
+ dagreBB.w = dagreBB.x2 - dagreBB.x1;
+ dagreBB.h = dagreBB.y2 - dagreBB.y1;
+ } else {
+ dagreBB = bb;
+ }
+
+ var constrainPos = function( p ){
+ if( options.boundingBox ){
+ var xPct = (p.x - dagreBB.x1) / dagreBB.w;
+ var yPct = (p.y - dagreBB.y1) / dagreBB.h;
+
+ return {
+ x: bb.x1 + xPct * bb.w,
+ y: bb.y1 + yPct * bb.h
+ };
+ } else {
+ return p;
+ }
+ };
+
+ nodes.layoutPositions(layout, options, function(){
+ var dModel = this.scratch().dagre;
+
+ return constrainPos({
+ x: dModel.x,
+ y: dModel.y
+ });
+ });
+
+ return this; // chaining
+ };
+
+ cytoscape('layout', 'dagre', DagreLayout);
+
+ };
+
+ if( typeof module !== 'undefined' && module.exports ){ // expose as a commonjs module
+ module.exports = register;
+ }
+
+ if( typeof define !== 'undefined' && define.amd ){ // expose as an amd/requirejs module
+ define('cytoscape-dagre', function(){
+ return register;
+ });
+ }
+
+ if( typeof cytoscape !== 'undefined' && typeof dagre !== 'undefined' ){ // expose to global cytoscape (i.e. window.cytoscape)
+ register( cytoscape, dagre );
+ }
+
+})();
diff --git a/docs/htmldoc/js/cytoscape-panzoom.js b/docs/htmldoc/js/cytoscape-panzoom.js
new file mode 100644
index 0000000..4680775
--- /dev/null
+++ b/docs/htmldoc/js/cytoscape-panzoom.js
@@ -0,0 +1,550 @@
+;(function(){ 'use strict';
+
+ // registers the extension on a cytoscape lib ref
+ var register = function( cytoscape, $ ){
+ if( !cytoscape ){ return; } // can't register if cytoscape unspecified
+
+ $.fn.cyPanzoom = $.fn.cytoscapePanzoom = function( options ){
+ panzoom.apply( this, [ options ] );
+
+ return this; // chainability
+ };
+
+ // if you want a core extension
+ cytoscape('core', 'panzoom', function( options ){ // could use options object, but args are up to you
+ var cy = this;
+
+ panzoom.apply( cy.container(), [ options ] );
+
+ return this; // chainability
+ });
+
+ };
+
+ var defaults = {
+ zoomFactor: 0.05, // zoom factor per zoom tick
+ zoomDelay: 45, // how many ms between zoom ticks
+ minZoom: 0.1, // min zoom level
+ maxZoom: 10, // max zoom level
+ fitPadding: 50, // padding when fitting
+ panSpeed: 10, // how many ms in between pan ticks
+ panDistance: 10, // max pan distance per tick
+ panDragAreaSize: 75, // the length of the pan drag box in which the vector for panning is calculated (bigger = finer control of pan speed and direction)
+ panMinPercentSpeed: 0.25, // the slowest speed we can pan by (as a percent of panSpeed)
+ panInactiveArea: 8, // radius of inactive area in pan drag box
+ panIndicatorMinOpacity: 0.5, // min opacity of pan indicator (the draggable nib); scales from this to 1.0
+ zoomOnly: false, // a minimal version of the ui only with zooming (useful on systems with bad mousewheel resolution)
+
+ // icon class names
+ sliderHandleIcon: 'fa fa-minus',
+ zoomInIcon: 'fa fa-plus',
+ zoomOutIcon: 'fa fa-minus',
+ resetIcon: 'fa fa-expand'
+ };
+
+ var panzoom = function(params){
+ var options = $.extend(true, {}, defaults, params);
+ var fn = params;
+
+ var functions = {
+ destroy: function(){
+ var $this = $(this);
+ var $pz = $this.find(".cy-panzoom");
+
+ $pz.data('winbdgs').forEach(function( l ){
+ $(window).unbind( l.evt, l.fn );
+ });
+
+ $pz.data('cybdgs').forEach(function( l ){
+ $(this).cytoscape('get').off( l.evt, l.fn );
+ });
+
+ $pz.remove();
+ },
+
+ init: function(){
+ var browserIsMobile = 'ontouchstart' in window;
+
+ return $(this).each(function(){
+ var $container = $(this);
+
+ var winbdgs = [];
+ var $win = $(window);
+
+ var windowBind = function( evt, fn ){
+ winbdgs.push({ evt: evt, fn: fn });
+
+ $win.bind( evt, fn );
+ };
+
+ var windowUnbind = function( evt, fn ){
+ for( var i = 0; i < winbdgs.length; i++ ){
+ var l = winbdgs[i];
+
+ if( l.evt === evt && l.fn === fn ){
+ winbdgs.splice( i, 1 );
+ break;
+ }
+ }
+
+ $win.unbind( evt, fn );
+ };
+
+ var cybdgs = [];
+ var cy = $container.cytoscape('get');
+
+ var cyOn = function( evt, fn ){
+ cybdgs.push({ evt: evt, fn: fn });
+
+ cy.on( evt, fn );
+ };
+
+ var cyOff = function( evt, fn ){
+ for( var i = 0; i < cybdgs.length; i++ ){
+ var l = cybdgs[i];
+
+ if( l.evt === evt && l.fn === fn ){
+ cybdgs.splice( i, 1 );
+ break;
+ }
+ }
+
+ cy.off( evt, fn );
+ };
+
+ var $panzoom = $('<div class="cy-panzoom"></div>');
+ $container.append( $panzoom );
+
+ $panzoom.data('winbdgs', winbdgs);
+ $panzoom.data('cybdgs', cybdgs);
+
+ if( options.zoomOnly ){
+ $panzoom.addClass("cy-panzoom-zoom-only");
+ }
+
+ // add base html elements
+ /////////////////////////
+
+ var $zoomIn = $('<div class="cy-panzoom-zoom-in cy-panzoom-zoom-button"><span class="icon '+ options.zoomInIcon +'"></span></div>');
+ $panzoom.append( $zoomIn );
+
+ var $zoomOut = $('<div class="cy-panzoom-zoom-out cy-panzoom-zoom-button"><span class="icon ' + options.zoomOutIcon + '"></span></div>');
+ $panzoom.append( $zoomOut );
+
+ var $reset = $('<div class="cy-panzoom-reset cy-panzoom-zoom-button"><span class="icon ' + options.resetIcon + '"></span></div>');
+ $panzoom.append( $reset );
+
+ var $slider = $('<div class="cy-panzoom-slider"></div>');
+ $panzoom.append( $slider );
+
+ $slider.append('<div class="cy-panzoom-slider-background"></div>');
+
+ var $sliderHandle = $('<div class="cy-panzoom-slider-handle"><span class="icon ' + options.sliderHandleIcon + '"></span></div>');
+ $slider.append( $sliderHandle );
+
+ var $noZoomTick = $('<div class="cy-panzoom-no-zoom-tick"></div>');
+ $slider.append( $noZoomTick );
+
+ var $panner = $('<div class="cy-panzoom-panner"></div>');
+ $panzoom.append( $panner );
+
+ var $pHandle = $('<div class="cy-panzoom-panner-handle"></div>');
+ $panner.append( $pHandle );
+
+ var $pUp = $('<div class="cy-panzoom-pan-up cy-panzoom-pan-button"></div>');
+ var $pDown = $('<div class="cy-panzoom-pan-down cy-panzoom-pan-button"></div>');
+ var $pLeft = $('<div class="cy-panzoom-pan-left cy-panzoom-pan-button"></div>');
+ var $pRight = $('<div class="cy-panzoom-pan-right cy-panzoom-pan-button"></div>');
+ $panner.append( $pUp ).append( $pDown ).append( $pLeft ).append( $pRight );
+
+ var $pIndicator = $('<div class="cy-panzoom-pan-indicator"></div>');
+ $panner.append( $pIndicator );
+
+ // functions for calculating panning
+ ////////////////////////////////////
+
+ function handle2pan(e){
+ var v = {
+ x: e.originalEvent.pageX - $panner.offset().left - $panner.width()/2,
+ y: e.originalEvent.pageY - $panner.offset().top - $panner.height()/2
+ }
+
+ var r = options.panDragAreaSize;
+ var d = Math.sqrt( v.x*v.x + v.y*v.y );
+ var percent = Math.min( d/r, 1 );
+
+ if( d < options.panInactiveArea ){
+ return {
+ x: NaN,
+ y: NaN
+ };
+ }
+
+ v = {
+ x: v.x/d,
+ y: v.y/d
+ };
+
+ percent = Math.max( options.panMinPercentSpeed, percent );
+
+ var vnorm = {
+ x: -1 * v.x * (percent * options.panDistance),
+ y: -1 * v.y * (percent * options.panDistance)
+ };
+
+ return vnorm;
+ }
+
+ function donePanning(){
+ clearInterval(panInterval);
+ windowUnbind("mousemove", handler);
+
+ $pIndicator.hide();
+ }
+
+ function positionIndicator(pan){
+ var v = pan;
+ var d = Math.sqrt( v.x*v.x + v.y*v.y );
+ var vnorm = {
+ x: -1 * v.x/d,
+ y: -1 * v.y/d
+ };
+
+ var w = $panner.width();
+ var h = $panner.height();
+ var percent = d/options.panDistance;
+ var opacity = Math.max( options.panIndicatorMinOpacity, percent );
+ var color = 255 - Math.round( opacity * 255 );
+
+ $pIndicator.show().css({
+ left: w/2 * vnorm.x + w/2,
+ top: h/2 * vnorm.y + h/2,
+ background: "rgb(" + color + ", " + color + ", " + color + ")"
+ });
+ }
+
+ function calculateZoomCenterPoint(){
+ var cy = $container.cytoscape("get");
+ var pan = cy.pan();
+ var zoom = cy.zoom();
+
+ zx = $container.width()/2;
+ zy = $container.height()/2;
+ }
+
+ var zooming = false;
+ function startZooming(){
+ zooming = true;
+
+ calculateZoomCenterPoint();
+ }
+
+
+ function endZooming(){
+ zooming = false;
+ }
+
+ var zx, zy;
+ function zoomTo(level){
+ var cy = $container.cytoscape("get");
+
+ if( !zooming ){ // for non-continuous zooming (e.g. click slider at pt)
+ calculateZoomCenterPoint();
+ }
+
+ cy.zoom({
+ level: level,
+ renderedPosition: { x: zx, y: zy }
+ });
+ }
+
+ var panInterval;
+
+ var handler = function(e){
+ e.stopPropagation(); // don't trigger dragging of panzoom
+ e.preventDefault(); // don't cause text selection
+ clearInterval(panInterval);
+
+ var pan = handle2pan(e);
+
+ if( isNaN(pan.x) || isNaN(pan.y) ){
+ $pIndicator.hide();
+ return;
+ }
+
+ positionIndicator(pan);
+ panInterval = setInterval(function(){
+ $container.cytoscape("get").panBy(pan);
+ }, options.panSpeed);
+ };
+
+ $pHandle.bind("mousedown", function(e){
+ // handle click of icon
+ handler(e);
+
+ // update on mousemove
+ windowBind("mousemove", handler);
+ });
+
+ $pHandle.bind("mouseup", function(){
+ donePanning();
+ });
+
+ windowBind("mouseup blur", function(){
+ donePanning();
+ });
+
+
+
+ // set up slider behaviour
+ //////////////////////////
+
+ $slider.bind('mousedown', function(){
+ return false; // so we don't pan close to the slider handle
+ });
+
+ var sliderVal;
+ var sliding = false;
+ var sliderPadding = 2;
+
+ function setSliderFromMouse(evt, handleOffset){
+ if( handleOffset === undefined ){
+ handleOffset = 0;
+ }
+
+ var padding = sliderPadding;
+ var min = 0 + padding;
+ var max = $slider.height() - $sliderHandle.height() - 2*padding;
+ var top = evt.pageY - $slider.offset().top - handleOffset;
+
+ // constrain to slider bounds
+ if( top < min ){ top = min }
+ if( top > max ){ top = max }
+
+ var percent = 1 - (top - min) / ( max - min );
+
+ // move the handle
+ $sliderHandle.css('top', top);
+
+ var zmin = options.minZoom;
+ var zmax = options.maxZoom;
+
+ // assume (zoom = zmax ^ p) where p ranges on (x, 1) with x negative
+ var x = Math.log(zmin) / Math.log(zmax);
+ var p = (1 - x)*percent + x;
+
+ // change the zoom level
+ var z = Math.pow( zmax, p );
+
+ // bound the zoom value in case of floating pt rounding error
+ if( z < zmin ){
+ z = zmin;
+ } else if( z > zmax ){
+ z = zmax;
+ }
+
+ zoomTo( z );
+ }
+
+ var sliderMdownHandler, sliderMmoveHandler;
+ $sliderHandle.bind('mousedown', sliderMdownHandler = function( mdEvt ){
+ var handleOffset = mdEvt.target === $sliderHandle[0] ? mdEvt.offsetY : 0;
+ sliding = true;
+
+ startZooming();
+ $sliderHandle.addClass("active");
+
+ var lastMove = 0;
+ windowBind('mousemove', sliderMmoveHandler = function( mmEvt ){
+ var now = +new Date;
+
+ // throttle the zooms every 10 ms so we don't call zoom too often and cause lag
+ if( now > lastMove + 10 ){
+ lastMove = now;
+ } else {
+ return false;
+ }
+
+ setSliderFromMouse(mmEvt, handleOffset);
+
+ return false;
+ });
+
+ // unbind when
+ windowBind('mouseup', function(){
+ windowUnbind('mousemove', sliderMmoveHandler);
+ sliding = false;
+
+ $sliderHandle.removeClass("active");
+ endZooming();
+ });
+
+ return false;
+ });
+
+ $slider.bind('mousedown', function(e){
+ if( e.target !== $sliderHandle[0] ){
+ sliderMdownHandler(e);
+ setSliderFromMouse(e);
+ }
+ });
+
+ function positionSliderFromZoom(){
+ var cy = $container.cytoscape("get");
+ var z = cy.zoom();
+ var zmin = options.minZoom;
+ var zmax = options.maxZoom;
+
+ // assume (zoom = zmax ^ p) where p ranges on (x, 1) with x negative
+ var x = Math.log(zmin) / Math.log(zmax);
+ var p = Math.log(z) / Math.log(zmax);
+ var percent = 1 - (p - x) / (1 - x); // the 1- bit at the front b/c up is in the -ve y direction
+
+ var min = sliderPadding;
+ var max = $slider.height() - $sliderHandle.height() - 2*sliderPadding;
+ var top = percent * ( max - min );
+
+ // constrain to slider bounds
+ if( top < min ){ top = min }
+ if( top > max ){ top = max }
+
+ // move the handle
+ $sliderHandle.css('top', top);
+ }
+
+ positionSliderFromZoom();
+
+ cyOn('zoom', function(){
+ if( !sliding ){
+ positionSliderFromZoom();
+ }
+ });
+
+ // set the position of the zoom=1 tick
+ (function(){
+ var z = 1;
+ var zmin = options.minZoom;
+ var zmax = options.maxZoom;
+
+ // assume (zoom = zmax ^ p) where p ranges on (x, 1) with x negative
+ var x = Math.log(zmin) / Math.log(zmax);
+ var p = Math.log(z) / Math.log(zmax);
+ var percent = 1 - (p - x) / (1 - x); // the 1- bit at the front b/c up is in the -ve y direction
+
+ if( percent > 1 || percent < 0 ){
+ $noZoomTick.hide();
+ return;
+ }
+
+ var min = sliderPadding;
+ var max = $slider.height() - $sliderHandle.height() - 2*sliderPadding;
+ var top = percent * ( max - min );
+
+ // constrain to slider bounds
+ if( top < min ){ top = min }
+ if( top > max ){ top = max }
+
+ $noZoomTick.css('top', top);
+ })();
+
+ // set up zoom in/out buttons
+ /////////////////////////////
+
+ function bindButton($button, factor){
+ var zoomInterval;
+
+ $button.bind("mousedown", function(e){
+ e.preventDefault();
+ e.stopPropagation();
+
+ if( e.button != 0 ){
+ return;
+ }
+
+ var cy = $container.cytoscape("get");
+ var doZoom = function(){
+ var zoom = cy.zoom();
+ var lvl = cy.zoom() * factor;
+
+ if( lvl < options.minZoom ){
+ lvl = options.minZoom;
+ }
+
+ if( lvl > options.maxZoom ){
+ lvl = options.maxZoom;
+ }
+
+ if( (lvl == options.maxZoom && zoom == options.maxZoom) ||
+ (lvl == options.minZoom && zoom == options.minZoom)
+ ){
+ return;
+ }
+
+ zoomTo(lvl);
+ };
+
+ startZooming();
+ doZoom();
+ zoomInterval = setInterval(doZoom, options.zoomDelay);
+
+ return false;
+ });
+
+ windowBind("mouseup blur", function(){
+ clearInterval(zoomInterval);
+ endZooming();
+ });
+ }
+
+ bindButton( $zoomIn, (1 + options.zoomFactor) );
+ bindButton( $zoomOut, (1 - options.zoomFactor) );
+
+ $reset.bind("mousedown", function(e){
+ if( e.button != 0 ){
+ return;
+ }
+
+ var cy = $container.cytoscape("get");
+
+ if( cy.elements().size() === 0 ){
+ cy.reset();
+ } else {
+ cy.fit( options.fitPadding );
+ }
+
+ return false;
+ });
+
+
+
+ });
+ }
+ };
+
+ if( functions[fn] ){
+ return functions[fn].apply(this, Array.prototype.slice.call( arguments, 1 ));
+ } else if( typeof fn == 'object' || !fn ) {
+ return functions.init.apply( this, arguments );
+ } else {
+ $.error("No such function `"+ fn +"` for jquery.cytoscapePanzoom");
+ }
+
+ return $(this);
+ };
+
+
+ if( typeof module !== 'undefined' && module.exports ){ // expose as a commonjs module
+ module.exports = register;
+ }
+
+ if( typeof define !== 'undefined' && define.amd ){ // expose as an amd/requirejs module
+ define('cytoscape-panzoom', function(){
+ return register;
+ });
+ }
+
+ if( typeof cytoscape !== 'undefined' ){ // expose to global cytoscape (i.e. window.cytoscape)
+ register( cytoscape, jQuery || {} );
+ }
+
+})();
diff --git a/docs/htmldoc/js/cytoscape-qtip.js b/docs/htmldoc/js/cytoscape-qtip.js
new file mode 100644
index 0000000..43ad8b9
--- /dev/null
+++ b/docs/htmldoc/js/cytoscape-qtip.js
@@ -0,0 +1,362 @@
+;(function( $, $$ ){ 'use strict';
+
+ var isObject = function(o){
+ return o != null && typeof o === 'object';
+ };
+
+ var isFunction = function(o){
+ return o != null && typeof o === 'function';
+ };
+
+ var isNumber = function(o){
+ return o != null && typeof o === 'number';
+ };
+
+ var throttle = function(func, wait, options) {
+ var leading = true,
+ trailing = true;
+
+ if (options === false) {
+ leading = false;
+ } else if (isObject(options)) {
+ leading = 'leading' in options ? options.leading : leading;
+ trailing = 'trailing' in options ? options.trailing : trailing;
+ }
+ options = options || {};
+ options.leading = leading;
+ options.maxWait = wait;
+ options.trailing = trailing;
+
+ return debounce(func, wait, options);
+ };
+
+ var debounce = function(func, wait, options) { // ported lodash debounce function
+ var args,
+ maxTimeoutId,
+ result,
+ stamp,
+ thisArg,
+ timeoutId,
+ trailingCall,
+ lastCalled = 0,
+ maxWait = false,
+ trailing = true;
+
+ if (!isFunction(func)) {
+ return;
+ }
+ wait = Math.max(0, wait) || 0;
+ if (options === true) {
+ var leading = true;
+ trailing = false;
+ } else if (isObject(options)) {
+ leading = options.leading;
+ maxWait = 'maxWait' in options && (Math.max(wait, options.maxWait) || 0);
+ trailing = 'trailing' in options ? options.trailing : trailing;
+ }
+ var delayed = function() {
+ var remaining = wait - (Date.now() - stamp);
+ if (remaining <= 0) {
+ if (maxTimeoutId) {
+ clearTimeout(maxTimeoutId);
+ }
+ var isCalled = trailingCall;
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (isCalled) {
+ lastCalled = Date.now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ }
+ } else {
+ timeoutId = setTimeout(delayed, remaining);
+ }
+ };
+
+ var maxDelayed = function() {
+ if (timeoutId) {
+ clearTimeout(timeoutId);
+ }
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (trailing || (maxWait !== wait)) {
+ lastCalled = Date.now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ }
+ };
+
+ return function() {
+ args = arguments;
+ stamp = Date.now();
+ thisArg = this;
+ trailingCall = trailing && (timeoutId || !leading);
+
+ if (maxWait === false) {
+ var leadingCall = leading && !timeoutId;
+ } else {
+ if (!maxTimeoutId && !leading) {
+ lastCalled = stamp;
+ }
+ var remaining = maxWait - (stamp - lastCalled),
+ isCalled = remaining <= 0;
+
+ if (isCalled) {
+ if (maxTimeoutId) {
+ maxTimeoutId = clearTimeout(maxTimeoutId);
+ }
+ lastCalled = stamp;
+ result = func.apply(thisArg, args);
+ }
+ else if (!maxTimeoutId) {
+ maxTimeoutId = setTimeout(maxDelayed, remaining);
+ }
+ }
+ if (isCalled && timeoutId) {
+ timeoutId = clearTimeout(timeoutId);
+ }
+ else if (!timeoutId && wait !== maxWait) {
+ timeoutId = setTimeout(delayed, wait);
+ }
+ if (leadingCall) {
+ isCalled = true;
+ result = func.apply(thisArg, args);
+ }
+ if (isCalled && !timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ return result;
+ };
+ };
+
+ function register( $$, $ ){
+
+ // use a single dummy dom ele as target for every qtip
+ var $qtipContainer = $('<div></div>');
+ var viewportDebounceRate = 250;
+
+ function generateOpts( target, passedOpts ){
+ var qtip = target.scratch().qtip;
+ var opts = $.extend( {}, passedOpts );
+
+ if( !opts.id ){
+ opts.id = 'cy-qtip-target-' + ( Date.now() + Math.round( Math.random() * 10000) );
+ }
+
+ if( !qtip.$domEle ){
+ qtip.$domEle = $qtipContainer;
+ }
+
+ // qtip should be positioned relative to cy dom container
+ opts.position = opts.position || {};
+ opts.position.container = opts.position.container || $( document.body );
+ opts.position.viewport = opts.position.viewport || $( document.body );
+ opts.position.target = [0, 0];
+ opts.position.my = opts.position.my || 'top center';
+ opts.position.at = opts.position.at || 'bottom center';
+
+ // adjust
+ var adjust = opts.position.adjust = opts.position.adjust || {};
+ adjust.method = adjust.method || 'flip';
+ adjust.mouse = false;
+
+ if( adjust.cyAdjustToEleBB === undefined ){
+ adjust.cyAdjustToEleBB = true;
+ }
+
+ // default show event
+ opts.show = opts.show || {};
+
+ if( !opts.show.event ){
+ opts.show.event = 'tap';
+ }
+
+ // default hide event
+ opts.hide = opts.hide || {};
+ opts.hide.cyViewport = opts.hide.cyViewport === undefined ? true : opts.hide.cyViewport;
+
+ if( !opts.hide.event ){
+ opts.hide.event = 'unfocus';
+ }
+
+ // so multiple qtips can exist at once (only works on recent qtip2 versions)
+ opts.overwrite = false;
+
+ var content;
+ if( opts.content ){
+ if( isFunction(opts.content) ){
+ content = opts.content;
+ } else if( opts.content.text && isFunction(opts.content.text) ){
+ content = opts.content.text;
+ }
+
+ if( content ){
+ opts.content = function(event, api){
+ return content.apply( target, [event, api] );
+ };
+ }
+ }
+
+ return opts;
+ }
+
+ $$('collection', 'qtip', function( passedOpts ){
+ var eles = this;
+ var cy = this.cy();
+ var container = cy.container();
+
+ if( passedOpts === 'api' ){
+ return this.scratch().qtip.api;
+ }
+
+ eles.each(function(i, ele){
+ var scratch = ele.scratch();
+ var qtip = scratch.qtip = scratch.qtip || {};
+ var opts = generateOpts( ele, passedOpts );
+ var adjNums = opts.position.adjust;
+
+
+ qtip.$domEle.qtip( opts );
+ var qtipApi = qtip.api = qtip.$domEle.qtip('api'); // save api ref
+ qtip.$domEle.removeData('qtip'); // remove qtip dom/api ref to be safe
+
+ var updatePosition = function(e){
+ var cOff = container.getBoundingClientRect();
+ var pos = ele.renderedPosition() || ( e ? e.cyRenderedPosition : undefined );
+ if( !pos || pos.x == null || isNaN(pos.x) ){ return; }
+
+ if( opts.position.adjust.cyAdjustToEleBB && ele.isNode() ){
+ var my = opts.position.my.toLowerCase();
+ var at = opts.position.at.toLowerCase();
+ var z = cy.zoom();
+ var w = ele.outerWidth() * z;
+ var h = ele.outerHeight() * z;
+
+ if( at.match('top') ){
+ pos.y -= h/2;
+ } else if( at.match('bottom') ){
+ pos.y += h/2;
+ }
+
+ if( at.match('left') ){
+ pos.x -= w/2;
+ } else if( at.match('right') ){
+ pos.x += w/2;
+ }
+
+ if( isNumber(adjNums.x) ){
+ pos.x += adjNums.x;
+ }
+
+ if( isNumber(adjNums.y) ){
+ pos.y += adjNums.y;
+ }
+ }
+
+ qtipApi.set('position.adjust.x', cOff.left + pos.x + window.pageXOffset);
+ qtipApi.set('position.adjust.y', cOff.top + pos.y + window.pageYOffset);
+ };
+ updatePosition();
+
+ ele.on( opts.show.event, function(e){
+ updatePosition(e);
+
+ qtipApi.show();
+ } );
+
+ ele.on( opts.hide.event, function(e){
+ qtipApi.hide();
+ } );
+
+ if( opts.hide.cyViewport ){
+ cy.on('viewport', debounce(function(){
+ qtipApi.hide();
+ }, viewportDebounceRate, { leading: true }) );
+ }
+
+ if( opts.position.adjust.cyViewport ){
+ cy.on('pan zoom', debounce(function(e){
+ updatePosition(e);
+
+ qtipApi.reposition();
+ }, viewportDebounceRate, { trailing: true }) );
+ }
+
+ });
+
+ return this; // chainability
+
+ });
+
+ $$('core', 'qtip', function( passedOpts ){
+ var cy = this;
+ var container = cy.container();
+
+ if( passedOpts === 'api' ){
+ return this.scratch().qtip.api;
+ }
+
+ var scratch = cy.scratch();
+ var qtip = scratch.qtip = scratch.qtip || {};
+ var opts = generateOpts( cy, passedOpts );
+
+
+ qtip.$domEle.qtip( opts );
+ var qtipApi = qtip.api = qtip.$domEle.qtip('api'); // save api ref
+ qtip.$domEle.removeData('qtip'); // remove qtip dom/api ref to be safe
+
+ var updatePosition = function(e){
+ var cOff = container.getBoundingClientRect();
+ var pos = e.cyRenderedPosition;
+ if( !pos || pos.x == null || isNaN(pos.x) ){ return; }
+
+ qtipApi.set('position.adjust.x', cOff.left + pos.x + window.pageXOffset);
+ qtipApi.set('position.adjust.y', cOff.top + pos.y + window.pageYOffset);
+ };
+
+ cy.on( opts.show.event, function(e){
+ if( !opts.show.cyBgOnly || (opts.show.cyBgOnly && e.cyTarget === cy) ){
+ updatePosition(e);
+
+ qtipApi.show();
+ }
+ } );
+
+ cy.on( opts.hide.event, function(e){
+ if( !opts.hide.cyBgOnly || (opts.hide.cyBgOnly && e.cyTarget === cy) ){
+ qtipApi.hide();
+ }
+ } );
+
+ if( opts.hide.cyViewport ){
+ cy.on('viewport', debounce(function(){
+ qtipApi.hide();
+ }, viewportDebounceRate, { leading: true }) );
+ }
+
+ return this; // chainability
+
+ });
+
+ }
+
+ if( typeof module !== 'undefined' && module.exports ){ // expose as a commonjs module
+ module.exports = register;
+ }
+
+ if( typeof define !== 'undefined' && define.amd ){ // expose as an amd/requirejs module
+ define('cytoscape-qtip', function(){
+ return register;
+ });
+ }
+
+ if( $ && $$ ){
+ register( $$, $ );
+ }
+
+})(
+ typeof jQuery !== 'undefined' ? jQuery : null,
+ typeof cytoscape !== 'undefined' ? cytoscape : null
+);
diff --git a/docs/htmldoc/js/cytoscape.js b/docs/htmldoc/js/cytoscape.js
new file mode 100644
index 0000000..601e6db
--- /dev/null
+++ b/docs/htmldoc/js/cytoscape.js
@@ -0,0 +1,24515 @@
+/*!
+ * This file is part of Cytoscape.js 2.5.1.
+ *
+ * Cytoscape.js is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Cytoscape.js is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * Cytoscape.js. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.cytoscape = f()}})(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(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('./util');
+var is = _dereq_('./is');
+var Promise = _dereq_('./promise');
+
+var Animation = function( target, opts, opts2 ){
+ if( !(this instanceof Animation) ){
+ return new Animation( target, opts, opts2 );
+ }
+
+ var _p = this._private = util.extend( {
+ duration: 1000
+ }, opts, opts2 );
+
+ _p.target = target;
+ _p.style = _p.style || _p.css;
+ _p.started = false;
+ _p.playing = false;
+ _p.hooked = false;
+ _p.applying = false;
+ _p.progress = 0;
+ _p.completes = [];
+ _p.frames = [];
+
+ if( _p.complete && is.fn(_p.complete) ){
+ _p.completes.push( _p.complete );
+ }
+
+ // for future timeline/animations impl
+ this.length = 1;
+ this[0] = this;
+};
+
+var anifn = Animation.prototype;
+
+util.extend( anifn, {
+
+ instanceString: function(){ return 'animation'; },
+
+ hook: function(){
+ var _p = this._private;
+
+ if( !_p.hooked ){
+ // add to target's animation queue
+ var q;
+ var tAni = _p.target._private.animation;
+ if( _p.queue ){
+ q = tAni.queue;
+ } else {
+ q = tAni.current;
+ }
+ q.push( this );
+
+ // add to the animation loop pool
+ if( is.elementOrCollection( _p.target ) ){
+ _p.target.cy().addToAnimationPool( _p.target );
+ }
+
+ _p.hooked = true;
+ }
+
+ return this;
+ },
+
+ play: function(){
+ var _p = this._private;
+
+ // autorewind
+ if( _p.progress === 1 ){
+ _p.progress = 0;
+ }
+
+ _p.playing = true;
+ _p.started = false; // needs to be started by animation loop
+ _p.stopped = false;
+
+ this.hook();
+
+ // the animation loop will start the animation...
+
+ return this;
+ },
+
+ playing: function(){
+ return this._private.playing;
+ },
+
+ apply: function(){
+ var _p = this._private;
+
+ _p.applying = true;
+ _p.started = false; // needs to be started by animation loop
+ _p.stopped = false;
+
+ this.hook();
+
+ // the animation loop will apply the animation at this progress
+
+ return this;
+ },
+
+ applying: function(){
+ return this._private.applying;
+ },
+
+ pause: function(){
+ var _p = this._private;
+
+ _p.playing = false;
+ _p.started = false;
+
+ return this;
+ },
+
+ stop: function(){
+ var _p = this._private;
+
+ _p.playing = false;
+ _p.started = false;
+ _p.stopped = true; // to be removed from animation queues
+
+ return this;
+ },
+
+ rewind: function(){
+ return this.progress(0);
+ },
+
+ fastforward: function(){
+ return this.progress(1);
+ },
+
+ time: function( t ){
+ var _p = this._private;
+
+ if( t === undefined ){
+ return _p.progress * _p.duration;
+ } else {
+ return this.progress( t / _p.duration );
+ }
+ },
+
+ progress: function( p ){
+ var _p = this._private;
+ var wasPlaying = _p.playing;
+
+ if( p === undefined ){
+ return _p.progress;
+ } else {
+ if( wasPlaying ){
+ this.pause();
+ }
+
+ _p.progress = p;
+ _p.started = false;
+
+ if( wasPlaying ){
+ this.play();
+ }
+ }
+
+ return this;
+ },
+
+ completed: function(){
+ return this._private.progress === 1;
+ },
+
+ reverse: function(){
+ var _p = this._private;
+ var wasPlaying = _p.playing;
+
+ if( wasPlaying ){
+ this.pause();
+ }
+
+ _p.progress = 1 - _p.progress;
+ _p.started = false;
+
+ var swap = function( a, b ){
+ var _pa = _p[a];
+
+ _p[a] = _p[b];
+ _p[b] = _pa;
+ };
+
+ swap( 'zoom', 'startZoom' );
+ swap( 'pan', 'startPan' );
+ swap( 'position', 'startPosition' );
+
+ // swap styles
+ for( var i = 0; i < _p.style.length; i++ ){
+ var prop = _p.style[i];
+ var name = prop.name;
+ var startStyleProp = _p.startStyle[ name ];
+
+ _p.startStyle[ name ] = _p.startStyle[ util.dash2camel( name ) ] = prop;
+ _p.style[i] = startStyleProp;
+ }
+
+ if( wasPlaying ){
+ this.play();
+ }
+
+ return this;
+ },
+
+ promise: function( type ){
+ var _p = this._private;
+
+ var arr;
+
+ switch( type ){
+ case 'frame':
+ arr = _p.frames;
+ break;
+ default:
+ case 'complete':
+ case 'completed':
+ arr = _p.completes;
+ }
+
+ return new Promise(function( resolve, reject ){
+ arr.push(function(){
+ resolve();
+ });
+ });
+ }
+
+} );
+
+anifn.complete = anifn.completed;
+
+module.exports = Animation;
+
+},{"./is":77,"./promise":80,"./util":94}],2:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../is');
+
+var elesfn = ({
+
+ // Implemented from pseudocode from wikipedia
+ aStar: function(options) {
+ var eles = this;
+
+ options = options || {};
+
+ // Reconstructs the path from Start to End, acumulating the result in pathAcum
+ var reconstructPath = function(start, end, cameFromMap, pathAcum) {
+ // Base case
+ if (start == end) {
+ pathAcum.push( cy.getElementById(end) );
+ return pathAcum;
+ }
+
+ if (end in cameFromMap) {
+ // We know which node is before the last one
+ var previous = cameFromMap[end];
+ var previousEdge = cameFromEdge[end];
+
+ pathAcum.push( cy.getElementById(end) );
+ pathAcum.push( cy.getElementById(previousEdge) );
+
+
+ return reconstructPath(start,
+ previous,
+ cameFromMap,
+ pathAcum);
+ }
+
+ // We should not reach here!
+ return undefined;
+ };
+
+ // Returns the index of the element in openSet which has minimum fScore
+ var findMin = function(openSet, fScore) {
+ if (openSet.length === 0) {
+ // Should never be the case
+ return undefined;
+ }
+ var minPos = 0;
+ var tempScore = fScore[openSet[0]];
+ for (var i = 1; i < openSet.length; i++) {
+ var s = fScore[openSet[i]];
+ if (s < tempScore) {
+ tempScore = s;
+ minPos = i;
+ }
+ }
+ return minPos;
+ };
+
+ var cy = this._private.cy;
+
+ // root - mandatory!
+ if (options != null && options.root != null) {
+ var source = is.string(options.root) ?
+ // use it as a selector, e.g. "#rootID
+ this.filter(options.root)[0] :
+ options.root[0];
+ } else {
+ return undefined;
+ }
+
+ // goal - mandatory!
+ if (options.goal != null) {
+ var target = is.string(options.goal) ?
+ // use it as a selector, e.g. "#goalID
+ this.filter(options.goal)[0] :
+ options.goal[0];
+ } else {
+ return undefined;
+ }
+
+ // Heuristic function - optional
+ if (options.heuristic != null && is.fn(options.heuristic)) {
+ var heuristic = options.heuristic;
+ } else {
+ var heuristic = function(){ return 0; }; // use constant if unspecified
+ }
+
+ // Weight function - optional
+ if (options.weight != null && is.fn(options.weight)) {
+ var weightFn = options.weight;
+ } else {
+ // If not specified, assume each edge has equal weight (1)
+ var weightFn = function(e) {return 1;};
+ }
+
+ // directed - optional
+ if (options.directed != null) {
+ var directed = options.directed;
+ } else {
+ var directed = false;
+ }
+
+ var closedSet = [];
+ var openSet = [source.id()];
+ var cameFrom = {};
+ var cameFromEdge = {};
+ var gScore = {};
+ var fScore = {};
+
+ gScore[source.id()] = 0;
+ fScore[source.id()] = heuristic(source);
+
+ var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });
+ var nodes = this.nodes();
+
+ // Counter
+ var steps = 0;
+
+ // Main loop
+ while (openSet.length > 0) {
+ var minPos = findMin(openSet, fScore);
+ var cMin = cy.getElementById( openSet[minPos] );
+ steps++;
+
+ // If we've found our goal, then we are done
+ if (cMin.id() == target.id()) {
+ var rPath = reconstructPath(source.id(), target.id(), cameFrom, []);
+ rPath.reverse();
+ return {
+ found : true,
+ distance : gScore[cMin.id()],
+ path : eles.spawn(rPath),
+ steps : steps
+ };
+ }
+
+ // Add cMin to processed nodes
+ closedSet.push(cMin.id());
+ // Remove cMin from boundary nodes
+ openSet.splice(minPos, 1);
+
+ // Update scores for neighbors of cMin
+ // Take into account if graph is directed or not
+ var vwEdges = cMin.connectedEdges();
+ if( directed ){ vwEdges = vwEdges.stdFilter(function(ele){ return ele.data('source') === cMin.id(); }); }
+ vwEdges = vwEdges.intersect(edges);
+
+ for (var i = 0; i < vwEdges.length; i++) {
+ var e = vwEdges[i];
+ var w = e.connectedNodes().stdFilter(function(n){ return n.id() !== cMin.id(); }).intersect(nodes);
+
+ // if node is in closedSet, ignore it
+ if (closedSet.indexOf(w.id()) != -1) {
+ continue;
+ }
+
+ // New tentative score for node w
+ var tempScore = gScore[cMin.id()] + weightFn.apply(e, [e]);
+
+ // Update gScore for node w if:
+ // w not present in openSet
+ // OR
+ // tentative gScore is less than previous value
+
+ // w not in openSet
+ if (openSet.indexOf(w.id()) == -1) {
+ gScore[w.id()] = tempScore;
+ fScore[w.id()] = tempScore + heuristic(w);
+ openSet.push(w.id()); // Add node to openSet
+ cameFrom[w.id()] = cMin.id();
+ cameFromEdge[w.id()] = e.id();
+ continue;
+ }
+ // w already in openSet, but with greater gScore
+ if (tempScore < gScore[w.id()]) {
+ gScore[w.id()] = tempScore;
+ fScore[w.id()] = tempScore + heuristic(w);
+ cameFrom[w.id()] = cMin.id();
+ }
+
+ } // End of neighbors update
+
+ } // End of main loop
+
+ // If we've reached here, then we've not reached our goal
+ return {
+ found : false,
+ distance : undefined,
+ path : undefined,
+ steps : steps
+ };
+ }
+
+}); // elesfn
+
+
+module.exports = elesfn;
+
+},{"../../is":77}],3:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../is');
+var util = _dereq_('../../util');
+
+var elesfn = ({
+
+ // Implemented from pseudocode from wikipedia
+ bellmanFord: function(options) {
+ var eles = this;
+
+ options = options || {};
+
+ // Weight function - optional
+ if (options.weight != null && is.fn(options.weight)) {
+ var weightFn = options.weight;
+ } else {
+ // If not specified, assume each edge has equal weight (1)
+ var weightFn = function(e) {return 1;};
+ }
+
+ // directed - optional
+ if (options.directed != null) {
+ var directed = options.directed;
+ } else {
+ var directed = false;
+ }
+
+ // root - mandatory!
+ if (options.root != null) {
+ if (is.string(options.root)) {
+ // use it as a selector, e.g. "#rootID
+ var source = this.filter(options.root)[0];
+ } else {
+ var source = options.root[0];
+ }
+ } else {
+ return undefined;
+ }
+
+ var cy = this._private.cy;
+ var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });
+ var nodes = this.nodes();
+ var numNodes = nodes.length;
+
+ // mapping: node id -> position in nodes array
+ var id2position = {};
+ for (var i = 0; i < numNodes; i++) {
+ id2position[nodes[i].id()] = i;
+ }
+
+ // Initializations
+ var cost = [];
+ var predecessor = [];
+ var predEdge = [];
+
+ for (var i = 0; i < numNodes; i++) {
+ if (nodes[i].id() === source.id()) {
+ cost[i] = 0;
+ } else {
+ cost[i] = Infinity;
+ }
+ predecessor[i] = undefined;
+ }
+
+ // Edges relaxation
+ var flag = false;
+ for (var i = 1; i < numNodes; i++) {
+ flag = false;
+ for (var e = 0; e < edges.length; e++) {
+ var sourceIndex = id2position[edges[e].source().id()];
+ var targetIndex = id2position[edges[e].target().id()];
+ var weight = weightFn.apply(edges[e], [edges[e]]);
+
+ var temp = cost[sourceIndex] + weight;
+ if (temp < cost[targetIndex]) {
+ cost[targetIndex] = temp;
+ predecessor[targetIndex] = sourceIndex;
+ predEdge[targetIndex] = edges[e];
+ flag = true;
+ }
+
+ // If undirected graph, we need to take into account the 'reverse' edge
+ if (!directed) {
+ var temp = cost[targetIndex] + weight;
+ if (temp < cost[sourceIndex]) {
+ cost[sourceIndex] = temp;
+ predecessor[sourceIndex] = targetIndex;
+ predEdge[sourceIndex] = edges[e];
+ flag = true;
+ }
+ }
+ }
+
+ if (!flag) {
+ break;
+ }
+ }
+
+ if (flag) {
+ // Check for negative weight cycles
+ for (var e = 0; e < edges.length; e++) {
+ var sourceIndex = id2position[edges[e].source().id()];
+ var targetIndex = id2position[edges[e].target().id()];
+ var weight = weightFn.apply(edges[e], [edges[e]]);
+
+ if (cost[sourceIndex] + weight < cost[targetIndex]) {
+ util.error("Graph contains a negative weight cycle for Bellman-Ford");
+ return { pathTo: undefined,
+ distanceTo: undefined,
+ hasNegativeWeightCycle: true};
+ }
+ }
+ }
+
+ // Build result object
+ var position2id = [];
+ for (var i = 0; i < numNodes; i++) {
+ position2id.push(nodes[i].id());
+ }
+
+
+ var res = {
+ distanceTo : function(to) {
+ if (is.string(to)) {
+ // to is a selector string
+ var toId = (cy.filter(to)[0]).id();
+ } else {
+ // to is a node
+ var toId = to.id();
+ }
+
+ return cost[id2position[toId]];
+ },
+
+ pathTo : function(to) {
+
+ var reconstructPathAux = function(predecessor, fromPos, toPos, position2id, acumPath, predEdge) {
+ for(;;){
+ // Add toId to path
+ acumPath.push( cy.getElementById(position2id[toPos]) );
+ acumPath.push( predEdge[toPos] );
+
+ if (fromPos === toPos) {
+ // reached starting node
+ return acumPath;
+ }
+
+ // If no path exists, discart acumulated path and return undefined
+ var predPos = predecessor[toPos];
+ if (typeof predPos === "undefined") {
+ return undefined;
+ }
+
+ toPos = predPos;
+ }
+
+ };
+
+ if (is.string(to)) {
+ // to is a selector string
+ var toId = (cy.filter(to)[0]).id();
+ } else {
+ // to is a node
+ var toId = to.id();
+ }
+ var path = [];
+
+ // This returns a reversed path
+ var res = reconstructPathAux(predecessor,
+ id2position[source.id()],
+ id2position[toId],
+ position2id,
+ path,
+ predEdge);
+
+ // Get it in the correct order and return it
+ if (res != null) {
+ res.reverse();
+ }
+
+ return eles.spawn(res);
+ },
+
+ hasNegativeWeightCycle: false
+ };
+
+ return res;
+
+ } // bellmanFord
+
+}); // elesfn
+
+module.exports = elesfn;
+
+},{"../../is":77,"../../util":94}],4:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../is');
+
+var elesfn = ({
+
+ // Implemented from the algorithm in the paper "On Variants of Shortest-Path Betweenness Centrality and their Generic Computation" by Ulrik Brandes
+ betweennessCentrality: function (options) {
+ options = options || {};
+
+ // Weight - optional
+ if (options.weight != null && is.fn(options.weight)) {
+ var weightFn = options.weight;
+ var weighted = true;
+ } else {
+ var weighted = false;
+ }
+
+ // Directed - default false
+ if (options.directed != null && is.bool(options.directed)) {
+ var directed = options.directed;
+ } else {
+ var directed = false;
+ }
+
+ var priorityInsert = function (queue, ele) {
+ queue.unshift(ele);
+ for (var i = 0; d[queue[i]] < d[queue[i + 1]] && i < queue.length - 1; i++) {
+ var tmp = queue[i];
+ queue[i] = queue[i + 1];
+ queue[i + 1] = tmp;
+ }
+ };
+
+ var cy = this._private.cy;
+
+ // starting
+ var V = this.nodes();
+ var A = {};
+ var C = {};
+
+ // A contains the neighborhoods of every node
+ for (var i = 0; i < V.length; i++) {
+ if (directed) {
+ A[V[i].id()] = V[i].outgoers("node"); // get outgoers of every node
+ } else {
+ A[V[i].id()] = V[i].openNeighborhood("node"); // get neighbors of every node
+ }
+ }
+
+ // C contains the betweenness values
+ for (var i = 0; i < V.length; i++) {
+ C[V[i].id()] = 0;
+ }
+
+ for (var s = 0; s < V.length; s++) {
+ var S = []; // stack
+ var P = {};
+ var g = {};
+ var d = {};
+ var Q = []; // queue
+
+ // init dictionaries
+ for (var i = 0; i < V.length; i++) {
+ P[V[i].id()] = [];
+ g[V[i].id()] = 0;
+ d[V[i].id()] = Number.POSITIVE_INFINITY;
+ }
+
+ g[V[s].id()] = 1; // sigma
+ d[V[s].id()] = 0; // distance to s
+
+ Q.unshift(V[s].id());
+
+ while (Q.length > 0) {
+ var v = Q.pop();
+ S.push(v);
+ if (weighted) {
+ A[v].forEach(function (w) {
+ if (cy.$('#' + v).edgesTo(w).length > 0) {
+ var edge = cy.$('#' + v).edgesTo(w)[0];
+ } else {
+ var edge = w.edgesTo('#' + v)[0];
+ }
+
+ var edgeWeight = weightFn.apply(edge, [edge]);
+
+ if (d[w.id()] > d[v] + edgeWeight) {
+ d[w.id()] = d[v] + edgeWeight;
+ if (Q.indexOf(w.id()) < 0) { //if w is not in Q
+ priorityInsert(Q, w.id());
+ } else { // update position if w is in Q
+ Q.splice(Q.indexOf(w.id()), 1);
+ priorityInsert(Q, w.id());
+ }
+ g[w.id()] = 0;
+ P[w.id()] = [];
+ }
+ if (d[w.id()] == d[v] + edgeWeight) {
+ g[w.id()] = g[w.id()] + g[v];
+ P[w.id()].push(v);
+ }
+ });
+ } else {
+ A[v].forEach(function (w) {
+ if (d[w.id()] == Number.POSITIVE_INFINITY) {
+ Q.unshift(w.id());
+ d[w.id()] = d[v] + 1;
+ }
+ if (d[w.id()] == d[v] + 1) {
+ g[w.id()] = g[w.id()] + g[v];
+ P[w.id()].push(v);
+ }
+ });
+ }
+ }
+
+ var e = {};
+ for (var i = 0; i < V.length; i++) {
+ e[V[i].id()] = 0;
+ }
+
+ while (S.length > 0) {
+ var w = S.pop();
+ P[w].forEach(function (v) {
+ e[v] = e[v] + (g[v] / g[w]) * (1 + e[w]);
+ if (w != V[s].id())
+ C[w] = C[w] + e[w];
+ });
+ }
+ }
+
+ var max = 0;
+ for (var key in C) {
+ if (max < C[key])
+ max = C[key];
+ }
+
+ var ret = {
+ betweenness: function (node) {
+ if (is.string(node)) {
+ var node = (cy.filter(node)[0]).id();
+ } else {
+ var node = node.id();
+ }
+
+ return C[node];
+ },
+
+ betweennessNormalized: function (node) {
+ if (is.string(node)) {
+ var node = (cy.filter(node)[0]).id();
+ } else {
+ var node = node.id();
+ }
+
+ return C[node] / max;
+ }
+ };
+
+ // alias
+ ret.betweennessNormalised = ret.betweennessNormalized;
+
+ return ret;
+ } // betweennessCentrality
+
+}); // elesfn
+
+// nice, short mathemathical alias
+elesfn.bc = elesfn.betweennessCentrality;
+
+module.exports = elesfn;
+
+},{"../../is":77}],5:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../is');
+var Heap = _dereq_('../../heap');
+
+var defineSearch = function( params ){
+ params = {
+ bfs: params.bfs || !params.dfs,
+ dfs: params.dfs || !params.bfs
+ };
+
+ // from pseudocode on wikipedia
+ return function searchFn( roots, fn, directed ){
+ var options;
+ var std;
+ var thisArg;
+ if( is.plainObject(roots) && !is.elementOrCollection(roots) ){
+ options = roots;
+ roots = options.roots || options.root;
+ fn = options.visit;
+ directed = options.directed;
+ std = options.std;
+ thisArg = options.thisArg;
+ }
+
+ directed = arguments.length === 2 && !is.fn(fn) ? fn : directed;
+ fn = is.fn(fn) ? fn : function(){};
+
+ var cy = this._private.cy;
+ var v = roots = is.string(roots) ? this.filter(roots) : roots;
+ var Q = [];
+ var connectedNodes = [];
+ var connectedBy = {};
+ var id2depth = {};
+ var V = {};
+ var j = 0;
+ var found;
+ var nodes = this.nodes();
+ var edges = this.edges();
+
+ // enqueue v
+ for( var i = 0; i < v.length; i++ ){
+ if( v[i].isNode() ){
+ Q.unshift( v[i] );
+
+ if( params.bfs ){
+ V[ v[i].id() ] = true;
+
+ connectedNodes.push( v[i] );
+ }
+
+ id2depth[ v[i].id() ] = 0;
+ }
+ }
+
+ while( Q.length !== 0 ){
+ var v = params.bfs ? Q.shift() : Q.pop();
+
+ if( params.dfs ){
+ if( V[ v.id() ] ){ continue; }
+
+ V[ v.id() ] = true;
+
+ connectedNodes.push( v );
+ }
+
+ var depth = id2depth[ v.id() ];
+ var prevEdge = connectedBy[ v.id() ];
+ var prevNode = prevEdge == null ? undefined : prevEdge.connectedNodes().not( v )[0];
+ var ret;
+
+ if( std ){
+ ret = fn.call(thisArg, v, prevEdge, prevNode, j++, depth);
+ } else {
+ ret = fn.call(v, j++, depth, v, prevEdge, prevNode);
+ }
+
+ if( ret === true ){
+ found = v;
+ break;
+ }
+
+ if( ret === false ){
+ break;
+ }
+
+ var vwEdges = v.connectedEdges(directed ? function(){ return this.data('source') === v.id(); } : undefined).intersect( edges );
+ for( var i = 0; i < vwEdges.length; i++ ){
+ var e = vwEdges[i];
+ var w = e.connectedNodes(function(){ return this.id() !== v.id(); }).intersect( nodes );
+
+ if( w.length !== 0 && !V[ w.id() ] ){
+ w = w[0];
+
+ Q.push( w );
+
+ if( params.bfs ){
+ V[ w.id() ] = true;
+
+ connectedNodes.push( w );
+ }
+
+ connectedBy[ w.id() ] = e;
+
+ id2depth[ w.id() ] = id2depth[ v.id() ] + 1;
+ }
+ }
+
+ }
+
+ var connectedEles = [];
+
+ for( var i = 0; i < connectedNodes.length; i++ ){
+ var node = connectedNodes[i];
+ var edge = connectedBy[ node.id() ];
+
+ if( edge ){
+ connectedEles.push( edge );
+ }
+
+ connectedEles.push( node );
+ }
+
+ return {
+ path: cy.collection( connectedEles, { unique: true } ),
+ found: cy.collection( found )
+ };
+ };
+};
+
+// search, spanning trees, etc
+var elesfn = ({
+
+ breadthFirstSearch: defineSearch({ bfs: true }),
+ depthFirstSearch: defineSearch({ dfs: true }),
+
+ // kruskal's algorithm (finds min spanning tree, assuming undirected graph)
+ // implemented from pseudocode from wikipedia
+ kruskal: function( weightFn ){
+ var cy = this.cy();
+
+ weightFn = is.fn(weightFn) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1)
+
+ function findSet(ele){
+ for( var i = 0; i < forest.length; i++ ){
+ var eles = forest[i];
+
+ if( eles.anySame(ele) ){
+ return {
+ eles: eles,
+ index: i
+ };
+ }
+ }
+ }
+
+ var A = cy.collection(cy, []);
+ var forest = [];
+ var nodes = this.nodes();
+
+ for( var i = 0; i < nodes.length; i++ ){
+ forest.push( nodes[i].collection() );
+ }
+
+ var edges = this.edges();
+ var S = edges.toArray().sort(function(a, b){
+ var weightA = weightFn.call(a, a);
+ var weightB = weightFn.call(b, b);
+
+ return weightA - weightB;
+ });
+
+ for(var i = 0; i < S.length; i++){
+ var edge = S[i];
+ var u = edge.source()[0];
+ var v = edge.target()[0];
+ var setU = findSet(u);
+ var setV = findSet(v);
+
+ if( setU.index !== setV.index ){
+ A = A.add( edge );
+
+ // combine forests for u and v
+ forest[ setU.index ] = setU.eles.add( setV.eles );
+ forest.splice( setV.index, 1 );
+ }
+ }
+
+ return nodes.add( A );
+
+ },
+
+ dijkstra: function( root, weightFn, directed ){
+ var options;
+ if( is.plainObject(root) && !is.elementOrCollection(root) ){
+ options = root;
+ root = options.root;
+ weightFn = options.weight;
+ directed = options.directed;
+ }
+
+ var cy = this._private.cy;
+ weightFn = is.fn(weightFn) ? weightFn : function(){ return 1; }; // if not specified, assume each edge has equal weight (1)
+
+ var source = is.string(root) ? this.filter(root)[0] : root[0];
+ var dist = {};
+ var prev = {};
+ var knownDist = {};
+
+ var edges = this.edges().filter(function(){ return !this.isLoop(); });
+ var nodes = this.nodes();
+
+ var getDist = function(node){
+ return dist[ node.id() ];
+ };
+
+ var setDist = function(node, d){
+ dist[ node.id() ] = d;
+
+ Q.updateItem( node );
+ };
+
+ var Q = new Heap(function( a, b ){
+ return getDist(a) - getDist(b);
+ });
+
+ for( var i = 0; i < nodes.length; i++ ){
+ var node = nodes[i];
+
+ dist[ node.id() ] = node.same( source ) ? 0 : Infinity;
+ Q.push( node );
+ }
+
+ var distBetween = function(u, v){
+ var uvs = ( directed ? u.edgesTo(v) : u.edgesWith(v) ).intersect(edges);
+ var smallestDistance = Infinity;
+ var smallestEdge;
+
+ for( var i = 0; i < uvs.length; i++ ){
+ var edge = uvs[i];
+ var weight = weightFn.apply( edge, [edge] );
+
+ if( weight < smallestDistance || !smallestEdge ){
+ smallestDistance = weight;
+ smallestEdge = edge;
+ }
+ }
+
+ return {
+ edge: smallestEdge,
+ dist: smallestDistance
+ };
+ };
+
+ while( Q.size() > 0 ){
+ var u = Q.pop();
+ var smalletsDist = getDist(u);
+ var uid = u.id();
+
+ knownDist[uid] = smalletsDist;
+
+ if( smalletsDist === Math.Infinite ){
+ break;
+ }
+
+ var neighbors = u.neighborhood().intersect(nodes);
+ for( var i = 0; i < neighbors.length; i++ ){
+ var v = neighbors[i];
+ var vid = v.id();
+ var vDist = distBetween(u, v);
+
+ var alt = smalletsDist + vDist.dist;
+
+ if( alt < getDist(v) ){
+ setDist(v, alt);
+
+ prev[ vid ] = {
+ node: u,
+ edge: vDist.edge
+ };
+ }
+ } // for
+ } // while
+
+ return {
+ distanceTo: function(node){
+ var target = is.string(node) ? nodes.filter(node)[0] : node[0];
+
+ return knownDist[ target.id() ];
+ },
+
+ pathTo: function(node){
+ var target = is.string(node) ? nodes.filter(node)[0] : node[0];
+ var S = [];
+ var u = target;
+
+ if( target.length > 0 ){
+ S.unshift( target );
+
+ while( prev[ u.id() ] ){
+ var p = prev[ u.id() ];
+
+ S.unshift( p.edge );
+ S.unshift( p.node );
+
+ u = p.node;
+ }
+ }
+
+ return cy.collection( S );
+ }
+ };
+ }
+});
+
+// nice, short mathemathical alias
+elesfn.bfs = elesfn.breadthFirstSearch;
+elesfn.dfs = elesfn.depthFirstSearch;
+
+module.exports = elesfn;
+
+},{"../../heap":75,"../../is":77}],6:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../is');
+
+var elesfn = ({
+
+ closenessCentralityNormalized: function (options) {
+ options = options || {};
+
+ var cy = this.cy();
+
+ var harmonic = options.harmonic;
+ if( harmonic === undefined ){
+ harmonic = true;
+ }
+
+ var closenesses = {};
+ var maxCloseness = 0;
+ var nodes = this.nodes();
+ var fw = this.floydWarshall({ weight: options.weight, directed: options.directed });
+
+ // Compute closeness for every node and find the maximum closeness
+ for(var i = 0; i < nodes.length; i++){
+ var currCloseness = 0;
+ for (var j = 0; j < nodes.length; j++) {
+ if (i != j) {
+ var d = fw.distance(nodes[i], nodes[j]);
+
+ if( harmonic ){
+ currCloseness += 1 / d;
+ } else {
+ currCloseness += d;
+ }
+ }
+ }
+
+ if( !harmonic ){
+ currCloseness = 1 / currCloseness;
+ }
+
+ if (maxCloseness < currCloseness){
+ maxCloseness = currCloseness;
+ }
+
+ closenesses[nodes[i].id()] = currCloseness;
+ }
+
+ return {
+ closeness: function (node) {
+ if (is.string(node)) {
+ // from is a selector string
+ var node = (cy.filter(node)[0]).id();
+ } else {
+ // from is a node
+ var node = node.id();
+ }
+
+ return closenesses[node] / maxCloseness;
+ }
+ };
+ },
+
+ // Implemented from pseudocode from wikipedia
+ closenessCentrality: function (options) {
+ options = options || {};
+
+ // root - mandatory!
+ if (options.root != null) {
+ if (is.string(options.root)) {
+ // use it as a selector, e.g. "#rootID
+ var root = this.filter(options.root)[0];
+ } else {
+ var root = options.root[0];
+ }
+ } else {
+ return undefined;
+ }
+
+ // weight - optional
+ if (options.weight != null && is.fn(options.weight)) {
+ var weight = options.weight;
+ } else {
+ var weight = function(){return 1;};
+ }
+
+ // directed - optional
+ if (options.directed != null && is.bool(options.directed)) {
+ var directed = options.directed;
+ } else {
+ var directed = false;
+ }
+
+ var harmonic = options.harmonic;
+ if( harmonic === undefined ){
+ harmonic = true;
+ }
+
+ // we need distance from this node to every other node
+ var dijkstra = this.dijkstra({
+ root: root,
+ weight: weight,
+ directed: directed
+ });
+ var totalDistance = 0;
+
+ var nodes = this.nodes();
+ for (var i = 0; i < nodes.length; i++){
+ if (nodes[i].id() != root.id()){
+ var d = dijkstra.distanceTo(nodes[i]);
+
+ if( harmonic ){
+ totalDistance += 1 / d;
+ } else {
+ totalDistance += d;
+ }
+ }
+ }
+
+ return harmonic ? totalDistance : 1 / totalDistance;
+ } // closenessCentrality
+
+}); // elesfn
+
+// nice, short mathemathical alias
+elesfn.cc = elesfn.closenessCentrality;
+elesfn.ccn = elesfn.closenessCentralityNormalised = elesfn.closenessCentralityNormalized;
+
+module.exports = elesfn;
+
+},{"../../is":77}],7:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../is');
+var util = _dereq_('../../util');
+
+var elesfn = ({
+
+ degreeCentralityNormalized: function (options) {
+ options = options || {};
+
+ var cy = this.cy();
+
+ // directed - optional
+ if (options.directed != null) {
+ var directed = options.directed;
+ } else {
+ var directed = false;
+ }
+
+ var nodes = this.nodes();
+ var numNodes = nodes.length;
+
+ if (!directed) {
+ var degrees = {};
+ var maxDegree = 0;
+
+ for (var i = 0; i < numNodes; i++) {
+ var node = nodes[i];
+ // add current node to the current options object and call degreeCentrality
+ var currDegree = this.degreeCentrality(util.extend({}, options, {root: node}));
+ if (maxDegree < currDegree.degree)
+ maxDegree = currDegree.degree;
+
+ degrees[node.id()] = currDegree.degree;
+ }
+
+ return {
+ degree: function (node) {
+ if (is.string(node)) {
+ // from is a selector string
+ var node = (cy.filter(node)[0]).id();
+ } else {
+ // from is a node
+ var node = node.id();
+ }
+
+ return degrees[node] / maxDegree;
+ }
+ };
+ } else {
+ var indegrees = {};
+ var outdegrees = {};
+ var maxIndegree = 0;
+ var maxOutdegree = 0;
+
+ for (var i = 0; i < numNodes; i++) {
+ var node = nodes[i];
+ // add current node to the current options object and call degreeCentrality
+ var currDegree = this.degreeCentrality(util.extend({}, options, {root: node}));
+
+ if (maxIndegree < currDegree.indegree)
+ maxIndegree = currDegree.indegree;
+
+ if (maxOutdegree < currDegree.outdegree)
+ maxOutdegree = currDegree.outdegree;
+
+ indegrees[node.id()] = currDegree.indegree;
+ outdegrees[node.id()] = currDegree.outdegree;
+ }
+
+ return {
+ indegree: function (node) {
+ if (is.string(node)) {
+ // from is a selector string
+ var node = (cy.filter(node)[0]).id();
+ } else {
+ // from is a node
+ var node = node.id();
+ }
+
+ return indegrees[node] / maxIndegree;
+ },
+ outdegree: function (node) {
+ if (is.string(node)) {
+ // from is a selector string
+ var node = (cy.filter(node)[0]).id();
+ } else {
+ // from is a node
+ var node = node.id();
+ }
+
+ return outdegrees[node] / maxOutdegree;
+ }
+
+ };
+ }
+
+ }, // degreeCentralityNormalized
+
+ // Implemented from the algorithm in Opsahl's paper
+ // "Node centrality in weighted networks: Generalizing degree and shortest paths"
+ // check the heading 2 "Degree"
+ degreeCentrality: function (options) {
+ options = options || {};
+
+ var callingEles = this;
+
+ // root - mandatory!
+ if (options != null && options.root != null) {
+ var root = is.string(options.root) ? this.filter(options.root)[0] : options.root[0];
+ } else {
+ return undefined;
+ }
+
+ // weight - optional
+ if (options.weight != null && is.fn(options.weight)) {
+ var weightFn = options.weight;
+ } else {
+ // If not specified, assume each edge has equal weight (1)
+ var weightFn = function (e) {
+ return 1;
+ };
+ }
+
+ // directed - optional
+ if (options.directed != null) {
+ var directed = options.directed;
+ } else {
+ var directed = false;
+ }
+
+ // alpha - optional
+ if (options.alpha != null && is.number(options.alpha)) {
+ var alpha = options.alpha;
+ } else {
+ alpha = 0;
+ }
+
+
+ if (!directed) {
+ var connEdges = root.connectedEdges().intersection( callingEles );
+ var k = connEdges.length;
+ var s = 0;
+
+ // Now, sum edge weights
+ for (var i = 0; i < connEdges.length; i++) {
+ var edge = connEdges[i];
+ s += weightFn.apply(edge, [edge]);
+ }
+
+ return {
+ degree: Math.pow(k, 1 - alpha) * Math.pow(s, alpha)
+ };
+ } else {
+ var incoming = root.connectedEdges('edge[target = "' + root.id() + '"]').intersection( callingEles );
+ var outgoing = root.connectedEdges('edge[source = "' + root.id() + '"]').intersection( callingEles );
+ var k_in = incoming.length;
+ var k_out = outgoing.length;
+ var s_in = 0;
+ var s_out = 0;
+
+ // Now, sum incoming edge weights
+ for (var i = 0; i < incoming.length; i++) {
+ var edge = incoming[i];
+ s_in += weightFn.apply(edge, [edge]);
+ }
+
+ // Now, sum outgoing edge weights
+ for (var i = 0; i < outgoing.length; i++) {
+ var edge = outgoing[i];
+ s_out += weightFn.apply(edge, [edge]);
+ }
+
+ return {
+ indegree: Math.pow(k_in, 1 - alpha) * Math.pow(s_in, alpha),
+ outdegree: Math.pow(k_out, 1 - alpha) * Math.pow(s_out, alpha)
+ };
+ }
+ } // degreeCentrality
+
+}); // elesfn
+
+// nice, short mathemathical alias
+elesfn.dc = elesfn.degreeCentrality;
+elesfn.dcn = elesfn.degreeCentralityNormalised = elesfn.degreeCentralityNormalized;
+
+module.exports = elesfn;
+
+},{"../../is":77,"../../util":94}],8:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../is');
+
+var elesfn = ({
+
+ // Implemented from pseudocode from wikipedia
+ floydWarshall: function(options) {
+ options = options || {};
+
+ var cy = this.cy();
+
+ // Weight function - optional
+ if (options.weight != null && is.fn(options.weight)) {
+ var weightFn = options.weight;
+ } else {
+ // If not specified, assume each edge has equal weight (1)
+ var weightFn = function(e) {return 1;};
+ }
+
+ // directed - optional
+ if (options.directed != null) {
+ var directed = options.directed;
+ } else {
+ var directed = false;
+ }
+
+ var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });
+ var nodes = this.nodes();
+ var numNodes = nodes.length;
+
+ // mapping: node id -> position in nodes array
+ var id2position = {};
+ for (var i = 0; i < numNodes; i++) {
+ id2position[nodes[i].id()] = i;
+ }
+
+ // Initialize distance matrix
+ var dist = [];
+ for (var i = 0; i < numNodes; i++) {
+ var newRow = new Array(numNodes);
+ for (var j = 0; j < numNodes; j++) {
+ if (i == j) {
+ newRow[j] = 0;
+ } else {
+ newRow[j] = Infinity;
+ }
+ }
+ dist.push(newRow);
+ }
+
+ // Initialize matrix used for path reconstruction
+ // Initialize distance matrix
+ var next = [];
+ var edgeNext = [];
+
+ var initMatrix = function(next){
+ for (var i = 0; i < numNodes; i++) {
+ var newRow = new Array(numNodes);
+ for (var j = 0; j < numNodes; j++) {
+ newRow[j] = undefined;
+ }
+ next.push(newRow);
+ }
+ };
+
+ initMatrix(next);
+ initMatrix(edgeNext);
+
+ // Process edges
+ for (var i = 0; i < edges.length ; i++) {
+ var sourceIndex = id2position[edges[i].source().id()];
+ var targetIndex = id2position[edges[i].target().id()];
+ var weight = weightFn.apply(edges[i], [edges[i]]);
+
+ // Check if already process another edge between same 2 nodes
+ if (dist[sourceIndex][targetIndex] > weight) {
+ dist[sourceIndex][targetIndex] = weight;
+ next[sourceIndex][targetIndex] = targetIndex;
+ edgeNext[sourceIndex][targetIndex] = edges[i];
+ }
+ }
+
+ // If undirected graph, process 'reversed' edges
+ if (!directed) {
+ for (var i = 0; i < edges.length ; i++) {
+ var sourceIndex = id2position[edges[i].target().id()];
+ var targetIndex = id2position[edges[i].source().id()];
+ var weight = weightFn.apply(edges[i], [edges[i]]);
+
+ // Check if already process another edge between same 2 nodes
+ if (dist[sourceIndex][targetIndex] > weight) {
+ dist[sourceIndex][targetIndex] = weight;
+ next[sourceIndex][targetIndex] = targetIndex;
+ edgeNext[sourceIndex][targetIndex] = edges[i];
+ }
+ }
+ }
+
+ // Main loop
+ for (var k = 0; k < numNodes; k++) {
+ for (var i = 0; i < numNodes; i++) {
+ for (var j = 0; j < numNodes; j++) {
+ if (dist[i][k] + dist[k][j] < dist[i][j]) {
+ dist[i][j] = dist[i][k] + dist[k][j];
+ next[i][j] = next[i][k];
+ }
+ }
+ }
+ }
+
+ // Build result object
+ var position2id = [];
+ for (var i = 0; i < numNodes; i++) {
+ position2id.push(nodes[i].id());
+ }
+
+ var res = {
+ distance: function(from, to) {
+ if (is.string(from)) {
+ // from is a selector string
+ var fromId = (cy.filter(from)[0]).id();
+ } else {
+ // from is a node
+ var fromId = from.id();
+ }
+
+ if (is.string(to)) {
+ // to is a selector string
+ var toId = (cy.filter(to)[0]).id();
+ } else {
+ // to is a node
+ var toId = to.id();
+ }
+
+ return dist[id2position[fromId]][id2position[toId]];
+ },
+
+ path: function(from, to) {
+ var reconstructPathAux = function(from, to, next, position2id, edgeNext) {
+ if (from === to) {
+ return cy.getElementById( position2id[from] );
+ }
+ if (next[from][to] === undefined) {
+ return undefined;
+ }
+
+ var path = [ cy.getElementById(position2id[from]) ];
+ var prev = from;
+ while (from !== to) {
+ prev = from;
+ from = next[from][to];
+
+ var edge = edgeNext[prev][from];
+ path.push( edge );
+
+ path.push( cy.getElementById(position2id[from]) );
+ }
+ return path;
+ };
+
+ if (is.string(from)) {
+ // from is a selector string
+ var fromId = (cy.filter(from)[0]).id();
+ } else {
+ // from is a node
+ var fromId = from.id();
+ }
+
+ if (is.string(to)) {
+ // to is a selector string
+ var toId = (cy.filter(to)[0]).id();
+ } else {
+ // to is a node
+ var toId = to.id();
+ }
+
+ var pathArr = reconstructPathAux(id2position[fromId],
+ id2position[toId],
+ next,
+ position2id,
+ edgeNext);
+
+ return cy.collection( pathArr );
+ },
+ };
+
+ return res;
+
+ } // floydWarshall
+
+}); // elesfn
+
+module.exports = elesfn;
+
+},{"../../is":77}],9:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../../util');
+
+var elesfn = {};
+
+[
+ _dereq_('./bfs-dfs'),
+ _dereq_('./a-star'),
+ _dereq_('./floyd-warshall'),
+ _dereq_('./bellman-ford'),
+ _dereq_('./kerger-stein'),
+ _dereq_('./page-rank'),
+ _dereq_('./degree-centrality'),
+ _dereq_('./closeness-centrality'),
+ _dereq_('./betweenness-centrality')
+].forEach(function( props ){
+ util.extend( elesfn, props );
+});
+
+module.exports = elesfn;
+
+},{"../../util":94,"./a-star":2,"./bellman-ford":3,"./betweenness-centrality":4,"./bfs-dfs":5,"./closeness-centrality":6,"./degree-centrality":7,"./floyd-warshall":8,"./kerger-stein":10,"./page-rank":11}],10:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../../util');
+
+var elesfn = ({
+
+ // Computes the minimum cut of an undirected graph
+ // Returns the correct answer with high probability
+ kargerStein: function(options) {
+ var eles = this;
+
+ options = options || {};
+
+ // Function which colapses 2 (meta) nodes into one
+ // Updates the remaining edge lists
+ // Receives as a paramater the edge which causes the collapse
+ var colapse = function(edgeIndex, nodeMap, remainingEdges) {
+ var edgeInfo = remainingEdges[edgeIndex];
+ var sourceIn = edgeInfo[1];
+ var targetIn = edgeInfo[2];
+ var partition1 = nodeMap[sourceIn];
+ var partition2 = nodeMap[targetIn];
+
+ // Delete all edges between partition1 and partition2
+ var newEdges = remainingEdges.filter(function(edge) {
+ if (nodeMap[edge[1]] === partition1 && nodeMap[edge[2]] === partition2) {
+ return false;
+ }
+ if (nodeMap[edge[1]] === partition2 && nodeMap[edge[2]] === partition1) {
+ return false;
+ }
+ return true;
+ });
+
+ // All edges pointing to partition2 should now point to partition1
+ for (var i = 0; i < newEdges.length; i++) {
+ var edge = newEdges[i];
+ if (edge[1] === partition2) { // Check source
+ newEdges[i] = edge.slice(0);
+ newEdges[i][1] = partition1;
+ } else if (edge[2] === partition2) { // Check target
+ newEdges[i] = edge.slice(0);
+ newEdges[i][2] = partition1;
+ }
+ }
+
+ // Move all nodes from partition2 to partition1
+ for (var i = 0; i < nodeMap.length; i++) {
+ if (nodeMap[i] === partition2) {
+ nodeMap[i] = partition1;
+ }
+ }
+
+ return newEdges;
+ };
+
+
+ // Contracts a graph until we reach a certain number of meta nodes
+ var contractUntil = function(metaNodeMap,
+ remainingEdges,
+ size,
+ sizeLimit) {
+ // Stop condition
+ if (size <= sizeLimit) {
+ return remainingEdges;
+ }
+
+ // Choose an edge randomly
+ var edgeIndex = Math.floor((Math.random() * remainingEdges.length));
+
+ // Colapse graph based on edge
+ var newEdges = colapse(edgeIndex, metaNodeMap, remainingEdges);
+
+ return contractUntil(metaNodeMap,
+ newEdges,
+ size - 1,
+ sizeLimit);
+ };
+
+ var cy = this._private.cy;
+ var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });
+ var nodes = this.nodes();
+ var numNodes = nodes.length;
+ var numEdges = edges.length;
+ var numIter = Math.ceil(Math.pow(Math.log(numNodes) / Math.LN2, 2));
+ var stopSize = Math.floor(numNodes / Math.sqrt(2));
+
+ if (numNodes < 2) {
+ util.error("At least 2 nodes are required for Karger-Stein algorithm");
+ return undefined;
+ }
+
+ // Create numerical identifiers for each node
+ // mapping: node id -> position in nodes array
+ // for reverse mapping, simply use nodes array
+ var id2position = {};
+ for (var i = 0; i < numNodes; i++) {
+ id2position[nodes[i].id()] = i;
+ }
+
+ // Now store edge destination as indexes
+ // Format for each edge (edge index, source node index, target node index)
+ var edgeIndexes = [];
+ for (var i = 0; i < numEdges; i++) {
+ var e = edges[i];
+ edgeIndexes.push([i, id2position[e.source().id()], id2position[e.target().id()]]);
+ }
+
+ // We will store the best cut found here
+ var minCutSize = Infinity;
+ var minCut;
+
+ // Initial meta node partition
+ var originalMetaNode = [];
+ for (var i = 0; i < numNodes; i++) {
+ originalMetaNode.push(i);
+ }
+
+ // Main loop
+ for (var iter = 0; iter <= numIter; iter++) {
+ // Create new meta node partition
+ var metaNodeMap = originalMetaNode.slice(0);
+
+ // Contract until stop point (stopSize nodes)
+ var edgesState = contractUntil(metaNodeMap, edgeIndexes, numNodes, stopSize);
+
+ // Create a copy of the colapsed nodes state
+ var metaNodeMap2 = metaNodeMap.slice(0);
+
+ // Run 2 iterations starting in the stop state
+ var res1 = contractUntil(metaNodeMap, edgesState, stopSize, 2);
+ var res2 = contractUntil(metaNodeMap2, edgesState, stopSize, 2);
+
+ // Is any of the 2 results the best cut so far?
+ if (res1.length <= res2.length && res1.length < minCutSize) {
+ minCutSize = res1.length;
+ minCut = [res1, metaNodeMap];
+ } else if (res2.length <= res1.length && res2.length < minCutSize) {
+ minCutSize = res2.length;
+ minCut = [res2, metaNodeMap2];
+ }
+ } // end of main loop
+
+
+ // Construct result
+ var resEdges = (minCut[0]).map(function(e){ return edges[e[0]]; });
+ var partition1 = [];
+ var partition2 = [];
+
+ // traverse metaNodeMap for best cut
+ var witnessNodePartition = minCut[1][0];
+ for (var i = 0; i < minCut[1].length; i++) {
+ var partitionId = minCut[1][i];
+ if (partitionId === witnessNodePartition) {
+ partition1.push(nodes[i]);
+ } else {
+ partition2.push(nodes[i]);
+ }
+ }
+
+ var ret = {
+ cut: eles.spawn(cy, resEdges),
+ partition1: eles.spawn(partition1),
+ partition2: eles.spawn(partition2)
+ };
+
+ return ret;
+ }
+}); // elesfn
+
+
+module.exports = elesfn;
+
+},{"../../util":94}],11:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../is');
+
+var elesfn = ({
+
+ pageRank: function(options) {
+ options = options || {};
+
+ var normalizeVector = function(vector) {
+ var length = vector.length;
+
+ // First, get sum of all elements
+ var total = 0;
+ for (var i = 0; i < length; i++) {
+ total += vector[i];
+ }
+
+ // Now, divide each by the sum of all elements
+ for (var i = 0; i < length; i++) {
+ vector[i] = vector[i] / total;
+ }
+ };
+
+ // dampingFactor - optional
+ if (options != null &&
+ options.dampingFactor != null) {
+ var dampingFactor = options.dampingFactor;
+ } else {
+ var dampingFactor = 0.8; // Default damping factor
+ }
+
+ // desired precision - optional
+ if (options != null &&
+ options.precision != null) {
+ var epsilon = options.precision;
+ } else {
+ var epsilon = 0.000001; // Default precision
+ }
+
+ // Max number of iterations - optional
+ if (options != null &&
+ options.iterations != null) {
+ var numIter = options.iterations;
+ } else {
+ var numIter = 200; // Default number of iterations
+ }
+
+ // Weight function - optional
+ if (options != null &&
+ options.weight != null &&
+ is.fn(options.weight)) {
+ var weightFn = options.weight;
+ } else {
+ // If not specified, assume each edge has equal weight (1)
+ var weightFn = function(e) {return 1;};
+ }
+
+ var cy = this._private.cy;
+ var edges = this.edges().stdFilter(function(e){ return !e.isLoop(); });
+ var nodes = this.nodes();
+ var numNodes = nodes.length;
+ var numEdges = edges.length;
+
+ // Create numerical identifiers for each node
+ // mapping: node id -> position in nodes array
+ // for reverse mapping, simply use nodes array
+ var id2position = {};
+ for (var i = 0; i < numNodes; i++) {
+ id2position[nodes[i].id()] = i;
+ }
+
+ // Construct transposed adjacency matrix
+ // First lets have a zeroed matrix of the right size
+ // We'll also keep track of the sum of each column
+ var matrix = [];
+ var columnSum = [];
+ var additionalProb = (1 - dampingFactor) / numNodes;
+
+ // Create null matric
+ for (var i = 0; i < numNodes; i++) {
+ var newRow = [];
+ for (var j = 0; j < numNodes; j++) {
+ newRow.push(0.0);
+ }
+ matrix.push(newRow);
+ columnSum.push(0.0);
+ }
+
+ // Now, process edges
+ for (var i = 0; i < numEdges; i++) {
+ var edge = edges[i];
+ var s = id2position[edge.source().id()];
+ var t = id2position[edge.target().id()];
+ var w = weightFn.apply(edge, [edge]);
+
+ // Update matrix
+ matrix[t][s] += w;
+
+ // Update column sum
+ columnSum[s] += w;
+ }
+
+ // Add additional probability based on damping factor
+ // Also, take into account columns that have sum = 0
+ var p = 1.0 / numNodes + additionalProb; // Shorthand
+ // Traverse matrix, column by column
+ for (var j = 0; j < numNodes; j++) {
+ if (columnSum[j] === 0) {
+ // No 'links' out from node jth, assume equal probability for each possible node
+ for (var i = 0; i < numNodes; i++) {
+ matrix[i][j] = p;
+ }
+ } else {
+ // Node jth has outgoing link, compute normalized probabilities
+ for (var i = 0; i < numNodes; i++) {
+ matrix[i][j] = matrix[i][j] / columnSum[j] + additionalProb;
+ }
+ }
+ }
+
+ // Compute dominant eigenvector using power method
+ var eigenvector = [];
+ var nullVector = [];
+ var previous;
+
+ // Start with a vector of all 1's
+ // Also, initialize a null vector which will be used as shorthand
+ for (var i = 0; i < numNodes; i++) {
+ eigenvector.push(1.0);
+ nullVector.push(0.0);
+ }
+
+ for (var iter = 0; iter < numIter; iter++) {
+ // New array with all 0's
+ var temp = nullVector.slice(0);
+
+ // Multiply matrix with previous result
+ for (var i = 0; i < numNodes; i++) {
+ for (var j = 0; j < numNodes; j++) {
+ temp[i] += matrix[i][j] * eigenvector[j];
+ }
+ }
+
+ normalizeVector(temp);
+ previous = eigenvector;
+ eigenvector = temp;
+
+ var diff = 0;
+ // Compute difference (squared module) of both vectors
+ for (var i = 0; i < numNodes; i++) {
+ diff += Math.pow(previous[i] - eigenvector[i], 2);
+ }
+
+ // If difference is less than the desired threshold, stop iterating
+ if (diff < epsilon) {
+ break;
+ }
+ }
+
+ // Construct result
+ var res = {
+ rank : function(node) {
+ if (is.string(node)) {
+ // is a selector string
+ var nodeId = (cy.filter(node)[0]).id();
+ } else {
+ // is a node object
+ var nodeId = node.id();
+ }
+ return eigenvector[id2position[nodeId]];
+ }
+ };
+
+
+ return res;
+ } // pageRank
+
+}); // elesfn
+
+module.exports = elesfn;
+
+},{"../../is":77}],12:[function(_dereq_,module,exports){
+'use strict';
+
+var define = _dereq_('../define');
+
+var elesfn = ({
+ animate: define.animate(),
+ animation: define.animation(),
+ animated: define.animated(),
+ clearQueue: define.clearQueue(),
+ delay: define.delay(),
+ delayAnimation: define.delayAnimation(),
+ stop: define.stop(),
+});
+
+module.exports = elesfn;
+
+},{"../define":41}],13:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+
+var elesfn = ({
+ classes: function( classes ){
+ classes = classes.match(/\S+/g) || [];
+ var self = this;
+ var changed = [];
+ var classesMap = {};
+
+ // fill in classes map
+ for( var i = 0; i < classes.length; i++ ){
+ var cls = classes[i];
+
+ classesMap[ cls ] = true;
+ }
+
+ // check and update each ele
+ for( var j = 0; j < self.length; j++ ){
+ var ele = self[j];
+ var _p = ele._private;
+ var eleClasses = _p.classes;
+ var changedEle = false;
+
+ // check if ele has all of the passed classes
+ for( var i = 0; i < classes.length; i++ ){
+ var cls = classes[i];
+ var eleHasClass = eleClasses[ cls ];
+
+ if( !eleHasClass ){
+ changedEle = true;
+ break;
+ }
+ }
+
+ // check if ele has classes outside of those passed
+ if( !changedEle ){ for( var eleCls in eleClasses ){
+ var eleHasClass = eleClasses[ eleCls ];
+ var specdClass = classesMap[ eleCls ]; // i.e. this class is passed to the function
+
+ if( eleHasClass && !specdClass ){
+ changedEle = true;
+ break;
+ }
+ } }
+
+ if( changedEle ){
+ _p.classes = util.copy( classesMap );
+
+ changed.push( ele );
+ }
+ }
+
+ // trigger update style on those eles that had class changes
+ if( changed.length > 0 ){
+ this.spawn(changed)
+ .updateStyle()
+ .trigger('class')
+ ;
+ }
+
+ return self;
+ },
+
+ addClass: function( classes ){
+ return this.toggleClass( classes, true );
+ },
+
+ hasClass: function( className ){
+ var ele = this[0];
+ return ( ele != null && ele._private.classes[className] ) ? true : false;
+ },
+
+ toggleClass: function( classesStr, toggle ){
+ var classes = classesStr.match(/\S+/g) || [];
+ var self = this;
+ var changed = []; // eles who had classes changed
+
+ for( var i = 0, il = self.length; i < il; i++ ){
+ var ele = self[i];
+ var changedEle = false;
+
+ for( var j = 0; j < classes.length; j++ ){
+ var cls = classes[j];
+ var eleClasses = ele._private.classes;
+ var hasClass = eleClasses[cls];
+ var shouldAdd = toggle || (toggle === undefined && !hasClass);
+
+ if( shouldAdd ){
+ eleClasses[cls] = true;
+
+ if( !hasClass && !changedEle ){
+ changed.push(ele);
+ changedEle = true;
+ }
+ } else { // then remove
+ eleClasses[cls] = false;
+
+ if( hasClass && !changedEle ){
+ changed.push(ele);
+ changedEle = true;
+ }
+ }
+
+ } // for j classes
+ } // for i eles
+
+ // trigger update style on those eles that had class changes
+ if( changed.length > 0 ){
+ this.spawn(changed)
+ .updateStyle()
+ .trigger('class')
+ ;
+ }
+
+ return self;
+ },
+
+ removeClass: function( classes ){
+ return this.toggleClass( classes, false );
+ },
+
+ flashClass: function( classes, duration ){
+ var self = this;
+
+ if( duration == null ){
+ duration = 250;
+ } else if( duration === 0 ){
+ return self; // nothing to do really
+ }
+
+ self.addClass( classes );
+ setTimeout(function(){
+ self.removeClass( classes );
+ }, duration);
+
+ return self;
+ }
+});
+
+module.exports = elesfn;
+
+},{"../util":94}],14:[function(_dereq_,module,exports){
+'use strict';
+
+var elesfn = ({
+ allAre: function( selector ){
+ return this.filter(selector).length === this.length;
+ },
+
+ is: function( selector ){
+ return this.filter(selector).length > 0;
+ },
+
+ some: function( fn, thisArg ){
+ for( var i = 0; i < this.length; i++ ){
+ var ret = !thisArg ? fn( this[i], i, this ) : fn.apply( thisArg, [ this[i], i, this ] );
+
+ if( ret ){
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ every: function( fn, thisArg ){
+ for( var i = 0; i < this.length; i++ ){
+ var ret = !thisArg ? fn( this[i], i, this ) : fn.apply( thisArg, [ this[i], i, this ] );
+
+ if( !ret ){
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ same: function( collection ){
+ collection = this.cy().collection( collection );
+
+ // cheap extra check
+ if( this.length !== collection.length ){
+ return false;
+ }
+
+ return this.intersect( collection ).length === this.length;
+ },
+
+ anySame: function( collection ){
+ collection = this.cy().collection( collection );
+
+ return this.intersect( collection ).length > 0;
+ },
+
+ allAreNeighbors: function( collection ){
+ collection = this.cy().collection( collection );
+
+ return this.neighborhood().intersect( collection ).length === collection.length;
+ }
+});
+
+elesfn.allAreNeighbours = elesfn.allAreNeighbors;
+
+module.exports = elesfn;
+
+},{}],15:[function(_dereq_,module,exports){
+'use strict';
+
+var elesfn = ({
+ parent: function( selector ){
+ var parents = [];
+ var cy = this._private.cy;
+
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+ var parent = cy.getElementById( ele._private.data.parent );
+
+ if( parent.size() > 0 ){
+ parents.push( parent );
+ }
+ }
+
+ return this.spawn( parents, { unique: true } ).filter( selector );
+ },
+
+ parents: function( selector ){
+ var parents = [];
+
+ var eles = this.parent();
+ while( eles.nonempty() ){
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ parents.push( ele );
+ }
+
+ eles = eles.parent();
+ }
+
+ return this.spawn( parents, { unique: true } ).filter( selector );
+ },
+
+ commonAncestors: function( selector ){
+ var ancestors;
+
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+ var parents = ele.parents();
+
+ ancestors = ancestors || parents;
+
+ ancestors = ancestors.intersect( parents ); // current list must be common with current ele parents set
+ }
+
+ return ancestors.filter( selector );
+ },
+
+ orphans: function( selector ){
+ return this.stdFilter(function( ele ){
+ return ele.isNode() && ele.parent().empty();
+ }).filter( selector );
+ },
+
+ nonorphans: function( selector ){
+ return this.stdFilter(function( ele ){
+ return ele.isNode() && ele.parent().nonempty();
+ }).filter( selector );
+ },
+
+ children: function( selector ){
+ var children = [];
+
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+ children = children.concat( ele._private.children );
+ }
+
+ return this.spawn( children, { unique: true } ).filter( selector );
+ },
+
+ siblings: function( selector ){
+ return this.parent().children().not( this ).filter( selector );
+ },
+
+ isParent: function(){
+ var ele = this[0];
+
+ if( ele ){
+ return ele._private.children.length !== 0;
+ }
+ },
+
+ isChild: function(){
+ var ele = this[0];
+
+ if( ele ){
+ return ele._private.data.parent !== undefined && ele.parent().length !== 0;
+ }
+ },
+
+ descendants: function( selector ){
+ var elements = [];
+
+ function add( eles ){
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+
+ elements.push( ele );
+
+ if( ele.children().nonempty() ){
+ add( ele.children() );
+ }
+ }
+ }
+
+ add( this.children() );
+
+ return this.spawn( elements, { unique: true } ).filter( selector );
+ }
+});
+
+// aliases
+elesfn.ancestors = elesfn.parents;
+
+module.exports = elesfn;
+
+},{}],16:[function(_dereq_,module,exports){
+'use strict';
+
+var define = _dereq_('../define');
+var fn, elesfn;
+
+fn = elesfn = ({
+
+ data: define.data({
+ field: 'data',
+ bindingEvent: 'data',
+ allowBinding: true,
+ allowSetting: true,
+ settingEvent: 'data',
+ settingTriggersEvent: true,
+ triggerFnName: 'trigger',
+ allowGetting: true,
+ immutableKeys: {
+ 'id': true,
+ 'source': true,
+ 'target': true,
+ 'parent': true
+ },
+ updateStyle: true
+ }),
+
+ removeData: define.removeData({
+ field: 'data',
+ event: 'data',
+ triggerFnName: 'trigger',
+ triggerEvent: true,
+ immutableKeys: {
+ 'id': true,
+ 'source': true,
+ 'target': true,
+ 'parent': true
+ },
+ updateStyle: true
+ }),
+
+ scratch: define.data({
+ field: 'scratch',
+ bindingEvent: 'scratch',
+ allowBinding: true,
+ allowSetting: true,
+ settingEvent: 'scratch',
+ settingTriggersEvent: true,
+ triggerFnName: 'trigger',
+ allowGetting: true,
+ updateStyle: true
+ }),
+
+ removeScratch: define.removeData({
+ field: 'scratch',
+ event: 'scratch',
+ triggerFnName: 'trigger',
+ triggerEvent: true,
+ updateStyle: true
+ }),
+
+ rscratch: define.data({
+ field: 'rscratch',
+ allowBinding: false,
+ allowSetting: true,
+ settingTriggersEvent: false,
+ allowGetting: true
+ }),
+
+ removeRscratch: define.removeData({
+ field: 'rscratch',
+ triggerEvent: false
+ }),
+
+ id: function(){
+ var ele = this[0];
+
+ if( ele ){
+ return ele._private.data.id;
+ }
+ }
+
+});
+
+// aliases
+fn.attr = fn.data;
+fn.removeAttr = fn.removeData;
+
+module.exports = elesfn;
+
+},{"../define":41}],17:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+
+var elesfn = {};
+
+function defineDegreeFunction(callback){
+ return function( includeLoops ){
+ var self = this;
+
+ if( includeLoops === undefined ){
+ includeLoops = true;
+ }
+
+ if( self.length === 0 ){ return; }
+
+ if( self.isNode() && !self.removed() ){
+ var degree = 0;
+ var node = self[0];
+ var connectedEdges = node._private.edges;
+
+ for( var i = 0; i < connectedEdges.length; i++ ){
+ var edge = connectedEdges[i];
+
+ if( !includeLoops && edge.isLoop() ){
+ continue;
+ }
+
+ degree += callback( node, edge );
+ }
+
+ return degree;
+ } else {
+ return;
+ }
+ };
+}
+
+util.extend(elesfn, {
+ degree: defineDegreeFunction(function(node, edge){
+ if( edge.source().same( edge.target() ) ){
+ return 2;
+ } else {
+ return 1;
+ }
+ }),
+
+ indegree: defineDegreeFunction(function(node, edge){
+ if( edge.target().same(node) ){
+ return 1;
+ } else {
+ return 0;
+ }
+ }),
+
+ outdegree: defineDegreeFunction(function(node, edge){
+ if( edge.source().same(node) ){
+ return 1;
+ } else {
+ return 0;
+ }
+ })
+});
+
+function defineDegreeBoundsFunction(degreeFn, callback){
+ return function( includeLoops ){
+ var ret;
+ var nodes = this.nodes();
+
+ for( var i = 0; i < nodes.length; i++ ){
+ var ele = nodes[i];
+ var degree = ele[degreeFn]( includeLoops );
+ if( degree !== undefined && (ret === undefined || callback(degree, ret)) ){
+ ret = degree;
+ }
+ }
+
+ return ret;
+ };
+}
+
+util.extend(elesfn, {
+ minDegree: defineDegreeBoundsFunction('degree', function(degree, min){
+ return degree < min;
+ }),
+
+ maxDegree: defineDegreeBoundsFunction('degree', function(degree, max){
+ return degree > max;
+ }),
+
+ minIndegree: defineDegreeBoundsFunction('indegree', function(degree, min){
+ return degree < min;
+ }),
+
+ maxIndegree: defineDegreeBoundsFunction('indegree', function(degree, max){
+ return degree > max;
+ }),
+
+ minOutdegree: defineDegreeBoundsFunction('outdegree', function(degree, min){
+ return degree < min;
+ }),
+
+ maxOutdegree: defineDegreeBoundsFunction('outdegree', function(degree, max){
+ return degree > max;
+ })
+});
+
+util.extend(elesfn, {
+ totalDegree: function( includeLoops ){
+ var total = 0;
+ var nodes = this.nodes();
+
+ for( var i = 0; i < nodes.length; i++ ){
+ total += nodes[i].degree( includeLoops );
+ }
+
+ return total;
+ }
+});
+
+module.exports = elesfn;
+
+},{"../util":94}],18:[function(_dereq_,module,exports){
+'use strict';
+
+var define = _dereq_('../define');
+var is = _dereq_('../is');
+var util = _dereq_('../util');
+var fn, elesfn;
+
+fn = elesfn = ({
+
+ position: define.data({
+ field: 'position',
+ bindingEvent: 'position',
+ allowBinding: true,
+ allowSetting: true,
+ settingEvent: 'position',
+ settingTriggersEvent: true,
+ triggerFnName: 'rtrigger',
+ allowGetting: true,
+ validKeys: ['x', 'y'],
+ onSet: function( eles ){
+ var updatedEles = eles.updateCompoundBounds();
+ updatedEles.rtrigger('position');
+ },
+ canSet: function( ele ){
+ return !ele.locked() && !ele.isParent();
+ }
+ }),
+
+ // position but no notification to renderer
+ silentPosition: define.data({
+ field: 'position',
+ bindingEvent: 'position',
+ allowBinding: false,
+ allowSetting: true,
+ settingEvent: 'position',
+ settingTriggersEvent: false,
+ triggerFnName: 'trigger',
+ allowGetting: true,
+ validKeys: ['x', 'y'],
+ onSet: function( eles ){
+ eles.updateCompoundBounds();
+ },
+ canSet: function( ele ){
+ return !ele.locked() && !ele.isParent();
+ }
+ }),
+
+ positions: function( pos, silent ){
+ if( is.plainObject(pos) ){
+ this.position(pos);
+
+ } else if( is.fn(pos) ){
+ var fn = pos;
+
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+
+ var pos = fn.apply(ele, [i, ele]);
+
+ if( pos && !ele.locked() && !ele.isParent() ){
+ var elePos = ele._private.position;
+ elePos.x = pos.x;
+ elePos.y = pos.y;
+ }
+ }
+
+ var updatedEles = this.updateCompoundBounds();
+ var toTrigger = updatedEles.length > 0 ? this.add( updatedEles ) : this;
+
+ if( silent ){
+ toTrigger.trigger('position');
+ } else {
+ toTrigger.rtrigger('position');
+ }
+ }
+
+ return this; // chaining
+ },
+
+ silentPositions: function( pos ){
+ return this.positions( pos, true );
+ },
+
+ // get/set the rendered (i.e. on screen) positon of the element
+ renderedPosition: function( dim, val ){
+ var ele = this[0];
+ var cy = this.cy();
+ var zoom = cy.zoom();
+ var pan = cy.pan();
+ var rpos = is.plainObject( dim ) ? dim : undefined;
+ var setting = rpos !== undefined || ( val !== undefined && is.string(dim) );
+
+ if( ele && ele.isNode() ){ // must have an element and must be a node to return position
+ if( setting ){
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+
+ if( val !== undefined ){ // set one dimension
+ ele._private.position[dim] = ( val - pan[dim] )/zoom;
+ } else if( rpos !== undefined ){ // set whole position
+ ele._private.position = {
+ x: ( rpos.x - pan.x ) /zoom,
+ y: ( rpos.y - pan.y ) /zoom
+ };
+ }
+ }
+
+ this.rtrigger('position');
+ } else { // getting
+ var pos = ele._private.position;
+ rpos = {
+ x: pos.x * zoom + pan.x,
+ y: pos.y * zoom + pan.y
+ };
+
+ if( dim === undefined ){ // then return the whole rendered position
+ return rpos;
+ } else { // then return the specified dimension
+ return rpos[ dim ];
+ }
+ }
+ } else if( !setting ){
+ return undefined; // for empty collection case
+ }
+
+ return this; // chaining
+ },
+
+ // get/set the position relative to the parent
+ relativePosition: function( dim, val ){
+ var ele = this[0];
+ var cy = this.cy();
+ var ppos = is.plainObject( dim ) ? dim : undefined;
+ var setting = ppos !== undefined || ( val !== undefined && is.string(dim) );
+ var hasCompoundNodes = cy.hasCompoundNodes();
+
+ if( ele && ele.isNode() ){ // must have an element and must be a node to return position
+ if( setting ){
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+ var parent = hasCompoundNodes ? ele.parent() : null;
+ var hasParent = parent && parent.length > 0;
+ var relativeToParent = hasParent;
+
+ if( hasParent ){
+ parent = parent[0];
+ }
+
+ var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 };
+
+ if( val !== undefined ){ // set one dimension
+ ele._private.position[dim] = val + origin[dim];
+ } else if( ppos !== undefined ){ // set whole position
+ ele._private.position = {
+ x: ppos.x + origin.x,
+ y: ppos.y + origin.y,
+ };
+ }
+ }
+
+ this.rtrigger('position');
+
+ } else { // getting
+ var pos = ele._private.position;
+ var parent = hasCompoundNodes ? ele.parent() : null;
+ var hasParent = parent && parent.length > 0;
+ var relativeToParent = hasParent;
+
+ if( hasParent ){
+ parent = parent[0];
+ }
+
+ var origin = relativeToParent ? parent._private.position : { x: 0, y: 0 };
+
+ ppos = {
+ x: pos.x - origin.x,
+ y: pos.y - origin.y
+ };
+
+ if( dim === undefined ){ // then return the whole rendered position
+ return ppos;
+ } else { // then return the specified dimension
+ return ppos[ dim ];
+ }
+ }
+ } else if( !setting ){
+ return undefined; // for empty collection case
+ }
+
+ return this; // chaining
+ },
+
+ renderedBoundingBox: function( options ){
+ var bb = this.boundingBox( options );
+ var cy = this.cy();
+ var zoom = cy.zoom();
+ var pan = cy.pan();
+
+ var x1 = bb.x1 * zoom + pan.x;
+ var x2 = bb.x2 * zoom + pan.x;
+ var y1 = bb.y1 * zoom + pan.y;
+ var y2 = bb.y2 * zoom + pan.y;
+
+ return {
+ x1: x1,
+ x2: x2,
+ y1: y1,
+ y2: y2,
+ w: x2 - x1,
+ h: y2 - y1
+ };
+ },
+
+ updateCompoundBounds: function(){
+ var cy = this.cy();
+
+ if( !cy.styleEnabled() || !cy.hasCompoundNodes() ){ return cy.collection(); } // save cycles for non compound graphs or when style disabled
+
+ var updated = [];
+
+ function update( parent ){
+ var children = parent.children();
+ var style = parent._private.style;
+ var includeLabels = style['compound-sizing-wrt-labels'].value === 'include';
+ var bb = children.boundingBox({ includeLabels: includeLabels, includeEdges: true });
+ var padding = {
+ top: style['padding-top'].pfValue,
+ bottom: style['padding-bottom'].pfValue,
+ left: style['padding-left'].pfValue,
+ right: style['padding-right'].pfValue
+ };
+ var pos = parent._private.position;
+ var didUpdate = false;
+
+ if( style['width'].value === 'auto' ){
+ parent._private.autoWidth = bb.w;
+ pos.x = (bb.x1 + bb.x2 - padding.left + padding.right)/2;
+ didUpdate = true;
+ }
+
+ if( style['height'].value === 'auto' ){
+ parent._private.autoHeight = bb.h;
+ pos.y = (bb.y1 + bb.y2 - padding.top + padding.bottom)/2;
+ didUpdate = true;
+ }
+
+ if( didUpdate ){
+ updated.push( parent );
+ }
+ }
+
+ // go up, level by level
+ var eles = this.parent();
+ while( eles.nonempty() ){
+
+ // update each parent node in this level
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+
+ update( ele );
+ }
+
+ // next level
+ eles = eles.parent();
+ }
+
+ // return changed
+ return this.spawn( updated );
+ },
+
+ // get the bounding box of the elements (in raw model position)
+ boundingBox: function( options ){
+ var eles = this;
+ var cy = eles._private.cy;
+ var cy_p = cy._private;
+ var styleEnabled = cy_p.styleEnabled;
+
+ options = options || util.staticEmptyObject();
+
+ var includeNodes = options.includeNodes === undefined ? true : options.includeNodes;
+ var includeEdges = options.includeEdges === undefined ? true : options.includeEdges;
+ var includeLabels = options.includeLabels === undefined ? true : options.includeLabels;
+
+ // recalculate projections etc
+ if( styleEnabled ){
+ cy_p.renderer.recalculateRenderedStyle( this );
+ }
+
+ var x1 = Infinity;
+ var x2 = -Infinity;
+ var y1 = Infinity;
+ var y2 = -Infinity;
+
+ // find bounds of elements
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ var _p = ele._private;
+ var style = _p.style;
+ var display = styleEnabled ? _p.style['display'].value : 'element';
+ var isNode = _p.group === 'nodes';
+ var ex1, ex2, ey1, ey2, x, y;
+ var includedEle = false;
+
+ if( display === 'none' ){ continue; } // then ele doesn't take up space
+
+ if( isNode && includeNodes ){
+ includedEle = true;
+
+ var pos = _p.position;
+ x = pos.x;
+ y = pos.y;
+ var w = ele.outerWidth();
+ var halfW = w/2;
+ var h = ele.outerHeight();
+ var halfH = h/2;
+
+ // handle node dimensions
+ /////////////////////////
+
+ ex1 = x - halfW;
+ ex2 = x + halfW;
+ ey1 = y - halfH;
+ ey2 = y + halfH;
+
+ x1 = ex1 < x1 ? ex1 : x1;
+ x2 = ex2 > x2 ? ex2 : x2;
+ y1 = ey1 < y1 ? ey1 : y1;
+ y2 = ey2 > y2 ? ey2 : y2;
+
+ } else if( ele.isEdge() && includeEdges ){
+ includedEle = true;
+
+ var n1 = _p.source;
+ var n1_p = n1._private;
+ var n1pos = n1_p.position;
+
+ var n2 = _p.target;
+ var n2_p = n2._private;
+ var n2pos = n2_p.position;
+
+
+ // handle edge dimensions (rough box estimate)
+ //////////////////////////////////////////////
+
+ var rstyle = _p.rstyle || {};
+ var w = 0;
+ var wHalf = 0;
+
+ if( styleEnabled ){
+ w = style['width'].pfValue;
+ wHalf = w/2;
+ }
+
+ ex1 = n1pos.x;
+ ex2 = n2pos.x;
+ ey1 = n1pos.y;
+ ey2 = n2pos.y;
+
+ if( ex1 > ex2 ){
+ var temp = ex1;
+ ex1 = ex2;
+ ex2 = temp;
+ }
+
+ if( ey1 > ey2 ){
+ var temp = ey1;
+ ey1 = ey2;
+ ey2 = temp;
+ }
+
+ // take into account edge width
+ ex1 -= wHalf;
+ ex2 += wHalf;
+ ey1 -= wHalf;
+ ey2 += wHalf;
+
+ x1 = ex1 < x1 ? ex1 : x1;
+ x2 = ex2 > x2 ? ex2 : x2;
+ y1 = ey1 < y1 ? ey1 : y1;
+ y2 = ey2 > y2 ? ey2 : y2;
+
+ // handle points along edge (sanity check)
+ //////////////////////////////////////////
+
+ if( styleEnabled ){
+ var pts = rstyle.bezierPts || rstyle.linePts || [];
+
+ for( var j = 0; j < pts.length; j++ ){
+ var pt = pts[j];
+
+ ex1 = pt.x - wHalf;
+ ex2 = pt.x + wHalf;
+ ey1 = pt.y - wHalf;
+ ey2 = pt.y + wHalf;
+
+ x1 = ex1 < x1 ? ex1 : x1;
+ x2 = ex2 > x2 ? ex2 : x2;
+ y1 = ey1 < y1 ? ey1 : y1;
+ y2 = ey2 > y2 ? ey2 : y2;
+ }
+ }
+
+ // precise haystacks (sanity check)
+ ///////////////////////////////////
+
+ if( styleEnabled && style['curve-style'].strValue === 'haystack' ){
+ var hpts = rstyle.haystackPts;
+
+ ex1 = hpts[0].x;
+ ey1 = hpts[0].y;
+ ex2 = hpts[1].x;
+ ey2 = hpts[1].y;
+
+ if( ex1 > ex2 ){
+ var temp = ex1;
+ ex1 = ex2;
+ ex2 = temp;
+ }
+
+ if( ey1 > ey2 ){
+ var temp = ey1;
+ ey1 = ey2;
+ ey2 = temp;
+ }
+
+ x1 = ex1 < x1 ? ex1 : x1;
+ x2 = ex2 > x2 ? ex2 : x2;
+ y1 = ey1 < y1 ? ey1 : y1;
+ y2 = ey2 > y2 ? ey2 : y2;
+ }
+
+ } // edges
+
+
+ // handle label dimensions
+ //////////////////////////
+
+ if( styleEnabled ){
+
+ var _p = ele._private;
+ var style = _p.style;
+ var rstyle = _p.rstyle;
+ var label = style['label'].strValue;
+ var fontSize = style['font-size'];
+ var halign = style['text-halign'];
+ var valign = style['text-valign'];
+ var labelWidth = rstyle.labelWidth;
+ var labelHeight = rstyle.labelHeight;
+ var labelX = rstyle.labelX;
+ var labelY = rstyle.labelY;
+ var isEdge = ele.isEdge();
+ var autorotate = style['edge-text-rotation'].strValue === 'autorotate';
+
+ if( includeLabels && label && fontSize && labelHeight != null && labelWidth != null && labelX != null && labelY != null && halign && valign ){
+ var lh = labelHeight;
+ var lw = labelWidth;
+ var lx1, lx2, ly1, ly2;
+
+ if( isEdge ){
+ lx1 = labelX - lw/2;
+ lx2 = labelX + lw/2;
+ ly1 = labelY - lh/2;
+ ly2 = labelY + lh/2;
+
+ if( autorotate ){
+ var theta = _p.rscratch.labelAngle;
+ var cos = Math.cos( theta );
+ var sin = Math.sin( theta );
+
+ var rotate = function( x, y ){
+ x = x - labelX;
+ y = y - labelY;
+
+ return {
+ x: x*cos - y*sin + labelX,
+ y: x*sin + y*cos + labelY
+ };
+ };
+
+ var px1y1 = rotate( lx1, ly1 );
+ var px1y2 = rotate( lx1, ly2 );
+ var px2y1 = rotate( lx2, ly1 );
+ var px2y2 = rotate( lx2, ly2 );
+
+ lx1 = Math.min( px1y1.x, px1y2.x, px2y1.x, px2y2.x );
+ lx2 = Math.max( px1y1.x, px1y2.x, px2y1.x, px2y2.x );
+ ly1 = Math.min( px1y1.y, px1y2.y, px2y1.y, px2y2.y );
+ ly2 = Math.max( px1y1.y, px1y2.y, px2y1.y, px2y2.y );
+ }
+ } else {
+ switch( halign.value ){
+ case 'left':
+ lx1 = labelX - lw;
+ lx2 = labelX;
+ break;
+
+ case 'center':
+ lx1 = labelX - lw/2;
+ lx2 = labelX + lw/2;
+ break;
+
+ case 'right':
+ lx1 = labelX;
+ lx2 = labelX + lw;
+ break;
+ }
+
+ switch( valign.value ){
+ case 'top':
+ ly1 = labelY - lh;
+ ly2 = labelY;
+ break;
+
+ case 'center':
+ ly1 = labelY - lh/2;
+ ly2 = labelY + lh/2;
+ break;
+
+ case 'bottom':
+ ly1 = labelY;
+ ly2 = labelY + lh;
+ break;
+ }
+ }
+
+ x1 = lx1 < x1 ? lx1 : x1;
+ x2 = lx2 > x2 ? lx2 : x2;
+ y1 = ly1 < y1 ? ly1 : y1;
+ y2 = ly2 > y2 ? ly2 : y2;
+ }
+ } // style enabled for labels
+ } // for
+
+ var noninf = function(x){
+ if( x === Infinity || x === -Infinity ){
+ return 0;
+ }
+
+ return x;
+ };
+
+ x1 = noninf(x1);
+ x2 = noninf(x2);
+ y1 = noninf(y1);
+ y2 = noninf(y2);
+
+ return {
+ x1: x1,
+ x2: x2,
+ y1: y1,
+ y2: y2,
+ w: x2 - x1,
+ h: y2 - y1
+ };
+ }
+});
+
+var defineDimFns = function( opts ){
+ opts.uppercaseName = util.capitalize( opts.name );
+ opts.autoName = 'auto' + opts.uppercaseName;
+ opts.labelName = 'label' + opts.uppercaseName;
+ opts.outerName = 'outer' + opts.uppercaseName;
+ opts.uppercaseOuterName = util.capitalize( opts.outerName );
+
+ fn[ opts.name ] = function dimImpl(){
+ var ele = this[0];
+ var _p = ele._private;
+ var cy = _p.cy;
+ var styleEnabled = cy._private.styleEnabled;
+
+ if( ele ){
+ if( styleEnabled ){
+ var d = _p.style[ opts.name ];
+
+ switch( d.strValue ){
+ case 'auto':
+ return _p[ opts.autoName ] || 0;
+ case 'label':
+ return _p.rstyle[ opts.labelName ] || 0;
+ default:
+ return d.pfValue;
+ }
+ } else {
+ return 1;
+ }
+ }
+ };
+
+ fn[ 'outer' + opts.uppercaseName ] = function outerDimImpl(){
+ var ele = this[0];
+ var _p = ele._private;
+ var cy = _p.cy;
+ var styleEnabled = cy._private.styleEnabled;
+
+ if( ele ){
+ if( styleEnabled ){
+ var style = _p.style;
+ var dim = ele[ opts.name ]();
+ var border = style['border-width'].pfValue;
+ var padding = style[ opts.paddings[0] ].pfValue + style[ opts.paddings[1] ].pfValue;
+
+ return dim + border + padding;
+ } else {
+ return 1;
+ }
+ }
+ };
+
+ fn[ 'rendered' + opts.uppercaseName ] = function renderedDimImpl(){
+ var ele = this[0];
+
+ if( ele ){
+ var d = ele[ opts.name ]();
+ return d * this.cy().zoom();
+ }
+ };
+
+ fn[ 'rendered' + opts.uppercaseOuterName ] = function renderedOuterDimImpl(){
+ var ele = this[0];
+
+ if( ele ){
+ var od = ele[ opts.outerName ]();
+ return od * this.cy().zoom();
+ }
+ };
+};
+
+defineDimFns({
+ name: 'width',
+ paddings: ['padding-left', 'padding-right']
+});
+
+defineDimFns({
+ name: 'height',
+ paddings: ['padding-top', 'padding-bottom']
+});
+
+// aliases
+fn.modelPosition = fn.point = fn.position;
+fn.modelPositions = fn.points = fn.positions;
+fn.renderedPoint = fn.renderedPosition;
+fn.relativePoint = fn.relativePosition;
+fn.boundingbox = fn.boundingBox;
+fn.renderedBoundingbox = fn.renderedBoundingBox;
+
+module.exports = elesfn;
+
+},{"../define":41,"../is":77,"../util":94}],19:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+var is = _dereq_('../is');
+
+// represents a node or an edge
+var Element = function(cy, params, restore){
+ if( !(this instanceof Element) ){
+ return new Element(cy, params, restore);
+ }
+
+ var self = this;
+ restore = (restore === undefined || restore ? true : false);
+
+ if( cy === undefined || params === undefined || !is.core(cy) ){
+ util.error('An element must have a core reference and parameters set');
+ return;
+ }
+
+ var group = params.group;
+
+ // try to automatically infer the group if unspecified
+ if( group == null ){
+ if( params.data.source != null && params.data.target != null ){
+ group = 'edges';
+ } else {
+ group = 'nodes';
+ }
+ }
+
+ // validate group
+ if( group !== 'nodes' && group !== 'edges' ){
+ util.error('An element must be of type `nodes` or `edges`; you specified `' + group + '`');
+ return;
+ }
+
+ // make the element array-like, just like a collection
+ this.length = 1;
+ this[0] = this;
+
+ // NOTE: when something is added here, add also to ele.json()
+ this._private = {
+ cy: cy,
+ single: true, // indicates this is an element
+ data: params.data || {}, // data object
+ position: params.position || {}, // (x, y) position pair
+ autoWidth: undefined, // width and height of nodes calculated by the renderer when set to special 'auto' value
+ autoHeight: undefined,
+ listeners: [], // array of bound listeners
+ group: group, // string; 'nodes' or 'edges'
+ style: {}, // properties as set by the style
+ rstyle: {}, // properties for style sent from the renderer to the core
+ styleCxts: [], // applied style contexts from the styler
+ removed: true, // whether it's inside the vis; true if removed (set true here since we call restore)
+ selected: params.selected ? true : false, // whether it's selected
+ selectable: params.selectable === undefined ? true : ( params.selectable ? true : false ), // whether it's selectable
+ locked: params.locked ? true : false, // whether the element is locked (cannot be moved)
+ grabbed: false, // whether the element is grabbed by the mouse; renderer sets this privately
+ grabbable: params.grabbable === undefined ? true : ( params.grabbable ? true : false ), // whether the element can be grabbed
+ active: false, // whether the element is active from user interaction
+ classes: {}, // map ( className => true )
+ animation: { // object for currently-running animations
+ current: [],
+ queue: []
+ },
+ rscratch: {}, // object in which the renderer can store information
+ scratch: params.scratch || {}, // scratch objects
+ edges: [], // array of connected edges
+ children: [] // array of children
+ };
+
+ // renderedPosition overrides if specified
+ if( params.renderedPosition ){
+ var rpos = params.renderedPosition;
+ var pan = cy.pan();
+ var zoom = cy.zoom();
+
+ this._private.position = {
+ x: (rpos.x - pan.x)/zoom,
+ y: (rpos.y - pan.y)/zoom
+ };
+ }
+
+ if( is.string(params.classes) ){
+ var classes = params.classes.split(/\s+/);
+ for( var i = 0, l = classes.length; i < l; i++ ){
+ var cls = classes[i];
+ if( !cls || cls === '' ){ continue; }
+
+ self._private.classes[cls] = true;
+ }
+ }
+
+ if( params.style || params.css ){
+ cy.style().applyBypass( this, params.style || params.css );
+ }
+
+ if( restore === undefined || restore ){
+ this.restore();
+ }
+
+};
+
+module.exports = Element;
+
+},{"../is":77,"../util":94}],20:[function(_dereq_,module,exports){
+'use strict';
+
+var define = _dereq_('../define');
+
+var elesfn = ({
+ on: define.on(), // .on( events [, selector] [, data], handler)
+ one: define.on({ unbindSelfOnTrigger: true }),
+ once: define.on({ unbindAllBindersOnTrigger: true }),
+ off: define.off(), // .off( events [, selector] [, handler] )
+ trigger: define.trigger(), // .trigger( events [, extraParams] )
+
+ rtrigger: function(event, extraParams){ // for internal use only
+ if( this.length === 0 ){ return; } // empty collections don't need to notify anything
+
+ // notify renderer
+ this.cy().notify({
+ type: event,
+ collection: this
+ });
+
+ this.trigger(event, extraParams);
+ return this;
+ }
+});
+
+// aliases:
+define.eventAliasesOn( elesfn );
+
+module.exports = elesfn;
+
+},{"../define":41}],21:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+var Selector = _dereq_('../selector');
+
+var elesfn = ({
+ nodes: function( selector ){
+ return this.filter(function(i, element){
+ return element.isNode();
+ }).filter(selector);
+ },
+
+ edges: function( selector ){
+ return this.filter(function(i, element){
+ return element.isEdge();
+ }).filter(selector);
+ },
+
+ filter: function( filter ){
+ if( is.fn(filter) ){
+ var elements = [];
+
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+
+ if( filter.apply(ele, [i, ele]) ){
+ elements.push(ele);
+ }
+ }
+
+ return this.spawn(elements);
+
+ } else if( is.string(filter) || is.elementOrCollection(filter) ){
+ return Selector(filter).filter(this);
+
+ } else if( filter === undefined ){
+ return this;
+ }
+
+ return this.spawn(); // if not handled by above, give 'em an empty collection
+ },
+
+ not: function( toRemove ){
+ if( !toRemove ){
+ return this;
+ } else {
+
+ if( is.string( toRemove ) ){
+ toRemove = this.filter( toRemove );
+ }
+
+ var elements = [];
+
+ for( var i = 0; i < this.length; i++ ){
+ var element = this[i];
+
+ var remove = toRemove._private.ids[ element.id() ];
+ if( !remove ){
+ elements.push( element );
+ }
+ }
+
+ return this.spawn( elements );
+ }
+
+ },
+
+ absoluteComplement: function(){
+ var cy = this._private.cy;
+
+ return cy.elements().not( this );
+ },
+
+ intersect: function( other ){
+ // if a selector is specified, then filter by it instead
+ if( is.string(other) ){
+ var selector = other;
+ return this.filter( selector );
+ }
+
+ var elements = [];
+ var col1 = this;
+ var col2 = other;
+ var col1Smaller = this.length < other.length;
+ // var ids1 = col1Smaller ? col1._private.ids : col2._private.ids;
+ var ids2 = col1Smaller ? col2._private.ids : col1._private.ids;
+ var col = col1Smaller ? col1 : col2;
+
+ for( var i = 0; i < col.length; i++ ){
+ var id = col[i]._private.data.id;
+ var ele = ids2[ id ];
+
+ if( ele ){
+ elements.push( ele );
+ }
+ }
+
+ return this.spawn( elements );
+ },
+
+ xor: function( other ){
+ var cy = this._private.cy;
+
+ if( is.string(other) ){
+ other = cy.$( other );
+ }
+
+ var elements = [];
+ var col1 = this;
+ var col2 = other;
+
+ var add = function( col, other ){
+
+ for( var i = 0; i < col.length; i++ ){
+ var ele = col[i];
+ var id = ele._private.data.id;
+ var inOther = other._private.ids[ id ];
+
+ if( !inOther ){
+ elements.push( ele );
+ }
+ }
+
+ };
+
+ add( col1, col2 );
+ add( col2, col1 );
+
+ return this.spawn( elements );
+ },
+
+ diff: function( other ){
+ var cy = this._private.cy;
+
+ if( is.string(other) ){
+ other = cy.$( other );
+ }
+
+ var left = [];
+ var right = [];
+ var both = [];
+ var col1 = this;
+ var col2 = other;
+
+ var add = function( col, other, retEles ){
+
+ for( var i = 0; i < col.length; i++ ){
+ var ele = col[i];
+ var id = ele._private.data.id;
+ var inOther = other._private.ids[ id ];
+
+ if( inOther ){
+ both.push( ele );
+ } else {
+ retEles.push( ele );
+ }
+ }
+
+ };
+
+ add( col1, col2, left );
+ add( col2, col1, right );
+
+ return {
+ left: this.spawn( left, { unique: true } ),
+ right: this.spawn( right, { unique: true } ),
+ both: this.spawn( both, { unique: true } )
+ };
+ },
+
+ add: function( toAdd ){
+ var cy = this._private.cy;
+
+ if( !toAdd ){
+ return this;
+ }
+
+ if( is.string(toAdd) ){
+ var selector = toAdd;
+ toAdd = cy.elements(selector);
+ }
+
+ var elements = [];
+
+ for( var i = 0; i < this.length; i++ ){
+ elements.push( this[i] );
+ }
+
+ for( var i = 0; i < toAdd.length; i++ ){
+
+ var add = !this._private.ids[ toAdd[i].id() ];
+ if( add ){
+ elements.push( toAdd[i] );
+ }
+ }
+
+ return this.spawn(elements);
+ },
+
+ // in place merge on calling collection
+ merge: function( toAdd ){
+ var _p = this._private;
+ var cy = _p.cy;
+
+ if( !toAdd ){
+ return this;
+ }
+
+ if( is.string(toAdd) ){
+ var selector = toAdd;
+ toAdd = cy.elements(selector);
+ }
+
+ for( var i = 0; i < toAdd.length; i++ ){
+ var toAddEle = toAdd[i];
+ var id = toAddEle.id();
+ var add = !_p.ids[ id ];
+
+ if( add ){
+ var index = this.length++;
+
+ this[ index ] = toAddEle;
+ _p.ids[ id ] = toAddEle;
+ _p.indexes[ id ] = index;
+ }
+ }
+
+ return this; // chaining
+ },
+
+ // remove single ele in place in calling collection
+ unmergeOne: function( ele ){
+ ele = ele[0];
+
+ var _p = this._private;
+ var id = ele.id();
+ var i = _p.indexes[ id ];
+
+ if( i == null ){
+ return this; // no need to remove
+ }
+
+ // remove ele
+ this[i] = undefined;
+ _p.ids[ id ] = undefined;
+ _p.indexes[ id ] = undefined;
+
+ var unmergedLastEle = i === this.length - 1;
+
+ // replace empty spot with last ele in collection
+ if( this.length > 1 && !unmergedLastEle ){
+ var lastEleI = this.length - 1;
+ var lastEle = this[ lastEleI ];
+
+ this[ lastEleI ] = undefined;
+ this[i] = lastEle;
+ _p.indexes[ lastEle.id() ] = i;
+ }
+
+ // the collection is now 1 ele smaller
+ this.length--;
+
+ return this;
+ },
+
+ // remove eles in place on calling collection
+ unmerge: function( toRemove ){
+ var cy = this._private.cy;
+
+ if( !toRemove ){
+ return this;
+ }
+
+ if( is.string(toRemove) ){
+ var selector = toRemove;
+ toRemove = cy.elements(selector);
+ }
+
+ for( var i = 0; i < toRemove.length; i++ ){
+ this.unmergeOne( toRemove[i] );
+ }
+
+ return this; // chaining
+ },
+
+ map: function( mapFn, thisArg ){
+ var arr = [];
+ var eles = this;
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ var ret = thisArg ? mapFn.apply( thisArg, [ele, i, eles] ) : mapFn( ele, i, eles );
+
+ arr.push( ret );
+ }
+
+ return arr;
+ },
+
+ stdFilter: function( fn, thisArg ){
+ var filterEles = [];
+ var eles = this;
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ var include = thisArg ? fn.apply( thisArg, [ele, i, eles] ) : fn( ele, i, eles );
+
+ if( include ){
+ filterEles.push( ele );
+ }
+ }
+
+ return this.spawn( filterEles );
+ },
+
+ max: function( valFn, thisArg ){
+ var max = -Infinity;
+ var maxEle;
+ var eles = this;
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles );
+
+ if( val > max ){
+ max = val;
+ maxEle = ele;
+ }
+ }
+
+ return {
+ value: max,
+ ele: maxEle
+ };
+ },
+
+ min: function( valFn, thisArg ){
+ var min = Infinity;
+ var minEle;
+ var eles = this;
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ var val = thisArg ? valFn.apply( thisArg, [ ele, i, eles ] ) : valFn( ele, i, eles );
+
+ if( val < min ){
+ min = val;
+ minEle = ele;
+ }
+ }
+
+ return {
+ value: min,
+ ele: minEle
+ };
+ }
+});
+
+// aliases
+var fn = elesfn;
+fn['u'] = fn['|'] = fn['+'] = fn.union = fn.or = fn.add;
+fn['\\'] = fn['!'] = fn['-'] = fn.difference = fn.relativeComplement = fn.subtract = fn.not;
+fn['n'] = fn['&'] = fn['.'] = fn.and = fn.intersection = fn.intersect;
+fn['^'] = fn['(+)'] = fn['(-)'] = fn.symmetricDifference = fn.symdiff = fn.xor;
+fn.fnFilter = fn.filterFn = fn.stdFilter;
+fn.complement = fn.abscomp = fn.absoluteComplement;
+
+module.exports = elesfn;
+
+},{"../is":77,"../selector":81}],22:[function(_dereq_,module,exports){
+'use strict';
+
+var elesfn = ({
+ isNode: function(){
+ return this.group() === 'nodes';
+ },
+
+ isEdge: function(){
+ return this.group() === 'edges';
+ },
+
+ isLoop: function(){
+ return this.isEdge() && this.source().id() === this.target().id();
+ },
+
+ isSimple: function(){
+ return this.isEdge() && this.source().id() !== this.target().id();
+ },
+
+ group: function(){
+ var ele = this[0];
+
+ if( ele ){
+ return ele._private.group;
+ }
+ }
+});
+
+
+module.exports = elesfn;
+
+},{}],23:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+var is = _dereq_('../is');
+
+var Element = _dereq_('./element');
+
+// factory for generating edge ids when no id is specified for a new element
+var idFactory = {
+ prefix: 'ele',
+ id: 0,
+ generate: function(cy, element, tryThisId){
+ var json = is.element( element ) ? element._private : element;
+ var id = tryThisId != null ? tryThisId : this.prefix + this.id;
+
+ if( cy.getElementById(id).empty() ){
+ this.id++; // we've used the current id, so move it up
+ } else { // otherwise keep trying successive unused ids
+ while( !cy.getElementById(id).empty() ){
+ id = this.prefix + ( ++this.id );
+ }
+ }
+
+ return id;
+ }
+};
+
+// represents a set of nodes, edges, or both together
+var Collection = function(cy, elements, options){
+ if( !(this instanceof Collection) ){
+ return new Collection(cy, elements, options);
+ }
+
+ if( cy === undefined || !is.core(cy) ){
+ util.error('A collection must have a reference to the core');
+ return;
+ }
+
+ var ids = {};
+ var indexes = {};
+ var createdElements = false;
+
+ if( !elements ){
+ elements = [];
+ } else if( elements.length > 0 && is.plainObject( elements[0] ) && !is.element( elements[0] ) ){
+ createdElements = true;
+
+ // make elements from json and restore all at once later
+ var eles = [];
+ var elesIds = {};
+
+ for( var i = 0, l = elements.length; i < l; i++ ){
+ var json = elements[i];
+
+ if( json.data == null ){
+ json.data = {};
+ }
+
+ var data = json.data;
+
+ // make sure newly created elements have valid ids
+ if( data.id == null ){
+ data.id = idFactory.generate( cy, json );
+ } else if( cy.getElementById( data.id ).length !== 0 || elesIds[ data.id ] ){
+ continue; // can't create element if prior id already exists
+ }
+
+ var ele = new Element( cy, json, false );
+ eles.push( ele );
+ elesIds[ data.id ] = true;
+ }
+
+ elements = eles;
+ }
+
+ this.length = 0;
+
+ for( var i = 0, l = elements.length; i < l; i++ ){
+ var element = elements[i];
+ if( !element ){ continue; }
+
+ var id = element._private.data.id;
+
+ if( !options || (options.unique && !ids[ id ] ) ){
+ ids[ id ] = element;
+ indexes[ id ] = this.length;
+
+ this[ this.length ] = element;
+ this.length++;
+ }
+ }
+
+ this._private = {
+ cy: cy,
+ ids: ids,
+ indexes: indexes
+ };
+
+ // restore the elements if we created them from json
+ if( createdElements ){
+ this.restore();
+ }
+};
+
+// Functions
+////////////////////////////////////////////////////////////////////////////////////////////////////
+
+// keep the prototypes in sync (an element has the same functions as a collection)
+// and use elefn and elesfn as shorthands to the prototypes
+var elesfn = Element.prototype = Collection.prototype;
+
+elesfn.instanceString = function(){
+ return 'collection';
+};
+
+elesfn.spawn = function( cy, eles, opts ){
+ if( !is.core(cy) ){ // cy is optional
+ opts = eles;
+ eles = cy;
+ cy = this.cy();
+ }
+
+ return new Collection( cy, eles, opts );
+};
+
+elesfn.cy = function(){
+ return this._private.cy;
+};
+
+elesfn.element = function(){
+ return this[0];
+};
+
+elesfn.collection = function(){
+ if( is.collection(this) ){
+ return this;
+ } else { // an element
+ return new Collection( this._private.cy, [this] );
+ }
+};
+
+elesfn.unique = function(){
+ return new Collection( this._private.cy, this, { unique: true } );
+};
+
+elesfn.getElementById = function( id ){
+ var cy = this._private.cy;
+ var ele = this._private.ids[ id ];
+
+ return ele ? ele : new Collection(cy); // get ele or empty collection
+};
+
+elesfn.json = function( obj ){
+ var ele = this.element();
+ var cy = this.cy();
+
+ if( ele == null && obj ){ return this; } // can't set to no eles
+
+ if( ele == null ){ return undefined; } // can't get from no eles
+
+ var p = ele._private;
+
+ if( is.plainObject(obj) ){ // set
+
+ cy.startBatch();
+
+ if( obj.data ){
+ ele.data( obj.data );
+ }
+
+ if( obj.position ){
+ ele.position( obj.position );
+ }
+
+ // ignore group -- immutable
+
+ var checkSwitch = function( k, trueFnName, falseFnName ){
+ var obj_k = obj[k];
+
+ if( obj_k != null && obj_k !== p[k] ){
+ if( obj_k ){
+ ele[ trueFnName ]();
+ } else {
+ ele[ falseFnName ]();
+ }
+ }
+ };
+
+ checkSwitch( 'removed', 'remove', 'restore' );
+
+ checkSwitch( 'selected', 'select', 'unselect' );
+
+ checkSwitch( 'selectable', 'selectify', 'unselectify' );
+
+ checkSwitch( 'locked', 'lock', 'unlock' );
+
+ checkSwitch( 'grabbable', 'grabify', 'ungrabify' );
+
+ if( obj.classes != null ){
+ ele.classes( obj.classes );
+ }
+
+ cy.endBatch();
+
+ return this;
+
+ } else if( obj === undefined ){ // get
+
+ var json = {
+ data: util.copy( p.data ),
+ position: util.copy( p.position ),
+ group: p.group,
+ removed: p.removed,
+ selected: p.selected,
+ selectable: p.selectable,
+ locked: p.locked,
+ grabbable: p.grabbable,
+ classes: null
+ };
+
+ var classes = [];
+ for( var cls in p.classes ){
+ if( p.classes[cls] ){
+ classes.push(cls);
+ }
+ }
+ json.classes = classes.join(' ');
+
+ return json;
+ }
+};
+
+elesfn.jsons = function(){
+ var jsons = [];
+
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+ var json = ele.json();
+
+ jsons.push( json );
+ }
+
+ return jsons;
+};
+
+elesfn.clone = function(){
+ var cy = this.cy();
+ var elesArr = [];
+
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+ var json = ele.json();
+ var clone = new Element(cy, json, false); // NB no restore
+
+ elesArr.push( clone );
+ }
+
+ return new Collection( cy, elesArr );
+};
+elesfn.copy = elesfn.clone;
+
+elesfn.restore = function( notifyRenderer ){
+ var self = this;
+ var restored = [];
+ var cy = self.cy();
+
+ if( notifyRenderer === undefined ){
+ notifyRenderer = true;
+ }
+
+ // create arrays of nodes and edges, since we need to
+ // restore the nodes first
+ var elements = [];
+ var nodes = [], edges = [];
+ var numNodes = 0;
+ var numEdges = 0;
+ for( var i = 0, l = self.length; i < l; i++ ){
+ var ele = self[i];
+
+ // keep nodes first in the array and edges after
+ if( ele.isNode() ){ // put to front of array if node
+ nodes.push( ele );
+ numNodes++;
+ } else { // put to end of array if edge
+ edges.push( ele );
+ numEdges++;
+ }
+ }
+
+ elements = nodes.concat( edges );
+
+ // now, restore each element
+ for( var i = 0, l = elements.length; i < l; i++ ){
+ var ele = elements[i];
+
+ if( !ele.removed() ){
+ // don't need to do anything
+ continue;
+ }
+
+ var _private = ele._private;
+ var data = _private.data;
+
+ // set id and validate
+ if( data.id === undefined ){
+ data.id = idFactory.generate( cy, ele );
+
+ } else if( is.number(data.id) ){
+ data.id = '' + data.id; // now it's a string
+
+ } else if( is.emptyString(data.id) || !is.string(data.id) ){
+ util.error('Can not create element with invalid string ID `' + data.id + '`');
+
+ // can't create element if it has empty string as id or non-string id
+ continue;
+ } else if( cy.getElementById( data.id ).length !== 0 ){
+ util.error('Can not create second element with ID `' + data.id + '`');
+
+ // can't create element if one already has that id
+ continue;
+ }
+
+ var id = data.id; // id is finalised, now let's keep a ref
+
+ if( ele.isNode() ){ // extra checks for nodes
+ var node = ele;
+ var pos = _private.position;
+
+ // make sure the nodes have a defined position
+
+ if( pos.x == null ){
+ pos.x = 0;
+ }
+
+ if( pos.y == null ){
+ pos.y = 0;
+ }
+ }
+
+ if( ele.isEdge() ){ // extra checks for edges
+
+ var edge = ele;
+ var fields = ['source', 'target'];
+ var fieldsLength = fields.length;
+ var badSourceOrTarget = false;
+ for(var j = 0; j < fieldsLength; j++){
+
+ var field = fields[j];
+ var val = data[field];
+
+ if( is.number(val) ){
+ val = data[field] = '' + data[field]; // now string
+ }
+
+ if( val == null || val === '' ){
+ // can't create if source or target is not defined properly
+ util.error('Can not create edge `' + id + '` with unspecified ' + field);
+ badSourceOrTarget = true;
+ } else if( cy.getElementById(val).empty() ){
+ // can't create edge if one of its nodes doesn't exist
+ util.error('Can not create edge `' + id + '` with nonexistant ' + field + ' `' + val + '`');
+ badSourceOrTarget = true;
+ }
+ }
+
+ if( badSourceOrTarget ){ continue; } // can't create this
+
+ var src = cy.getElementById( data.source );
+ var tgt = cy.getElementById( data.target );
+
+ src._private.edges.push( edge );
+ tgt._private.edges.push( edge );
+
+ edge._private.source = src;
+ edge._private.target = tgt;
+
+ } // if is edge
+
+ // create mock ids map for element so it can be used like collections
+ _private.ids = {};
+ _private.ids[ id ] = ele;
+
+ _private.removed = false;
+ cy.addToPool( ele );
+
+ restored.push( ele );
+ } // for each element
+
+ // do compound node sanity checks
+ for( var i = 0; i < numNodes; i++ ){ // each node
+ var node = elements[i];
+ var data = node._private.data;
+
+ if( is.number(data.parent) ){ // then automake string
+ data.parent = '' + data.parent;
+ }
+
+ var parentId = data.parent;
+
+ var specifiedParent = parentId != null;
+
+ if( specifiedParent ){
+ var parent = cy.getElementById( parentId );
+
+ if( parent.empty() ){
+ // non-existant parent; just remove it
+ data.parent = undefined;
+ } else {
+ var selfAsParent = false;
+ var ancestor = parent;
+ while( !ancestor.empty() ){
+ if( node.same(ancestor) ){
+ // mark self as parent and remove from data
+ selfAsParent = true;
+ data.parent = undefined; // remove parent reference
+
+ // exit or we loop forever
+ break;
+ }
+
+ ancestor = ancestor.parent();
+ }
+
+ if( !selfAsParent ){
+ // connect with children
+ parent[0]._private.children.push( node );
+ node._private.parent = parent[0];
+
+ // let the core know we have a compound graph
+ cy._private.hasCompoundNodes = true;
+ }
+ } // else
+ } // if specified parent
+ } // for each node
+
+ restored = new Collection( cy, restored );
+ if( restored.length > 0 ){
+
+ var toUpdateStyle = restored.add( restored.connectedNodes() ).add( restored.parent() );
+ toUpdateStyle.updateStyle( notifyRenderer );
+
+ if( notifyRenderer ){
+ restored.rtrigger('add');
+ } else {
+ restored.trigger('add');
+ }
+ }
+
+ return self; // chainability
+};
+
+elesfn.removed = function(){
+ var ele = this[0];
+ return ele && ele._private.removed;
+};
+
+elesfn.inside = function(){
+ var ele = this[0];
+ return ele && !ele._private.removed;
+};
+
+elesfn.remove = function( notifyRenderer ){
+ var self = this;
+ var removed = [];
+ var elesToRemove = [];
+ var elesToRemoveIds = {};
+ var cy = self._private.cy;
+
+ if( notifyRenderer === undefined ){
+ notifyRenderer = true;
+ }
+
+ // add connected edges
+ function addConnectedEdges(node){
+ var edges = node._private.edges;
+ for( var i = 0; i < edges.length; i++ ){
+ add( edges[i] );
+ }
+ }
+
+
+ // add descendant nodes
+ function addChildren(node){
+ var children = node._private.children;
+
+ for( var i = 0; i < children.length; i++ ){
+ add( children[i] );
+ }
+ }
+
+ function add( ele ){
+ var alreadyAdded = elesToRemoveIds[ ele.id() ];
+ if( alreadyAdded ){
+ return;
+ } else {
+ elesToRemoveIds[ ele.id() ] = true;
+ }
+
+ if( ele.isNode() ){
+ elesToRemove.push( ele ); // nodes are removed last
+
+ addConnectedEdges( ele );
+ addChildren( ele );
+ } else {
+ elesToRemove.unshift( ele ); // edges are removed first
+ }
+ }
+
+ // make the list of elements to remove
+ // (may be removing more than specified due to connected edges etc)
+
+ for( var i = 0, l = self.length; i < l; i++ ){
+ var ele = self[i];
+
+ add( ele );
+ }
+
+ function removeEdgeRef(node, edge){
+ var connectedEdges = node._private.edges;
+ for( var j = 0; j < connectedEdges.length; j++ ){
+ var connectedEdge = connectedEdges[j];
+
+ if( edge === connectedEdge ){
+ connectedEdges.splice( j, 1 );
+ break;
+ }
+ }
+ }
+
+ function removeChildRef(parent, ele){
+ ele = ele[0];
+ parent = parent[0];
+ var children = parent._private.children;
+
+ for( var j = 0; j < children.length; j++ ){
+ if( children[j][0] === ele[0] ){
+ children.splice(j, 1);
+ break;
+ }
+ }
+ }
+
+ for( var i = 0; i < elesToRemove.length; i++ ){
+ var ele = elesToRemove[i];
+
+ // mark as removed
+ ele._private.removed = true;
+
+ // remove from core pool
+ cy.removeFromPool( ele );
+
+ // add to list of removed elements
+ removed.push( ele );
+
+ if( ele.isEdge() ){ // remove references to this edge in its connected nodes
+ var src = ele.source()[0];
+ var tgt = ele.target()[0];
+
+ removeEdgeRef( src, ele );
+ removeEdgeRef( tgt, ele );
+
+ } else { // remove reference to parent
+ var parent = ele.parent();
+
+ if( parent.length !== 0 ){
+ removeChildRef(parent, ele);
+ }
+ }
+ }
+
+ // check to see if we have a compound graph or not
+ var elesStillInside = cy._private.elements;
+ cy._private.hasCompoundNodes = false;
+ for( var i = 0; i < elesStillInside.length; i++ ){
+ var ele = elesStillInside[i];
+
+ if( ele.isParent() ){
+ cy._private.hasCompoundNodes = true;
+ break;
+ }
+ }
+
+ var removedElements = new Collection( this.cy(), removed );
+ if( removedElements.size() > 0 ){
+ // must manually notify since trigger won't do this automatically once removed
+
+ if( notifyRenderer ){
+ this.cy().notify({
+ type: 'remove',
+ collection: removedElements
+ });
+ }
+
+ removedElements.trigger('remove');
+ }
+
+ // check for empty remaining parent nodes
+ var checkedParentId = {};
+ for( var i = 0; i < elesToRemove.length; i++ ){
+ var ele = elesToRemove[i];
+ var isNode = ele._private.group === 'nodes';
+ var parentId = ele._private.data.parent;
+
+ if( isNode && parentId !== undefined && !checkedParentId[ parentId ] ){
+ checkedParentId[ parentId ] = true;
+ var parent = cy.getElementById( parentId );
+
+ if( parent && parent.length !== 0 && !parent._private.removed && parent.children().length === 0 ){
+ parent.updateStyle();
+ }
+ }
+ }
+
+ return new Collection( cy, removed );
+};
+
+elesfn.move = function( struct ){
+ var cy = this._private.cy;
+
+ if( struct.source !== undefined || struct.target !== undefined ){
+ var srcId = struct.source;
+ var tgtId = struct.target;
+ var srcExists = cy.getElementById( srcId ).length > 0;
+ var tgtExists = cy.getElementById( tgtId ).length > 0;
+
+ if( srcExists || tgtExists ){
+ var jsons = this.jsons();
+
+ this.remove();
+
+ for( var i = 0; i < jsons.length; i++ ){
+ var json = jsons[i];
+
+ if( json.group === 'edges' ){
+ if( srcExists ){ json.data.source = srcId; }
+ if( tgtExists ){ json.data.target = tgtId; }
+ }
+ }
+
+ return cy.add( jsons );
+ }
+
+ } else if( struct.parent !== undefined ){ // move node to new parent
+ var parentId = struct.parent;
+ var parentExists = parentId === null || cy.getElementById( parentId ).length > 0;
+
+ if( parentExists ){
+ var jsons = this.jsons();
+ var descs = this.descendants();
+ var descsEtc = descs.merge( descs.add(this).connectedEdges() );
+
+ this.remove(); // NB: also removes descendants and their connected edges
+
+ for( var i = 0; i < this.length; i++ ){
+ var json = jsons[i];
+
+ if( json.group === 'nodes' ){
+ json.data.parent = parentId === null ? undefined : parentId;
+ }
+ }
+ }
+
+ return cy.add( jsons ).merge( descsEtc.restore() );
+ }
+
+ return this; // if nothing done
+};
+
+[
+ _dereq_('./algorithms'),
+ _dereq_('./animation'),
+ _dereq_('./class'),
+ _dereq_('./comparators'),
+ _dereq_('./compounds'),
+ _dereq_('./data'),
+ _dereq_('./degree'),
+ _dereq_('./dimensions'),
+ _dereq_('./events'),
+ _dereq_('./filter'),
+ _dereq_('./group'),
+ _dereq_('./index'),
+ _dereq_('./iteration'),
+ _dereq_('./layout'),
+ _dereq_('./style'),
+ _dereq_('./switch-functions'),
+ _dereq_('./traversing')
+].forEach(function( props ){
+ util.extend( elesfn, props );
+});
+
+module.exports = Collection;
+
+},{"../is":77,"../util":94,"./algorithms":9,"./animation":12,"./class":13,"./comparators":14,"./compounds":15,"./data":16,"./degree":17,"./dimensions":18,"./element":19,"./events":20,"./filter":21,"./group":22,"./index":23,"./iteration":24,"./layout":25,"./style":26,"./switch-functions":27,"./traversing":28}],24:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+var zIndexSort = _dereq_('./zsort');
+
+var elesfn = ({
+ each: function(fn){
+ if( is.fn(fn) ){
+ for(var i = 0; i < this.length; i++){
+ var ele = this[i];
+ var ret = fn.apply( ele, [ i, ele ] );
+
+ if( ret === false ){ break; } // exit each early on return false
+ }
+ }
+ return this;
+ },
+
+ forEach: function(fn, thisArg){
+ if( is.fn(fn) ){
+
+ for(var i = 0; i < this.length; i++){
+ var ele = this[i];
+ var ret = thisArg ? fn.apply( thisArg, [ ele, i, this ] ) : fn( ele, i, this );
+
+ if( ret === false ){ break; } // exit each early on return false
+ }
+ }
+
+ return this;
+ },
+
+ toArray: function(){
+ var array = [];
+
+ for(var i = 0; i < this.length; i++){
+ array.push( this[i] );
+ }
+
+ return array;
+ },
+
+ slice: function(start, end){
+ var array = [];
+ var thisSize = this.length;
+
+ if( end == null ){
+ end = thisSize;
+ }
+
+ if( start == null ){
+ start = 0;
+ }
+
+ if( start < 0 ){
+ start = thisSize + start;
+ }
+
+ if( end < 0 ){
+ end = thisSize + end;
+ }
+
+ for(var i = start; i >= 0 && i < end && i < thisSize; i++){
+ array.push( this[i] );
+ }
+
+ return this.spawn(array);
+ },
+
+ size: function(){
+ return this.length;
+ },
+
+ eq: function(i){
+ return this[i] || this.spawn();
+ },
+
+ first: function(){
+ return this[0] || this.spawn();
+ },
+
+ last: function(){
+ return this[ this.length - 1 ] || this.spawn();
+ },
+
+ empty: function(){
+ return this.length === 0;
+ },
+
+ nonempty: function(){
+ return !this.empty();
+ },
+
+ sort: function( sortFn ){
+ if( !is.fn( sortFn ) ){
+ return this;
+ }
+
+ var sorted = this.toArray().sort( sortFn );
+
+ return this.spawn(sorted);
+ },
+
+ sortByZIndex: function(){
+ return this.sort( zIndexSort );
+ },
+
+ zDepth: function(){
+ var ele = this[0];
+ if( !ele ){ return undefined; }
+
+ // var cy = ele.cy();
+ var _p = ele._private;
+ var group = _p.group;
+
+ if( group === 'nodes' ){
+ var depth = _p.data.parent ? ele.parents().size() : 0;
+
+ if( !ele.isParent() ){
+ return Number.MAX_VALUE; // childless nodes always on top
+ }
+
+ return depth;
+ } else {
+ var src = _p.source;
+ var tgt = _p.target;
+ var srcDepth = src.zDepth();
+ var tgtDepth = tgt.zDepth();
+
+ return Math.max( srcDepth, tgtDepth, 0 ); // depth of deepest parent
+ }
+ }
+});
+
+module.exports = elesfn;
+
+},{"../is":77,"./zsort":29}],25:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+var util = _dereq_('../util');
+
+var elesfn = ({
+
+ // using standard layout options, apply position function (w/ or w/o animation)
+ layoutPositions: function( layout, options, fn ){
+ var nodes = this.nodes();
+ var cy = this.cy();
+
+ layout.trigger({ type: 'layoutstart', layout: layout });
+
+ layout.animations = [];
+
+ if( options.animate ){
+ for( var i = 0; i < nodes.length; i++ ){
+ var node = nodes[i];
+ var lastNode = i === nodes.length - 1;
+
+ var newPos = fn.call( node, i, node );
+ var pos = node.position();
+
+ if( !is.number(pos.x) || !is.number(pos.y) ){
+ node.silentPosition({ x: 0, y: 0 });
+ }
+
+ var ani = node.animation({
+ position: newPos,
+ duration: options.animationDuration,
+ easing: options.animationEasing,
+ step: !lastNode ? undefined : function(){
+ if( options.fit ){
+ cy.fit( options.eles, options.padding );
+ }
+ },
+ complete: !lastNode ? undefined : function(){
+ if( options.zoom != null ){
+ cy.zoom( options.zoom );
+ }
+
+ if( options.pan ){
+ cy.pan( options.pan );
+ }
+
+ if( options.fit ){
+ cy.fit( options.eles, options.padding );
+ }
+
+ layout.one('layoutstop', options.stop);
+ layout.trigger({ type: 'layoutstop', layout: layout });
+ }
+ });
+
+ layout.animations.push( ani );
+
+ ani.play();
+ }
+
+ layout.one('layoutready', options.ready);
+ layout.trigger({ type: 'layoutready', layout: layout });
+ } else {
+ nodes.positions( fn );
+
+ if( options.fit ){
+ cy.fit( options.eles, options.padding );
+ }
+
+ if( options.zoom != null ){
+ cy.zoom( options.zoom );
+ }
+
+ if( options.pan ){
+ cy.pan( options.pan );
+ }
+
+ layout.one('layoutready', options.ready);
+ layout.trigger({ type: 'layoutready', layout: layout });
+
+ layout.one('layoutstop', options.stop);
+ layout.trigger({ type: 'layoutstop', layout: layout });
+ }
+
+ return this; // chaining
+ },
+
+ layout: function( options ){
+ var cy = this.cy();
+
+ cy.layout( util.extend({}, options, {
+ eles: this
+ }) );
+
+ return this;
+ },
+
+ makeLayout: function( options ){
+ var cy = this.cy();
+
+ return cy.makeLayout( util.extend({}, options, {
+ eles: this
+ }) );
+ }
+
+});
+
+// aliases:
+elesfn.createLayout = elesfn.makeLayout;
+
+module.exports = elesfn;
+
+},{"../is":77,"../util":94}],26:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+
+var elesfn = ({
+
+ // fully updates (recalculates) the style for the elements
+ updateStyle: function( notifyRenderer ){
+ var cy = this._private.cy;
+
+ if( !cy.styleEnabled() ){ return this; }
+
+ if( cy._private.batchingStyle ){
+ var bEles = cy._private.batchStyleEles;
+
+ bEles.merge( this );
+
+ return this; // chaining and exit early when batching
+ }
+
+ var style = cy.style();
+ notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;
+
+ style.apply( this );
+
+ var updatedCompounds = this.updateCompoundBounds();
+ var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;
+
+ if( notifyRenderer ){
+ toNotify.rtrigger('style'); // let renderer know we changed style
+ } else {
+ toNotify.trigger('style'); // just fire the event
+ }
+ return this; // chaining
+ },
+
+ // just update the mappers in the elements' styles; cheaper than eles.updateStyle()
+ updateMappers: function( notifyRenderer ){
+ var cy = this._private.cy;
+ var style = cy.style();
+ notifyRenderer = notifyRenderer || notifyRenderer === undefined ? true : false;
+
+ if( !cy.styleEnabled() ){ return this; }
+
+ style.updateMappers( this );
+
+ var updatedCompounds = this.updateCompoundBounds();
+ var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;
+
+ if( notifyRenderer ){
+ toNotify.rtrigger('style'); // let renderer know we changed style
+ } else {
+ toNotify.trigger('style'); // just fire the event
+ }
+ return this; // chaining
+ },
+
+ // get the specified css property as a rendered value (i.e. on-screen value)
+ // or get the whole rendered style if no property specified (NB doesn't allow setting)
+ renderedCss: function( property ){
+ var cy = this.cy();
+ if( !cy.styleEnabled() ){ return this; }
+
+ var ele = this[0];
+
+ if( ele ){
+ var renstyle = ele.cy().style().getRenderedStyle( ele );
+
+ if( property === undefined ){
+ return renstyle;
+ } else {
+ return renstyle[ property ];
+ }
+ }
+ },
+
+ // read the calculated css style of the element or override the style (via a bypass)
+ css: function( name, value ){
+ var cy = this.cy();
+
+ if( !cy.styleEnabled() ){ return this; }
+
+ var updateTransitions = false;
+ var style = cy.style();
+
+ if( is.plainObject(name) ){ // then extend the bypass
+ var props = name;
+ style.applyBypass( this, props, updateTransitions );
+
+ var updatedCompounds = this.updateCompoundBounds();
+ var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;
+ toNotify.rtrigger('style'); // let the renderer know we've updated style
+
+ } else if( is.string(name) ){
+
+ if( value === undefined ){ // then get the property from the style
+ var ele = this[0];
+
+ if( ele ){
+ return style.getStylePropertyValue( ele, name );
+ } else { // empty collection => can't get any value
+ return;
+ }
+
+ } else { // then set the bypass with the property value
+ style.applyBypass( this, name, value, updateTransitions );
+
+ var updatedCompounds = this.updateCompoundBounds();
+ var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;
+ toNotify.rtrigger('style'); // let the renderer know we've updated style
+ }
+
+ } else if( name === undefined ){
+ var ele = this[0];
+
+ if( ele ){
+ return style.getRawStyle( ele );
+ } else { // empty collection => can't get any value
+ return;
+ }
+ }
+
+ return this; // chaining
+ },
+
+ removeCss: function( names ){
+ var cy = this.cy();
+
+ if( !cy.styleEnabled() ){ return this; }
+
+ var updateTransitions = false;
+ var style = cy.style();
+ var eles = this;
+
+ if( names === undefined ){
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+
+ style.removeAllBypasses( ele, updateTransitions );
+ }
+ } else {
+ names = names.split(/\s+/);
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+
+ style.removeBypasses( ele, names, updateTransitions );
+ }
+ }
+
+ var updatedCompounds = this.updateCompoundBounds();
+ var toNotify = updatedCompounds.length > 0 ? this.add( updatedCompounds ) : this;
+ toNotify.rtrigger('style'); // let the renderer know we've updated style
+
+ return this; // chaining
+ },
+
+ show: function(){
+ this.css('display', 'element');
+ return this; // chaining
+ },
+
+ hide: function(){
+ this.css('display', 'none');
+ return this; // chaining
+ },
+
+ visible: function(){
+ var cy = this.cy();
+ if( !cy.styleEnabled() ){ return true; }
+
+ var ele = this[0];
+ var hasCompoundNodes = cy.hasCompoundNodes();
+
+ if( ele ){
+ var style = ele._private.style;
+
+ if(
+ style['visibility'].value !== 'visible'
+ || style['display'].value !== 'element'
+ ){
+ return false;
+ }
+
+ if( ele._private.group === 'nodes' ){
+ if( !hasCompoundNodes ){ return true; }
+
+ var parents = ele._private.data.parent ? ele.parents() : null;
+
+ if( parents ){
+ for( var i = 0; i < parents.length; i++ ){
+ var parent = parents[i];
+ var pStyle = parent._private.style;
+ var pVis = pStyle['visibility'].value;
+ var pDis = pStyle['display'].value;
+
+ if( pVis !== 'visible' || pDis !== 'element' ){
+ return false;
+ }
+ }
+ }
+
+ return true;
+ } else {
+ var src = ele._private.source;
+ var tgt = ele._private.target;
+
+ return src.visible() && tgt.visible();
+ }
+
+ }
+ },
+
+ hidden: function(){
+ var ele = this[0];
+
+ if( ele ){
+ return !ele.visible();
+ }
+ },
+
+ effectiveOpacity: function(){
+ var cy = this.cy();
+ if( !cy.styleEnabled() ){ return 1; }
+
+ var hasCompoundNodes = cy.hasCompoundNodes();
+ var ele = this[0];
+
+ if( ele ){
+ var _p = ele._private;
+ var parentOpacity = _p.style.opacity.value;
+
+ if( !hasCompoundNodes ){ return parentOpacity; }
+
+ var parents = !_p.data.parent ? null : ele.parents();
+
+ if( parents ){
+ for( var i = 0; i < parents.length; i++ ){
+ var parent = parents[i];
+ var opacity = parent._private.style.opacity.value;
+
+ parentOpacity = opacity * parentOpacity;
+ }
+ }
+
+ return parentOpacity;
+ }
+ },
+
+ transparent: function(){
+ var cy = this.cy();
+ if( !cy.styleEnabled() ){ return false; }
+
+ var ele = this[0];
+ var hasCompoundNodes = ele.cy().hasCompoundNodes();
+
+ if( ele ){
+ if( !hasCompoundNodes ){
+ return ele._private.style.opacity.value === 0;
+ } else {
+ return ele.effectiveOpacity() === 0;
+ }
+ }
+ },
+
+ isFullAutoParent: function(){
+ var cy = this.cy();
+ if( !cy.styleEnabled() ){ return false; }
+
+ var ele = this[0];
+
+ if( ele ){
+ var autoW = ele._private.style['width'].value === 'auto';
+ var autoH = ele._private.style['height'].value === 'auto';
+
+ return ele.isParent() && autoW && autoH;
+ }
+ },
+
+ backgrounding: function(){
+ var cy = this.cy();
+ if( !cy.styleEnabled() ){ return false; }
+
+ var ele = this[0];
+
+ return ele._private.backgrounding ? true : false;
+ }
+
+});
+
+
+elesfn.bypass = elesfn.style = elesfn.css;
+elesfn.renderedStyle = elesfn.renderedCss;
+elesfn.removeBypass = elesfn.removeStyle = elesfn.removeCss;
+
+module.exports = elesfn;
+
+},{"../is":77}],27:[function(_dereq_,module,exports){
+'use strict';
+
+var elesfn = {};
+
+function defineSwitchFunction(params){
+ return function(){
+ var args = arguments;
+ var changedEles = [];
+
+ // e.g. cy.nodes().select( data, handler )
+ if( args.length === 2 ){
+ var data = args[0];
+ var handler = args[1];
+ this.bind( params.event, data, handler );
+ }
+
+ // e.g. cy.nodes().select( handler )
+ else if( args.length === 1 ){
+ var handler = args[0];
+ this.bind( params.event, handler );
+ }
+
+ // e.g. cy.nodes().select()
+ else if( args.length === 0 ){
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+ var able = !params.ableField || ele._private[params.ableField];
+ var changed = ele._private[params.field] != params.value;
+
+ if( params.overrideAble ){
+ var overrideAble = params.overrideAble(ele);
+
+ if( overrideAble !== undefined ){
+ able = overrideAble;
+
+ if( !overrideAble ){ return this; } // to save cycles assume not able for all on override
+ }
+ }
+
+ if( able ){
+ ele._private[params.field] = params.value;
+
+ if( changed ){
+ changedEles.push( ele );
+ }
+ }
+ }
+
+ var changedColl = this.spawn( changedEles );
+ changedColl.updateStyle(); // change of state => possible change of style
+ changedColl.trigger( params.event );
+ }
+
+ return this;
+ };
+}
+
+function defineSwitchSet( params ){
+ elesfn[ params.field ] = function(){
+ var ele = this[0];
+
+ if( ele ){
+ if( params.overrideField ){
+ var val = params.overrideField(ele);
+
+ if( val !== undefined ){
+ return val;
+ }
+ }
+
+ return ele._private[ params.field ];
+ }
+ };
+
+ elesfn[ params.on ] = defineSwitchFunction({
+ event: params.on,
+ field: params.field,
+ ableField: params.ableField,
+ overrideAble: params.overrideAble,
+ value: true
+ });
+
+ elesfn[ params.off ] = defineSwitchFunction({
+ event: params.off,
+ field: params.field,
+ ableField: params.ableField,
+ overrideAble: params.overrideAble,
+ value: false
+ });
+}
+
+defineSwitchSet({
+ field: 'locked',
+ overrideField: function(ele){
+ return ele.cy().autolock() ? true : undefined;
+ },
+ on: 'lock',
+ off: 'unlock'
+});
+
+defineSwitchSet({
+ field: 'grabbable',
+ overrideField: function(ele){
+ return ele.cy().autoungrabify() ? false : undefined;
+ },
+ on: 'grabify',
+ off: 'ungrabify'
+});
+
+defineSwitchSet({
+ field: 'selected',
+ ableField: 'selectable',
+ overrideAble: function(ele){
+ return ele.cy().autounselectify() ? false : undefined;
+ },
+ on: 'select',
+ off: 'unselect'
+});
+
+defineSwitchSet({
+ field: 'selectable',
+ overrideField: function(ele){
+ return ele.cy().autounselectify() ? false : undefined;
+ },
+ on: 'selectify',
+ off: 'unselectify'
+});
+
+elesfn.deselect = elesfn.unselect;
+
+elesfn.grabbed = function(){
+ var ele = this[0];
+ if( ele ){
+ return ele._private.grabbed;
+ }
+};
+
+defineSwitchSet({
+ field: 'active',
+ on: 'activate',
+ off: 'unactivate'
+});
+
+elesfn.inactive = function(){
+ var ele = this[0];
+ if( ele ){
+ return !ele._private.active;
+ }
+};
+
+module.exports = elesfn;
+
+},{}],28:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+var is = _dereq_('../is');
+
+var elesfn = {};
+
+util.extend(elesfn, {
+ // get the root nodes in the DAG
+ roots: function( selector ){
+ var eles = this;
+ var roots = [];
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ if( !ele.isNode() ){
+ continue;
+ }
+
+ var hasEdgesPointingIn = ele.connectedEdges(function(){
+ return this.data('target') === ele.id() && this.data('source') !== ele.id();
+ }).length > 0;
+
+ if( !hasEdgesPointingIn ){
+ roots.push( ele );
+ }
+ }
+
+ return this.spawn( roots, { unique: true } ).filter( selector );
+ },
+
+ // get the leaf nodes in the DAG
+ leaves: function( selector ){
+ var eles = this;
+ var leaves = [];
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ if( !ele.isNode() ){
+ continue;
+ }
+
+ var hasEdgesPointingOut = ele.connectedEdges(function(){
+ return this.data('source') === ele.id() && this.data('target') !== ele.id();
+ }).length > 0;
+
+ if( !hasEdgesPointingOut ){
+ leaves.push( ele );
+ }
+ }
+
+ return this.spawn( leaves, { unique: true } ).filter( selector );
+ },
+
+ // normally called children in graph theory
+ // these nodes =edges=> outgoing nodes
+ outgoers: function( selector ){
+ var eles = this;
+ var oEles = [];
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ var eleId = ele.id();
+
+ if( !ele.isNode() ){ continue; }
+
+ var edges = ele._private.edges;
+ for( var j = 0; j < edges.length; j++ ){
+ var edge = edges[j];
+ var srcId = edge._private.data.source;
+ var tgtId = edge._private.data.target;
+
+ if( srcId === eleId && tgtId !== eleId ){
+ oEles.push( edge );
+ oEles.push( edge.target()[0] );
+ }
+ }
+ }
+
+ return this.spawn( oEles, { unique: true } ).filter( selector );
+ },
+
+ // aka DAG descendants
+ successors: function( selector ){
+ var eles = this;
+ var sEles = [];
+ var sElesIds = {};
+
+ for(;;){
+ var outgoers = eles.outgoers();
+
+ if( outgoers.length === 0 ){ break; } // done if no outgoers left
+
+ var newOutgoers = false;
+ for( var i = 0; i < outgoers.length; i++ ){
+ var outgoer = outgoers[i];
+ var outgoerId = outgoer.id();
+
+ if( !sElesIds[ outgoerId ] ){
+ sElesIds[ outgoerId ] = true;
+ sEles.push( outgoer );
+ newOutgoers = true;
+ }
+ }
+
+ if( !newOutgoers ){ break; } // done if touched all outgoers already
+
+ eles = outgoers;
+ }
+
+ return this.spawn( sEles, { unique: true } ).filter( selector );
+ },
+
+ // normally called parents in graph theory
+ // these nodes <=edges= incoming nodes
+ incomers: function( selector ){
+ var eles = this;
+ var oEles = [];
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ var eleId = ele.id();
+
+ if( !ele.isNode() ){ continue; }
+
+ var edges = ele._private.edges;
+ for( var j = 0; j < edges.length; j++ ){
+ var edge = edges[j];
+ var srcId = edge._private.data.source;
+ var tgtId = edge._private.data.target;
+
+ if( tgtId === eleId && srcId !== eleId ){
+ oEles.push( edge );
+ oEles.push( edge.source()[0] );
+ }
+ }
+ }
+
+ return this.spawn( oEles, { unique: true } ).filter( selector );
+ },
+
+ // aka DAG ancestors
+ predecessors: function( selector ){
+ var eles = this;
+ var pEles = [];
+ var pElesIds = {};
+
+ for(;;){
+ var incomers = eles.incomers();
+
+ if( incomers.length === 0 ){ break; } // done if no incomers left
+
+ var newIncomers = false;
+ for( var i = 0; i < incomers.length; i++ ){
+ var incomer = incomers[i];
+ var incomerId = incomer.id();
+
+ if( !pElesIds[ incomerId ] ){
+ pElesIds[ incomerId ] = true;
+ pEles.push( incomer );
+ newIncomers = true;
+ }
+ }
+
+ if( !newIncomers ){ break; } // done if touched all incomers already
+
+ eles = incomers;
+ }
+
+ return this.spawn( pEles, { unique: true } ).filter( selector );
+ }
+});
+
+
+// Neighbourhood functions
+//////////////////////////
+
+util.extend(elesfn, {
+ neighborhood: function(selector){
+ var elements = [];
+ var nodes = this.nodes();
+
+ for( var i = 0; i < nodes.length; i++ ){ // for all nodes
+ var node = nodes[i];
+ var connectedEdges = node.connectedEdges();
+
+ // for each connected edge, add the edge and the other node
+ for( var j = 0; j < connectedEdges.length; j++ ){
+ var edge = connectedEdges[j];
+ var src = edge._private.source;
+ var tgt = edge._private.target;
+ var otherNode = node === src ? tgt : src;
+
+ // need check in case of loop
+ if( otherNode.length > 0 ){
+ elements.push( otherNode[0] ); // add node 1 hop away
+ }
+
+ // add connected edge
+ elements.push( edge[0] );
+ }
+
+ }
+
+ return ( this.spawn( elements, { unique: true } ) ).filter( selector );
+ },
+
+ closedNeighborhood: function(selector){
+ return this.neighborhood().add( this ).filter( selector );
+ },
+
+ openNeighborhood: function(selector){
+ return this.neighborhood( selector );
+ }
+});
+
+// aliases
+elesfn.neighbourhood = elesfn.neighborhood;
+elesfn.closedNeighbourhood = elesfn.closedNeighborhood;
+elesfn.openNeighbourhood = elesfn.openNeighborhood;
+
+// Edge functions
+/////////////////
+
+util.extend(elesfn, {
+ source: function( selector ){
+ var ele = this[0];
+ var src;
+
+ if( ele ){
+ src = ele._private.source;
+ }
+
+ return src && selector ? src.filter( selector ) : src;
+ },
+
+ target: function( selector ){
+ var ele = this[0];
+ var tgt;
+
+ if( ele ){
+ tgt = ele._private.target;
+ }
+
+ return tgt && selector ? tgt.filter( selector ) : tgt;
+ },
+
+ sources: defineSourceFunction({
+ attr: 'source'
+ }),
+
+ targets: defineSourceFunction({
+ attr: 'target'
+ })
+});
+
+function defineSourceFunction( params ){
+ return function( selector ){
+ var sources = [];
+
+ for( var i = 0; i < this.length; i++ ){
+ var ele = this[i];
+ var src = ele._private[ params.attr ];
+
+ if( src ){
+ sources.push( src );
+ }
+ }
+
+ return this.spawn( sources, { unique: true } ).filter( selector );
+ };
+}
+
+util.extend(elesfn, {
+ edgesWith: defineEdgesWithFunction(),
+
+ edgesTo: defineEdgesWithFunction({
+ thisIs: 'source'
+ })
+});
+
+function defineEdgesWithFunction( params ){
+
+ return function edgesWithImpl( otherNodes ){
+ var elements = [];
+ var cy = this._private.cy;
+ var p = params || {};
+
+ // get elements if a selector is specified
+ if( is.string(otherNodes) ){
+ otherNodes = cy.$( otherNodes );
+ }
+
+ var thisIds = this._private.ids;
+ var otherIds = otherNodes._private.ids;
+
+ for( var h = 0; h < otherNodes.length; h++ ){
+ var edges = otherNodes[h]._private.edges;
+
+ for( var i = 0; i < edges.length; i++ ){
+ var edge = edges[i];
+ var edgeData = edge._private.data;
+ var thisToOther = thisIds[ edgeData.source ] && otherIds[ edgeData.target ];
+ var otherToThis = otherIds[ edgeData.source ] && thisIds[ edgeData.target ];
+ var edgeConnectsThisAndOther = thisToOther || otherToThis;
+
+ if( !edgeConnectsThisAndOther ){ continue; }
+
+ if( p.thisIs ){
+ if( p.thisIs === 'source' && !thisToOther ){ continue; }
+
+ if( p.thisIs === 'target' && !otherToThis ){ continue; }
+ }
+
+ elements.push( edge );
+ }
+ }
+
+ return this.spawn( elements, { unique: true } );
+ };
+}
+
+util.extend(elesfn, {
+ connectedEdges: function( selector ){
+ var retEles = [];
+
+ var eles = this;
+ for( var i = 0; i < eles.length; i++ ){
+ var node = eles[i];
+ if( !node.isNode() ){ continue; }
+
+ var edges = node._private.edges;
+
+ for( var j = 0; j < edges.length; j++ ){
+ var edge = edges[j];
+ retEles.push( edge );
+ }
+ }
+
+ return this.spawn( retEles, { unique: true } ).filter( selector );
+ },
+
+ connectedNodes: function( selector ){
+ var retEles = [];
+
+ var eles = this;
+ for( var i = 0; i < eles.length; i++ ){
+ var edge = eles[i];
+ if( !edge.isEdge() ){ continue; }
+
+ retEles.push( edge.source()[0] );
+ retEles.push( edge.target()[0] );
+ }
+
+ return this.spawn( retEles, { unique: true } ).filter( selector );
+ },
+
+ parallelEdges: defineParallelEdgesFunction(),
+
+ codirectedEdges: defineParallelEdgesFunction({
+ codirected: true
+ })
+});
+
+function defineParallelEdgesFunction(params){
+ var defaults = {
+ codirected: false
+ };
+ params = util.extend({}, defaults, params);
+
+ return function( selector ){
+ var elements = [];
+ var edges = this.edges();
+ var p = params;
+
+ // look at all the edges in the collection
+ for( var i = 0; i < edges.length; i++ ){
+ var edge1 = edges[i];
+ var src1 = edge1.source()[0];
+ var srcid1 = src1.id();
+ var tgt1 = edge1.target()[0];
+ var tgtid1 = tgt1.id();
+ var srcEdges1 = src1._private.edges;
+
+ // look at edges connected to the src node of this edge
+ for( var j = 0; j < srcEdges1.length; j++ ){
+ var edge2 = srcEdges1[j];
+ var edge2data = edge2._private.data;
+ var tgtid2 = edge2data.target;
+ var srcid2 = edge2data.source;
+
+ var codirected = tgtid2 === tgtid1 && srcid2 === srcid1;
+ var oppdirected = srcid1 === tgtid2 && tgtid1 === srcid2;
+
+ if( (p.codirected && codirected) || (!p.codirected && (codirected || oppdirected)) ){
+ elements.push( edge2 );
+ }
+ }
+ }
+
+ return this.spawn( elements, { unique: true } ).filter( selector );
+ };
+
+}
+
+// Misc functions
+/////////////////
+
+util.extend(elesfn, {
+ components: function(){
+ var cy = this.cy();
+ var visited = cy.collection();
+ var unvisited = this.nodes();
+ var components = [];
+
+ var visitInComponent = function( node, component ){
+ visited.merge( node );
+ unvisited.unmerge( node );
+ component.merge( node );
+ };
+
+ do {
+ var component = cy.collection();
+ components.push( component );
+
+ var root = unvisited[0];
+ visitInComponent( root, component );
+
+ this.bfs({
+ directed: false,
+ roots: root,
+ visit: function( i, depth, v, e, u ){
+ visitInComponent( v, component );
+ }
+ });
+
+ } while( unvisited.length > 0 );
+
+ return components.map(function( component ){
+ return component.closedNeighborhood(); // add the edges
+ });
+ }
+});
+
+module.exports = elesfn;
+
+},{"../is":77,"../util":94}],29:[function(_dereq_,module,exports){
+'use strict';
+
+var zIndexSort = function( a, b ){
+ var cy = a.cy();
+ var a_p = a._private;
+ var b_p = b._private;
+ var zDiff = a_p.style['z-index'].value - b_p.style['z-index'].value;
+ var depthA = 0;
+ var depthB = 0;
+ var hasCompoundNodes = cy.hasCompoundNodes();
+ var aIsNode = a_p.group === 'nodes';
+ var aIsEdge = a_p.group === 'edges';
+ var bIsNode = b_p.group === 'nodes';
+ var bIsEdge = b_p.group === 'edges';
+
+ // no need to calculate element depth if there is no compound node
+ if( hasCompoundNodes ){
+ depthA = a.zDepth();
+ depthB = b.zDepth();
+ }
+
+ var depthDiff = depthA - depthB;
+ var sameDepth = depthDiff === 0;
+
+ if( sameDepth ){
+
+ if( aIsNode && bIsEdge ){
+ return 1; // 'a' is a node, it should be drawn later
+
+ } else if( aIsEdge && bIsNode ){
+ return -1; // 'a' is an edge, it should be drawn first
+
+ } else { // both nodes or both edges
+ if( zDiff === 0 ){ // same z-index => compare indices in the core (order added to graph w/ last on top)
+ return a_p.index - b_p.index;
+ } else {
+ return zDiff;
+ }
+ }
+
+ // elements on different level
+ } else {
+ return depthDiff; // deeper element should be drawn later
+ }
+
+};
+
+module.exports = zIndexSort;
+
+},{}],30:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+var util = _dereq_('../util');
+var Collection = _dereq_('../collection');
+var Element = _dereq_('../collection/element');
+var window = _dereq_('../window');
+var document = window ? window.document : null;
+var NullRenderer = _dereq_('../extensions/renderer/null');
+
+var corefn = {
+ add: function(opts){
+
+ var elements;
+ var cy = this;
+
+ // add the elements
+ if( is.elementOrCollection(opts) ){
+ var eles = opts;
+
+ if( eles._private.cy === cy ){ // same instance => just restore
+ elements = eles.restore();
+
+ } else { // otherwise, copy from json
+ var jsons = [];
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ jsons.push( ele.json() );
+ }
+
+ elements = new Collection( cy, jsons );
+ }
+ }
+
+ // specify an array of options
+ else if( is.array(opts) ){
+ var jsons = opts;
+
+ elements = new Collection(cy, jsons);
+ }
+
+ // specify via opts.nodes and opts.edges
+ else if( is.plainObject(opts) && (is.array(opts.nodes) || is.array(opts.edges)) ){
+ var elesByGroup = opts;
+ var jsons = [];
+
+ var grs = ['nodes', 'edges'];
+ for( var i = 0, il = grs.length; i < il; i++ ){
+ var group = grs[i];
+ var elesArray = elesByGroup[group];
+
+ if( is.array(elesArray) ){
+
+ for( var j = 0, jl = elesArray.length; j < jl; j++ ){
+ var json = util.extend( { group: group }, elesArray[j] );
+
+ jsons.push( json );
+ }
+ }
+ }
+
+ elements = new Collection(cy, jsons);
+ }
+
+ // specify options for one element
+ else {
+ var json = opts;
+ elements = (new Element( cy, json )).collection();
+ }
+
+ return elements;
+ },
+
+ remove: function(collection){
+ if( is.elementOrCollection(collection) ){
+ collection = collection;
+ } else if( is.string(collection) ){
+ var selector = collection;
+ collection = this.$( selector );
+ }
+
+ return collection.remove();
+ },
+
+ load: function(elements, onload, ondone){
+ var cy = this;
+
+ cy.notifications(false);
+
+ // remove old elements
+ var oldEles = cy.elements();
+ if( oldEles.length > 0 ){
+ oldEles.remove();
+ }
+
+ if( elements != null ){
+ if( is.plainObject(elements) || is.array(elements) ){
+ cy.add( elements );
+ }
+ }
+
+ cy.one('layoutready', function(e){
+ cy.notifications(true);
+ cy.trigger(e); // we missed this event by turning notifications off, so pass it on
+
+ cy.notify({
+ type: 'load',
+ collection: cy.elements()
+ });
+
+ cy.one('load', onload);
+ cy.trigger('load');
+ }).one('layoutstop', function(){
+ cy.one('done', ondone);
+ cy.trigger('done');
+ });
+
+ var layoutOpts = util.extend({}, cy._private.options.layout);
+ layoutOpts.eles = cy.$();
+
+ cy.layout( layoutOpts );
+
+ return this;
+ }
+};
+
+module.exports = corefn;
+
+},{"../collection":23,"../collection/element":19,"../extensions/renderer/null":73,"../is":77,"../util":94,"../window":100}],31:[function(_dereq_,module,exports){
+'use strict';
+
+var define = _dereq_('../define');
+var util = _dereq_('../util');
+var is = _dereq_('../is');
+
+var corefn = ({
+
+ // pull in animation functions
+ animate: define.animate(),
+ animation: define.animation(),
+ animated: define.animated(),
+ clearQueue: define.clearQueue(),
+ delay: define.delay(),
+ delayAnimation: define.delayAnimation(),
+ stop: define.stop(),
+
+ addToAnimationPool: function( eles ){
+ var cy = this;
+
+ if( !cy.styleEnabled() ){ return; } // save cycles when no style used
+
+ cy._private.aniEles.merge( eles );
+ },
+
+ stopAnimationLoop: function(){
+ this._private.animationsRunning = false;
+ },
+
+ startAnimationLoop: function(){
+ var cy = this;
+
+ cy._private.animationsRunning = true;
+
+ if( !cy.styleEnabled() ){ return; } // save cycles when no style used
+
+ // NB the animation loop will exec in headless environments if style enabled
+ // and explicit cy.destroy() is necessary to stop the loop
+
+ function globalAnimationStep(){
+ if( !cy._private.animationsRunning ){ return; }
+
+ util.requestAnimationFrame(function(now){
+ handleElements(now);
+ globalAnimationStep();
+ });
+ }
+
+ globalAnimationStep(); // first call
+
+ function handleElements( now ){
+ var eles = cy._private.aniEles;
+ var doneEles = [];
+
+ function handleElement( ele, isCore ){
+ var _p = ele._private;
+ var current = _p.animation.current;
+ var queue = _p.animation.queue;
+ var ranAnis = false;
+
+ // if nothing currently animating, get something from the queue
+ if( current.length === 0 ){
+ var next = queue.shift();
+
+ if( next ){
+ current.push( next );
+ }
+ }
+
+ var callbacks = function( callbacks ){
+ for( var j = callbacks.length - 1; j >= 0; j-- ){
+ var cb = callbacks[j];
+
+ cb();
+ }
+
+ callbacks.splice( 0, callbacks.length );
+ };
+
+ // step and remove if done
+ for( var i = current.length - 1; i >= 0; i-- ){
+ var ani = current[i];
+ var ani_p = ani._private;
+
+ if( ani_p.stopped ){
+ current.splice( i, 1 );
+
+ ani_p.hooked = false;
+ ani_p.playing = false;
+ ani_p.started = false;
+
+ callbacks( ani_p.frames );
+
+ continue;
+ }
+
+ if( !ani_p.playing && !ani_p.applying ){ continue; }
+
+ // an apply() while playing shouldn't do anything
+ if( ani_p.playing && ani_p.applying ){
+ ani_p.applying = false;
+ }
+
+ if( !ani_p.started ){
+ startAnimation( ele, ani, now );
+ }
+
+ step( ele, ani, now, isCore );
+
+ if( ani_p.applying ){
+ ani_p.applying = false;
+ }
+
+ callbacks( ani_p.frames );
+
+ if( ani.completed() ){
+ current.splice(i, 1);
+
+ ani_p.hooked = false;
+ ani_p.playing = false;
+ ani_p.started = false;
+
+ callbacks( ani_p.completes );
+ }
+
+ ranAnis = true;
+ }
+
+ if( !isCore && current.length === 0 && queue.length === 0 ){
+ doneEles.push( ele );
+ }
+
+ return ranAnis;
+ } // handleElement
+
+ // handle all eles
+ var ranEleAni = false;
+ for( var e = 0; e < eles.length; e++ ){
+ var ele = eles[e];
+ var handledThisEle = handleElement( ele );
+
+ ranEleAni = ranEleAni || handledThisEle;
+ } // each element
+
+ var ranCoreAni = handleElement( cy, true );
+
+ // notify renderer
+ if( ranEleAni || ranCoreAni ){
+ var toNotify;
+
+ if( eles.length > 0 ){
+ var updatedEles = eles.updateCompoundBounds();
+ toNotify = updatedEles.length > 0 ? eles.add( updatedEles ) : eles;
+ }
+
+ cy.notify({
+ type: 'draw',
+ collection: toNotify
+ });
+ }
+
+ // remove elements from list of currently animating if its queues are empty
+ eles.unmerge( doneEles );
+
+ } // handleElements
+
+ function startAnimation( self, ani, now ){
+ var isCore = is.core( self );
+ var isEles = !isCore;
+ var ele = self;
+ var style = cy._private.style;
+ var ani_p = ani._private;
+
+ if( isEles ){
+ var pos = ele._private.position;
+
+ ani_p.startPosition = ani_p.startPosition || {
+ x: pos.x,
+ y: pos.y
+ };
+
+ ani_p.startStyle = ani_p.startStyle || style.getValueStyle( ele );
+ }
+
+ if( isCore ){
+ var pan = cy._private.pan;
+
+ ani_p.startPan = ani_p.startPan || {
+ x: pan.x,
+ y: pan.y
+ };
+
+ ani_p.startZoom = ani_p.startZoom != null ? ani_p.startZoom : cy._private.zoom;
+ }
+
+ ani_p.started = true;
+ ani_p.startTime = now - ani_p.progress * ani_p.duration;
+ }
+
+ function step( self, ani, now, isCore ){
+ var style = cy._private.style;
+ var isEles = !isCore;
+ var _p = self._private;
+ var ani_p = ani._private;
+ var pEasing = ani_p.easing;
+ var startTime = ani_p.startTime;
+
+ if( !ani_p.easingImpl ){
+
+ if( pEasing == null ){ // use default
+ ani_p.easingImpl = easings['linear'];
+
+ } else { // then define w/ name
+ var easingVals;
+
+ if( is.string( pEasing ) ){
+ var easingProp = style.parse('transition-timing-function', pEasing);
+
+ easingVals = easingProp.value;
+
+ } else { // then assume preparsed array
+ easingVals = pEasing;
+ }
+
+ var name, args;
+
+ if( is.string( easingVals ) ){
+ name = easingVals;
+ args = [];
+ } else {
+ name = easingVals[1];
+ args = easingVals.slice(2).map(function(n){ return +n; });
+ }
+
+ if( args.length > 0 ){ // create with args
+ if( name === 'spring' ){
+ args.push( ani_p.duration ); // need duration to generate spring
+ }
+
+ ani_p.easingImpl = easings[ name ].apply( null, args );
+ } else { // static impl by name
+ ani_p.easingImpl = easings[ name ];
+ }
+ }
+
+ }
+
+ var easing = ani_p.easingImpl;
+ var percent;
+
+ if( ani_p.duration === 0 ){
+ percent = 1;
+ } else {
+ percent = (now - startTime) / ani_p.duration;
+ }
+
+ if( ani_p.applying ){
+ percent = ani_p.progress;
+ }
+
+ if( percent < 0 ){
+ percent = 0;
+ } else if( percent > 1 ){
+ percent = 1;
+ }
+
+ if( ani_p.delay == null ){ // then update
+
+ var startPos = ani_p.startPosition;
+ var endPos = ani_p.position;
+ var pos = _p.position;
+ if( endPos && isEles ){
+ if( valid( startPos.x, endPos.x ) ){
+ pos.x = ease( startPos.x, endPos.x, percent, easing );
+ }
+
+ if( valid( startPos.y, endPos.y ) ){
+ pos.y = ease( startPos.y, endPos.y, percent, easing );
+ }
+ }
+
+ var startPan = ani_p.startPan;
+ var endPan = ani_p.pan;
+ var pan = _p.pan;
+ var animatingPan = endPan != null && isCore;
+ if( animatingPan ){
+ if( valid( startPan.x, endPan.x ) ){
+ pan.x = ease( startPan.x, endPan.x, percent, easing );
+ }
+
+ if( valid( startPan.y, endPan.y ) ){
+ pan.y = ease( startPan.y, endPan.y, percent, easing );
+ }
+
+ self.trigger('pan');
+ }
+
+ var startZoom = ani_p.startZoom;
+ var endZoom = ani_p.zoom;
+ var animatingZoom = endZoom != null && isCore;
+ if( animatingZoom ){
+ if( valid( startZoom, endZoom ) ){
+ _p.zoom = ease( startZoom, endZoom, percent, easing );
+ }
+
+ self.trigger('zoom');
+ }
+
+ if( animatingPan || animatingZoom ){
+ self.trigger('viewport');
+ }
+
+ var props = ani_p.style;
+ if( props && isEles ){
+
+ for( var i = 0; i < props.length; i++ ){
+ var prop = props[i];
+ var name = prop.name;
+ var end = prop;
+
+ var start = ani_p.startStyle[ name ];
+ var easedVal = ease( start, end, percent, easing );
+
+ style.overrideBypass( self, name, easedVal );
+ } // for props
+
+ } // if
+
+ }
+
+ if( is.fn(ani_p.step) ){
+ ani_p.step.apply( self, [ now ] );
+ }
+
+ ani_p.progress = percent;
+
+ return percent;
+ }
+
+ function valid(start, end){
+ if( start == null || end == null ){
+ return false;
+ }
+
+ if( is.number(start) && is.number(end) ){
+ return true;
+ } else if( (start) && (end) ){
+ return true;
+ }
+
+ return false;
+ }
+
+ // assumes p0 = 0, p3 = 1
+ function evalCubicBezier( p1, p2, t ){
+ var one_t = 1 - t;
+ var tsq = t*t;
+
+ return ( 3 * one_t * one_t * t * p1 ) + ( 3 * one_t * tsq * p2 ) + tsq * t;
+ }
+
+ function cubicBezier( p1, p2 ){
+ return function( start, end, percent ){
+ return start + (end - start) * evalCubicBezier( p1, p2, percent );
+ };
+ }
+
+ /* Runge-Kutta spring physics function generator. Adapted from Framer.js, copyright Koen Bok. MIT License: http://en.wikipedia.org/wiki/MIT_License */
+ /* Given a tension, friction, and duration, a simulation at 60FPS will first run without a defined duration in order to calculate the full path. A second pass
+ then adjusts the time delta -- using the relation between actual time and duration -- to calculate the path for the duration-constrained animation. */
+ var generateSpringRK4 = (function () {
+ function springAccelerationForState (state) {
+ return (-state.tension * state.x) - (state.friction * state.v);
+ }
+
+ function springEvaluateStateWithDerivative (initialState, dt, derivative) {
+ var state = {
+ x: initialState.x + derivative.dx * dt,
+ v: initialState.v + derivative.dv * dt,
+ tension: initialState.tension,
+ friction: initialState.friction
+ };
+
+ return { dx: state.v, dv: springAccelerationForState(state) };
+ }
+
+ function springIntegrateState (state, dt) {
+ var a = {
+ dx: state.v,
+ dv: springAccelerationForState(state)
+ },
+ b = springEvaluateStateWithDerivative(state, dt * 0.5, a),
+ c = springEvaluateStateWithDerivative(state, dt * 0.5, b),
+ d = springEvaluateStateWithDerivative(state, dt, c),
+ dxdt = 1.0 / 6.0 * (a.dx + 2.0 * (b.dx + c.dx) + d.dx),
+ dvdt = 1.0 / 6.0 * (a.dv + 2.0 * (b.dv + c.dv) + d.dv);
+
+ state.x = state.x + dxdt * dt;
+ state.v = state.v + dvdt * dt;
+
+ return state;
+ }
+
+ return function springRK4Factory (tension, friction, duration) {
+
+ var initState = {
+ x: -1,
+ v: 0,
+ tension: null,
+ friction: null
+ },
+ path = [0],
+ time_lapsed = 0,
+ tolerance = 1 / 10000,
+ DT = 16 / 1000,
+ have_duration, dt, last_state;
+
+ tension = parseFloat(tension) || 500;
+ friction = parseFloat(friction) || 20;
+ duration = duration || null;
+
+ initState.tension = tension;
+ initState.friction = friction;
+
+ have_duration = duration !== null;
+
+ /* Calculate the actual time it takes for this animation to complete with the provided conditions. */
+ if (have_duration) {
+ /* Run the simulation without a duration. */
+ time_lapsed = springRK4Factory(tension, friction);
+ /* Compute the adjusted time delta. */
+ dt = time_lapsed / duration * DT;
+ } else {
+ dt = DT;
+ }
+
+ while (true) {
+ /* Next/step function .*/
+ last_state = springIntegrateState(last_state || initState, dt);
+ /* Store the position. */
+ path.push(1 + last_state.x);
+ time_lapsed += 16;
+ /* If the change threshold is reached, break. */
+ if (!(Math.abs(last_state.x) > tolerance && Math.abs(last_state.v) > tolerance)) {
+ break;
+ }
+ }
+
+ /* If duration is not defined, return the actual time required for completing this animation. Otherwise, return a closure that holds the
+ computed path and returns a snapshot of the position according to a given percentComplete. */
+ return !have_duration ? time_lapsed : function(percentComplete) { return path[ (percentComplete * (path.length - 1)) | 0 ]; };
+ };
+ }());
+
+ var easings = {
+ 'linear': function( start, end, percent ){
+ return start + (end - start) * percent;
+ },
+
+ // default easings
+ 'ease': cubicBezier( 0.25, 0.1, 0.25, 1 ),
+ 'ease-in': cubicBezier( 0.42, 0, 1, 1 ),
+ 'ease-out': cubicBezier( 0, 0, 0.58, 1 ),
+ 'ease-in-out': cubicBezier( 0.42, 0, 0.58, 1 ),
+
+ // sine
+ 'ease-in-sine': cubicBezier( 0.47, 0, 0.745, 0.715 ),
+ 'ease-out-sine': cubicBezier( 0.39, 0.575, 0.565, 1 ),
+ 'ease-in-out-sine': cubicBezier( 0.445, 0.05, 0.55, 0.95 ),
+
+ // quad
+ 'ease-in-quad': cubicBezier( 0.55, 0.085, 0.68, 0.53 ),
+ 'ease-out-quad': cubicBezier( 0.25, 0.46, 0.45, 0.94 ),
+ 'ease-in-out-quad': cubicBezier( 0.455, 0.03, 0.515, 0.955 ),
+
+ // cubic
+ 'ease-in-cubic': cubicBezier( 0.55, 0.055, 0.675, 0.19 ),
+ 'ease-out-cubic': cubicBezier( 0.215, 0.61, 0.355, 1 ),
+ 'ease-in-out-cubic': cubicBezier( 0.645, 0.045, 0.355, 1 ),
+
+ // quart
+ 'ease-in-quart': cubicBezier( 0.895, 0.03, 0.685, 0.22 ),
+ 'ease-out-quart': cubicBezier( 0.165, 0.84, 0.44, 1 ),
+ 'ease-in-out-quart': cubicBezier( 0.77, 0, 0.175, 1 ),
+
+ // quint
+ 'ease-in-quint': cubicBezier( 0.755, 0.05, 0.855, 0.06 ),
+ 'ease-out-quint': cubicBezier( 0.23, 1, 0.32, 1 ),
+ 'ease-in-out-quint': cubicBezier( 0.86, 0, 0.07, 1 ),
+
+ // expo
+ 'ease-in-expo': cubicBezier( 0.95, 0.05, 0.795, 0.035 ),
+ 'ease-out-expo': cubicBezier( 0.19, 1, 0.22, 1 ),
+ 'ease-in-out-expo': cubicBezier( 1, 0, 0, 1 ),
+
+ // circ
+ 'ease-in-circ': cubicBezier( 0.6, 0.04, 0.98, 0.335 ),
+ 'ease-out-circ': cubicBezier( 0.075, 0.82, 0.165, 1 ),
+ 'ease-in-out-circ': cubicBezier( 0.785, 0.135, 0.15, 0.86 ),
+
+
+ // user param easings...
+
+ 'spring': function( tension, friction, duration ){
+ var spring = generateSpringRK4( tension, friction, duration );
+
+ return function( start, end, percent ){
+ return start + (end - start) * spring( percent );
+ };
+ },
+
+ 'cubic-bezier': function( x1, y1, x2, y2 ){
+ return cubicBezier( x1, y1, x2, y2 );
+ }
+ };
+
+ function ease( startProp, endProp, percent, easingFn ){
+ if( percent < 0 ){
+ percent = 0;
+ } else if( percent > 1 ){
+ percent = 1;
+ }
+
+ var start, end;
+
+ if( startProp.pfValue != null || startProp.value != null ){
+ start = startProp.pfValue != null ? startProp.pfValue : startProp.value;
+ } else {
+ start = startProp;
+ }
+
+ if( endProp.pfValue != null || endProp.value != null ){
+ end = endProp.pfValue != null ? endProp.pfValue : endProp.value;
+ } else {
+ end = endProp;
+ }
+
+ if( is.number(start) && is.number(end) ){
+ return easingFn( start, end, percent );
+
+ } else if( is.array(start) && is.array(end) ){
+ var easedArr = [];
+
+ for( var i = 0; i < end.length; i++ ){
+ var si = start[i];
+ var ei = end[i];
+
+ if( si != null && ei != null ){
+ var val = easingFn(si, ei, percent);
+
+ if( startProp.roundValue ){ val = Math.round( val ); }
+
+ easedArr.push( val );
+ } else {
+ easedArr.push( ei );
+ }
+ }
+
+ return easedArr;
+ }
+
+ return undefined;
+ }
+
+ }
+
+});
+
+module.exports = corefn;
+
+},{"../define":41,"../is":77,"../util":94}],32:[function(_dereq_,module,exports){
+'use strict';
+
+var define = _dereq_('../define');
+
+var corefn = ({
+ on: define.on(), // .on( events [, selector] [, data], handler)
+ one: define.on({ unbindSelfOnTrigger: true }),
+ once: define.on({ unbindAllBindersOnTrigger: true }),
+ off: define.off(), // .off( events [, selector] [, handler] )
+ trigger: define.trigger() // .trigger( events [, extraParams] )
+});
+
+define.eventAliasesOn( corefn );
+
+module.exports = corefn;
+
+},{"../define":41}],33:[function(_dereq_,module,exports){
+'use strict';
+
+var corefn = ({
+
+ png: function( options ){
+ var renderer = this._private.renderer;
+ options = options || {};
+
+ return renderer.png( options );
+ },
+
+ jpg: function( options ){
+ var renderer = this._private.renderer;
+ options = options || {};
+
+ options.bg = options.bg || '#fff';
+
+ return renderer.jpg( options );
+ }
+
+});
+
+corefn.jpeg = corefn.jpg;
+
+module.exports = corefn;
+
+},{}],34:[function(_dereq_,module,exports){
+'use strict';
+
+var window = _dereq_('../window');
+var util = _dereq_('../util');
+var Collection = _dereq_('../collection');
+var is = _dereq_('../is');
+var Promise = _dereq_('../promise');
+var define = _dereq_('../define');
+
+var Core = function( opts ){
+ if( !(this instanceof Core) ){
+ return new Core(opts);
+ }
+ var cy = this;
+
+ opts = util.extend({}, opts);
+
+ var container = opts.container;
+
+ // allow for passing a wrapped jquery object
+ // e.g. cytoscape({ container: $('#cy') })
+ if( container && !is.htmlElement( container ) && is.htmlElement( container[0] ) ){
+ container = container[0];
+ }
+
+ var reg = container ? container._cyreg : null; // e.g. already registered some info (e.g. readies) via jquery
+ reg = reg || {};
+
+ if( reg && reg.cy ){
+ reg.cy.destroy();
+
+ reg = {}; // old instance => replace reg completely
+ }
+
+ var readies = reg.readies = reg.readies || [];
+
+ if( container ){ container._cyreg = reg; } // make sure container assoc'd reg points to this cy
+ reg.cy = cy;
+
+ var head = window !== undefined && container !== undefined && !opts.headless;
+ var options = opts;
+ options.layout = util.extend( { name: head ? 'grid' : 'null' }, options.layout );
+ options.renderer = util.extend( { name: head ? 'canvas' : 'null' }, options.renderer );
+
+ var defVal = function( def, val, altVal ){
+ if( val !== undefined ){
+ return val;
+ } else if( altVal !== undefined ){
+ return altVal;
+ } else {
+ return def;
+ }
+ };
+
+ var _p = this._private = {
+ container: container, // html dom ele container
+ ready: false, // whether ready has been triggered
+ initrender: false, // has initrender has been triggered
+ options: options, // cached options
+ elements: [], // array of elements
+ id2index: {}, // element id => index in elements array
+ listeners: [], // list of listeners
+ onRenders: [], // rendering listeners
+ aniEles: Collection(this), // elements being animated
+ scratch: {}, // scratch object for core
+ layout: null,
+ renderer: null,
+ notificationsEnabled: true, // whether notifications are sent to the renderer
+ minZoom: 1e-50,
+ maxZoom: 1e50,
+ zoomingEnabled: defVal(true, options.zoomingEnabled),
+ userZoomingEnabled: defVal(true, options.userZoomingEnabled),
+ panningEnabled: defVal(true, options.panningEnabled),
+ userPanningEnabled: defVal(true, options.userPanningEnabled),
+ boxSelectionEnabled: defVal(true, options.boxSelectionEnabled),
+ autolock: defVal(false, options.autolock, options.autolockNodes),
+ autoungrabify: defVal(false, options.autoungrabify, options.autoungrabifyNodes),
+ autounselectify: defVal(false, options.autounselectify),
+ styleEnabled: options.styleEnabled === undefined ? head : options.styleEnabled,
+ zoom: is.number(options.zoom) ? options.zoom : 1,
+ pan: {
+ x: is.plainObject(options.pan) && is.number(options.pan.x) ? options.pan.x : 0,
+ y: is.plainObject(options.pan) && is.number(options.pan.y) ? options.pan.y : 0
+ },
+ animation: { // object for currently-running animations
+ current: [],
+ queue: []
+ },
+ hasCompoundNodes: false,
+ deferredExecQueue: []
+ };
+
+ // set selection type
+ var selType = options.selectionType;
+ if( selType === undefined || (selType !== 'additive' && selType !== 'single') ){
+ // then set default
+
+ _p.selectionType = 'single';
+ } else {
+ _p.selectionType = selType;
+ }
+
+ // init zoom bounds
+ if( is.number(options.minZoom) && is.number(options.maxZoom) && options.minZoom < options.maxZoom ){
+ _p.minZoom = options.minZoom;
+ _p.maxZoom = options.maxZoom;
+ } else if( is.number(options.minZoom) && options.maxZoom === undefined ){
+ _p.minZoom = options.minZoom;
+ } else if( is.number(options.maxZoom) && options.minZoom === undefined ){
+ _p.maxZoom = options.maxZoom;
+ }
+
+ var loadExtData = function( next ){
+ var anyIsPromise = false;
+
+ for( var i = 0; i < extData.length; i++ ){
+ var datum = extData[i];
+
+ if( is.promise(datum) ){
+ anyIsPromise = true;
+ break;
+ }
+ }
+
+ if( anyIsPromise ){
+ return Promise.all( extData ).then( next ); // load all data asynchronously, then exec rest of init
+ } else {
+ next( extData ); // exec synchronously for convenience
+ }
+ };
+
+ // create the renderer
+ cy.initRenderer( util.extend({
+ hideEdgesOnViewport: options.hideEdgesOnViewport,
+ hideLabelsOnViewport: options.hideLabelsOnViewport,
+ textureOnViewport: options.textureOnViewport,
+ wheelSensitivity: is.number(options.wheelSensitivity) && options.wheelSensitivity > 0 ? options.wheelSensitivity : 1,
+ motionBlur: options.motionBlur === undefined ? true : options.motionBlur, // on by default
+ motionBlurOpacity: options.motionBlurOpacity === undefined ? 0.05 : options.motionBlurOpacity,
+ pixelRatio: is.number(options.pixelRatio) && options.pixelRatio > 0 ? options.pixelRatio : (options.pixelRatio === 'auto' ? undefined : 1),
+ desktopTapThreshold: options.desktopTapThreshold === undefined ? 4 : options.desktopTapThreshold,
+ touchTapThreshold: options.touchTapThreshold === undefined ? 8 : options.touchTapThreshold
+ }, options.renderer) );
+
+ var extData = [ options.style, options.elements ];
+ loadExtData(function( thens ){
+ var initStyle = thens[0];
+ var initEles = thens[1];
+
+ // init style
+ if( _p.styleEnabled ){
+ cy.setStyle( initStyle );
+ }
+
+ // trigger the passed function for the `initrender` event
+ if( options.initrender ){
+ cy.on('initrender', options.initrender);
+ cy.on('initrender', function(){
+ _p.initrender = true;
+ });
+ }
+
+ // initial load
+ cy.load(initEles, function(){ // onready
+ cy.startAnimationLoop();
+ _p.ready = true;
+
+ // if a ready callback is specified as an option, the bind it
+ if( is.fn( options.ready ) ){
+ cy.on('ready', options.ready);
+ }
+
+ // bind all the ready handlers registered before creating this instance
+ for( var i = 0; i < readies.length; i++ ){
+ var fn = readies[i];
+ cy.on('ready', fn);
+ }
+ if( reg ){ reg.readies = []; } // clear b/c we've bound them all and don't want to keep it around in case a new core uses the same div etc
+
+ cy.trigger('ready');
+ }, options.done);
+
+ });
+};
+
+var corefn = Core.prototype; // short alias
+
+util.extend(corefn, {
+ instanceString: function(){
+ return 'core';
+ },
+
+ isReady: function(){
+ return this._private.ready;
+ },
+
+ ready: function( fn ){
+ if( this.isReady() ){
+ this.trigger('ready', [], fn); // just calls fn as though triggered via ready event
+ } else {
+ this.on('ready', fn);
+ }
+
+ return this;
+ },
+
+ initrender: function(){
+ return this._private.initrender;
+ },
+
+ destroy: function(){
+ var cy = this;
+
+ cy.stopAnimationLoop();
+
+ cy.notify({ type: 'destroy' }); // destroy the renderer
+
+ var domEle = cy.container();
+ if( domEle ){
+ domEle._cyreg = null;
+
+ while( domEle.childNodes.length > 0 ){
+ domEle.removeChild( domEle.childNodes[0] );
+ }
+ }
+
+ return cy;
+ },
+
+ getElementById: function( id ){
+ var index = this._private.id2index[ id ];
+ if( index !== undefined ){
+ return this._private.elements[ index ];
+ }
+
+ // worst case, return an empty collection
+ return Collection( this );
+ },
+
+ selectionType: function(){
+ return this._private.selectionType;
+ },
+
+ hasCompoundNodes: function(){
+ return this._private.hasCompoundNodes;
+ },
+
+ styleEnabled: function(){
+ return this._private.styleEnabled;
+ },
+
+ addToPool: function( eles ){
+ var elements = this._private.elements;
+ var id2index = this._private.id2index;
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+
+ var id = ele._private.data.id;
+ var index = id2index[ id ];
+ var alreadyInPool = index !== undefined;
+
+ if( !alreadyInPool ){
+ index = elements.length;
+ elements.push( ele );
+ id2index[ id ] = index;
+ ele._private.index = index;
+ }
+ }
+
+ return this; // chaining
+ },
+
+ removeFromPool: function( eles ){
+ var elements = this._private.elements;
+ var id2index = this._private.id2index;
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+
+ var id = ele._private.data.id;
+ var index = id2index[ id ];
+ var inPool = index !== undefined;
+
+ if( inPool ){
+ this._private.id2index[ id ] = undefined;
+ elements.splice(index, 1);
+
+ // adjust the index of all elements past this index
+ for( var j = index; j < elements.length; j++ ){
+ var jid = elements[j]._private.data.id;
+ id2index[ jid ]--;
+ elements[j]._private.index--;
+ }
+ }
+ }
+ },
+
+ container: function(){
+ return this._private.container;
+ },
+
+ options: function(){
+ return util.copy( this._private.options );
+ },
+
+ json: function( obj ){
+ var cy = this;
+ var _p = cy._private;
+
+ if( is.plainObject(obj) ){ // set
+
+ cy.startBatch();
+
+ if( obj.elements ){
+ var idInJson = {};
+
+ var updateEles = function( jsons, gr ){
+ for( var i = 0; i < jsons.length; i++ ){
+ var json = jsons[i];
+ var id = json.data.id;
+ var ele = cy.getElementById( id );
+
+ idInJson[ id ] = true;
+
+ if( ele.length !== 0 ){ // existing element should be updated
+ ele.json( json );
+ } else { // otherwise should be added
+ if( gr ){
+ cy.add( util.extend({ group: gr }, json) );
+ } else {
+ cy.add( json );
+ }
+ }
+ }
+ };
+
+ if( is.array(obj.elements) ){ // elements: []
+ updateEles( obj.elements );
+
+ } else { // elements: { nodes: [], edges: [] }
+ var grs = ['nodes', 'edges'];
+ for( var i = 0; i < grs.length; i++ ){
+ var gr = grs[i];
+ var elements = obj.elements[ gr ];
+
+ if( is.array(elements) ){
+ updateEles( elements, gr );
+ }
+ }
+ }
+
+ // elements not specified in json should be removed
+ cy.elements().stdFilter(function( ele ){
+ return !idInJson[ ele.id() ];
+ }).remove();
+ }
+
+ if( obj.style ){
+ cy.style( obj.style );
+ }
+
+ if( obj.zoom != null && obj.zoom !== _p.zoom ){
+ cy.zoom( obj.zoom );
+ }
+
+ if( obj.pan ){
+ if( obj.pan.x !== _p.pan.x || obj.pan.y !== _p.pan.y ){
+ cy.pan( obj.pan );
+ }
+ }
+
+ var fields = [
+ 'minZoom', 'maxZoom', 'zoomingEnabled', 'userZoomingEnabled',
+ 'panningEnabled', 'userPanningEnabled',
+ 'boxSelectionEnabled',
+ 'autolock', 'autoungrabify', 'autounselectify'
+ ];
+
+ for( var i = 0; i < fields.length; i++ ){
+ var f = fields[i];
+
+ if( obj[f] != null ){
+ cy[f]( obj[f] );
+ }
+ }
+
+ cy.endBatch();
+
+ return this; // chaining
+ } else if( obj === undefined ){ // get
+ var json = {};
+
+ json.elements = {};
+ cy.elements().each(function(i, ele){
+ var group = ele.group();
+
+ if( !json.elements[group] ){
+ json.elements[group] = [];
+ }
+
+ json.elements[group].push( ele.json() );
+ });
+
+ if( this._private.styleEnabled ){
+ json.style = cy.style().json();
+ }
+
+ json.zoomingEnabled = cy._private.zoomingEnabled;
+ json.userZoomingEnabled = cy._private.userZoomingEnabled;
+ json.zoom = cy._private.zoom;
+ json.minZoom = cy._private.minZoom;
+ json.maxZoom = cy._private.maxZoom;
+ json.panningEnabled = cy._private.panningEnabled;
+ json.userPanningEnabled = cy._private.userPanningEnabled;
+ json.pan = util.copy( cy._private.pan );
+ json.boxSelectionEnabled = cy._private.boxSelectionEnabled;
+ json.renderer = util.copy( cy._private.options.renderer );
+ json.hideEdgesOnViewport = cy._private.options.hideEdgesOnViewport;
+ json.hideLabelsOnViewport = cy._private.options.hideLabelsOnViewport;
+ json.textureOnViewport = cy._private.options.textureOnViewport;
+ json.wheelSensitivity = cy._private.options.wheelSensitivity;
+ json.motionBlur = cy._private.options.motionBlur;
+
+ return json;
+ }
+ },
+
+ scratch: define.data({
+ field: 'scratch',
+ bindingEvent: 'scratch',
+ allowBinding: true,
+ allowSetting: true,
+ settingEvent: 'scratch',
+ settingTriggersEvent: true,
+ triggerFnName: 'trigger',
+ allowGetting: true
+ }),
+
+ removeScratch: define.removeData({
+ field: 'scratch',
+ event: 'scratch',
+ triggerFnName: 'trigger',
+ triggerEvent: true
+ })
+
+});
+
+[
+ _dereq_('./add-remove'),
+ _dereq_('./animation'),
+ _dereq_('./events'),
+ _dereq_('./export'),
+ _dereq_('./layout'),
+ _dereq_('./notification'),
+ _dereq_('./renderer'),
+ _dereq_('./search'),
+ _dereq_('./style'),
+ _dereq_('./viewport')
+].forEach(function( props ){
+ util.extend( corefn, props );
+});
+
+module.exports = Core;
+
+},{"../collection":23,"../define":41,"../is":77,"../promise":80,"../util":94,"../window":100,"./add-remove":30,"./animation":31,"./events":32,"./export":33,"./layout":35,"./notification":36,"./renderer":37,"./search":38,"./style":39,"./viewport":40}],35:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+var is = _dereq_('../is');
+
+var corefn = ({
+
+ layout: function( params ){
+ var layout = this._private.prevLayout = ( params == null ? this._private.prevLayout : this.makeLayout( params ) );
+
+ layout.run();
+
+ return this; // chaining
+ },
+
+ makeLayout: function( options ){
+ var cy = this;
+
+ if( options == null ){
+ util.error('Layout options must be specified to make a layout');
+ return;
+ }
+
+ if( options.name == null ){
+ util.error('A `name` must be specified to make a layout');
+ return;
+ }
+
+ var name = options.name;
+ var Layout = cy.extension('layout', name);
+
+ if( Layout == null ){
+ util.error('Can not apply layout: No such layout `' + name + '` found; did you include its JS file?');
+ return;
+ }
+
+ var eles;
+ if( is.string( options.eles ) ){
+ eles = cy.$( options.eles );
+ } else {
+ eles = options.eles != null ? options.eles : cy.$();
+ }
+
+ var layout = new Layout( util.extend({}, options, {
+ cy: cy,
+ eles: eles
+ }) );
+
+ return layout;
+ }
+
+});
+
+corefn.createLayout = corefn.makeLayout;
+
+module.exports = corefn;
+
+},{"../is":77,"../util":94}],36:[function(_dereq_,module,exports){
+'use strict';
+
+var corefn = ({
+ notify: function( params ){
+ var _p = this._private;
+
+ if( _p.batchingNotify ){
+ var bEles = _p.batchNotifyEles;
+ var bTypes = _p.batchNotifyTypes;
+
+ if( params.collection ){
+ bEles.merge( params.collection );
+ }
+
+ if( !bTypes.ids[ params.type ] ){
+ bTypes.push( params.type );
+ }
+
+ return; // notifications are disabled during batching
+ }
+
+ if( !_p.notificationsEnabled ){ return; } // exit on disabled
+
+ var renderer = this.renderer();
+
+ renderer.notify(params);
+ },
+
+ notifications: function( bool ){
+ var p = this._private;
+
+ if( bool === undefined ){
+ return p.notificationsEnabled;
+ } else {
+ p.notificationsEnabled = bool ? true : false;
+ }
+ },
+
+ noNotifications: function( callback ){
+ this.notifications(false);
+ callback();
+ this.notifications(true);
+ },
+
+ startBatch: function(){
+ var _p = this._private;
+
+ if( _p.batchCount == null ){
+ _p.batchCount = 0;
+ }
+
+ if( _p.batchCount === 0 ){
+ _p.batchingStyle = _p.batchingNotify = true;
+ _p.batchStyleEles = this.collection();
+ _p.batchNotifyEles = this.collection();
+ _p.batchNotifyTypes = [];
+
+ _p.batchNotifyTypes.ids = {};
+ }
+
+ _p.batchCount++;
+
+ return this;
+ },
+
+ endBatch: function(){
+ var _p = this._private;
+
+ _p.batchCount--;
+
+ if( _p.batchCount === 0 ){
+ // update style for dirty eles
+ _p.batchingStyle = false;
+ _p.batchStyleEles.updateStyle();
+
+ // notify the renderer of queued eles and event types
+ _p.batchingNotify = false;
+ this.notify({
+ type: _p.batchNotifyTypes,
+ collection: _p.batchNotifyEles
+ });
+ }
+
+ return this;
+ },
+
+ batch: function( callback ){
+ this.startBatch();
+ callback();
+ this.endBatch();
+
+ return this;
+ },
+
+ // for backwards compatibility
+ batchData: function( map ){
+ var cy = this;
+
+ return this.batch(function(){
+ for( var id in map ){
+ var data = map[id];
+ var ele = cy.getElementById( id );
+
+ ele.data( data );
+ }
+ });
+ }
+});
+
+module.exports = corefn;
+
+},{}],37:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+
+var corefn = ({
+
+ renderTo: function( context, zoom, pan, pxRatio ){
+ var r = this._private.renderer;
+
+ r.renderTo( context, zoom, pan, pxRatio );
+ return this;
+ },
+
+ renderer: function(){
+ return this._private.renderer;
+ },
+
+ forceRender: function(){
+ this.notify({
+ type: 'draw'
+ });
+
+ return this;
+ },
+
+ resize: function(){
+ this.notify({
+ type: 'resize'
+ });
+
+ this.trigger('resize');
+
+ return this;
+ },
+
+ initRenderer: function( options ){
+ var cy = this;
+
+ var RendererProto = cy.extension('renderer', options.name);
+ if( RendererProto == null ){
+ util.error('Can not initialise: No such renderer `%s` found; did you include its JS file?', options.name);
+ return;
+ }
+
+ var rOpts = util.extend({}, options, {
+ cy: cy
+ });
+ var renderer = cy._private.renderer = new RendererProto( rOpts );
+
+ renderer.init( rOpts );
+
+ },
+
+ triggerOnRender: function(){
+ var cbs = this._private.onRenders;
+
+ for( var i = 0; i < cbs.length; i++ ){
+ var cb = cbs[i];
+
+ cb();
+ }
+
+ return this;
+ },
+
+ onRender: function( cb ){
+ this._private.onRenders.push( cb );
+
+ return this;
+ },
+
+ offRender: function( fn ){
+ var cbs = this._private.onRenders;
+
+ if( fn == null ){ // unbind all
+ this._private.onRenders = [];
+ return this;
+ }
+
+ for( var i = 0; i < cbs.length; i++ ){ // unbind specified
+ var cb = cbs[i];
+
+ if( fn === cb ){
+ cbs.splice( i, 1 );
+ break;
+ }
+ }
+
+ return this;
+ }
+
+});
+
+corefn.invalidateDimensions = corefn.resize;
+
+module.exports = corefn;
+
+},{"../util":94}],38:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+var Collection = _dereq_('../collection');
+
+var corefn = ({
+
+ // get a collection
+ // - empty collection on no args
+ // - collection of elements in the graph on selector arg
+ // - guarantee a returned collection when elements or collection specified
+ collection: function( eles, opts ){
+
+ if( is.string( eles ) ){
+ return this.$( eles );
+
+ } else if( is.elementOrCollection( eles ) ){
+ return eles.collection();
+
+ } else if( is.array( eles ) ){
+ return Collection( this, eles, opts );
+ }
+
+ return Collection( this );
+ },
+
+ nodes: function( selector ){
+ var nodes = this.$(function(){
+ return this.isNode();
+ });
+
+ if( selector ){
+ return nodes.filter( selector );
+ }
+
+ return nodes;
+ },
+
+ edges: function( selector ){
+ var edges = this.$(function(){
+ return this.isEdge();
+ });
+
+ if( selector ){
+ return edges.filter( selector );
+ }
+
+ return edges;
+ },
+
+ // search the graph like jQuery
+ $: function( selector ){
+ var eles = new Collection( this, this._private.elements );
+
+ if( selector ){
+ return eles.filter( selector );
+ }
+
+ return eles;
+ }
+
+});
+
+// aliases
+corefn.elements = corefn.filter = corefn.$;
+
+module.exports = corefn;
+
+},{"../collection":23,"../is":77}],39:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+var Style = _dereq_('../style');
+
+var corefn = ({
+
+ style: function( newStyle ){
+ if( newStyle ){
+ var s = this.setStyle( newStyle );
+
+ s.update();
+ }
+
+ return this._private.style;
+ },
+
+ setStyle: function( style ){
+ var _p = this._private;
+
+ if( is.stylesheet(style) ){
+ _p.style = style.generateStyle(this);
+
+ } else if( is.array(style) ) {
+ _p.style = Style.fromJson(this, style);
+
+ } else if( is.string(style) ){
+ _p.style = Style.fromString(this, style);
+
+ } else {
+ _p.style = Style( this );
+ }
+
+ return _p.style;
+ }
+});
+
+module.exports = corefn;
+
+},{"../is":77,"../style":86}],40:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+
+var corefn = ({
+
+ autolock: function(bool){
+ if( bool !== undefined ){
+ this._private.autolock = bool ? true : false;
+ } else {
+ return this._private.autolock;
+ }
+
+ return this; // chaining
+ },
+
+ autoungrabify: function(bool){
+ if( bool !== undefined ){
+ this._private.autoungrabify = bool ? true : false;
+ } else {
+ return this._private.autoungrabify;
+ }
+
+ return this; // chaining
+ },
+
+ autounselectify: function(bool){
+ if( bool !== undefined ){
+ this._private.autounselectify = bool ? true : false;
+ } else {
+ return this._private.autounselectify;
+ }
+
+ return this; // chaining
+ },
+
+ panningEnabled: function( bool ){
+ if( bool !== undefined ){
+ this._private.panningEnabled = bool ? true : false;
+ } else {
+ return this._private.panningEnabled;
+ }
+
+ return this; // chaining
+ },
+
+ userPanningEnabled: function( bool ){
+ if( bool !== undefined ){
+ this._private.userPanningEnabled = bool ? true : false;
+ } else {
+ return this._private.userPanningEnabled;
+ }
+
+ return this; // chaining
+ },
+
+ zoomingEnabled: function( bool ){
+ if( bool !== undefined ){
+ this._private.zoomingEnabled = bool ? true : false;
+ } else {
+ return this._private.zoomingEnabled;
+ }
+
+ return this; // chaining
+ },
+
+ userZoomingEnabled: function( bool ){
+ if( bool !== undefined ){
+ this._private.userZoomingEnabled = bool ? true : false;
+ } else {
+ return this._private.userZoomingEnabled;
+ }
+
+ return this; // chaining
+ },
+
+ boxSelectionEnabled: function( bool ){
+ if( bool !== undefined ){
+ this._private.boxSelectionEnabled = bool ? true : false;
+ } else {
+ return this._private.boxSelectionEnabled;
+ }
+
+ return this; // chaining
+ },
+
+ pan: function(){
+ var args = arguments;
+ var pan = this._private.pan;
+ var dim, val, dims, x, y;
+
+ switch( args.length ){
+ case 0: // .pan()
+ return pan;
+
+ case 1:
+
+ if( is.string( args[0] ) ){ // .pan('x')
+ dim = args[0];
+ return pan[ dim ];
+
+ } else if( is.plainObject( args[0] ) ) { // .pan({ x: 0, y: 100 })
+ if( !this._private.panningEnabled ){
+ return this;
+ }
+
+ dims = args[0];
+ x = dims.x;
+ y = dims.y;
+
+ if( is.number(x) ){
+ pan.x = x;
+ }
+
+ if( is.number(y) ){
+ pan.y = y;
+ }
+
+ this.trigger('pan viewport');
+ }
+ break;
+
+ case 2: // .pan('x', 100)
+ if( !this._private.panningEnabled ){
+ return this;
+ }
+
+ dim = args[0];
+ val = args[1];
+
+ if( (dim === 'x' || dim === 'y') && is.number(val) ){
+ pan[dim] = val;
+ }
+
+ this.trigger('pan viewport');
+ break;
+
+ default:
+ break; // invalid
+ }
+
+ this.notify({ // notify the renderer that the viewport changed
+ type: 'viewport'
+ });
+
+ return this; // chaining
+ },
+
+ panBy: function(params){
+ var args = arguments;
+ var pan = this._private.pan;
+ var dim, val, dims, x, y;
+
+ if( !this._private.panningEnabled ){
+ return this;
+ }
+
+ switch( args.length ){
+ case 1:
+
+ if( is.plainObject( args[0] ) ) { // .panBy({ x: 0, y: 100 })
+ dims = args[0];
+ x = dims.x;
+ y = dims.y;
+
+ if( is.number(x) ){
+ pan.x += x;
+ }
+
+ if( is.number(y) ){
+ pan.y += y;
+ }
+
+ this.trigger('pan viewport');
+ }
+ break;
+
+ case 2: // .panBy('x', 100)
+ dim = args[0];
+ val = args[1];
+
+ if( (dim === 'x' || dim === 'y') && is.number(val) ){
+ pan[dim] += val;
+ }
+
+ this.trigger('pan viewport');
+ break;
+
+ default:
+ break; // invalid
+ }
+
+ this.notify({ // notify the renderer that the viewport changed
+ type: 'viewport'
+ });
+
+ return this; // chaining
+ },
+
+ fit: function( elements, padding ){
+ var viewportState = this.getFitViewport( elements, padding );
+
+ if( viewportState ){
+ var _p = this._private;
+ _p.zoom = viewportState.zoom;
+ _p.pan = viewportState.pan;
+
+ this.trigger('pan zoom viewport');
+
+ this.notify({ // notify the renderer that the viewport changed
+ type: 'viewport'
+ });
+ }
+
+ return this; // chaining
+ },
+
+ getFitViewport: function( elements, padding ){
+ if( is.number(elements) && padding === undefined ){ // elements is optional
+ padding = elements;
+ elements = undefined;
+ }
+
+ if( !this._private.panningEnabled || !this._private.zoomingEnabled ){
+ return;
+ }
+
+ var bb;
+
+ if( is.string(elements) ){
+ var sel = elements;
+ elements = this.$( sel );
+
+ } else if( is.boundingBox(elements) ){ // assume bb
+ var bbe = elements;
+ bb = {
+ x1: bbe.x1,
+ y1: bbe.y1,
+ x2: bbe.x2,
+ y2: bbe.y2
+ };
+
+ bb.w = bb.x2 - bb.x1;
+ bb.h = bb.y2 - bb.y1;
+
+ } else if( !is.elementOrCollection(elements) ){
+ elements = this.elements();
+ }
+
+ bb = bb || elements.boundingBox();
+
+ var w = this.width();
+ var h = this.height();
+ var zoom;
+ padding = is.number(padding) ? padding : 0;
+
+ if( !isNaN(w) && !isNaN(h) && w > 0 && h > 0 && !isNaN(bb.w) && !isNaN(bb.h) && bb.w > 0 && bb.h > 0 ){
+ zoom = Math.min( (w - 2*padding)/bb.w, (h - 2*padding)/bb.h );
+
+ // crop zoom
+ zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom;
+ zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom;
+
+ var pan = { // now pan to middle
+ x: (w - zoom*( bb.x1 + bb.x2 ))/2,
+ y: (h - zoom*( bb.y1 + bb.y2 ))/2
+ };
+
+ return {
+ zoom: zoom,
+ pan: pan
+ };
+ }
+
+ return;
+ },
+
+ minZoom: function( zoom ){
+ if( zoom === undefined ){
+ return this._private.minZoom;
+ } else if( is.number(zoom) ){
+ this._private.minZoom = zoom;
+ }
+
+ return this;
+ },
+
+ maxZoom: function( zoom ){
+ if( zoom === undefined ){
+ return this._private.maxZoom;
+ } else if( is.number(zoom) ){
+ this._private.maxZoom = zoom;
+ }
+
+ return this;
+ },
+
+ zoom: function( params ){
+ var pos; // in rendered px
+ var zoom;
+
+ if( params === undefined ){ // then get the zoom
+ return this._private.zoom;
+
+ } else if( is.number(params) ){ // then set the zoom
+ zoom = params;
+
+ } else if( is.plainObject(params) ){ // then zoom about a point
+ zoom = params.level;
+
+ if( params.position ){
+ var p = params.position;
+ var pan = this._private.pan;
+ var z = this._private.zoom;
+
+ pos = { // convert to rendered px
+ x: p.x * z + pan.x,
+ y: p.y * z + pan.y
+ };
+ } else if( params.renderedPosition ){
+ pos = params.renderedPosition;
+ }
+
+ if( pos && !this._private.panningEnabled ){
+ return this; // panning disabled
+ }
+ }
+
+ if( !this._private.zoomingEnabled ){
+ return this; // zooming disabled
+ }
+
+ if( !is.number(zoom) || ( pos && (!is.number(pos.x) || !is.number(pos.y)) ) ){
+ return this; // can't zoom with invalid params
+ }
+
+ // crop zoom
+ zoom = zoom > this._private.maxZoom ? this._private.maxZoom : zoom;
+ zoom = zoom < this._private.minZoom ? this._private.minZoom : zoom;
+
+ if( pos ){ // set zoom about position
+ var pan1 = this._private.pan;
+ var zoom1 = this._private.zoom;
+ var zoom2 = zoom;
+
+ var pan2 = {
+ x: -zoom2/zoom1 * (pos.x - pan1.x) + pos.x,
+ y: -zoom2/zoom1 * (pos.y - pan1.y) + pos.y
+ };
+
+ this._private.zoom = zoom;
+ this._private.pan = pan2;
+
+ var posChanged = pan1.x !== pan2.x || pan1.y !== pan2.y;
+ this.trigger(' zoom ' + (posChanged ? ' pan ' : '') + ' viewport ' );
+
+ } else { // just set the zoom
+ this._private.zoom = zoom;
+ this.trigger('zoom viewport');
+ }
+
+ this.notify({ // notify the renderer that the viewport changed
+ type: 'viewport'
+ });
+
+ return this; // chaining
+ },
+
+ viewport: function( opts ){
+ var _p = this._private;
+ var zoomDefd = true;
+ var panDefd = true;
+ var events = []; // to trigger
+ var zoomFailed = false;
+ var panFailed = false;
+
+ if( !opts ){ return this; }
+ if( !is.number(opts.zoom) ){ zoomDefd = false; }
+ if( !is.plainObject(opts.pan) ){ panDefd = false; }
+ if( !zoomDefd && !panDefd ){ return this; }
+
+ if( zoomDefd ){
+ var z = opts.zoom;
+
+ if( z < _p.minZoom || z > _p.maxZoom || !_p.zoomingEnabled ){
+ zoomFailed = true;
+
+ } else {
+ _p.zoom = z;
+
+ events.push('zoom');
+ }
+ }
+
+ if( panDefd && (!zoomFailed || !opts.cancelOnFailedZoom) && _p.panningEnabled ){
+ var p = opts.pan;
+
+ if( is.number(p.x) ){
+ _p.pan.x = p.x;
+ panFailed = false;
+ }
+
+ if( is.number(p.y) ){
+ _p.pan.y = p.y;
+ panFailed = false;
+ }
+
+ if( !panFailed ){
+ events.push('pan');
+ }
+ }
+
+ if( events.length > 0 ){
+ events.push('viewport');
+ this.trigger( events.join(' ') );
+
+ this.notify({
+ type: 'viewport'
+ });
+ }
+
+ return this; // chaining
+ },
+
+ center: function( elements ){
+ var pan = this.getCenterPan( elements );
+
+ if( pan ){
+ this._private.pan = pan;
+
+ this.trigger('pan viewport');
+
+ this.notify({ // notify the renderer that the viewport changed
+ type: 'viewport'
+ });
+ }
+
+ return this; // chaining
+ },
+
+ getCenterPan: function( elements, zoom ){
+ if( !this._private.panningEnabled ){
+ return;
+ }
+
+ if( is.string(elements) ){
+ var selector = elements;
+ elements = this.elements( selector );
+ } else if( !is.elementOrCollection(elements) ){
+ elements = this.elements();
+ }
+
+ var bb = elements.boundingBox();
+ var w = this.width();
+ var h = this.height();
+ zoom = zoom === undefined ? this._private.zoom : zoom;
+
+ var pan = { // middle
+ x: (w - zoom*( bb.x1 + bb.x2 ))/2,
+ y: (h - zoom*( bb.y1 + bb.y2 ))/2
+ };
+
+ return pan;
+ },
+
+ reset: function(){
+ if( !this._private.panningEnabled || !this._private.zoomingEnabled ){
+ return this;
+ }
+
+ this.viewport({
+ pan: { x: 0, y: 0 },
+ zoom: 1
+ });
+
+ return this; // chaining
+ },
+
+ width: function(){
+ var container = this._private.container;
+
+ if( container ){
+ return container.clientWidth;
+ }
+
+ return 1; // fallback if no container (not 0 b/c can be used for dividing etc)
+ },
+
+ height: function(){
+ var container = this._private.container;
+
+ if( container ){
+ return container.clientHeight;
+ }
+
+ return 1; // fallback if no container (not 0 b/c can be used for dividing etc)
+ },
+
+ extent: function(){
+ var pan = this._private.pan;
+ var zoom = this._private.zoom;
+ var rb = this.renderedExtent();
+
+ var b = {
+ x1: ( rb.x1 - pan.x )/zoom,
+ x2: ( rb.x2 - pan.x )/zoom,
+ y1: ( rb.y1 - pan.y )/zoom,
+ y2: ( rb.y2 - pan.y )/zoom,
+ };
+
+ b.w = b.x2 - b.x1;
+ b.h = b.y2 - b.y1;
+
+ return b;
+ },
+
+ renderedExtent: function(){
+ var width = this.width();
+ var height = this.height();
+
+ return {
+ x1: 0,
+ y1: 0,
+ x2: width,
+ y2: height,
+ w: width,
+ h: height
+ };
+ }
+});
+
+// aliases
+corefn.centre = corefn.center;
+
+// backwards compatibility
+corefn.autolockNodes = corefn.autolock;
+corefn.autoungrabifyNodes = corefn.autoungrabify;
+
+module.exports = corefn;
+
+},{"../is":77}],41:[function(_dereq_,module,exports){
+'use strict';
+
+// use this module to cherry pick functions into your prototype
+// (useful for functions shared between the core and collections, for example)
+
+// e.g.
+// var foo = define.foo({ /* params... */ })
+
+var util = _dereq_('./util');
+var is = _dereq_('./is');
+var Selector = _dereq_('./selector');
+var Promise = _dereq_('./promise');
+var Event = _dereq_('./event');
+var Animation = _dereq_('./animation');
+
+var define = {
+
+ // access data field
+ data: function( params ){
+ var defaults = {
+ field: 'data',
+ bindingEvent: 'data',
+ allowBinding: false,
+ allowSetting: false,
+ allowGetting: false,
+ settingEvent: 'data',
+ settingTriggersEvent: false,
+ triggerFnName: 'trigger',
+ immutableKeys: {}, // key => true if immutable
+ updateStyle: false,
+ onSet: function( self ){},
+ canSet: function( self ){ return true; }
+ };
+ params = util.extend({}, defaults, params);
+
+ return function dataImpl( name, value ){
+ var p = params;
+ var self = this;
+ var selfIsArrayLike = self.length !== undefined;
+ var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
+ var single = selfIsArrayLike ? self[0] : self;
+
+ // .data('foo', ...)
+ if( is.string(name) ){ // set or get property
+
+ // .data('foo')
+ if( p.allowGetting && value === undefined ){ // get
+
+ var ret;
+ if( single ){
+ ret = single._private[ p.field ][ name ];
+ }
+ return ret;
+
+ // .data('foo', 'bar')
+ } else if( p.allowSetting && value !== undefined ) { // set
+ var valid = !p.immutableKeys[name];
+ if( valid ){
+ for( var i = 0, l = all.length; i < l; i++ ){
+ if( p.canSet( all[i] ) ){
+ all[i]._private[ p.field ][ name ] = value;
+ }
+ }
+
+ // update mappers if asked
+ if( p.updateStyle ){ self.updateStyle(); }
+
+ // call onSet callback
+ p.onSet( self );
+
+ if( p.settingTriggersEvent ){
+ self[ p.triggerFnName ]( p.settingEvent );
+ }
+ }
+ }
+
+ // .data({ 'foo': 'bar' })
+ } else if( p.allowSetting && is.plainObject(name) ){ // extend
+ var obj = name;
+ var k, v;
+
+ for( k in obj ){
+ v = obj[ k ];
+
+ var valid = !p.immutableKeys[k];
+ if( valid ){
+ for( var i = 0, l = all.length; i < l; i++ ){
+ if( p.canSet( all[i] ) ){
+ all[i]._private[ p.field ][ k ] = v;
+ }
+ }
+ }
+ }
+
+ // update mappers if asked
+ if( p.updateStyle ){ self.updateStyle(); }
+
+ // call onSet callback
+ p.onSet( self );
+
+ if( p.settingTriggersEvent ){
+ self[ p.triggerFnName ]( p.settingEvent );
+ }
+
+ // .data(function(){ ... })
+ } else if( p.allowBinding && is.fn(name) ){ // bind to event
+ var fn = name;
+ self.bind( p.bindingEvent, fn );
+
+ // .data()
+ } else if( p.allowGetting && name === undefined ){ // get whole object
+ var ret;
+ if( single ){
+ ret = single._private[ p.field ];
+ }
+ return ret;
+ }
+
+ return self; // maintain chainability
+ }; // function
+ }, // data
+
+ // remove data field
+ removeData: function( params ){
+ var defaults = {
+ field: 'data',
+ event: 'data',
+ triggerFnName: 'trigger',
+ triggerEvent: false,
+ immutableKeys: {} // key => true if immutable
+ };
+ params = util.extend({}, defaults, params);
+
+ return function removeDataImpl( names ){
+ var p = params;
+ var self = this;
+ var selfIsArrayLike = self.length !== undefined;
+ var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
+
+ // .removeData('foo bar')
+ if( is.string(names) ){ // then get the list of keys, and delete them
+ var keys = names.split(/\s+/);
+ var l = keys.length;
+
+ for( var i = 0; i < l; i++ ){ // delete each non-empty key
+ var key = keys[i];
+ if( is.emptyString(key) ){ continue; }
+
+ var valid = !p.immutableKeys[ key ]; // not valid if immutable
+ if( valid ){
+ for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){
+ all[ i_a ]._private[ p.field ][ key ] = undefined;
+ }
+ }
+ }
+
+ if( p.triggerEvent ){
+ self[ p.triggerFnName ]( p.event );
+ }
+
+ // .removeData()
+ } else if( names === undefined ){ // then delete all keys
+
+ for( var i_a = 0, l_a = all.length; i_a < l_a; i_a++ ){
+ var _privateFields = all[ i_a ]._private[ p.field ];
+
+ for( var key in _privateFields ){
+ var validKeyToDelete = !p.immutableKeys[ key ];
+
+ if( validKeyToDelete ){
+ _privateFields[ key ] = undefined;
+ }
+ }
+ }
+
+ if( p.triggerEvent ){
+ self[ p.triggerFnName ]( p.event );
+ }
+ }
+
+ return self; // maintain chaining
+ }; // function
+ }, // removeData
+
+ // event function reusable stuff
+ event: {
+ regex: /(\w+)(\.\w+)?/, // regex for matching event strings (e.g. "click.namespace")
+ optionalTypeRegex: /(\w+)?(\.\w+)?/,
+ falseCallback: function(){ return false; }
+ },
+
+ // event binding
+ on: function( params ){
+ var defaults = {
+ unbindSelfOnTrigger: false,
+ unbindAllBindersOnTrigger: false
+ };
+ params = util.extend({}, defaults, params);
+
+ return function onImpl(events, selector, data, callback){
+ var self = this;
+ var selfIsArrayLike = self.length !== undefined;
+ var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
+ var eventsIsString = is.string(events);
+ var p = params;
+
+ if( is.plainObject(selector) ){ // selector is actually data
+ callback = data;
+ data = selector;
+ selector = undefined;
+ } else if( is.fn(selector) || selector === false ){ // selector is actually callback
+ callback = selector;
+ data = undefined;
+ selector = undefined;
+ }
+
+ if( is.fn(data) || data === false ){ // data is actually callback
+ callback = data;
+ data = undefined;
+ }
+
+ // if there isn't a callback, we can't really do anything
+ // (can't speak for mapped events arg version)
+ if( !(is.fn(callback) || callback === false) && eventsIsString ){
+ return self; // maintain chaining
+ }
+
+ if( eventsIsString ){ // then convert to map
+ var map = {};
+ map[ events ] = callback;
+ events = map;
+ }
+
+ for( var evts in events ){
+ callback = events[evts];
+ if( callback === false ){
+ callback = define.event.falseCallback;
+ }
+
+ if( !is.fn(callback) ){ continue; }
+
+ evts = evts.split(/\s+/);
+ for( var i = 0; i < evts.length; i++ ){
+ var evt = evts[i];
+ if( is.emptyString(evt) ){ continue; }
+
+ var match = evt.match( define.event.regex ); // type[.namespace]
+
+ if( match ){
+ var type = match[1];
+ var namespace = match[2] ? match[2] : undefined;
+
+ var listener = {
+ callback: callback, // callback to run
+ data: data, // extra data in eventObj.data
+ delegated: selector ? true : false, // whether the evt is delegated
+ selector: selector, // the selector to match for delegated events
+ selObj: new Selector(selector), // cached selector object to save rebuilding
+ type: type, // the event type (e.g. 'click')
+ namespace: namespace, // the event namespace (e.g. ".foo")
+ unbindSelfOnTrigger: p.unbindSelfOnTrigger,
+ unbindAllBindersOnTrigger: p.unbindAllBindersOnTrigger,
+ binders: all // who bound together
+ };
+
+ for( var j = 0; j < all.length; j++ ){
+ var _p = all[j]._private;
+
+ _p.listeners = _p.listeners || [];
+ _p.listeners.push( listener );
+ }
+ }
+ } // for events array
+ } // for events map
+
+ return self; // maintain chaining
+ }; // function
+ }, // on
+
+ eventAliasesOn: function( proto ){
+ var p = proto;
+
+ p.addListener = p.listen = p.bind = p.on;
+ p.removeListener = p.unlisten = p.unbind = p.off;
+ p.emit = p.trigger;
+
+ // this is just a wrapper alias of .on()
+ p.pon = p.promiseOn = function( events, selector ){
+ var self = this;
+ var args = Array.prototype.slice.call( arguments, 0 );
+
+ return new Promise(function( resolve, reject ){
+ var callback = function( e ){
+ self.off.apply( self, offArgs );
+
+ resolve( e );
+ };
+
+ var onArgs = args.concat([ callback ]);
+ var offArgs = onArgs.concat([]);
+
+ self.on.apply( self, onArgs );
+ });
+ };
+ },
+
+ off: function offImpl( params ){
+ var defaults = {
+ };
+ params = util.extend({}, defaults, params);
+
+ return function(events, selector, callback){
+ var self = this;
+ var selfIsArrayLike = self.length !== undefined;
+ var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
+ var eventsIsString = is.string(events);
+
+ if( arguments.length === 0 ){ // then unbind all
+
+ for( var i = 0; i < all.length; i++ ){
+ all[i]._private.listeners = [];
+ }
+
+ return self; // maintain chaining
+ }
+
+ if( is.fn(selector) || selector === false ){ // selector is actually callback
+ callback = selector;
+ selector = undefined;
+ }
+
+ if( eventsIsString ){ // then convert to map
+ var map = {};
+ map[ events ] = callback;
+ events = map;
+ }
+
+ for( var evts in events ){
+ callback = events[evts];
+
+ if( callback === false ){
+ callback = define.event.falseCallback;
+ }
+
+ evts = evts.split(/\s+/);
+ for( var h = 0; h < evts.length; h++ ){
+ var evt = evts[h];
+ if( is.emptyString(evt) ){ continue; }
+
+ var match = evt.match( define.event.optionalTypeRegex ); // [type][.namespace]
+ if( match ){
+ var type = match[1] ? match[1] : undefined;
+ var namespace = match[2] ? match[2] : undefined;
+
+ for( var i = 0; i < all.length; i++ ){ //
+ var listeners = all[i]._private.listeners = all[i]._private.listeners || [];
+
+ for( var j = 0; j < listeners.length; j++ ){
+ var listener = listeners[j];
+ var nsMatches = !namespace || namespace === listener.namespace;
+ var typeMatches = !type || listener.type === type;
+ var cbMatches = !callback || callback === listener.callback;
+ var listenerMatches = nsMatches && typeMatches && cbMatches;
+
+ // delete listener if it matches
+ if( listenerMatches ){
+ listeners.splice(j, 1);
+ j--;
+ }
+ } // for listeners
+ } // for all
+ } // if match
+ } // for events array
+
+ } // for events map
+
+ return self; // maintain chaining
+ }; // function
+ }, // off
+
+ trigger: function( params ){
+ var defaults = {};
+ params = util.extend({}, defaults, params);
+
+ return function triggerImpl(events, extraParams, fnToTrigger){
+ var self = this;
+ var selfIsArrayLike = self.length !== undefined;
+ var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
+ var eventsIsString = is.string(events);
+ var eventsIsObject = is.plainObject(events);
+ var eventsIsEvent = is.event(events);
+ var cy = this._private.cy || ( is.core(this) ? this : null );
+ var hasCompounds = cy ? cy.hasCompoundNodes() : false;
+
+ if( eventsIsString ){ // then make a plain event object for each event name
+ var evts = events.split(/\s+/);
+ events = [];
+
+ for( var i = 0; i < evts.length; i++ ){
+ var evt = evts[i];
+ if( is.emptyString(evt) ){ continue; }
+
+ var match = evt.match( define.event.regex ); // type[.namespace]
+ var type = match[1];
+ var namespace = match[2] ? match[2] : undefined;
+
+ events.push( {
+ type: type,
+ namespace: namespace
+ } );
+ }
+ } else if( eventsIsObject ){ // put in length 1 array
+ var eventArgObj = events;
+
+ events = [ eventArgObj ];
+ }
+
+ if( extraParams ){
+ if( !is.array(extraParams) ){ // make sure extra params are in an array if specified
+ extraParams = [ extraParams ];
+ }
+ } else { // otherwise, we've got nothing
+ extraParams = [];
+ }
+
+ for( var i = 0; i < events.length; i++ ){ // trigger each event in order
+ var evtObj = events[i];
+
+ for( var j = 0; j < all.length; j++ ){ // for each
+ var triggerer = all[j];
+ var listeners = triggerer._private.listeners = triggerer._private.listeners || [];
+ var triggererIsElement = is.element(triggerer);
+ var bubbleUp = triggererIsElement || params.layout;
+
+ // create the event for this element from the event object
+ var evt;
+
+ if( eventsIsEvent ){ // then just get the object
+ evt = evtObj;
+
+ evt.cyTarget = evt.cyTarget || triggerer;
+ evt.cy = evt.cy || cy;
+
+ } else { // then we have to make one
+ evt = new Event( evtObj, {
+ cyTarget: triggerer,
+ cy: cy,
+ namespace: evtObj.namespace
+ } );
+ }
+
+ // if a layout was specified, then put it in the typed event
+ if( evtObj.layout ){
+ evt.layout = evtObj.layout;
+ }
+
+ // if triggered by layout, put in event
+ if( params.layout ){
+ evt.layout = triggerer;
+ }
+
+ // create a rendered position based on the passed position
+ if( evt.cyPosition ){
+ var pos = evt.cyPosition;
+ var zoom = cy.zoom();
+ var pan = cy.pan();
+
+ evt.cyRenderedPosition = {
+ x: pos.x * zoom + pan.x,
+ y: pos.y * zoom + pan.y
+ };
+ }
+
+ if( fnToTrigger ){ // then override the listeners list with just the one we specified
+ listeners = [{
+ namespace: evt.namespace,
+ type: evt.type,
+ callback: fnToTrigger
+ }];
+ }
+
+ for( var k = 0; k < listeners.length; k++ ){ // check each listener
+ var lis = listeners[k];
+ var nsMatches = !lis.namespace || lis.namespace === evt.namespace;
+ var typeMatches = lis.type === evt.type;
+ var targetMatches = lis.delegated ? ( triggerer !== evt.cyTarget && is.element(evt.cyTarget) && lis.selObj.matches(evt.cyTarget) ) : (true); // we're not going to validate the hierarchy; that's too expensive
+ var listenerMatches = nsMatches && typeMatches && targetMatches;
+
+ if( listenerMatches ){ // then trigger it
+ var args = [ evt ];
+ args = args.concat( extraParams ); // add extra params to args list
+
+ if( lis.data ){ // add on data plugged into binding
+ evt.data = lis.data;
+ } else { // or clear it in case the event obj is reused
+ evt.data = undefined;
+ }
+
+ if( lis.unbindSelfOnTrigger || lis.unbindAllBindersOnTrigger ){ // then remove listener
+ listeners.splice(k, 1);
+ k--;
+ }
+
+ if( lis.unbindAllBindersOnTrigger ){ // then delete the listener for all binders
+ var binders = lis.binders;
+ for( var l = 0; l < binders.length; l++ ){
+ var binder = binders[l];
+ if( !binder || binder === triggerer ){ continue; } // already handled triggerer or we can't handle it
+
+ var binderListeners = binder._private.listeners;
+ for( var m = 0; m < binderListeners.length; m++ ){
+ var binderListener = binderListeners[m];
+
+ if( binderListener === lis ){ // delete listener from list
+ binderListeners.splice(m, 1);
+ m--;
+ }
+ }
+ }
+ }
+
+ // run the callback
+ var context = lis.delegated ? evt.cyTarget : triggerer;
+ var ret = lis.callback.apply( context, args );
+
+ if( ret === false || evt.isPropagationStopped() ){
+ // then don't bubble
+ bubbleUp = false;
+
+ if( ret === false ){
+ // returning false is a shorthand for stopping propagation and preventing the def. action
+ evt.stopPropagation();
+ evt.preventDefault();
+ }
+ }
+ } // if listener matches
+ } // for each listener
+
+ // bubble up event for elements
+ if( bubbleUp ){
+ var parent = hasCompounds ? triggerer._private.parent : null;
+ var hasParent = parent != null && parent.length !== 0;
+
+ if( hasParent ){ // then bubble up to parent
+ parent = parent[0];
+ parent.trigger(evt);
+ } else { // otherwise, bubble up to the core
+ cy.trigger(evt);
+ }
+ }
+
+ } // for each of all
+ } // for each event
+
+ return self; // maintain chaining
+ }; // function
+ }, // trigger
+
+ animated: function( fnParams ){
+ var defaults = {};
+ fnParams = util.extend({}, defaults, fnParams);
+
+ return function animatedImpl(){
+ var self = this;
+ var selfIsArrayLike = self.length !== undefined;
+ var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
+ var cy = this._private.cy || this;
+
+ if( !cy.styleEnabled() ){ return false; }
+
+ var ele = all[0];
+
+ if( ele ){
+ return ele._private.animation.current.length > 0;
+ }
+ };
+ }, // animated
+
+ clearQueue: function( fnParams ){
+ var defaults = {};
+ fnParams = util.extend({}, defaults, fnParams);
+
+ return function clearQueueImpl(){
+ var self = this;
+ var selfIsArrayLike = self.length !== undefined;
+ var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
+ var cy = this._private.cy || this;
+
+ if( !cy.styleEnabled() ){ return this; }
+
+ for( var i = 0; i < all.length; i++ ){
+ var ele = all[i];
+ ele._private.animation.queue = [];
+ }
+
+ return this;
+ };
+ }, // clearQueue
+
+ delay: function( fnParams ){
+ var defaults = {};
+ fnParams = util.extend({}, defaults, fnParams);
+
+ return function delayImpl( time, complete ){
+ var cy = this._private.cy || this;
+
+ if( !cy.styleEnabled() ){ return this; }
+
+ return this.animate({
+ delay: time,
+ duration: time,
+ complete: complete
+ });
+ };
+ }, // delay
+
+ delayAnimation: function( fnParams ){
+ var defaults = {};
+ fnParams = util.extend({}, defaults, fnParams);
+
+ return function delayAnimationImpl( time, complete ){
+ var cy = this._private.cy || this;
+
+ if( !cy.styleEnabled() ){ return this; }
+
+ return this.animation({
+ delay: time,
+ duration: time,
+ complete: complete
+ });
+ };
+ }, // delay
+
+ animation: function( fnParams ){
+ var defaults = {};
+ fnParams = util.extend({}, defaults, fnParams);
+
+ return function animationImpl( properties, params ){
+ var self = this;
+ var selfIsArrayLike = self.length !== undefined;
+ var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
+ var cy = this._private.cy || this;
+ var isCore = !selfIsArrayLike;
+ var isEles = !isCore;
+
+ if( !cy.styleEnabled() ){ return this; }
+
+ var style = cy.style();
+
+ properties = util.extend( {}, properties, params );
+
+ if( properties.duration === undefined ){
+ properties.duration = 400;
+ }
+
+ switch( properties.duration ){
+ case 'slow':
+ properties.duration = 600;
+ break;
+ case 'fast':
+ properties.duration = 200;
+ break;
+ }
+
+ var propertiesEmpty = true;
+ if( properties ){ for( var i in properties ){ // jshint ignore:line
+ propertiesEmpty = false;
+ break;
+ } }
+
+ if( propertiesEmpty ){
+ return new Animation( all[0], properties ); // nothing to animate
+ }
+
+ if( isEles ){
+ properties.style = style.getPropsList( properties.style || properties.css );
+
+ properties.css = undefined;
+ }
+
+ if( properties.renderedPosition && isEles ){
+ var rpos = properties.renderedPosition;
+ var pan = cy.pan();
+ var zoom = cy.zoom();
+
+ properties.position = {
+ x: ( rpos.x - pan.x ) /zoom,
+ y: ( rpos.y - pan.y ) /zoom
+ };
+ }
+
+ // override pan w/ panBy if set
+ if( properties.panBy && isCore ){
+ var panBy = properties.panBy;
+ var cyPan = cy.pan();
+
+ properties.pan = {
+ x: cyPan.x + panBy.x,
+ y: cyPan.y + panBy.y
+ };
+ }
+
+ // override pan w/ center if set
+ var center = properties.center || properties.centre;
+ if( center && isCore ){
+ var centerPan = cy.getCenterPan( center.eles, properties.zoom );
+
+ if( centerPan ){
+ properties.pan = centerPan;
+ }
+ }
+
+ // override pan & zoom w/ fit if set
+ if( properties.fit && isCore ){
+ var fit = properties.fit;
+ var fitVp = cy.getFitViewport( fit.eles || fit.boundingBox, fit.padding );
+
+ if( fitVp ){
+ properties.pan = fitVp.pan;
+ properties.zoom = fitVp.zoom;
+ }
+ }
+
+ return new Animation( all[0], properties );
+ };
+ }, // animate
+
+ animate: function( fnParams ){
+ var defaults = {};
+ fnParams = util.extend({}, defaults, fnParams);
+
+ return function animateImpl( properties, params ){
+ var self = this;
+ var selfIsArrayLike = self.length !== undefined;
+ var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
+ var cy = this._private.cy || this;
+
+ if( !cy.styleEnabled() ){ return this; }
+
+ if( params ){
+ properties = util.extend( {}, properties, params );
+ }
+
+ // manually hook and run the animation
+ for( var i = 0; i < all.length; i++ ){
+ var ele = all[i];
+ var queue = ele.animated() && (properties.queue === undefined || properties.queue);
+
+ var ani = ele.animation( properties, (queue ? { queue: true } : undefined) );
+
+ ani.play();
+ }
+
+ return this; // chaining
+ };
+ }, // animate
+
+ stop: function( fnParams ){
+ var defaults = {};
+ fnParams = util.extend({}, defaults, fnParams);
+
+ return function stopImpl( clearQueue, jumpToEnd ){
+ var self = this;
+ var selfIsArrayLike = self.length !== undefined;
+ var all = selfIsArrayLike ? self : [self]; // put in array if not array-like
+ var cy = this._private.cy || this;
+
+ if( !cy.styleEnabled() ){ return this; }
+
+ for( var i = 0; i < all.length; i++ ){
+ var ele = all[i];
+ var _p = ele._private;
+ var anis = _p.animation.current;
+
+ for( var j = 0; j < anis.length; j++ ){
+ var ani = anis[j];
+ var ani_p = ani._private;
+
+ if( jumpToEnd ){
+ // next iteration of the animation loop, the animation
+ // will go straight to the end and be removed
+ ani_p.duration = 0;
+ }
+ }
+
+ // clear the queue of future animations
+ if( clearQueue ){
+ _p.animation.queue = [];
+ }
+
+ if( !jumpToEnd ){
+ _p.animation.current = [];
+ }
+ }
+
+ // we have to notify (the animation loop doesn't do it for us on `stop`)
+ cy.notify({
+ collection: this,
+ type: 'draw'
+ });
+
+ return this;
+ };
+ } // stop
+
+}; // define
+
+module.exports = define;
+
+},{"./animation":1,"./event":42,"./is":77,"./promise":80,"./selector":81,"./util":94}],42:[function(_dereq_,module,exports){
+'use strict';
+
+// ref
+// https://github.com/jquery/jquery/blob/master/src/event.js
+
+var Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof Event) ) {
+ return new Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ // util.extend( this, props );
+
+ // more efficient to manually copy fields we use
+ this.type = props.type !== undefined ? props.type : this.type;
+ this.cy = props.cy;
+ this.cyTarget = props.cyTarget;
+ this.cyPosition = props.cyPosition;
+ this.cyRenderedPosition = props.cyRenderedPosition;
+ this.namespace = props.namespace;
+ this.layout = props.layout;
+ this.data = props.data;
+ this.message = props.message;
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || Date.now();
+};
+
+function returnFalse() {
+ return false;
+}
+
+function returnTrue() {
+ return true;
+}
+
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+Event.prototype = {
+ instanceString: function(){
+ return 'event';
+ },
+
+ preventDefault: function() {
+ this.isDefaultPrevented = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if preventDefault exists run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+ }
+ },
+
+ stopPropagation: function() {
+ this.isPropagationStopped = returnTrue;
+
+ var e = this.originalEvent;
+ if ( !e ) {
+ return;
+ }
+
+ // if stopPropagation exists run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ },
+
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ },
+
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse
+};
+
+module.exports = Event;
+
+},{}],43:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('./util');
+var define = _dereq_('./define');
+var Collection = _dereq_('./collection');
+var Core = _dereq_('./core');
+var incExts = _dereq_('./extensions');
+var is = _dereq_('./is');
+
+// registered extensions to cytoscape, indexed by name
+var extensions = {};
+
+// registered modules for extensions, indexed by name
+var modules = {};
+
+function setExtension( type, name, registrant ){
+
+ var ext = registrant;
+
+ if( type === 'core' ){
+ Core.prototype[ name ] = registrant;
+
+ } else if( type === 'collection' ){
+ Collection.prototype[ name ] = registrant;
+
+ } else if( type === 'layout' ){
+ // fill in missing layout functions in the prototype
+
+ var Layout = function( options ){
+ this.options = options;
+
+ registrant.call( this, options );
+
+ // make sure layout has _private for use w/ std apis like .on()
+ if( !is.plainObject(this._private) ){
+ this._private = {};
+ }
+
+ this._private.cy = options.cy;
+ this._private.listeners = [];
+ };
+
+ var layoutProto = Layout.prototype = Object.create( registrant.prototype );
+
+ var optLayoutFns = [];
+
+ for( var i = 0; i < optLayoutFns.length; i++ ){
+ var fnName = optLayoutFns[i];
+
+ layoutProto[fnName] = layoutProto[fnName] || function(){ return this; };
+ }
+
+ // either .start() or .run() is defined, so autogen the other
+ if( layoutProto.start && !layoutProto.run ){
+ layoutProto.run = function(){ this.start(); return this; };
+ } else if( !layoutProto.start && layoutProto.run ){
+ layoutProto.start = function(){ this.run(); return this; };
+ }
+
+ if( !layoutProto.stop ){
+ layoutProto.stop = function(){
+ var opts = this.options;
+
+ if( opts && opts.animate ){
+ var anis = this.animations;
+ for( var i = 0; i < anis.length; i++ ){
+ anis[i].stop();
+ }
+ }
+
+ this.trigger('layoutstop');
+
+ return this;
+ };
+ }
+
+ if( !layoutProto.destroy ){
+ layoutProto.destroy = function(){
+ return this;
+ };
+ }
+
+ layoutProto.on = define.on({ layout: true });
+ layoutProto.one = define.on({ layout: true, unbindSelfOnTrigger: true });
+ layoutProto.once = define.on({ layout: true, unbindAllBindersOnTrigger: true });
+ layoutProto.off = define.off({ layout: true });
+ layoutProto.trigger = define.trigger({ layout: true });
+
+ define.eventAliasesOn( layoutProto );
+
+ ext = Layout; // replace with our wrapped layout
+
+ } else if( type === 'renderer' && name !== 'null' && name !== 'base' ){
+ // user registered renderers inherit from base
+
+ var bProto = getExtension( 'renderer', 'base' ).prototype;
+ var rProto = registrant.prototype;
+
+ for( var pName in bProto ){
+ var pVal = bProto[ pName ];
+ var existsInR = rProto[ pName ] != null;
+
+ if( existsInR ){
+ util.error('Can not register renderer `' + name + '` since it overrides `' + pName + '` in its prototype');
+ return;
+ }
+
+ rProto[ pName ] = pVal; // take impl from base
+ }
+
+ bProto.clientFunctions.forEach(function( name ){
+ rProto[ name ] = rProto[ name ] || function(){
+ util.error('Renderer does not implement `renderer.' + name + '()` on its prototype');
+ };
+ });
+
+ }
+
+ return util.setMap({
+ map: extensions,
+ keys: [ type, name ],
+ value: ext
+ });
+}
+
+function getExtension(type, name){
+ return util.getMap({
+ map: extensions,
+ keys: [ type, name ]
+ });
+}
+
+function setModule(type, name, moduleType, moduleName, registrant){
+ return util.setMap({
+ map: modules,
+ keys: [ type, name, moduleType, moduleName ],
+ value: registrant
+ });
+}
+
+function getModule(type, name, moduleType, moduleName){
+ return util.getMap({
+ map: modules,
+ keys: [ type, name, moduleType, moduleName ]
+ });
+}
+
+var extension = function(){
+ // e.g. extension('renderer', 'svg')
+ if( arguments.length === 2 ){
+ return getExtension.apply(null, arguments);
+ }
+
+ // e.g. extension('renderer', 'svg', { ... })
+ else if( arguments.length === 3 ){
+ return setExtension.apply(null, arguments);
+ }
+
+ // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse')
+ else if( arguments.length === 4 ){
+ return getModule.apply(null, arguments);
+ }
+
+ // e.g. extension('renderer', 'svg', 'nodeShape', 'ellipse', { ... })
+ else if( arguments.length === 5 ){
+ return setModule.apply(null, arguments);
+ }
+
+ else {
+ util.error('Invalid extension access syntax');
+ }
+
+};
+
+// allows a core instance to access extensions internally
+Core.prototype.extension = extension;
+
+// included extensions
+incExts.forEach(function( group ){
+ group.extensions.forEach(function( ext ){
+ setExtension( group.type, ext.name, ext.impl );
+ });
+});
+
+module.exports = extension;
+
+},{"./collection":23,"./core":34,"./define":41,"./extensions":44,"./is":77,"./util":94}],44:[function(_dereq_,module,exports){
+'use strict';
+
+module.exports = [
+ {
+ type: 'layout',
+ extensions: _dereq_('./layout')
+ },
+
+ {
+ type: 'renderer',
+ extensions: _dereq_('./renderer')
+ }
+];
+
+},{"./layout":50,"./renderer":72}],45:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../../util');
+var math = _dereq_('../../math');
+var is = _dereq_('../../is');
+
+var defaults = {
+ fit: true, // whether to fit the viewport to the graph
+ directed: false, // whether the tree is directed downwards (or edges can point in any direction if false)
+ padding: 30, // padding on fit
+ circle: false, // put depths in concentric circles if true, put depths top down if false
+ spacingFactor: 1.75, // positive spacing factor, larger => more space between nodes (N.B. n/a if causes overlap)
+ boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
+ avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space
+ roots: undefined, // the roots of the trees
+ maximalAdjustments: 0, // how many times to try to position the nodes in a maximal way (i.e. no backtracking)
+ animate: false, // whether to transition the node positions
+ animationDuration: 500, // duration of animation in ms if enabled
+ animationEasing: undefined, // easing of animation if enabled
+ ready: undefined, // callback on layoutready
+ stop: undefined // callback on layoutstop
+};
+
+function BreadthFirstLayout( options ){
+ this.options = util.extend({}, defaults, options);
+}
+
+BreadthFirstLayout.prototype.run = function(){
+ var params = this.options;
+ var options = params;
+
+ var cy = params.cy;
+ var eles = options.eles;
+ var nodes = eles.nodes().not(':parent');
+ var graph = eles;
+
+ var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {
+ x1: 0, y1: 0, w: cy.width(), h: cy.height()
+ } );
+
+ var roots;
+ if( is.elementOrCollection(options.roots) ){
+ roots = options.roots;
+ } else if( is.array(options.roots) ){
+ var rootsArray = [];
+
+ for( var i = 0; i < options.roots.length; i++ ){
+ var id = options.roots[i];
+ var ele = cy.getElementById( id );
+ rootsArray.push( ele );
+ }
+
+ roots = cy.collection( rootsArray );
+ } else if( is.string(options.roots) ){
+ roots = cy.$( options.roots );
+
+ } else {
+ if( options.directed ){
+ roots = nodes.roots();
+ } else {
+ var components = [];
+ var unhandledNodes = nodes;
+
+ while( unhandledNodes.length > 0 ){
+ var currComp = cy.collection();
+
+ eles.bfs({
+ roots: unhandledNodes[0],
+ visit: function(i, depth, node, edge, pNode){
+ currComp = currComp.add( node );
+ },
+ directed: false
+ });
+
+ unhandledNodes = unhandledNodes.not( currComp );
+ components.push( currComp );
+ }
+
+ roots = cy.collection();
+ for( var i = 0; i < components.length; i++ ){
+ var comp = components[i];
+ var maxDegree = comp.maxDegree( false );
+ var compRoots = comp.filter(function(){
+ return this.degree(false) === maxDegree;
+ });
+
+ roots = roots.add( compRoots );
+ }
+
+ }
+ }
+
+
+ var depths = [];
+ var foundByBfs = {};
+ var id2depth = {};
+ var prevNode = {};
+ var prevEdge = {};
+ var successors = {};
+
+ // find the depths of the nodes
+ graph.bfs({
+ roots: roots,
+ directed: options.directed,
+ visit: function(i, depth, node, edge, pNode){
+ var ele = this[0];
+ var id = ele.id();
+
+ if( !depths[depth] ){
+ depths[depth] = [];
+ }
+
+ depths[depth].push( ele );
+ foundByBfs[ id ] = true;
+ id2depth[ id ] = depth;
+ prevNode[ id ] = pNode;
+ prevEdge[ id ] = edge;
+
+ if( pNode ){
+ var prevId = pNode.id();
+ var succ = successors[ prevId ] = successors[ prevId ] || [];
+
+ succ.push( node );
+ }
+ }
+ });
+
+ // check for nodes not found by bfs
+ var orphanNodes = [];
+ for( var i = 0; i < nodes.length; i++ ){
+ var ele = nodes[i];
+
+ if( foundByBfs[ ele.id() ] ){
+ continue;
+ } else {
+ orphanNodes.push( ele );
+ }
+ }
+
+ // assign orphan nodes a depth from their neighborhood
+ var maxChecks = orphanNodes.length * 3;
+ var checks = 0;
+ while( orphanNodes.length !== 0 && checks < maxChecks ){
+ var node = orphanNodes.shift();
+ var neighbors = node.neighborhood().nodes();
+ var assignedDepth = false;
+
+ for( var i = 0; i < neighbors.length; i++ ){
+ var depth = id2depth[ neighbors[i].id() ];
+
+ if( depth !== undefined ){
+ depths[depth].push( node );
+ assignedDepth = true;
+ break;
+ }
+ }
+
+ if( !assignedDepth ){
+ orphanNodes.push( node );
+ }
+
+ checks++;
+ }
+
+ // assign orphan nodes that are still left to the depth of their subgraph
+ while( orphanNodes.length !== 0 ){
+ var node = orphanNodes.shift();
+ //var subgraph = graph.bfs( node ).path;
+ var assignedDepth = false;
+
+ // for( var i = 0; i < subgraph.length; i++ ){
+ // var depth = id2depth[ subgraph[i].id() ];
+
+ // if( depth !== undefined ){
+ // depths[depth].push( node );
+ // assignedDepth = true;
+ // break;
+ // }
+ // }
+
+ if( !assignedDepth ){ // worst case if the graph really isn't tree friendly, then just dump it in 0
+ if( depths.length === 0 ){
+ depths.push([]);
+ }
+
+ depths[0].push( node );
+ }
+ }
+
+ // assign the nodes a depth and index
+ var assignDepthsToEles = function(){
+ for( var i = 0; i < depths.length; i++ ){
+ var eles = depths[i];
+
+ for( var j = 0; j < eles.length; j++ ){
+ var ele = eles[j];
+
+ ele._private.scratch.breadthfirst = {
+ depth: i,
+ index: j
+ };
+ }
+ }
+ };
+ assignDepthsToEles();
+
+
+ var intersectsDepth = function( node ){ // returns true if has edges pointing in from a higher depth
+ var edges = node.connectedEdges(function(){
+ return this.data('target') === node.id();
+ });
+ var thisInfo = node._private.scratch.breadthfirst;
+ var highestDepthOfOther = 0;
+ var highestOther;
+ for( var i = 0; i < edges.length; i++ ){
+ var edge = edges[i];
+ var otherNode = edge.source()[0];
+ var otherInfo = otherNode._private.scratch.breadthfirst;
+
+ if( thisInfo.depth <= otherInfo.depth && highestDepthOfOther < otherInfo.depth ){
+ highestDepthOfOther = otherInfo.depth;
+ highestOther = otherNode;
+ }
+ }
+
+ return highestOther;
+ };
+
+ // make maximal if so set by adjusting depths
+ for( var adj = 0; adj < options.maximalAdjustments; adj++ ){
+
+ var nDepths = depths.length;
+ var elesToMove = [];
+ for( var i = 0; i < nDepths; i++ ){
+ var depth = depths[i];
+
+ var nDepth = depth.length;
+ for( var j = 0; j < nDepth; j++ ){
+ var ele = depth[j];
+ var info = ele._private.scratch.breadthfirst;
+ var intEle = intersectsDepth(ele);
+
+ if( intEle ){
+ info.intEle = intEle;
+ elesToMove.push( ele );
+ }
+ }
+ }
+
+ for( var i = 0; i < elesToMove.length; i++ ){
+ var ele = elesToMove[i];
+ var info = ele._private.scratch.breadthfirst;
+ var intEle = info.intEle;
+ var intInfo = intEle._private.scratch.breadthfirst;
+
+ depths[ info.depth ].splice( info.index, 1 ); // remove from old depth & index
+
+ // add to end of new depth
+ var newDepth = intInfo.depth + 1;
+ while( newDepth > depths.length - 1 ){
+ depths.push([]);
+ }
+ depths[ newDepth ].push( ele );
+
+ info.depth = newDepth;
+ info.index = depths[newDepth].length - 1;
+ }
+
+ assignDepthsToEles();
+ }
+
+ // find min distance we need to leave between nodes
+ var minDistance = 0;
+ if( options.avoidOverlap ){
+ for( var i = 0; i < nodes.length; i++ ){
+ var n = nodes[i];
+ var nbb = n.boundingBox();
+ var w = nbb.w;
+ var h = nbb.h;
+
+ minDistance = Math.max(minDistance, w, h);
+ }
+ minDistance *= options.spacingFactor; // just to have some nice spacing
+ }
+
+ // get the weighted percent for an element based on its connectivity to other levels
+ var cachedWeightedPercent = {};
+ var getWeightedPercent = function( ele ){
+ if( cachedWeightedPercent[ ele.id() ] ){
+ return cachedWeightedPercent[ ele.id() ];
+ }
+
+ var eleDepth = ele._private.scratch.breadthfirst.depth;
+ var neighbors = ele.neighborhood().nodes().not(':parent');
+ var percent = 0;
+ var samples = 0;
+
+ for( var i = 0; i < neighbors.length; i++ ){
+ var neighbor = neighbors[i];
+ var bf = neighbor._private.scratch.breadthfirst;
+ var index = bf.index;
+ var depth = bf.depth;
+ var nDepth = depths[depth].length;
+
+ if( eleDepth > depth || eleDepth === 0 ){ // only get influenced by elements above
+ percent += index / nDepth;
+ samples++;
+ }
+ }
+
+ samples = Math.max(1, samples);
+ percent = percent / samples;
+
+ if( samples === 0 ){ // so lone nodes have a "don't care" state in sorting
+ percent = undefined;
+ }
+
+ cachedWeightedPercent[ ele.id() ] = percent;
+ return percent;
+ };
+
+
+ // rearrange the indices in each depth level based on connectivity
+
+ var sortFn = function(a, b){
+ var apct = getWeightedPercent( a );
+ var bpct = getWeightedPercent( b );
+
+ return apct - bpct;
+ };
+
+ for( var times = 0; times < 3; times++ ){ // do it a few times b/c the depths are dynamic and we want a more stable result
+
+ for( var i = 0; i < depths.length; i++ ){
+ depths[i] = depths[i].sort( sortFn );
+ }
+ assignDepthsToEles(); // and update
+
+ }
+
+ var biggestDepthSize = 0;
+ for( var i = 0; i < depths.length; i++ ){
+ biggestDepthSize = Math.max( depths[i].length, biggestDepthSize );
+ }
+
+ var center = {
+ x: bb.x1 + bb.w/2,
+ y: bb.x1 + bb.h/2
+ };
+
+ var getPosition = function( ele, isBottomDepth ){
+ var info = ele._private.scratch.breadthfirst;
+ var depth = info.depth;
+ var index = info.index;
+ var depthSize = depths[depth].length;
+
+ var distanceX = Math.max( bb.w / (depthSize + 1), minDistance );
+ var distanceY = Math.max( bb.h / (depths.length + 1), minDistance );
+ var radiusStepSize = Math.min( bb.w / 2 / depths.length, bb.h / 2 / depths.length );
+ radiusStepSize = Math.max( radiusStepSize, minDistance );
+
+ if( !options.circle ){
+
+ var epos = {
+ x: center.x + (index + 1 - (depthSize + 1)/2) * distanceX,
+ y: (depth + 1) * distanceY
+ };
+
+ if( isBottomDepth ){
+ return epos;
+ }
+
+ // var succs = successors[ ele.id() ];
+ // if( succs ){
+ // epos.x = 0;
+ //
+ // for( var i = 0 ; i < succs.length; i++ ){
+ // var spos = pos[ succs[i].id() ];
+ //
+ // epos.x += spos.x;
+ // }
+ //
+ // epos.x /= succs.length;
+ // } else {
+ // //debugger;
+ // }
+
+ return epos;
+
+ } else {
+ if( options.circle ){
+ var radius = radiusStepSize * depth + radiusStepSize - (depths.length > 0 && depths[0].length <= 3 ? radiusStepSize/2 : 0);
+ var theta = 2 * Math.PI / depths[depth].length * index;
+
+ if( depth === 0 && depths[0].length === 1 ){
+ radius = 1;
+ }
+
+ return {
+ x: center.x + radius * Math.cos(theta),
+ y: center.y + radius * Math.sin(theta)
+ };
+
+ } else {
+ return {
+ x: center.x + (index + 1 - (depthSize + 1)/2) * distanceX,
+ y: (depth + 1) * distanceY
+ };
+ }
+ }
+
+ };
+
+ // get positions in reverse depth order
+ var pos = {};
+ for( var i = depths.length - 1; i >=0; i-- ){
+ var depth = depths[i];
+
+ for( var j = 0; j < depth.length; j++ ){
+ var node = depth[j];
+
+ pos[ node.id() ] = getPosition( node, i === depths.length - 1 );
+ }
+ }
+
+ nodes.layoutPositions(this, options, function(){
+ return pos[ this.id() ];
+ });
+
+ return this; // chaining
+};
+
+module.exports = BreadthFirstLayout;
+
+},{"../../is":77,"../../math":79,"../../util":94}],46:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../../util');
+var math = _dereq_('../../math');
+var is = _dereq_('../../is');
+
+var defaults = {
+ fit: true, // whether to fit the viewport to the graph
+ padding: 30, // the padding on fit
+ boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
+ avoidOverlap: true, // prevents node overlap, may overflow boundingBox and radius if not enough space
+ radius: undefined, // the radius of the circle
+ startAngle: 3/2 * Math.PI, // where nodes start in radians
+ sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)
+ clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)
+ sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }
+ animate: false, // whether to transition the node positions
+ animationDuration: 500, // duration of animation in ms if enabled
+ animationEasing: undefined, // easing of animation if enabled
+ ready: undefined, // callback on layoutready
+ stop: undefined // callback on layoutstop
+};
+
+function CircleLayout( options ){
+ this.options = util.extend({}, defaults, options);
+}
+
+CircleLayout.prototype.run = function(){
+ var params = this.options;
+ var options = params;
+
+ var cy = params.cy;
+ var eles = options.eles;
+
+ var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;
+
+ var nodes = eles.nodes().not(':parent');
+
+ if( options.sort ){
+ nodes = nodes.sort( options.sort );
+ }
+
+ var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {
+ x1: 0, y1: 0, w: cy.width(), h: cy.height()
+ } );
+
+ var center = {
+ x: bb.x1 + bb.w/2,
+ y: bb.y1 + bb.h/2
+ };
+
+ var sweep = options.sweep === undefined ? 2*Math.PI - 2*Math.PI/nodes.length : options.sweep;
+
+ var dTheta = sweep / ( Math.max(1, nodes.length - 1) );
+ var r;
+
+ var minDistance = 0;
+ for( var i = 0; i < nodes.length; i++ ){
+ var n = nodes[i];
+ var nbb = n.boundingBox();
+ var w = nbb.w;
+ var h = nbb.h;
+
+ minDistance = Math.max(minDistance, w, h);
+ }
+
+ if( is.number(options.radius) ){
+ r = options.radius;
+ } else if( nodes.length <= 1 ){
+ r = 0;
+ } else {
+ r = Math.min( bb.h, bb.w )/2 - minDistance;
+ }
+
+ // calculate the radius
+ if( nodes.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap)
+ minDistance *= 1.75; // just to have some nice spacing
+
+ var dcos = Math.cos(dTheta) - Math.cos(0);
+ var dsin = Math.sin(dTheta) - Math.sin(0);
+ var rMin = Math.sqrt( minDistance * minDistance / ( dcos*dcos + dsin*dsin ) ); // s.t. no nodes overlapping
+ r = Math.max( rMin, r );
+ }
+
+ var getPos = function( i, ele ){
+ var theta = options.startAngle + i * dTheta * ( clockwise ? 1 : -1 );
+
+ var rx = r * Math.cos( theta );
+ var ry = r * Math.sin( theta );
+ var pos = {
+ x: center.x + rx,
+ y: center.y + ry
+ };
+
+ return pos;
+ };
+
+ nodes.layoutPositions( this, options, getPos );
+
+ return this; // chaining
+};
+
+module.exports = CircleLayout;
+
+},{"../../is":77,"../../math":79,"../../util":94}],47:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../../util');
+var math = _dereq_('../../math');
+
+var defaults = {
+ fit: true, // whether to fit the viewport to the graph
+ padding: 30, // the padding on fit
+ startAngle: 3/2 * Math.PI, // where nodes start in radians
+ sweep: undefined, // how many radians should be between the first and last node (defaults to full circle)
+ clockwise: true, // whether the layout should go clockwise (true) or counterclockwise/anticlockwise (false)
+ equidistant: false, // whether levels have an equal radial distance betwen them, may cause bounding box overflow
+ minNodeSpacing: 10, // min spacing between outside of nodes (used for radius adjustment)
+ boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
+ avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space
+ height: undefined, // height of layout area (overrides container height)
+ width: undefined, // width of layout area (overrides container width)
+ concentric: function(node){ // returns numeric value for each node, placing higher nodes in levels towards the centre
+ return node.degree();
+ },
+ levelWidth: function(nodes){ // the variation of concentric values in each level
+ return nodes.maxDegree() / 4;
+ },
+ animate: false, // whether to transition the node positions
+ animationDuration: 500, // duration of animation in ms if enabled
+ animationEasing: undefined, // easing of animation if enabled
+ ready: undefined, // callback on layoutready
+ stop: undefined // callback on layoutstop
+};
+
+function ConcentricLayout( options ){
+ this.options = util.extend({}, defaults, options);
+}
+
+ConcentricLayout.prototype.run = function(){
+ var params = this.options;
+ var options = params;
+
+ var clockwise = options.counterclockwise !== undefined ? !options.counterclockwise : options.clockwise;
+
+ var cy = params.cy;
+
+ var eles = options.eles;
+ var nodes = eles.nodes().not(':parent');
+
+ var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {
+ x1: 0, y1: 0, w: cy.width(), h: cy.height()
+ } );
+
+ var center = {
+ x: bb.x1 + bb.w/2,
+ y: bb.y1 + bb.h/2
+ };
+
+ var nodeValues = []; // { node, value }
+ var theta = options.startAngle;
+ var maxNodeSize = 0;
+
+ for( var i = 0; i < nodes.length; i++ ){
+ var node = nodes[i];
+ var value;
+
+ // calculate the node value
+ value = options.concentric.apply(node, [ node ]);
+ nodeValues.push({
+ value: value,
+ node: node
+ });
+
+ // for style mapping
+ node._private.scratch.concentric = value;
+ }
+
+ // in case we used the `concentric` in style
+ nodes.updateStyle();
+
+ // calculate max size now based on potentially updated mappers
+ for( var i = 0; i < nodes.length; i++ ){
+ var node = nodes[i];
+ var nbb = node.boundingBox();
+
+ maxNodeSize = Math.max( maxNodeSize, nbb.w, nbb.h );
+ }
+
+ // sort node values in descreasing order
+ nodeValues.sort(function(a, b){
+ return b.value - a.value;
+ });
+
+ var levelWidth = options.levelWidth( nodes );
+
+ // put the values into levels
+ var levels = [ [] ];
+ var currentLevel = levels[0];
+ for( var i = 0; i < nodeValues.length; i++ ){
+ var val = nodeValues[i];
+
+ if( currentLevel.length > 0 ){
+ var diff = Math.abs( currentLevel[0].value - val.value );
+
+ if( diff >= levelWidth ){
+ currentLevel = [];
+ levels.push( currentLevel );
+ }
+ }
+
+ currentLevel.push( val );
+ }
+
+ // create positions from levels
+
+ var minDist = maxNodeSize + options.minNodeSpacing; // min dist between nodes
+
+ if( !options.avoidOverlap ){ // then strictly constrain to bb
+ var firstLvlHasMulti = levels.length > 0 && levels[0].length > 1;
+ var maxR = ( Math.min(bb.w, bb.h) / 2 - minDist );
+ var rStep = maxR / ( levels.length + firstLvlHasMulti ? 1 : 0 );
+
+ minDist = Math.min( minDist, rStep );
+ }
+
+ // find the metrics for each level
+ var r = 0;
+ for( var i = 0; i < levels.length; i++ ){
+ var level = levels[i];
+ var sweep = options.sweep === undefined ? 2*Math.PI - 2*Math.PI/level.length : options.sweep;
+ var dTheta = level.dTheta = sweep / ( Math.max(1, level.length - 1) );
+
+ // calculate the radius
+ if( level.length > 1 && options.avoidOverlap ){ // but only if more than one node (can't overlap)
+ var dcos = Math.cos(dTheta) - Math.cos(0);
+ var dsin = Math.sin(dTheta) - Math.sin(0);
+ var rMin = Math.sqrt( minDist * minDist / ( dcos*dcos + dsin*dsin ) ); // s.t. no nodes overlapping
+
+ r = Math.max( rMin, r );
+ }
+
+ level.r = r;
+
+ r += minDist;
+ }
+
+ if( options.equidistant ){
+ var rDeltaMax = 0;
+ var r = 0;
+
+ for( var i = 0; i < levels.length; i++ ){
+ var level = levels[i];
+ var rDelta = level.r - r;
+
+ rDeltaMax = Math.max( rDeltaMax, rDelta );
+ }
+
+ r = 0;
+ for( var i = 0; i < levels.length; i++ ){
+ var level = levels[i];
+
+ if( i === 0 ){
+ r = level.r;
+ }
+
+ level.r = r;
+
+ r += rDeltaMax;
+ }
+ }
+
+ // calculate the node positions
+ var pos = {}; // id => position
+ for( var i = 0; i < levels.length; i++ ){
+ var level = levels[i];
+ var dTheta = level.dTheta;
+ var r = level.r;
+
+ for( var j = 0; j < level.length; j++ ){
+ var val = level[j];
+ var theta = options.startAngle + (clockwise ? 1 : -1) * dTheta * j;
+
+ var p = {
+ x: center.x + r * Math.cos(theta),
+ y: center.y + r * Math.sin(theta)
+ };
+
+ pos[ val.node.id() ] = p;
+ }
+ }
+
+ // position the nodes
+ nodes.layoutPositions(this, options, function(){
+ var id = this.id();
+
+ return pos[id];
+ });
+
+ return this; // chaining
+};
+
+module.exports = ConcentricLayout;
+
+},{"../../math":79,"../../util":94}],48:[function(_dereq_,module,exports){
+'use strict';
+
+/*
+The CoSE layout was written by Gerardo Huck.
+https://www.linkedin.com/in/gerardohuck/
+
+Based on the following article:
+http://dl.acm.org/citation.cfm?id=1498047
+
+Modifications tracked on Github.
+*/
+
+var util = _dereq_('../../util');
+var math = _dereq_('../../math');
+var Thread = _dereq_('../../thread');
+var is = _dereq_('../../is');
+
+var DEBUG;
+
+/**
+ * @brief : default layout options
+ */
+var defaults = {
+ // Called on `layoutready`
+ ready : function() {},
+
+ // Called on `layoutstop`
+ stop : function() {},
+
+ // Whether to animate while running the layout
+ animate : true,
+
+ // The layout animates only after this many milliseconds
+ // (prevents flashing on fast runs)
+ animationThreshold : 250,
+
+ // Number of iterations between consecutive screen positions update
+ // (0 -> only updated on the end)
+ refresh : 20,
+
+ // Whether to fit the network view after when done
+ fit : true,
+
+ // Padding on fit
+ padding : 30,
+
+ // Constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
+ boundingBox : undefined,
+
+ // Extra spacing between components in non-compound graphs
+ componentSpacing : 100,
+
+ // Node repulsion (non overlapping) multiplier
+ nodeRepulsion : function( node ){ return 400000; },
+
+ // Node repulsion (overlapping) multiplier
+ nodeOverlap : 10,
+
+ // Ideal edge (non nested) length
+ idealEdgeLength : function( edge ){ return 10; },
+
+ // Divisor to compute edge forces
+ edgeElasticity : function( edge ){ return 100; },
+
+ // Nesting factor (multiplier) to compute ideal edge length for nested edges
+ nestingFactor : 5,
+
+ // Gravity force (constant)
+ gravity : 80,
+
+ // Maximum number of iterations to perform
+ numIter : 1000,
+
+ // Initial temperature (maximum node displacement)
+ initialTemp : 200,
+
+ // Cooling factor (how the temperature is reduced between consecutive iterations
+ coolingFactor : 0.95,
+
+ // Lower temperature threshold (below this point the layout will end)
+ minTemp : 1.0,
+
+ // Whether to use threading to speed up the layout
+ useMultitasking : true
+};
+
+
+/**
+ * @brief : constructor
+ * @arg options : object containing layout options
+ */
+function CoseLayout(options) {
+ this.options = util.extend({}, defaults, options);
+
+ this.options.layout = this;
+}
+
+
+/**
+ * @brief : runs the layout
+ */
+CoseLayout.prototype.run = function() {
+ var options = this.options;
+ var cy = options.cy;
+ var layout = this;
+ var thread = this.thread;
+
+ if( !thread || thread.stopped() ){
+ thread = this.thread = Thread({ disabled: !options.useMultitasking });
+ }
+
+ layout.stopped = false;
+
+ layout.trigger({ type: 'layoutstart', layout: layout });
+
+ // Set DEBUG - Global variable
+ if (true === options.debug) {
+ DEBUG = true;
+ } else {
+ DEBUG = false;
+ }
+
+ // Initialize layout info
+ var layoutInfo = createLayoutInfo(cy, layout, options);
+
+ // Show LayoutInfo contents if debugging
+ if (DEBUG) {
+ printLayoutInfo(layoutInfo);
+ }
+
+ // If required, randomize node positions
+ // if (true === options.randomize) {
+ randomizePositions(layoutInfo, cy);
+ // }
+
+ var startTime = Date.now();
+ var refreshRequested = false;
+ var refresh = function( rOpts ){
+ rOpts = rOpts || {};
+
+ if( refreshRequested ){
+ return;
+ }
+
+ if( !rOpts.force && Date.now() - startTime < options.animationThreshold ){
+ return;
+ }
+
+ refreshRequested = true;
+
+ util.requestAnimationFrame(function(){
+ refreshPositions(layoutInfo, cy, options);
+
+ // Fit the graph if necessary
+ if (true === options.fit) {
+ cy.fit( options.padding );
+ }
+
+ refreshRequested = false;
+ });
+ };
+
+ thread.on('message', function( e ){
+ var layoutNodes = e.message;
+
+ layoutInfo.layoutNodes = layoutNodes;
+ refresh();
+ });
+
+ thread.pass({
+ layoutInfo: layoutInfo,
+ options: {
+ animate: options.animate,
+ refresh: options.refresh,
+ componentSpacing: options.componentSpacing,
+ nodeOverlap: options.nodeOverlap,
+ nestingFactor: options.nestingFactor,
+ gravity: options.gravity,
+ numIter: options.numIter,
+ initialTemp: options.initialTemp,
+ coolingFactor: options.coolingFactor,
+ minTemp: options.minTemp
+ }
+ }).run(function( pass ){
+ var layoutInfo = pass.layoutInfo;
+ var options = pass.options;
+ var stopped = false;
+
+ /**
+ * @brief : Performs one iteration of the physical simulation
+ * @arg layoutInfo : LayoutInfo object already initialized
+ * @arg cy : Cytoscape object
+ * @arg options : Layout options
+ */
+ var step = function(layoutInfo, options, step) {
+ // var s = "\n\n###############################";
+ // s += "\nSTEP: " + step;
+ // s += "\n###############################\n";
+ // logDebug(s);
+
+ // Calculate node repulsions
+ calculateNodeForces(layoutInfo, options);
+ // Calculate edge forces
+ calculateEdgeForces(layoutInfo, options);
+ // Calculate gravity forces
+ calculateGravityForces(layoutInfo, options);
+ // Propagate forces from parent to child
+ propagateForces(layoutInfo, options);
+ // Update positions based on calculated forces
+ updatePositions(layoutInfo, options);
+ };
+
+ /**
+ * @brief : Computes the node repulsion forces
+ */
+ var calculateNodeForces = function(layoutInfo, options) {
+ // Go through each of the graphs in graphSet
+ // Nodes only repel each other if they belong to the same graph
+ // var s = 'calculateNodeForces';
+ // logDebug(s);
+ for (var i = 0; i < layoutInfo.graphSet.length; i ++) {
+ var graph = layoutInfo.graphSet[i];
+ var numNodes = graph.length;
+
+ // s = "Set: " + graph.toString();
+ // logDebug(s);
+
+ // Now get all the pairs of nodes
+ // Only get each pair once, (A, B) = (B, A)
+ for (var j = 0; j < numNodes; j++) {
+ var node1 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];
+
+ for (var k = j + 1; k < numNodes; k++) {
+ var node2 = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[k]]];
+
+ nodeRepulsion(node1, node2, layoutInfo, options);
+ }
+ }
+ }
+ };
+
+ /**
+ * @brief : Compute the node repulsion forces between a pair of nodes
+ */
+ var nodeRepulsion = function(node1, node2, layoutInfo, options) {
+ // var s = "Node repulsion. Node1: " + node1.id + " Node2: " + node2.id;
+
+ var cmptId1 = node1.cmptId;
+ var cmptId2 = node2.cmptId;
+
+ if( cmptId1 !== cmptId2 && !layoutInfo.isCompound ){ return; }
+
+ // Get direction of line connecting both node centers
+ var directionX = node2.positionX - node1.positionX;
+ var directionY = node2.positionY - node1.positionY;
+ // s += "\ndirectionX: " + directionX + ", directionY: " + directionY;
+
+ // If both centers are the same, apply a random force
+ if (0 === directionX && 0 === directionY) {
+ // s += "\nNodes have the same position.";
+ return; // TODO could be improved with random force
+ }
+
+ var overlap = nodesOverlap(node1, node2, directionX, directionY);
+
+ if (overlap > 0) {
+ // s += "\nNodes DO overlap.";
+ // s += "\nOverlap: " + overlap;
+ // If nodes overlap, repulsion force is proportional
+ // to the overlap
+ var force = options.nodeOverlap * overlap;
+
+ // Compute the module and components of the force vector
+ var distance = Math.sqrt(directionX * directionX + directionY * directionY);
+ // s += "\nDistance: " + distance;
+ var forceX = force * directionX / distance;
+ var forceY = force * directionY / distance;
+
+ } else {
+ // s += "\nNodes do NOT overlap.";
+ // If there's no overlap, force is inversely proportional
+ // to squared distance
+
+ // Get clipping points for both nodes
+ var point1 = findClippingPoint(node1, directionX, directionY);
+ var point2 = findClippingPoint(node2, -1 * directionX, -1 * directionY);
+
+ // Use clipping points to compute distance
+ var distanceX = point2.x - point1.x;
+ var distanceY = point2.y - point1.y;
+ var distanceSqr = distanceX * distanceX + distanceY * distanceY;
+ var distance = Math.sqrt(distanceSqr);
+ // s += "\nDistance: " + distance;
+
+ // Compute the module and components of the force vector
+ var force = ( node1.nodeRepulsion + node2.nodeRepulsion ) / distanceSqr;
+ var forceX = force * distanceX / distance;
+ var forceY = force * distanceY / distance;
+ }
+
+ // Apply force
+ if( !node1.isLocked ){
+ node1.offsetX -= forceX;
+ node1.offsetY -= forceY;
+ }
+
+ if( !node2.isLocked ){
+ node2.offsetX += forceX;
+ node2.offsetY += forceY;
+ }
+
+ // s += "\nForceX: " + forceX + " ForceY: " + forceY;
+ // logDebug(s);
+
+ return;
+ };
+
+ /**
+ * @brief : Determines whether two nodes overlap or not
+ * @return : Amount of overlapping (0 => no overlap)
+ */
+ var nodesOverlap = function(node1, node2, dX, dY) {
+
+ if (dX > 0) {
+ var overlapX = node1.maxX - node2.minX;
+ } else {
+ var overlapX = node2.maxX - node1.minX;
+ }
+
+ if (dY > 0) {
+ var overlapY = node1.maxY - node2.minY;
+ } else {
+ var overlapY = node2.maxY - node1.minY;
+ }
+
+ if (overlapX >= 0 && overlapY >= 0) {
+ return Math.sqrt(overlapX * overlapX + overlapY * overlapY);
+ } else {
+ return 0;
+ }
+ };
+
+ /**
+ * @brief : Finds the point in which an edge (direction dX, dY) intersects
+ * the rectangular bounding box of it's source/target node
+ */
+ var findClippingPoint = function(node, dX, dY) {
+
+ // Shorcuts
+ var X = node.positionX;
+ var Y = node.positionY;
+ var H = node.height || 1;
+ var W = node.width || 1;
+ var dirSlope = dY / dX;
+ var nodeSlope = H / W;
+
+ // var s = 'Computing clipping point of node ' + node.id +
+ // " . Height: " + H + ", Width: " + W +
+ // "\nDirection " + dX + ", " + dY;
+ //
+ // Compute intersection
+ var res = {};
+ do {
+ // Case: Vertical direction (up)
+ if (0 === dX && 0 < dY) {
+ res.x = X;
+ // s += "\nUp direction";
+ res.y = Y + H / 2;
+ break;
+ }
+
+ // Case: Vertical direction (down)
+ if (0 === dX && 0 > dY) {
+ res.x = X;
+ res.y = Y + H / 2;
+ // s += "\nDown direction";
+ break;
+ }
+
+ // Case: Intersects the right border
+ if (0 < dX &&
+ -1 * nodeSlope <= dirSlope &&
+ dirSlope <= nodeSlope) {
+ res.x = X + W / 2;
+ res.y = Y + (W * dY / 2 / dX);
+ // s += "\nRightborder";
+ break;
+ }
+
+ // Case: Intersects the left border
+ if (0 > dX &&
+ -1 * nodeSlope <= dirSlope &&
+ dirSlope <= nodeSlope) {
+ res.x = X - W / 2;
+ res.y = Y - (W * dY / 2 / dX);
+ // s += "\nLeftborder";
+ break;
+ }
+
+ // Case: Intersects the top border
+ if (0 < dY &&
+ ( dirSlope <= -1 * nodeSlope ||
+ dirSlope >= nodeSlope )) {
+ res.x = X + (H * dX / 2 / dY);
+ res.y = Y + H / 2;
+ // s += "\nTop border";
+ break;
+ }
+
+ // Case: Intersects the bottom border
+ if (0 > dY &&
+ ( dirSlope <= -1 * nodeSlope ||
+ dirSlope >= nodeSlope )) {
+ res.x = X - (H * dX / 2 / dY);
+ res.y = Y - H / 2;
+ // s += "\nBottom border";
+ break;
+ }
+
+ } while (false);
+
+ // s += "\nClipping point found at " + res.x + ", " + res.y;
+ // logDebug(s);
+ return res;
+ };
+
+ /**
+ * @brief : Calculates all edge forces
+ */
+ var calculateEdgeForces = function(layoutInfo, options) {
+ // Iterate over all edges
+ for (var i = 0; i < layoutInfo.edgeSize; i++) {
+ // Get edge, source & target nodes
+ var edge = layoutInfo.layoutEdges[i];
+ var sourceIx = layoutInfo.idToIndex[edge.sourceId];
+ var source = layoutInfo.layoutNodes[sourceIx];
+ var targetIx = layoutInfo.idToIndex[edge.targetId];
+ var target = layoutInfo.layoutNodes[targetIx];
+
+ // Get direction of line connecting both node centers
+ var directionX = target.positionX - source.positionX;
+ var directionY = target.positionY - source.positionY;
+
+ // If both centers are the same, do nothing.
+ // A random force has already been applied as node repulsion
+ if (0 === directionX && 0 === directionY) {
+ return;
+ }
+
+ // Get clipping points for both nodes
+ var point1 = findClippingPoint(source, directionX, directionY);
+ var point2 = findClippingPoint(target, -1 * directionX, -1 * directionY);
+
+
+ var lx = point2.x - point1.x;
+ var ly = point2.y - point1.y;
+ var l = Math.sqrt(lx * lx + ly * ly);
+
+ var force = Math.pow(edge.idealLength - l, 2) / edge.elasticity;
+
+ if (0 !== l) {
+ var forceX = force * lx / l;
+ var forceY = force * ly / l;
+ } else {
+ var forceX = 0;
+ var forceY = 0;
+ }
+
+ // Add this force to target and source nodes
+ if( !source.isLocked ){
+ source.offsetX += forceX;
+ source.offsetY += forceY;
+ }
+
+ if( !target.isLocked ){
+ target.offsetX -= forceX;
+ target.offsetY -= forceY;
+ }
+
+ // var s = 'Edge force between nodes ' + source.id + ' and ' + target.id;
+ // s += "\nDistance: " + l + " Force: (" + forceX + ", " + forceY + ")";
+ // logDebug(s);
+ }
+ };
+
+ /**
+ * @brief : Computes gravity forces for all nodes
+ */
+ var calculateGravityForces = function(layoutInfo, options) {
+ var distThreshold = 1;
+
+ // var s = 'calculateGravityForces';
+ // logDebug(s);
+ for (var i = 0; i < layoutInfo.graphSet.length; i ++) {
+ var graph = layoutInfo.graphSet[i];
+ var numNodes = graph.length;
+
+ // s = "Set: " + graph.toString();
+ // logDebug(s);
+
+ // Compute graph center
+ if (0 === i) {
+ var centerX = layoutInfo.clientHeight / 2;
+ var centerY = layoutInfo.clientWidth / 2;
+ } else {
+ // Get Parent node for this graph, and use its position as center
+ var temp = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[0]]];
+ var parent = layoutInfo.layoutNodes[layoutInfo.idToIndex[temp.parentId]];
+ var centerX = parent.positionX;
+ var centerY = parent.positionY;
+ }
+ // s = "Center found at: " + centerX + ", " + centerY;
+ // logDebug(s);
+
+ // Apply force to all nodes in graph
+ for (var j = 0; j < numNodes; j++) {
+ var node = layoutInfo.layoutNodes[layoutInfo.idToIndex[graph[j]]];
+ // s = "Node: " + node.id;
+
+ if( node.isLocked ){ continue; }
+
+ var dx = centerX - node.positionX;
+ var dy = centerY - node.positionY;
+ var d = Math.sqrt(dx * dx + dy * dy);
+ if (d > distThreshold) {
+ var fx = options.gravity * dx / d;
+ var fy = options.gravity * dy / d;
+ node.offsetX += fx;
+ node.offsetY += fy;
+ // s += ": Applied force: " + fx + ", " + fy;
+ } else {
+ // s += ": skypped since it's too close to center";
+ }
+ // logDebug(s);
+ }
+ }
+ };
+
+ /**
+ * @brief : This function propagates the existing offsets from
+ * parent nodes to its descendents.
+ * @arg layoutInfo : layoutInfo Object
+ * @arg cy : cytoscape Object
+ * @arg options : Layout options
+ */
+ var propagateForces = function(layoutInfo, options) {
+ // Inline implementation of a queue, used for traversing the graph in BFS order
+ var queue = [];
+ var start = 0; // Points to the start the queue
+ var end = -1; // Points to the end of the queue
+
+ // logDebug('propagateForces');
+
+ // Start by visiting the nodes in the root graph
+ queue.push.apply(queue, layoutInfo.graphSet[0]);
+ end += layoutInfo.graphSet[0].length;
+
+ // Traverse the graph, level by level,
+ while (start <= end) {
+ // Get the node to visit and remove it from queue
+ var nodeId = queue[start++];
+ var nodeIndex = layoutInfo.idToIndex[nodeId];
+ var node = layoutInfo.layoutNodes[nodeIndex];
+ var children = node.children;
+
+ // We only need to process the node if it's compound
+ if (0 < children.length && !node.isLocked) {
+ var offX = node.offsetX;
+ var offY = node.offsetY;
+
+ // var s = "Propagating offset from parent node : " + node.id +
+ // ". OffsetX: " + offX + ". OffsetY: " + offY;
+ // s += "\n Children: " + children.toString();
+ // logDebug(s);
+
+ for (var i = 0; i < children.length; i++) {
+ var childNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[children[i]]];
+ // Propagate offset
+ childNode.offsetX += offX;
+ childNode.offsetY += offY;
+ // Add children to queue to be visited
+ queue[++end] = children[i];
+ }
+
+ // Reset parent offsets
+ node.offsetX = 0;
+ node.offsetY = 0;
+ }
+
+ }
+ };
+
+ /**
+ * @brief : Updates the layout model positions, based on
+ * the accumulated forces
+ */
+ var updatePositions = function(layoutInfo, options) {
+ // var s = 'Updating positions';
+ // logDebug(s);
+
+ // Reset boundaries for compound nodes
+ for (var i = 0; i < layoutInfo.nodeSize; i++) {
+ var n = layoutInfo.layoutNodes[i];
+ if (0 < n.children.length) {
+ // logDebug("Resetting boundaries of compound node: " + n.id);
+ n.maxX = undefined;
+ n.minX = undefined;
+ n.maxY = undefined;
+ n.minY = undefined;
+ }
+ }
+
+ for (var i = 0; i < layoutInfo.nodeSize; i++) {
+ var n = layoutInfo.layoutNodes[i];
+ if (0 < n.children.length || n.isLocked) {
+ // No need to set compound or locked node position
+ // logDebug("Skipping position update of node: " + n.id);
+ continue;
+ }
+ // s = "Node: " + n.id + " Previous position: (" +
+ // n.positionX + ", " + n.positionY + ").";
+
+ // Limit displacement in order to improve stability
+ var tempForce = limitForce(n.offsetX, n.offsetY, layoutInfo.temperature);
+ n.positionX += tempForce.x;
+ n.positionY += tempForce.y;
+ n.offsetX = 0;
+ n.offsetY = 0;
+ n.minX = n.positionX - n.width;
+ n.maxX = n.positionX + n.width;
+ n.minY = n.positionY - n.height;
+ n.maxY = n.positionY + n.height;
+ // s += " New Position: (" + n.positionX + ", " + n.positionY + ").";
+ // logDebug(s);
+
+ // Update ancestry boudaries
+ updateAncestryBoundaries(n, layoutInfo);
+ }
+
+ // Update size, position of compund nodes
+ for (var i = 0; i < layoutInfo.nodeSize; i++) {
+ var n = layoutInfo.layoutNodes[i];
+ if ( 0 < n.children.length && !n.isLocked ) {
+ n.positionX = (n.maxX + n.minX) / 2;
+ n.positionY = (n.maxY + n.minY) / 2;
+ n.width = n.maxX - n.minX;
+ n.height = n.maxY - n.minY;
+ // s = "Updating position, size of compound node " + n.id;
+ // s += "\nPositionX: " + n.positionX + ", PositionY: " + n.positionY;
+ // s += "\nWidth: " + n.width + ", Height: " + n.height;
+ // logDebug(s);
+ }
+ }
+ };
+
+ /**
+ * @brief : Limits a force (forceX, forceY) to be not
+ * greater (in modulo) than max.
+ 8 Preserves force direction.
+ */
+ var limitForce = function(forceX, forceY, max) {
+ // var s = "Limiting force: (" + forceX + ", " + forceY + "). Max: " + max;
+ var force = Math.sqrt(forceX * forceX + forceY * forceY);
+
+ if (force > max) {
+ var res = {
+ x : max * forceX / force,
+ y : max * forceY / force
+ };
+
+ } else {
+ var res = {
+ x : forceX,
+ y : forceY
+ };
+ }
+
+ // s += ".\nResult: (" + res.x + ", " + res.y + ")";
+ // logDebug(s);
+
+ return res;
+ };
+
+ /**
+ * @brief : Function used for keeping track of compound node
+ * sizes, since they should bound all their subnodes.
+ */
+ var updateAncestryBoundaries = function(node, layoutInfo) {
+ // var s = "Propagating new position/size of node " + node.id;
+ var parentId = node.parentId;
+ if (null == parentId) {
+ // If there's no parent, we are done
+ // s += ". No parent node.";
+ // logDebug(s);
+ return;
+ }
+
+ // Get Parent Node
+ var p = layoutInfo.layoutNodes[layoutInfo.idToIndex[parentId]];
+ var flag = false;
+
+ // MaxX
+ if (null == p.maxX || node.maxX + p.padRight > p.maxX) {
+ p.maxX = node.maxX + p.padRight;
+ flag = true;
+ // s += "\nNew maxX for parent node " + p.id + ": " + p.maxX;
+ }
+
+ // MinX
+ if (null == p.minX || node.minX - p.padLeft < p.minX) {
+ p.minX = node.minX - p.padLeft;
+ flag = true;
+ // s += "\nNew minX for parent node " + p.id + ": " + p.minX;
+ }
+
+ // MaxY
+ if (null == p.maxY || node.maxY + p.padBottom > p.maxY) {
+ p.maxY = node.maxY + p.padBottom;
+ flag = true;
+ // s += "\nNew maxY for parent node " + p.id + ": " + p.maxY;
+ }
+
+ // MinY
+ if (null == p.minY || node.minY - p.padTop < p.minY) {
+ p.minY = node.minY - p.padTop;
+ flag = true;
+ // s += "\nNew minY for parent node " + p.id + ": " + p.minY;
+ }
+
+ // If updated boundaries, propagate changes upward
+ if (flag) {
+ // logDebug(s);
+ return updateAncestryBoundaries(p, layoutInfo);
+ }
+
+ // s += ". No changes in boundaries/position of parent node " + p.id;
+ // logDebug(s);
+ return;
+ };
+
+ var separateComponents = function(layutInfo, options){
+ var nodes = layoutInfo.layoutNodes;
+ var components = [];
+
+ for( var i = 0; i < nodes.length; i++ ){
+ var node = nodes[i];
+ var cid = node.cmptId;
+ var component = components[ cid ] = components[ cid ] || [];
+
+ component.push( node );
+ }
+
+ var totalA = 0;
+
+ for( var i = 0; i < components.length; i++ ){
+ var c = components[i];
+ c.x1 = Infinity;
+ c.x2 = -Infinity;
+ c.y1 = Infinity;
+ c.y2 = -Infinity;
+
+ for( var j = 0; j < c.length; j++ ){
+ var n = c[j];
+
+ c.x1 = Math.min( c.x1, n.positionX - n.width/2 );
+ c.x2 = Math.max( c.x2, n.positionX + n.width/2 );
+ c.y1 = Math.min( c.y1, n.positionY - n.height/2 );
+ c.y2 = Math.max( c.y2, n.positionY + n.height/2 );
+ }
+
+ c.w = c.x2 - c.x1;
+ c.h = c.y2 - c.y1;
+
+ totalA += c.w * c.h;
+ }
+
+ components.sort(function( c1, c2 ){
+ return c2.w*c2.h - c1.w*c1.h;
+ });
+
+ var x = 0;
+ var y = 0;
+ var usedW = 0;
+ var rowH = 0;
+ var maxRowW = Math.sqrt( totalA ) * layoutInfo.clientWidth / layoutInfo.clientHeight;
+
+ for( var i = 0; i < components.length; i++ ){
+ var c = components[i];
+
+ for( var j = 0; j < c.length; j++ ){
+ var n = c[j];
+
+ if( !n.isLocked ){
+ n.positionX += x;
+ n.positionY += y;
+ }
+ }
+
+ x += c.w + options.componentSpacing;
+ usedW += c.w + options.componentSpacing;
+ rowH = Math.max( rowH, c.h );
+
+ if( usedW > maxRowW ){
+ y += rowH + options.componentSpacing;
+ x = 0;
+ usedW = 0;
+ rowH = 0;
+ }
+ }
+ };
+
+ var mainLoop = function(i){
+ if( stopped ){
+ // logDebug("Layout manually stopped. Stopping computation in step " + i);
+ return false;
+ }
+
+ // Do one step in the phisical simulation
+ step(layoutInfo, options, i);
+
+ // Update temperature
+ layoutInfo.temperature = layoutInfo.temperature * options.coolingFactor;
+ // logDebug("New temperature: " + layoutInfo.temperature);
+
+ if (layoutInfo.temperature < options.minTemp) {
+ // logDebug("Temperature drop below minimum threshold. Stopping computation in step " + i);
+ return false;
+ }
+
+ return true;
+ };
+
+ var i = 0;
+ var loopRet;
+
+ do {
+ var f = 0;
+
+ while( f < options.refresh && i < options.numIter ){
+ var loopRet = mainLoop(i);
+ if( !loopRet ){ break; }
+
+ f++;
+ i++;
+ }
+
+ if( options.animate ){
+ broadcast( layoutInfo.layoutNodes ); // jshint ignore:line
+ }
+
+ } while ( loopRet && i + 1 < options.numIter );
+
+ separateComponents( layoutInfo, options );
+
+ return layoutInfo;
+ }).then(function( layoutInfoUpdated ){
+ layoutInfo.layoutNodes = layoutInfoUpdated.layoutNodes; // get the positions
+
+ thread.stop();
+ done();
+ });
+
+ var done = function(){
+ refresh({ force: true });
+
+ // Layout has finished
+ layout.one('layoutstop', options.stop);
+ layout.trigger({ type: 'layoutstop', layout: layout });
+ };
+
+ return this; // chaining
+};
+
+
+/**
+ * @brief : called on continuous layouts to stop them before they finish
+ */
+CoseLayout.prototype.stop = function(){
+ this.stopped = true;
+
+ if( this.thread ){
+ this.thread.stop();
+ }
+
+ this.trigger('layoutstop');
+
+ return this; // chaining
+};
+
+CoseLayout.prototype.destroy = function(){
+ if( this.thread ){
+ this.thread.stop();
+ }
+
+ return this; // chaining
+};
+
+
+/**
+ * @brief : Creates an object which is contains all the data
+ * used in the layout process
+ * @arg cy : cytoscape.js object
+ * @return : layoutInfo object initialized
+ */
+var createLayoutInfo = function(cy, layout, options) {
+ // Shortcut
+ var edges = options.eles.edges();
+ var nodes = options.eles.nodes();
+
+ var layoutInfo = {
+ isCompound : cy.hasCompoundNodes(),
+ layoutNodes : [],
+ idToIndex : {},
+ nodeSize : nodes.size(),
+ graphSet : [],
+ indexToGraph : [],
+ layoutEdges : [],
+ edgeSize : edges.size(),
+ temperature : options.initialTemp,
+ clientWidth : cy.width(),
+ clientHeight : cy.width(),
+ boundingBox : math.makeBoundingBox( options.boundingBox ? options.boundingBox : {
+ x1: 0, y1: 0, w: cy.width(), h: cy.height()
+ } )
+ };
+
+ var components = options.eles.components();
+ var id2cmptId = {};
+
+ for( var i = 0; i < components.length; i++ ){
+ var component = components[i];
+
+ for( var j = 0; j < component.length; j++ ){
+ var node = component[j];
+
+ id2cmptId[ node.id() ] = i;
+ }
+ }
+
+ // Iterate over all nodes, creating layout nodes
+ for (var i = 0; i < layoutInfo.nodeSize; i++) {
+ var n = nodes[i];
+ var nbb = n.boundingBox();
+
+ var tempNode = {};
+ tempNode.isLocked = n.locked();
+ tempNode.id = n.data('id');
+ tempNode.parentId = n.data('parent');
+ tempNode.cmptId = id2cmptId[ n.id() ];
+ tempNode.children = [];
+ tempNode.positionX = n.position('x');
+ tempNode.positionY = n.position('y');
+ tempNode.offsetX = 0;
+ tempNode.offsetY = 0;
+ tempNode.height = nbb.w;
+ tempNode.width = nbb.h;
+ tempNode.maxX = tempNode.positionX + tempNode.width / 2;
+ tempNode.minX = tempNode.positionX - tempNode.width / 2;
+ tempNode.maxY = tempNode.positionY + tempNode.height / 2;
+ tempNode.minY = tempNode.positionY - tempNode.height / 2;
+ tempNode.padLeft = parseFloat( n.style('padding-left') );
+ tempNode.padRight = parseFloat( n.style('padding-right') );
+ tempNode.padTop = parseFloat( n.style('padding-top') );
+ tempNode.padBottom = parseFloat( n.style('padding-bottom') );
+
+ // forces
+ tempNode.nodeRepulsion = is.fn( options.nodeRepulsion ) ? options.nodeRepulsion.call( n, n ) : options.nodeRepulsion;
+
+ // Add new node
+ layoutInfo.layoutNodes.push(tempNode);
+ // Add entry to id-index map
+ layoutInfo.idToIndex[tempNode.id] = i;
+ }
+
+ // Inline implementation of a queue, used for traversing the graph in BFS order
+ var queue = [];
+ var start = 0; // Points to the start the queue
+ var end = -1; // Points to the end of the queue
+
+ var tempGraph = [];
+
+ // Second pass to add child information and
+ // initialize queue for hierarchical traversal
+ for (var i = 0; i < layoutInfo.nodeSize; i++) {
+ var n = layoutInfo.layoutNodes[i];
+ var p_id = n.parentId;
+ // Check if node n has a parent node
+ if (null != p_id) {
+ // Add node Id to parent's list of children
+ layoutInfo.layoutNodes[layoutInfo.idToIndex[p_id]].children.push(n.id);
+ } else {
+ // If a node doesn't have a parent, then it's in the root graph
+ queue[++end] = n.id;
+ tempGraph.push(n.id);
+ }
+ }
+
+ // Add root graph to graphSet
+ layoutInfo.graphSet.push(tempGraph);
+
+ // Traverse the graph, level by level,
+ while (start <= end) {
+ // Get the node to visit and remove it from queue
+ var node_id = queue[start++];
+ var node_ix = layoutInfo.idToIndex[node_id];
+ var node = layoutInfo.layoutNodes[node_ix];
+ var children = node.children;
+ if (children.length > 0) {
+ // Add children nodes as a new graph to graph set
+ layoutInfo.graphSet.push(children);
+ // Add children to que queue to be visited
+ for (var i = 0; i < children.length; i++) {
+ queue[++end] = children[i];
+ }
+ }
+ }
+
+ // Create indexToGraph map
+ for (var i = 0; i < layoutInfo.graphSet.length; i++) {
+ var graph = layoutInfo.graphSet[i];
+ for (var j = 0; j < graph.length; j++) {
+ var index = layoutInfo.idToIndex[graph[j]];
+ layoutInfo.indexToGraph[index] = i;
+ }
+ }
+
+ // Iterate over all edges, creating Layout Edges
+ for (var i = 0; i < layoutInfo.edgeSize; i++) {
+ var e = edges[i];
+ var tempEdge = {};
+ tempEdge.id = e.data('id');
+ tempEdge.sourceId = e.data('source');
+ tempEdge.targetId = e.data('target');
+
+ // Compute ideal length
+ var idealLength = is.fn( options.idealEdgeLength ) ? options.idealEdgeLength.call( e, e ) : options.idealEdgeLength;
+ var elasticity = is.fn( options.edgeElasticity ) ? options.edgeElasticity.call( e, e ) : options.edgeElasticity;
+
+ // Check if it's an inter graph edge
+ var sourceIx = layoutInfo.idToIndex[tempEdge.sourceId];
+ var targetIx = layoutInfo.idToIndex[tempEdge.targetId];
+ var sourceGraph = layoutInfo.indexToGraph[sourceIx];
+ var targetGraph = layoutInfo.indexToGraph[targetIx];
+
+ if (sourceGraph != targetGraph) {
+ // Find lowest common graph ancestor
+ var lca = findLCA(tempEdge.sourceId, tempEdge.targetId, layoutInfo);
+
+ // Compute sum of node depths, relative to lca graph
+ var lcaGraph = layoutInfo.graphSet[lca];
+ var depth = 0;
+
+ // Source depth
+ var tempNode = layoutInfo.layoutNodes[sourceIx];
+ while ( -1 === lcaGraph.indexOf(tempNode.id) ) {
+ tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];
+ depth++;
+ }
+
+ // Target depth
+ tempNode = layoutInfo.layoutNodes[targetIx];
+ while ( -1 === lcaGraph.indexOf(tempNode.id) ) {
+ tempNode = layoutInfo.layoutNodes[layoutInfo.idToIndex[tempNode.parentId]];
+ depth++;
+ }
+
+ // logDebug('LCA of nodes ' + tempEdge.sourceId + ' and ' + tempEdge.targetId +
+ // ". Index: " + lca + " Contents: " + lcaGraph.toString() +
+ // ". Depth: " + depth);
+
+ // Update idealLength
+ idealLength *= depth * options.nestingFactor;
+ }
+
+ tempEdge.idealLength = idealLength;
+ tempEdge.elasticity = elasticity;
+
+ layoutInfo.layoutEdges.push(tempEdge);
+ }
+
+ // Finally, return layoutInfo object
+ return layoutInfo;
+};
+
+
+/**
+ * @brief : This function finds the index of the lowest common
+ * graph ancestor between 2 nodes in the subtree
+ * (from the graph hierarchy induced tree) whose
+ * root is graphIx
+ *
+ * @arg node1: node1's ID
+ * @arg node2: node2's ID
+ * @arg layoutInfo: layoutInfo object
+ *
+ */
+var findLCA = function(node1, node2, layoutInfo) {
+ // Find their common ancester, starting from the root graph
+ var res = findLCA_aux(node1, node2, 0, layoutInfo);
+ if (2 > res.count) {
+ // If aux function couldn't find the common ancester,
+ // then it is the root graph
+ return 0;
+ } else {
+ return res.graph;
+ }
+};
+
+
+/**
+ * @brief : Auxiliary function used for LCA computation
+ *
+ * @arg node1 : node1's ID
+ * @arg node2 : node2's ID
+ * @arg graphIx : subgraph index
+ * @arg layoutInfo : layoutInfo object
+ *
+ * @return : object of the form {count: X, graph: Y}, where:
+ * X is the number of ancesters (max: 2) found in
+ * graphIx (and it's subgraphs),
+ * Y is the graph index of the lowest graph containing
+ * all X nodes
+ */
+var findLCA_aux = function(node1, node2, graphIx, layoutInfo) {
+ var graph = layoutInfo.graphSet[graphIx];
+ // If both nodes belongs to graphIx
+ if (-1 < graph.indexOf(node1) && -1 < graph.indexOf(node2)) {
+ return {count:2, graph:graphIx};
+ }
+
+ // Make recursive calls for all subgraphs
+ var c = 0;
+ for (var i = 0; i < graph.length; i++) {
+ var nodeId = graph[i];
+ var nodeIx = layoutInfo.idToIndex[nodeId];
+ var children = layoutInfo.layoutNodes[nodeIx].children;
+
+ // If the node has no child, skip it
+ if (0 === children.length) {
+ continue;
+ }
+
+ var childGraphIx = layoutInfo.indexToGraph[layoutInfo.idToIndex[children[0]]];
+ var result = findLCA_aux(node1, node2, childGraphIx, layoutInfo);
+ if (0 === result.count) {
+ // Neither node1 nor node2 are present in this subgraph
+ continue;
+ } else if (1 === result.count) {
+ // One of (node1, node2) is present in this subgraph
+ c++;
+ if (2 === c) {
+ // We've already found both nodes, no need to keep searching
+ break;
+ }
+ } else {
+ // Both nodes are present in this subgraph
+ return result;
+ }
+ }
+
+ return {count:c, graph:graphIx};
+};
+
+
+/**
+ * @brief: printsLayoutInfo into js console
+ * Only used for debbuging
+ */
+var printLayoutInfo = function(layoutInfo) {
+ /* jshint ignore:start */
+
+ if (!DEBUG) {
+ return;
+ }
+ console.debug("layoutNodes:");
+ for (var i = 0; i < layoutInfo.nodeSize; i++) {
+ var n = layoutInfo.layoutNodes[i];
+ var s =
+ "\nindex: " + i +
+ "\nId: " + n.id +
+ "\nChildren: " + n.children.toString() +
+ "\nparentId: " + n.parentId +
+ "\npositionX: " + n.positionX +
+ "\npositionY: " + n.positionY +
+ "\nOffsetX: " + n.offsetX +
+ "\nOffsetY: " + n.offsetY +
+ "\npadLeft: " + n.padLeft +
+ "\npadRight: " + n.padRight +
+ "\npadTop: " + n.padTop +
+ "\npadBottom: " + n.padBottom;
+
+ console.debug(s);
+ }
+
+ console.debug('idToIndex');
+ for (var i in layoutInfo.idToIndex) {
+ console.debug("Id: " + i + "\nIndex: " + layoutInfo.idToIndex[i]);
+ }
+
+ console.debug('Graph Set');
+ var set = layoutInfo.graphSet;
+ for (var i = 0; i < set.length; i ++) {
+ console.debug("Set : " + i + ": " + set[i].toString());
+ }
+
+ var s = 'IndexToGraph';
+ for (var i = 0; i < layoutInfo.indexToGraph.length; i ++) {
+ s += "\nIndex : " + i + " Graph: "+ layoutInfo.indexToGraph[i];
+ }
+ console.debug(s);
+
+ s = 'Layout Edges';
+ for (var i = 0; i < layoutInfo.layoutEdges.length; i++) {
+ var e = layoutInfo.layoutEdges[i];
+ s += "\nEdge Index: " + i + " ID: " + e.id +
+ " SouceID: " + e.sourceId + " TargetId: " + e.targetId +
+ " Ideal Length: " + e.idealLength;
+ }
+ console.debug(s);
+
+ s = "nodeSize: " + layoutInfo.nodeSize;
+ s += "\nedgeSize: " + layoutInfo.edgeSize;
+ s += "\ntemperature: " + layoutInfo.temperature;
+ console.debug(s);
+
+ return;
+ /* jshint ignore:end */
+};
+
+
+/**
+ * @brief : Randomizes the position of all nodes
+ */
+var randomizePositions = function(layoutInfo, cy) {
+ var width = layoutInfo.clientWidth;
+ var height = layoutInfo.clientHeight;
+
+ for (var i = 0; i < layoutInfo.nodeSize; i++) {
+ var n = layoutInfo.layoutNodes[i];
+
+ // No need to randomize compound nodes or locked nodes
+ if ( 0 === n.children.length && !n.isLocked ) {
+ n.positionX = Math.random() * width;
+ n.positionY = Math.random() * height;
+ }
+ }
+};
+
+
+/**
+ * @brief : Updates the positions of nodes in the network
+ * @arg layoutInfo : LayoutInfo object
+ * @arg cy : Cytoscape object
+ * @arg options : Layout options
+ */
+var refreshPositions = function(layoutInfo, cy, options) {
+ // var s = 'Refreshing positions';
+ // logDebug(s);
+
+ var layout = options.layout;
+ var nodes = options.eles.nodes();
+ var bb = layoutInfo.boundingBox;
+ var coseBB = { x1: Infinity, x2: -Infinity, y1: Infinity, y2: -Infinity };
+
+ if( options.boundingBox ){
+ nodes.forEach(function( node ){
+ var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[node.data('id')]];
+
+ coseBB.x1 = Math.min( coseBB.x1, lnode.positionX );
+ coseBB.x2 = Math.max( coseBB.x2, lnode.positionX );
+
+ coseBB.y1 = Math.min( coseBB.y1, lnode.positionY );
+ coseBB.y2 = Math.max( coseBB.y2, lnode.positionY );
+ });
+
+ coseBB.w = coseBB.x2 - coseBB.x1;
+ coseBB.h = coseBB.y2 - coseBB.y1;
+ }
+
+ nodes.positions(function(i, ele) {
+ var lnode = layoutInfo.layoutNodes[layoutInfo.idToIndex[ele.data('id')]];
+ // s = "Node: " + lnode.id + ". Refreshed position: (" +
+ // lnode.positionX + ", " + lnode.positionY + ").";
+ // logDebug(s);
+
+ if( options.boundingBox ){ // then add extra bounding box constraint
+ var pctX = (lnode.positionX - coseBB.x1) / coseBB.w;
+ var pctY = (lnode.positionY - coseBB.y1) / coseBB.h;
+
+ return {
+ x: bb.x1 + pctX * bb.w,
+ y: bb.y1 + pctY * bb.h
+ };
+ } else {
+ return {
+ x: lnode.positionX,
+ y: lnode.positionY
+ };
+ }
+ });
+
+ // Trigger layoutReady only on first call
+ if (true !== layoutInfo.ready) {
+ // s = 'Triggering layoutready';
+ // logDebug(s);
+ layoutInfo.ready = true;
+ layout.one('layoutready', options.ready);
+ layout.trigger({ type: 'layoutready', layout: this });
+ }
+};
+
+/**
+ * @brief : Logs a debug message in JS console, if DEBUG is ON
+ */
+// var logDebug = function(text) {
+// if (DEBUG) {
+// console.debug(text);
+// }
+// };
+
+module.exports = CoseLayout;
+
+},{"../../is":77,"../../math":79,"../../thread":92,"../../util":94}],49:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../../util');
+var math = _dereq_('../../math');
+
+var defaults = {
+ fit: true, // whether to fit the viewport to the graph
+ padding: 30, // padding used on fit
+ boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
+ avoidOverlap: true, // prevents node overlap, may overflow boundingBox if not enough space
+ avoidOverlapPadding: 10, // extra spacing around nodes when avoidOverlap: true
+ condense: false, // uses all available space on false, uses minimal space on true
+ rows: undefined, // force num of rows in the grid
+ cols: undefined, // force num of columns in the grid
+ position: function( node ){}, // returns { row, col } for element
+ sort: undefined, // a sorting function to order the nodes; e.g. function(a, b){ return a.data('weight') - b.data('weight') }
+ animate: false, // whether to transition the node positions
+ animationDuration: 500, // duration of animation in ms if enabled
+ animationEasing: undefined, // easing of animation if enabled
+ ready: undefined, // callback on layoutready
+ stop: undefined // callback on layoutstop
+};
+
+function GridLayout( options ){
+ this.options = util.extend({}, defaults, options);
+}
+
+GridLayout.prototype.run = function(){
+ var params = this.options;
+ var options = params;
+
+ var cy = params.cy;
+ var eles = options.eles;
+ var nodes = eles.nodes().not(':parent');
+
+ if( options.sort ){
+ nodes = nodes.sort( options.sort );
+ }
+
+ var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {
+ x1: 0, y1: 0, w: cy.width(), h: cy.height()
+ } );
+
+ if( bb.h === 0 || bb.w === 0){
+ nodes.layoutPositions(this, options, function(){
+ return { x: bb.x1, y: bb.y1 };
+ });
+
+ } else {
+
+ // width/height * splits^2 = cells where splits is number of times to split width
+ var cells = nodes.size();
+ var splits = Math.sqrt( cells * bb.h/bb.w );
+ var rows = Math.round( splits );
+ var cols = Math.round( bb.w/bb.h * splits );
+
+ var small = function(val){
+ if( val == null ){
+ return Math.min(rows, cols);
+ } else {
+ var min = Math.min(rows, cols);
+ if( min == rows ){
+ rows = val;
+ } else {
+ cols = val;
+ }
+ }
+ };
+
+ var large = function(val){
+ if( val == null ){
+ return Math.max(rows, cols);
+ } else {
+ var max = Math.max(rows, cols);
+ if( max == rows ){
+ rows = val;
+ } else {
+ cols = val;
+ }
+ }
+ };
+
+ var oRows = options.rows;
+ var oCols = options.cols != null ? options.cols : options.columns;
+
+ // if rows or columns were set in options, use those values
+ if( oRows != null && oCols != null ){
+ rows = oRows;
+ cols = oCols;
+ } else if( oRows != null && oCols == null ){
+ rows = oRows;
+ cols = Math.ceil( cells / rows );
+ } else if( oRows == null && oCols != null ){
+ cols = oCols;
+ rows = Math.ceil( cells / cols );
+ }
+
+ // otherwise use the automatic values and adjust accordingly
+
+ // if rounding was up, see if we can reduce rows or columns
+ else if( cols * rows > cells ){
+ var sm = small();
+ var lg = large();
+
+ // reducing the small side takes away the most cells, so try it first
+ if( (sm - 1) * lg >= cells ){
+ small(sm - 1);
+ } else if( (lg - 1) * sm >= cells ){
+ large(lg - 1);
+ }
+ } else {
+
+ // if rounding was too low, add rows or columns
+ while( cols * rows < cells ){
+ var sm = small();
+ var lg = large();
+
+ // try to add to larger side first (adds less in multiplication)
+ if( (lg + 1) * sm >= cells ){
+ large(lg + 1);
+ } else {
+ small(sm + 1);
+ }
+ }
+ }
+
+ var cellWidth = bb.w / cols;
+ var cellHeight = bb.h / rows;
+
+ if( options.condense ){
+ cellWidth = 0;
+ cellHeight = 0;
+ }
+
+ if( options.avoidOverlap ){
+ for( var i = 0; i < nodes.length; i++ ){
+ var node = nodes[i];
+ var pos = node._private.position;
+
+ if( pos.x == null || pos.y == null ){ // for bb
+ pos.x = 0;
+ pos.y = 0;
+ }
+
+ var nbb = node.boundingBox();
+ var p = options.avoidOverlapPadding;
+
+ var w = nbb.w + p;
+ var h = nbb.h + p;
+
+ cellWidth = Math.max( cellWidth, w );
+ cellHeight = Math.max( cellHeight, h );
+ }
+ }
+
+ var cellUsed = {}; // e.g. 'c-0-2' => true
+
+ var used = function(row, col){
+ return cellUsed['c-' + row + '-' + col] ? true : false;
+ };
+
+ var use = function(row, col){
+ cellUsed['c-' + row + '-' + col] = true;
+ };
+
+ // to keep track of current cell position
+ var row = 0;
+ var col = 0;
+ var moveToNextCell = function(){
+ col++;
+ if( col >= cols ){
+ col = 0;
+ row++;
+ }
+ };
+
+ // get a cache of all the manual positions
+ var id2manPos = {};
+ for( var i = 0; i < nodes.length; i++ ){
+ var node = nodes[i];
+ var rcPos = options.position( node );
+
+ if( rcPos && (rcPos.row !== undefined || rcPos.col !== undefined) ){ // must have at least row or col def'd
+ var pos = {
+ row: rcPos.row,
+ col: rcPos.col
+ };
+
+ if( pos.col === undefined ){ // find unused col
+ pos.col = 0;
+
+ while( used(pos.row, pos.col) ){
+ pos.col++;
+ }
+ } else if( pos.row === undefined ){ // find unused row
+ pos.row = 0;
+
+ while( used(pos.row, pos.col) ){
+ pos.row++;
+ }
+ }
+
+ id2manPos[ node.id() ] = pos;
+ use( pos.row, pos.col );
+ }
+ }
+
+ var getPos = function(i, element){
+ var x, y;
+
+ if( element.locked() || element.isFullAutoParent() ){
+ return false;
+ }
+
+ // see if we have a manual position set
+ var rcPos = id2manPos[ element.id() ];
+ if( rcPos ){
+ x = rcPos.col * cellWidth + cellWidth/2 + bb.x1;
+ y = rcPos.row * cellHeight + cellHeight/2 + bb.y1;
+
+ } else { // otherwise set automatically
+
+ while( used(row, col) ){
+ moveToNextCell();
+ }
+
+ x = col * cellWidth + cellWidth/2 + bb.x1;
+ y = row * cellHeight + cellHeight/2 + bb.y1;
+ use( row, col );
+
+ moveToNextCell();
+ }
+
+ return { x: x, y: y };
+
+ };
+
+ nodes.layoutPositions( this, options, getPos );
+ }
+
+ return this; // chaining
+
+};
+
+module.exports = GridLayout;
+
+},{"../../math":79,"../../util":94}],50:[function(_dereq_,module,exports){
+'use strict';
+
+module.exports = [
+ { name: 'breadthfirst', impl: _dereq_('./breadthfirst') },
+ { name: 'circle', impl: _dereq_('./circle') },
+ { name: 'concentric',impl: _dereq_('./concentric') },
+ { name: 'cose', impl: _dereq_('./cose') },
+ { name: 'grid', impl: _dereq_('./grid') },
+ { name: 'null', impl: _dereq_('./null') },
+ { name: 'preset', impl: _dereq_('./preset') },
+ { name: 'random', impl: _dereq_('./random') }
+];
+
+},{"./breadthfirst":45,"./circle":46,"./concentric":47,"./cose":48,"./grid":49,"./null":51,"./preset":52,"./random":53}],51:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../../util');
+
+// default layout options
+var defaults = {
+ ready: function(){}, // on layoutready
+ stop: function(){} // on layoutstop
+};
+
+// constructor
+// options : object containing layout options
+function NullLayout( options ){
+ this.options = util.extend({}, defaults, options);
+}
+
+// runs the layout
+NullLayout.prototype.run = function(){
+ var options = this.options;
+ var eles = options.eles; // elements to consider in the layout
+ var layout = this;
+
+ // cy is automatically populated for us in the constructor
+ var cy = options.cy; // jshint ignore:line
+
+ layout.trigger('layoutstart');
+
+ // puts all nodes at (0, 0)
+ eles.nodes().positions(function(){
+ return {
+ x: 0,
+ y: 0
+ };
+ });
+
+ // trigger layoutready when each node has had its position set at least once
+ layout.one('layoutready', options.ready);
+ layout.trigger('layoutready');
+
+ // trigger layoutstop when the layout stops (e.g. finishes)
+ layout.one('layoutstop', options.stop);
+ layout.trigger('layoutstop');
+
+ return this; // chaining
+};
+
+// called on continuous layouts to stop them before they finish
+NullLayout.prototype.stop = function(){
+ return this; // chaining
+};
+
+module.exports = NullLayout;
+
+},{"../../util":94}],52:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../../util');
+var is = _dereq_('../../is');
+
+var defaults = {
+ positions: undefined, // map of (node id) => (position obj); or function(node){ return somPos; }
+ zoom: undefined, // the zoom level to set (prob want fit = false if set)
+ pan: undefined, // the pan level to set (prob want fit = false if set)
+ fit: true, // whether to fit to viewport
+ padding: 30, // padding on fit
+ animate: false, // whether to transition the node positions
+ animationDuration: 500, // duration of animation in ms if enabled
+ animationEasing: undefined, // easing of animation if enabled
+ ready: undefined, // callback on layoutready
+ stop: undefined // callback on layoutstop
+};
+
+function PresetLayout( options ){
+ this.options = util.extend({}, defaults, options);
+}
+
+PresetLayout.prototype.run = function(){
+ var options = this.options;
+ var eles = options.eles;
+
+ var nodes = eles.nodes();
+ var posIsFn = is.fn( options.positions );
+
+ function getPosition(node){
+ if( options.positions == null ){
+ return null;
+ }
+
+ if( posIsFn ){
+ return options.positions.apply( node, [ node ] );
+ }
+
+ var pos = options.positions[node._private.data.id];
+
+ if( pos == null ){
+ return null;
+ }
+
+ return pos;
+ }
+
+ nodes.layoutPositions(this, options, function(i, node){
+ var position = getPosition(node);
+
+ if( node.locked() || position == null ){
+ return false;
+ }
+
+ return position;
+ });
+
+ return this; // chaining
+};
+
+module.exports = PresetLayout;
+
+},{"../../is":77,"../../util":94}],53:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../../util');
+var math = _dereq_('../../math');
+
+var defaults = {
+ fit: true, // whether to fit to viewport
+ padding: 30, // fit padding
+ boundingBox: undefined, // constrain layout bounds; { x1, y1, x2, y2 } or { x1, y1, w, h }
+ animate: false, // whether to transition the node positions
+ animationDuration: 500, // duration of animation in ms if enabled
+ animationEasing: undefined, // easing of animation if enabled
+ ready: undefined, // callback on layoutready
+ stop: undefined // callback on layoutstop
+};
+
+function RandomLayout( options ){
+ this.options = util.extend({}, defaults, options);
+}
+
+RandomLayout.prototype.run = function(){
+ var options = this.options;
+ var cy = options.cy;
+ var eles = options.eles;
+ var nodes = eles.nodes().not(':parent');
+
+ var bb = math.makeBoundingBox( options.boundingBox ? options.boundingBox : {
+ x1: 0, y1: 0, w: cy.width(), h: cy.height()
+ } );
+
+ var getPos = function( i, node ){
+ return {
+ x: bb.x1 + Math.round( Math.random() * bb.w ),
+ y: bb.y1 + Math.round( Math.random() * bb.h )
+ };
+ };
+
+ nodes.layoutPositions( this, options, getPos );
+
+ return this; // chaining
+};
+
+module.exports = RandomLayout;
+
+},{"../../math":79,"../../util":94}],54:[function(_dereq_,module,exports){
+'use strict';
+
+var math = _dereq_('../../../math');
+var is = _dereq_('../../../is');
+var util = _dereq_('../../../util');
+
+var BRp = {};
+
+BRp.arrowShapeHeight = 0.3;
+
+BRp.registerArrowShapes = function(){
+ var arrowShapes = this.arrowShapes = {};
+ var renderer = this;
+
+ // Contract for arrow shapes:
+ // 0, 0 is arrow tip
+ // (0, 1) is direction towards node
+ // (1, 0) is right
+ //
+ // functional api:
+ // collide: check x, y in shape
+ // roughCollide: called before collide, no false negatives
+ // draw: draw
+ // spacing: dist(arrowTip, nodeBoundary)
+ // gap: dist(edgeTip, nodeBoundary), edgeTip may != arrowTip
+
+ var bbCollide = function( x, y, size, angle, translation, padding ){
+ var x1 = translation.x - size/2 - padding;
+ var x2 = translation.x + size/2 + padding;
+ var y1 = translation.y - size/2 - padding;
+ var y2 = translation.y + size/2 + padding;
+
+ var inside = (x1 <= x && x <= x2) && (y1 <= y && y <= y2);
+
+ return inside;
+ };
+
+ var transform = function( x, y, size, angle, translation ){
+ var xRotated = x * Math.cos(angle) - y * Math.sin(angle);
+ var yRotated = x * Math.sin(angle) + y * Math.cos(angle);
+
+ var xScaled = xRotated * size;
+ var yScaled = yRotated * size;
+
+ var xTranslated = xScaled + translation.x;
+ var yTranslated = yScaled + translation.y;
+
+ return {
+ x: xTranslated,
+ y: yTranslated
+ };
+ };
+
+ var transformPoints = function( pts, size, angle, translation ){
+ var retPts = [];
+
+ for( var i = 0; i < pts.length; i += 2 ){
+ var x = pts[i];
+ var y = pts[i + 1];
+
+ retPts.push( transform(x, y, size, angle, translation) );
+ }
+
+ return retPts;
+ };
+
+ var pointsToArr = function( pts ){
+ var ret = [];
+
+ for( var i = 0; i < pts.length; i++ ){
+ var p = pts[i];
+
+ ret.push( p.x, p.y );
+ }
+
+ return ret;
+ };
+
+ var defineArrowShape = function( name, defn ){
+ if( is.string(defn) ){
+ defn = arrowShapes[ defn ];
+ }
+
+ arrowShapes[ name ] = util.extend( {
+ name: name,
+
+ points: [
+ -0.15, -0.3,
+ 0.15, -0.3,
+ 0.15, 0.3,
+ -0.15, 0.3
+ ],
+
+ collide: function( x, y, size, angle, translation, padding ){
+ var points = pointsToArr( transformPoints( this.points, size + 2*padding, angle, translation ) );
+ var inside = math.pointInsidePolygonPoints( x, y, points );
+
+ return inside;
+ },
+
+ roughCollide: bbCollide,
+
+ draw: function( context, size, angle, translation ){
+ var points = transformPoints( this.points, size, angle, translation );
+
+ renderer.arrowShapeImpl('polygon')( context, points );
+ },
+
+ spacing: function( edge ){
+ return 0;
+ },
+
+ gap: function( edge ){
+ return edge._private.style['width'].pfValue * 2;
+ }
+ }, defn );
+ };
+
+ defineArrowShape( 'none', {
+ collide: util.falsify,
+
+ roughCollide: util.falsify,
+
+ draw: util.noop,
+
+ spacing: util.zeroify,
+
+ gap: util.zeroify
+ } );
+
+ defineArrowShape( 'triangle', {
+ points: [
+ -0.15, -0.3,
+ 0, 0,
+ 0.15, -0.3
+ ]
+ } );
+
+ defineArrowShape( 'arrow', 'triangle' );
+
+ defineArrowShape( 'triangle-backcurve', {
+ points: arrowShapes['triangle'].points,
+
+ controlPoint: [ 0, -0.15 ],
+
+ roughCollide: bbCollide,
+
+ draw: function( context, size, angle, translation ){
+ var ptsTrans = transformPoints( this.points, size, angle, translation );
+ var ctrlPt = this.controlPoint;
+ var ctrlPtTrans = transform( ctrlPt[0], ctrlPt[1], size, angle, translation );
+
+ renderer.arrowShapeImpl( this.name )( context, ptsTrans, ctrlPtTrans );
+ },
+
+ gap: function( edge ){
+ return edge._private.style['width'].pfValue;
+ }
+ } );
+
+
+ defineArrowShape( 'triangle-tee', {
+ points: [
+ -0.15, -0.3,
+ 0, 0,
+ 0.15, -0.3,
+ -0.15, -0.3
+ ],
+
+ pointsTee: [
+ -0.15, -0.4,
+ -0.15, -0.5,
+ 0.15, -0.5,
+ 0.15, -0.4
+ ],
+
+ collide: function( x, y, size, angle, translation, padding ){
+ var triPts = pointsToArr( transformPoints( this.points, size + 2*padding, angle, translation ) );
+ var teePts = pointsToArr( transformPoints( this.pointsTee, size + 2*padding, angle, translation ) );
+
+ var inside = math.pointInsidePolygonPoints( x, y, triPts ) || math.pointInsidePolygonPoints( x, y, teePts );
+
+ return inside;
+ },
+
+ draw: function( context, size, angle, translation ){
+ var triPts = transformPoints( this.points, size, angle, translation );
+ var teePts = transformPoints( this.pointsTee, size, angle, translation );
+
+ renderer.arrowShapeImpl( this.name )( context, triPts, teePts );
+ }
+ } );
+
+ defineArrowShape( 'vee', {
+ points: [
+ -0.15, -0.3,
+ 0, 0,
+ 0.15, -0.3,
+ 0, -0.15,
+ ],
+
+ gap: function( edge ){
+ return edge._private.style['width'].pfValue;
+ }
+ } );
+
+ defineArrowShape( 'half-triangle-overshot', {
+ points: [
+ 0, -0.25,
+ -0.5, -0.25,
+ 0.5, 0.25
+ ],
+
+ leavePathOpen: true,
+
+ matchEdgeWidth: true
+ } );
+
+ defineArrowShape( 'circle', {
+ radius: 0.15,
+
+ collide: function( x, y, size, angle, translation, padding ){
+ var t = translation;
+ var inside = ( Math.pow(t.x - x, 2) + Math.pow(t.y - y, 2) <= Math.pow((size + 2*padding) * this.radius, 2) );
+
+ return inside;
+ },
+
+ draw: function( context, size, angle, translation ){
+ renderer.arrowShapeImpl( this.name )( context, translation.x, translation.y, this.radius * size );
+ },
+
+ spacing: function( edge ){
+ return renderer.getArrowWidth(edge._private.style['width'].pfValue)
+ * this.radius;
+ },
+ } );
+
+ defineArrowShape( 'inhibitor', {
+ points: [
+ -0.25, 0,
+ -0.25, -0.1,
+ 0.25, -0.1,
+ 0.25, 0
+ ],
+
+ spacing: function( edge ){
+ return 1;
+ },
+
+ gap: function( edge ){
+ return 1;
+ }
+ } );
+
+ defineArrowShape( 'tee', 'inhibitor' );
+
+ defineArrowShape( 'square', {
+ points: [
+ -0.15, 0.00,
+ 0.15, 0.00,
+ 0.15, -0.3,
+ -0.15, -0.3
+ ]
+ } );
+
+ defineArrowShape( 'diamond', {
+ points: [
+ -0.15, -0.15,
+ 0, -0.3,
+ 0.15, -0.15,
+ 0, 0
+ ],
+
+ gap: function( edge ){
+ return edge._private.style['width'].pfValue;
+ }
+ } );
+
+};
+
+module.exports = BRp;
+
+},{"../../../is":77,"../../../math":79,"../../../util":94}],55:[function(_dereq_,module,exports){
+'use strict';
+
+var BRp = {};
+
+var delEleCache = function( r ){
+ r.eleEache = null;
+};
+
+var getEleCache = function( r ){
+ if( !r.eleEache ){
+ r.eleEache = {
+ nodes: r.cy.nodes(),
+ edges: r.cy.edges()
+ };
+ }
+
+ return r.eleEache;
+};
+
+BRp.getCachedElements = function(){
+ return getEleCache( this );
+};
+
+BRp.getCachedNodes = function(){
+ return getEleCache( this ).nodes;
+};
+
+BRp.getCachedEdges = function(){
+ return getEleCache( this ).edges;
+};
+
+BRp.updateElementsCache = function(){
+ var r = this;
+
+ delEleCache( r );
+
+ return getEleCache( r );
+};
+
+module.exports = BRp;
+
+},{}],56:[function(_dereq_,module,exports){
+'use strict';
+
+var math = _dereq_('../../../math');
+var is = _dereq_('../../../is');
+var zIndexSort = _dereq_('../../../collection/zsort');
+
+var BRp = {};
+
+// Project mouse
+BRp.projectIntoViewport = function(clientX, clientY) {
+ var offsets = this.findContainerClientCoords();
+ var offsetLeft = offsets[0];
+ var offsetTop = offsets[1];
+
+ var x = clientX - offsetLeft;
+ var y = clientY - offsetTop;
+
+ x -= this.cy.pan().x; y -= this.cy.pan().y; x /= this.cy.zoom(); y /= this.cy.zoom();
+ return [x, y];
+};
+
+BRp.findContainerClientCoords = function() {
+ var container = this.container;
+
+ var bb = this.containerBB = this.containerBB || container.getBoundingClientRect();
+
+ return [bb.left, bb.top, bb.right - bb.left, bb.bottom - bb.top];
+};
+
+BRp.invalidateContainerClientCoordsCache = function(){
+ this.containerBB = null;
+};
+
+// Find nearest element
+BRp.findNearestElement = function(x, y, visibleElementsOnly, isTouch){
+ var self = this;
+ var r = this;
+ var eles = r.getCachedZSortedEles();
+ var near = [];
+ var zoom = r.cy.zoom();
+ var hasCompounds = r.cy.hasCompoundNodes();
+ var edgeThreshold = (isTouch ? 24 : 8) / zoom;
+ var nodeThreshold = (isTouch ? 8 : 2) / zoom;
+ var labelThreshold = (isTouch ? 8 : 2) / zoom;
+
+ function checkNode(node){
+ var _p = node._private;
+
+ if( _p.style['events'].strValue === 'no' ){ return; }
+
+ var width = node.outerWidth() + 2*nodeThreshold;
+ var height = node.outerHeight() + 2*nodeThreshold;
+ var hw = width/2;
+ var hh = height/2;
+ var pos = _p.position;
+
+ if(
+ pos.x - hw <= x && x <= pos.x + hw // bb check x
+ &&
+ pos.y - hh <= y && y <= pos.y + hh // bb check y
+ ){
+ var visible = !visibleElementsOnly || ( node.visible() && !node.transparent() );
+
+ // exit early if invisible edge and must be visible
+ if( visibleElementsOnly && !visible ){
+ return;
+ }
+
+ var shape = r.nodeShapes[ self.getNodeShape(node) ];
+
+ if(
+ shape.checkPoint(x, y, 0, width, height, pos.x, pos.y)
+ ){
+ near.push( node );
+ }
+
+ }
+ }
+
+ function checkEdge(edge){
+ var _p = edge._private;
+
+ if( _p.style['events'].strValue === 'no' ){ return; }
+
+ var rs = _p.rscratch;
+ var style = _p.style;
+ var width = style['width'].pfValue/2 + edgeThreshold; // more like a distance radius from centre
+ var widthSq = width * width;
+ var width2 = width * 2;
+ var src = _p.source;
+ var tgt = _p.target;
+ var inEdgeBB = false;
+ var sqDist;
+
+ // exit early if invisible edge and must be visible
+ var passedVisibilityCheck;
+ var passesVisibilityCheck = function(){
+ if( passedVisibilityCheck !== undefined ){
+ return passedVisibilityCheck;
+ }
+
+ if( !visibleElementsOnly ){
+ passedVisibilityCheck = true;
+ return true;
+ }
+
+ var visible = edge.visible() && !edge.transparent();
+ if( visible ){
+ passedVisibilityCheck = true;
+ return true;
+ }
+
+ passedVisibilityCheck = false;
+ return false;
+ };
+
+ if( rs.edgeType === 'segments' || rs.edgeType === 'straight' || rs.edgeType === 'haystack' ){
+ var pts = rs.allpts;
+
+ for( var i = 0; i + 3 < pts.length; i += 2 ){
+ if(
+ (inEdgeBB = math.inLineVicinity(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], width2))
+ && passesVisibilityCheck() &&
+ widthSq > ( sqDist = math.sqDistanceToFiniteLine(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3]) )
+ ){
+ near.push( edge );
+ }
+ }
+
+ } else if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){
+ var pts = rs.allpts;
+ for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){
+ if(
+ (inEdgeBB = math.inBezierVicinity(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], pts[i+4], pts[i+5], width2))
+ && passesVisibilityCheck() &&
+ (widthSq > (sqDist = math.sqDistanceToQuadraticBezier(x, y, pts[i], pts[i+1], pts[i+2], pts[i+3], pts[i+4], pts[i+5])) )
+ ){
+ near.push( edge );
+ }
+ }
+ }
+
+ // if we're close to the edge but didn't hit it, maybe we hit its arrows
+ if( inEdgeBB && passesVisibilityCheck() && near.length === 0 || near[near.length - 1] !== edge ){
+ var src = src || _p.source;
+ var tgt = tgt || _p.target;
+
+ var eWidth = style['width'].pfValue;
+ var arSize = self.getArrowWidth( eWidth );
+
+ var arrows = [
+ { name: 'source', x: rs.arrowStartX, y: rs.arrowStartY, angle: rs.srcArrowAngle },
+ { name: 'target', x: rs.arrowEndX, y: rs.arrowEndY, angle: rs.tgtArrowAngle },
+ { name: 'mid-source', x: rs.midX, y: rs.midY, angle: rs.midsrcArrowAngle },
+ { name: 'mid-target', x: rs.midX, y: rs.midY, angle: rs.midtgtArrowAngle }
+ ];
+
+ for( var i = 0; i < arrows.length; i++ ){
+ var ar = arrows[i];
+ var shape = r.arrowShapes[ style[ar.name+'-arrow-shape'].value ];
+
+ if(
+ shape.roughCollide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold)
+ &&
+ shape.collide(x, y, arSize, ar.angle, { x: ar.x, y: ar.y }, edgeThreshold)
+ ){
+ near.push( edge );
+ break;
+ }
+ }
+ }
+
+ // for compound graphs, hitting edge may actually want a connected node instead (b/c edge may have greater z-index precedence)
+ if( hasCompounds && near.length > 0 && near[ near.length - 1 ] === edge ){
+ checkNode( src );
+ checkNode( tgt );
+ }
+ }
+
+ function checkLabel(ele){
+ var _p = ele._private;
+ var th = labelThreshold;
+
+ if( _p.style['text-events'].strValue === 'no' ){ return; }
+
+ // adjust bb w/ angle
+ if( _p.group === 'edges' && _p.style['edge-text-rotation'].strValue === 'autorotate' ){
+
+ var rstyle = _p.rstyle;
+ var lw = rstyle.labelWidth + 2*th;
+ var lh = rstyle.labelHeight + 2*th;
+ var lx = rstyle.labelX;
+ var ly = rstyle.labelY;
+
+ var theta = _p.rscratch.labelAngle;
+ var cos = Math.cos( theta );
+ var sin = Math.sin( theta );
+
+ var rotate = function( x, y ){
+ x = x - lx;
+ y = y - ly;
+
+ return {
+ x: x*cos - y*sin + lx,
+ y: x*sin + y*cos + ly
+ };
+ };
+
+ var lx1 = lx - lw/2;
+ var lx2 = lx + lw/2;
+ var ly1 = ly - lh/2;
+ var ly2 = ly + lh/2;
+
+ var px1y1 = rotate( lx1, ly1 );
+ var px1y2 = rotate( lx1, ly2 );
+ var px2y1 = rotate( lx2, ly1 );
+ var px2y2 = rotate( lx2, ly2 );
+
+ var points = [
+ px1y1.x, px1y1.y,
+ px2y1.x, px2y1.y,
+ px2y2.x, px2y2.y,
+ px1y2.x, px1y2.y
+ ];
+
+ if( math.pointInsidePolygonPoints( x, y, points ) ){
+ near.push( ele );
+ }
+
+ } else {
+ var bb = ele.boundingBox({
+ includeLabels: true,
+ includeNodes: false,
+ includeEdges: false
+ });
+
+ // adjust bb w/ threshold
+ bb.x1 -= th;
+ bb.y1 -= th;
+ bb.x2 += th;
+ bb.y2 += th;
+ bb.w = bb.x2 - bb.x1;
+ bb.h = bb.y2 - bb.y1;
+
+ if( math.inBoundingBox( bb, x, y ) ){
+ near.push( ele );
+ }
+ }
+
+ }
+
+ for( var i = eles.length - 1; i >= 0; i-- ){ // reverse order for precedence
+ var ele = eles[i];
+ var _p = ele._private;
+
+ if( near.length > 0 ){ break; } // since we check in z-order, first found is top and best result => exit early
+
+ if( _p.group === 'nodes' ){
+ checkNode( ele );
+
+ } else { // then edge
+ checkEdge( ele );
+ }
+
+ checkLabel( ele );
+
+ }
+
+
+ if( near.length > 0 ){
+ return near[ near.length - 1 ];
+ } else {
+ return null;
+ }
+};
+
+// 'Give me everything from this box'
+BRp.getAllInBox = function(x1, y1, x2, y2) {
+ var nodes = this.getCachedNodes();
+ var edges = this.getCachedEdges();
+ var box = [];
+
+ var x1c = Math.min(x1, x2);
+ var x2c = Math.max(x1, x2);
+ var y1c = Math.min(y1, y2);
+ var y2c = Math.max(y1, y2);
+
+ x1 = x1c;
+ x2 = x2c;
+ y1 = y1c;
+ y2 = y2c;
+
+ var boxBb = math.makeBoundingBox({
+ x1: x1, y1: y1,
+ x2: x2, y2: y2
+ });
+
+ for ( var i = 0; i < nodes.length; i++ ){
+ var node = nodes[i];
+ var nodeBb = node.boundingBox({
+ includeNodes: true,
+ includeEdges: false,
+ includeLabels: false
+ });
+
+ if( math.boundingBoxesIntersect(boxBb, nodeBb) ){
+ box.push(nodes[i]);
+ }
+ }
+
+ for( var e = 0; e < edges.length; e++ ){
+ var edge = edges[e];
+ var _p = edge._private;
+ var rs = _p.rscratch;
+
+ if( rs.startX != null && rs.startY != null && !math.inBoundingBox( boxBb, rs.startX, rs.startY ) ){ continue; }
+ if( rs.endX != null && rs.endY != null && !math.inBoundingBox( boxBb, rs.endX, rs.endY ) ){ continue; }
+
+ if( rs.edgeType === 'bezier' || rs.edgeType === 'multibezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' || rs.edgeType === 'segments' || rs.edgeType === 'haystack' ){
+
+ var pts = _p.rstyle.bezierPts || _p.rstyle.linePts || _p.rstyle.haystackPts;
+ var allInside = true;
+
+ for( var i = 0; i < pts.length; i++ ){
+ if( !math.pointInBoundingBox( boxBb, pts[i] ) ){
+ allInside = false;
+ break;
+ }
+ }
+
+ if( allInside ){
+ box.push( edge );
+ }
+
+ } else if( rs.edgeType === 'haystack' || rs.edgeType === 'straight' ){
+ box.push( edge );
+ }
+
+ }
+
+ return box;
+};
+
+
+/**
+ * Returns the shape of the given node. If the height or width of the given node
+ * is set to auto, the node is considered to be a compound.
+ *
+ * @param node a node
+ * @return {String} shape of the node
+ */
+BRp.getNodeShape = function( node ){
+ var r = this;
+ var style = node._private.style;
+ var shape = style['shape'].value;
+
+ if( node.isParent() ){
+ if( shape === 'rectangle' || shape === 'roundrectangle' ){
+ return shape;
+ } else {
+ return 'rectangle';
+ }
+ }
+
+ if( shape === 'polygon' ){
+ var points = style['shape-polygon-points'].value;
+
+ return r.nodeShapes.makePolygon( points ).name;
+ }
+
+ return shape;
+};
+
+BRp.updateCachedZSortedEles = function(){
+ this.getCachedZSortedEles( true );
+};
+
+BRp.getCachedZSortedEles = function( forceRecalc ){
+ var lastNodes = this.lastZOrderCachedNodes;
+ var lastEdges = this.lastZOrderCachedEdges;
+ var nodes = this.getCachedNodes();
+ var edges = this.getCachedEdges();
+ var eles = [];
+
+ if( forceRecalc || !lastNodes || !lastEdges || lastNodes !== nodes || lastEdges !== edges ){
+ //console.time('cachezorder')
+
+ for( var i = 0; i < nodes.length; i++ ){
+ var n = nodes[i];
+
+ if( n.animated() || (n.visible() && !n.transparent()) ){
+ eles.push( n );
+ }
+ }
+
+ for( var i = 0; i < edges.length; i++ ){
+ var e = edges[i];
+
+ if( e.animated() || (e.visible() && !e.transparent()) ){
+ eles.push( e );
+ }
+ }
+
+ eles.sort( zIndexSort );
+ this.cachedZSortedEles = eles;
+ //console.log('make cache')
+
+ //console.timeEnd('cachezorder')
+ } else {
+ eles = this.cachedZSortedEles;
+ //console.log('read cache')
+ }
+
+ this.lastZOrderCachedNodes = nodes;
+ this.lastZOrderCachedEdges = edges;
+
+ return eles;
+};
+
+function pushBezierPts(edge, pts){
+ var qbezierAt = function( p1, p2, p3, t ){ return math.qbezierAt(p1, p2, p3, t); };
+ var _p = edge._private;
+ var bpts = _p.rstyle.bezierPts;
+
+ bpts.push({
+ x: qbezierAt( pts[0], pts[2], pts[4], 0.05 ),
+ y: qbezierAt( pts[1], pts[3], pts[5], 0.05 )
+ });
+
+ bpts.push({
+ x: qbezierAt( pts[0], pts[2], pts[4], 0.25 ),
+ y: qbezierAt( pts[1], pts[3], pts[5], 0.25 )
+ });
+
+ bpts.push({
+ x: qbezierAt( pts[0], pts[2], pts[4], 0.4 ),
+ y: qbezierAt( pts[1], pts[3], pts[5], 0.4 )
+ });
+
+ bpts.push({
+ x: qbezierAt( pts[0], pts[2], pts[4], 0.5 ),
+ y: qbezierAt( pts[1], pts[3], pts[5], 0.5 )
+ });
+
+ bpts.push({
+ x: qbezierAt( pts[0], pts[2], pts[4], 0.6 ),
+ y: qbezierAt( pts[1], pts[3], pts[5], 0.6 )
+ });
+
+ bpts.push({
+ x: qbezierAt( pts[0], pts[2], pts[4], 0.75 ),
+ y: qbezierAt( pts[1], pts[3], pts[5], 0.75 )
+ });
+
+ bpts.push({
+ x: qbezierAt( pts[0], pts[2], pts[4], 0.95 ),
+ y: qbezierAt( pts[1], pts[3], pts[5], 0.95 )
+ });
+}
+
+BRp.projectLines = function( edge ){
+ var _p = edge._private;
+ var rs = _p.rscratch;
+ var et = rs.edgeType;
+
+ if( et === 'multibezier' || et === 'bezier' || et === 'self' || et === 'compound' ){
+ var bpts = _p.rstyle.bezierPts = []; // jshint ignore:line
+
+ for( var i = 0; i + 5 < rs.allpts.length; i += 4 ){
+ pushBezierPts( edge, rs.allpts.slice(i, i+6) );
+ }
+ } else if( et === 'segments' ){
+ var lpts = _p.rstyle.linePts = [];
+
+ for( var i = 0; i + 1 < rs.allpts.length; i += 2 ){
+ lpts.push({
+ x: rs.allpts[i],
+ y: rs.allpts[i+1]
+ });
+ }
+ } else if( et === 'haystack' ){
+ var hpts = rs.haystackPts;
+
+ _p.rstyle.haystackPts = [
+ { x: hpts[0], y: hpts[1] },
+ { x: hpts[2], y: hpts[3] }
+ ];
+ }
+};
+
+BRp.projectBezier = BRp.projectLines;
+
+BRp.recalculateNodeLabelProjection = function( node ){
+ var content = node._private.style['label'].strValue;
+ if( !content || content.match(/^\s+$/) ){ return; }
+
+ var textX, textY;
+ var nodeWidth = node.outerWidth();
+ var nodeHeight = node.outerHeight();
+ var nodePos = node._private.position;
+ var textHalign = node._private.style['text-halign'].strValue;
+ var textValign = node._private.style['text-valign'].strValue;
+ var rs = node._private.rscratch;
+ var rstyle = node._private.rstyle;
+
+ switch( textHalign ){
+ case 'left':
+ textX = nodePos.x - nodeWidth / 2;
+ break;
+
+ case 'right':
+ textX = nodePos.x + nodeWidth / 2;
+ break;
+
+ default: // e.g. center
+ textX = nodePos.x;
+ }
+
+ switch( textValign ){
+ case 'top':
+ textY = nodePos.y - nodeHeight / 2;
+ break;
+
+ case 'bottom':
+ textY = nodePos.y + nodeHeight / 2;
+ break;
+
+ default: // e.g. middle
+ textY = nodePos.y;
+ }
+
+ rs.labelX = textX;
+ rs.labelY = textY;
+ rstyle.labelX = textX;
+ rstyle.labelY = textY;
+
+ this.applyLabelDimensions( node );
+};
+
+BRp.recalculateEdgeLabelProjection = function( edge ){
+ var content = edge._private.style['label'].strValue;
+ if( !content || content.match(/^\s+$/) ){ return; }
+
+ var textX, textY;
+ var _p = edge._private;
+ var rs = _p.rscratch;
+ //var style = _p.style;
+ var rstyle = _p.rstyle;
+
+ textX = rs.midX;
+ textY = rs.midY;
+
+ // add center point to style so bounding box calculations can use it
+ rs.labelX = textX;
+ rs.labelY = textY;
+ rstyle.labelX = textX;
+ rstyle.labelY = textY;
+
+ this.applyLabelDimensions( edge );
+};
+
+BRp.applyLabelDimensions = function( ele ){
+ var rs = ele._private.rscratch;
+ var rstyle = ele._private.rstyle;
+
+ var text = this.getLabelText( ele );
+ var labelDims = this.calculateLabelDimensions( ele, text );
+
+ rstyle.labelWidth = labelDims.width;
+ rs.labelWidth = labelDims.width;
+
+ rstyle.labelHeight = labelDims.height;
+ rs.labelHeight = labelDims.height;
+};
+
+BRp.getLabelText = function( ele ){
+ var style = ele._private.style;
+ var text = ele._private.style['label'].strValue;
+ var textTransform = style['text-transform'].value;
+ var rscratch = ele._private.rscratch;
+
+ if (textTransform == 'none') {
+ } else if (textTransform == 'uppercase') {
+ text = text.toUpperCase();
+ } else if (textTransform == 'lowercase') {
+ text = text.toLowerCase();
+ }
+
+ if( style['text-wrap'].value === 'wrap' ){
+ //console.log('wrap');
+
+ // save recalc if the label is the same as before
+ if( rscratch.labelWrapKey === rscratch.labelKey ){
+ // console.log('wrap cache hit');
+ return rscratch.labelWrapCachedText;
+ }
+ // console.log('wrap cache miss');
+
+ var lines = text.split('\n');
+ var maxW = style['text-max-width'].pfValue;
+ var wrappedLines = [];
+
+ for( var l = 0; l < lines.length; l++ ){
+ var line = lines[l];
+ var lineDims = this.calculateLabelDimensions( ele, line, 'line=' + line );
+ var lineW = lineDims.width;
+
+ if( lineW > maxW ){ // line is too long
+ var words = line.split(/\s+/); // NB: assume collapsed whitespace into single space
+ var subline = '';
+
+ for( var w = 0; w < words.length; w++ ){
+ var word = words[w];
+ var testLine = subline.length === 0 ? word : subline + ' ' + word;
+ var testDims = this.calculateLabelDimensions( ele, testLine, 'testLine=' + testLine );
+ var testW = testDims.width;
+
+ if( testW <= maxW ){ // word fits on current line
+ subline += word + ' ';
+ } else { // word starts new line
+ wrappedLines.push( subline );
+ subline = word + ' ';
+ }
+ }
+
+ // if there's remaining text, put it in a wrapped line
+ if( !subline.match(/^\s+$/) ){
+ wrappedLines.push( subline );
+ }
+ } else { // line is already short enough
+ wrappedLines.push( line );
+ }
+ } // for
+
+ rscratch.labelWrapCachedLines = wrappedLines;
+ rscratch.labelWrapCachedText = text = wrappedLines.join('\n');
+ rscratch.labelWrapKey = rscratch.labelKey;
+
+ // console.log(text)
+ } // if wrap
+
+ return text;
+};
+
+BRp.calculateLabelDimensions = function( ele, text, extraKey ){
+ var r = this;
+ var style = ele._private.style;
+ var fStyle = style['font-style'].strValue;
+ var size = style['font-size'].pfValue + 'px';
+ var family = style['font-family'].strValue;
+ // var variant = style['font-variant'].strValue;
+ var weight = style['font-weight'].strValue;
+
+ var cacheKey = ele._private.labelKey;
+
+ if( extraKey ){
+ cacheKey += '$@$' + extraKey;
+ }
+
+ var cache = r.labelDimCache || (r.labelDimCache = {});
+
+ if( cache[cacheKey] ){
+ return cache[cacheKey];
+ }
+
+ var div = this.labelCalcDiv;
+
+ if( !div ){
+ div = this.labelCalcDiv = document.createElement('div');
+ document.body.appendChild( div );
+ }
+
+ var ds = div.style;
+
+ // from ele style
+ ds.fontFamily = family;
+ ds.fontStyle = fStyle;
+ ds.fontSize = size;
+ // ds.fontVariant = variant;
+ ds.fontWeight = weight;
+
+ // forced style
+ ds.position = 'absolute';
+ ds.left = '-9999px';
+ ds.top = '-9999px';
+ ds.zIndex = '-1';
+ ds.visibility = 'hidden';
+ ds.pointerEvents = 'none';
+ ds.padding = '0';
+ ds.lineHeight = '1';
+
+ if( style['text-wrap'].value === 'wrap' ){
+ ds.whiteSpace = 'pre'; // so newlines are taken into account
+ } else {
+ ds.whiteSpace = 'normal';
+ }
+
+ // put label content in div
+ div.textContent = text;
+
+ cache[cacheKey] = {
+ width: div.clientWidth,
+ height: div.clientHeight
+ };
+
+ return cache[cacheKey];
+};
+
+BRp.recalculateRenderedStyle = function( eles ){
+ var edges = [];
+ var nodes = [];
+ var handledEdge = {};
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ var _p = ele._private;
+ var style = _p.style;
+ var rs = _p.rscratch;
+ var rstyle = _p.rstyle;
+ var id = _p.data.id;
+ var bbStyleSame = rs.boundingBoxKey != null && _p.boundingBoxKey === rs.boundingBoxKey;
+ var labelStyleSame = rs.labelKey != null && _p.labelKey === rs.labelKey;
+ var styleSame = bbStyleSame && labelStyleSame;
+
+ if( _p.group === 'nodes' ){
+ var pos = _p.position;
+ var posSame = rstyle.nodeX != null && rstyle.nodeY != null && pos.x === rstyle.nodeX && pos.y === rstyle.nodeY;
+ var wSame = rstyle.nodeW != null && rstyle.nodeW === style['width'].pfValue;
+ var hSame = rstyle.nodeH != null && rstyle.nodeH === style['height'].pfValue;
+
+ if( !posSame || !styleSame || !wSame || !hSame ){
+ nodes.push( ele );
+ }
+
+ rstyle.nodeX = pos.x;
+ rstyle.nodeY = pos.y;
+ rstyle.nodeW = style['width'].pfValue;
+ rstyle.nodeH = style['height'].pfValue;
+ } else { // edges
+
+ var srcPos = _p.source._private.position;
+ var tgtPos = _p.target._private.position;
+ var srcSame = rstyle.srcX != null && rstyle.srcY != null && srcPos.x === rstyle.srcX && srcPos.y === rstyle.srcY;
+ var tgtSame = rstyle.tgtX != null && rstyle.tgtY != null && tgtPos.x === rstyle.tgtX && tgtPos.y === rstyle.tgtY;
+ var positionsSame = srcSame && tgtSame;
+
+ if( !positionsSame || !styleSame ){
+ if( rs.edgeType === 'bezier' || rs.edgeType === 'straight' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){
+ if( !handledEdge[ id ] ){
+ edges.push( ele );
+ handledEdge[ id ] = true;
+
+ var parallelEdges = ele.parallelEdges();
+ for( var i = 0; i < parallelEdges.length; i++ ){
+ var pEdge = parallelEdges[i];
+ var pId = pEdge._private.data.id;
+
+ if( !handledEdge[ pId ] ){
+ edges.push( pEdge );
+ handledEdge[ pId ] = true;
+ }
+
+ }
+ }
+ } else {
+ edges.push( ele );
+ }
+ } // if positions diff
+
+ // update rstyle positions
+ rstyle.srcX = srcPos.x;
+ rstyle.srcY = srcPos.y;
+ rstyle.tgtX = tgtPos.x;
+ rstyle.tgtY = tgtPos.y;
+
+ } // if edges
+
+ rs.boundingBoxKey = _p.boundingBoxKey;
+ rs.labelKey = _p.labelKey;
+ }
+
+ this.recalculateEdgeProjections( edges );
+ this.recalculateLabelProjections( nodes, edges );
+};
+
+BRp.recalculateLabelProjections = function( nodes, edges ){
+ for( var i = 0; i < nodes.length; i++ ){
+ this.recalculateNodeLabelProjection( nodes[i] );
+ }
+
+ for( var i = 0; i < edges.length; i++ ){
+ this.recalculateEdgeLabelProjection( edges[i] );
+ }
+};
+
+BRp.recalculateEdgeProjections = function( edges ){
+ this.findEdgeControlPoints( edges );
+};
+
+
+// Find edge control points
+BRp.findEdgeControlPoints = function(edges) {
+ if( !edges || edges.length === 0 ){ return; }
+
+ var r = this;
+ var cy = r.cy;
+ var hasCompounds = cy.hasCompoundNodes();
+ var hashTable = {};
+ var pairIds = [];
+ var haystackEdges = [];
+ var autorotateEdges = [];
+
+ // create a table of edge (src, tgt) => list of edges between them
+ var pairId;
+ for (var i = 0; i < edges.length; i++){
+ var edge = edges[i];
+ var _p = edge._private;
+ var data = _p.data;
+ var style = _p.style;
+ var curveStyle = style['curve-style'].value;
+ var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments';
+
+ // ignore edges who are not to be displayed
+ // they shouldn't take up space
+ if( style.display.value === 'none' ){
+ continue;
+ }
+
+ if( style['edge-text-rotation'].strValue === 'autorotate' ){
+ autorotateEdges.push( edge );
+ }
+
+ if( curveStyle === 'haystack' ){
+ haystackEdges.push( edge );
+ continue;
+ }
+
+ var srcId = data.source;
+ var tgtId = data.target;
+
+ pairId = srcId > tgtId ?
+ tgtId + '$-$' + srcId :
+ srcId + '$-$' + tgtId ;
+
+ if( edgeIsUnbundled ){
+ pairId = 'unbundled' + '$-$' + data.id;
+ }
+
+ if( hashTable[pairId] == null ){
+ hashTable[pairId] = [];
+ pairIds.push( pairId );
+ }
+
+ hashTable[pairId].push( edge );
+
+ if( edgeIsUnbundled ){
+ hashTable[pairId].hasUnbundled = true;
+ }
+ }
+
+ var src, tgt, src_p, tgt_p, srcPos, tgtPos, srcW, srcH, tgtW, tgtH, srcShape, tgtShape;
+ var vectorNormInverse;
+ var badBezier;
+
+ // for each pair (src, tgt), create the ctrl pts
+ // Nested for loop is OK; total number of iterations for both loops = edgeCount
+ for (var p = 0; p < pairIds.length; p++) {
+ pairId = pairIds[p];
+ var pairEdges = hashTable[pairId];
+
+ // for each pair id, the edges should be sorted by index
+ pairEdges.sort(function(edge1, edge2){
+ return edge1._private.index - edge2._private.index;
+ });
+
+ src = pairEdges[0]._private.source;
+ tgt = pairEdges[0]._private.target;
+
+ src_p = src._private;
+ tgt_p = tgt._private;
+
+ // make sure src/tgt distinction is consistent
+ // (src/tgt in this case are just for ctrlpts and don't actually have to be true src/tgt)
+ if( src_p.data.id > tgt_p.data.id ){
+ var temp = src;
+ src = tgt;
+ tgt = temp;
+ }
+
+ srcPos = src_p.position;
+ tgtPos = tgt_p.position;
+
+ srcW = src.outerWidth();
+ srcH = src.outerHeight();
+
+ tgtW = tgt.outerWidth();
+ tgtH = tgt.outerHeight();
+
+ srcShape = r.nodeShapes[ this.getNodeShape(src) ];
+ tgtShape = r.nodeShapes[ this.getNodeShape(tgt) ];
+
+ badBezier = false;
+
+
+ if( (pairEdges.length > 1 && src !== tgt) || pairEdges.hasUnbundled ){
+
+ // pt outside src shape to calc distance/displacement from src to tgt
+ var srcOutside = srcShape.intersectLine(
+ srcPos.x,
+ srcPos.y,
+ srcW,
+ srcH,
+ tgtPos.x,
+ tgtPos.y,
+ 0
+ );
+
+ // pt outside tgt shape to calc distance/displacement from src to tgt
+ var tgtOutside = tgtShape.intersectLine(
+ tgtPos.x,
+ tgtPos.y,
+ tgtW,
+ tgtH,
+ srcPos.x,
+ srcPos.y,
+ 0
+ );
+
+ var midptSrcPts = {
+ x1: srcOutside[0],
+ x2: tgtOutside[0],
+ y1: srcOutside[1],
+ y2: tgtOutside[1]
+ };
+
+ var dy = ( tgtOutside[1] - srcOutside[1] );
+ var dx = ( tgtOutside[0] - srcOutside[0] );
+ var l = Math.sqrt( dx*dx + dy*dy );
+
+ var vector = {
+ x: dx,
+ y: dy
+ };
+
+ var vectorNorm = {
+ x: vector.x/l,
+ y: vector.y/l
+ };
+ vectorNormInverse = {
+ x: -vectorNorm.y,
+ y: vectorNorm.x
+ };
+
+
+ // if src intersection is inside tgt or tgt intersection is inside src, then no ctrl pts to draw
+ if(
+ tgtShape.checkPoint( srcOutside[0], srcOutside[1], 0, tgtW, tgtH, tgtPos.x, tgtPos.y ) ||
+ srcShape.checkPoint( tgtOutside[0], tgtOutside[1], 0, srcW, srcH, srcPos.x, srcPos.y )
+ ){
+ vectorNormInverse = {};
+ badBezier = true;
+ }
+
+ }
+
+ var edge;
+ var edge_p;
+ var rs;
+
+ for (var i = 0; i < pairEdges.length; i++) {
+ edge = pairEdges[i];
+ edge_p = edge._private;
+ rs = edge_p.rscratch;
+
+ var edgeIndex1 = rs.lastEdgeIndex;
+ var edgeIndex2 = i;
+
+ var numEdges1 = rs.lastNumEdges;
+ var numEdges2 = pairEdges.length;
+
+ var eStyle = edge_p.style;
+ var style = eStyle;
+ var curveStyle = eStyle['curve-style'].value;
+ var ctrlptDists = eStyle['control-point-distances'];
+ var ctrlptWs = eStyle['control-point-weights'];
+ var bezierN = ctrlptDists && ctrlptWs ? Math.min( ctrlptDists.value.length, ctrlptWs.value.length ) : 1;
+ var stepSize = eStyle['control-point-step-size'].pfValue;
+ var ctrlptDist = ctrlptDists !== undefined ? ctrlptDists.pfValue[0] : undefined;
+ var ctrlptWeight = ctrlptWs.value[0];
+ var edgeIsUnbundled = curveStyle === 'unbundled-bezier' || curveStyle === 'segments';
+
+ var swappedDirection = edge_p.source !== src;
+
+ if( swappedDirection && edgeIsUnbundled ){
+ ctrlptDist *= -1;
+ }
+
+ var srcX1 = rs.lastSrcCtlPtX;
+ var srcX2 = srcPos.x;
+ var srcY1 = rs.lastSrcCtlPtY;
+ var srcY2 = srcPos.y;
+ var srcW1 = rs.lastSrcCtlPtW;
+ var srcW2 = src.outerWidth();
+ var srcH1 = rs.lastSrcCtlPtH;
+ var srcH2 = src.outerHeight();
+
+ var tgtX1 = rs.lastTgtCtlPtX;
+ var tgtX2 = tgtPos.x;
+ var tgtY1 = rs.lastTgtCtlPtY;
+ var tgtY2 = tgtPos.y;
+ var tgtW1 = rs.lastTgtCtlPtW;
+ var tgtW2 = tgt.outerWidth();
+ var tgtH1 = rs.lastTgtCtlPtH;
+ var tgtH2 = tgt.outerHeight();
+
+ var width1 = rs.lastW;
+ var width2 = eStyle['control-point-step-size'].pfValue;
+
+ if( badBezier ){
+ rs.badBezier = true;
+ } else {
+ rs.badBezier = false;
+ }
+
+ if( srcX1 === srcX2 && srcY1 === srcY2 && srcW1 === srcW2 && srcH1 === srcH2
+ && tgtX1 === tgtX2 && tgtY1 === tgtY2 && tgtW1 === tgtW2 && tgtH1 === tgtH2
+ && width1 === width2
+ && ((edgeIndex1 === edgeIndex2 && numEdges1 === numEdges2) || edgeIsUnbundled) ){
+ // console.log('edge ctrl pt cache HIT')
+ continue; // then the control points haven't changed and we can skip calculating them
+ } else {
+ rs.lastSrcCtlPtX = srcX2;
+ rs.lastSrcCtlPtY = srcY2;
+ rs.lastSrcCtlPtW = srcW2;
+ rs.lastSrcCtlPtH = srcH2;
+ rs.lastTgtCtlPtX = tgtX2;
+ rs.lastTgtCtlPtY = tgtY2;
+ rs.lastTgtCtlPtW = tgtW2;
+ rs.lastTgtCtlPtH = tgtH2;
+ rs.lastEdgeIndex = edgeIndex2;
+ rs.lastNumEdges = numEdges2;
+ rs.lastWidth = width2;
+ // console.log('edge ctrl pt cache MISS')
+ }
+
+ if( src === tgt ){
+ // Self-edge
+
+ rs.edgeType = 'self';
+
+ var j = i;
+ var loopDist = stepSize;
+
+ if( edgeIsUnbundled ){
+ j = 0;
+ loopDist = ctrlptDist;
+ }
+
+ rs.ctrlpts = [
+ srcPos.x,
+ srcPos.y - (1 + Math.pow(srcH, 1.12) / 100) * loopDist * (j / 3 + 1),
+
+ srcPos.x - (1 + Math.pow(srcW, 1.12) / 100) * loopDist * (j / 3 + 1),
+ srcPos.y
+ ];
+
+ } else if(
+ hasCompounds &&
+ ( src.isParent() || src.isChild() || tgt.isParent() || tgt.isChild() ) &&
+ ( src.parents().anySame(tgt) || tgt.parents().anySame(src) )
+ ){
+ // Compound edge
+
+ rs.edgeType = 'compound';
+
+ // because the line approximation doesn't apply for compound beziers
+ // (loop/self edges are already elided b/c of cheap src==tgt check)
+ rs.badBezier = false;
+
+ var j = i;
+ var loopDist = stepSize;
+
+ if( edgeIsUnbundled ){
+ j = 0;
+ loopDist = ctrlptDist;
+ }
+
+ var loopW = 50;
+
+ var loopaPos = {
+ x: srcPos.x - srcW/2,
+ y: srcPos.y - srcH/2
+ };
+
+ var loopbPos = {
+ x: tgtPos.x - tgtW/2,
+ y: tgtPos.y - tgtH/2
+ };
+
+ var loopPos = {
+ x: Math.min( loopaPos.x, loopbPos.x ),
+ y: Math.min( loopaPos.y, loopbPos.y )
+ };
+
+ // avoids cases with impossible beziers
+ var minCompoundStretch = 0.5;
+ var compoundStretchA = Math.max( minCompoundStretch, Math.log(srcW * 0.01) );
+ var compoundStretchB = Math.max( minCompoundStretch, Math.log(tgtW * 0.01) );
+
+ rs.ctrlpts = [
+ loopPos.x,
+ loopPos.y - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchA,
+
+ loopPos.x - (1 + Math.pow(loopW, 1.12) / 100) * loopDist * (j / 3 + 1) * compoundStretchB,
+ loopPos.y
+ ];
+
+ } else if( curveStyle === 'segments' ){
+ // Segments (multiple straight lines)
+
+ rs.edgeType = 'segments';
+ rs.segpts = [];
+
+ var segmentWs = eStyle['segment-weights'].pfValue;
+ var segmentDs = eStyle['segment-distances'].pfValue;
+ var segmentsN = Math.min( segmentWs.length, segmentDs.length );
+
+ for( var s = 0; s < segmentsN; s++ ){
+ var w = segmentWs[s];
+ var d = segmentDs[s];
+
+ // d = swappedDirection ? -d : d;
+ //
+ // d = Math.abs(d);
+
+ // var w1 = !swappedDirection ? (1 - w) : w;
+ // var w2 = !swappedDirection ? w : (1 - w);
+
+ var w1 = (1 - w);
+ var w2 = w;
+
+ var adjustedMidpt = {
+ x: midptSrcPts.x1 * w1 + midptSrcPts.x2 * w2,
+ y: midptSrcPts.y1 * w1 + midptSrcPts.y2 * w2
+ };
+
+ rs.segpts.push(
+ adjustedMidpt.x + vectorNormInverse.x * d,
+ adjustedMidpt.y + vectorNormInverse.y * d
+ );
+ }
+
+ // Straight edge
+ } else if (
+ pairEdges.length % 2 === 1
+ && i === Math.floor(pairEdges.length / 2)
+ && !edgeIsUnbundled
+ ){
+
+ rs.edgeType = 'straight';
+
+ } else {
+ // (Multi)bezier
+
+ var multi = edgeIsUnbundled;
+
+ rs.edgeType = multi ? 'multibezier' : 'bezier';
+ rs.ctrlpts = [];
+
+ for( var b = 0; b < bezierN; b++ ){
+ var normctrlptDist = (0.5 - pairEdges.length / 2 + i) * stepSize;
+ var manctrlptDist;
+ var sign = math.signum( normctrlptDist );
+
+ if( multi ){
+ ctrlptDist = ctrlptDists ? ctrlptDists.pfValue[b] : stepSize; // fall back on step size
+ ctrlptWeight = ctrlptWs.value[b];
+ }
+
+ if( edgeIsUnbundled ){ // multi or single unbundled
+ manctrlptDist = ctrlptDist;
+ } else {
+ manctrlptDist = ctrlptDist !== undefined ? sign * ctrlptDist : undefined;
+ }
+
+ var distanceFromMidpoint = manctrlptDist !== undefined ? manctrlptDist : normctrlptDist;
+
+ var w1 = !swappedDirection || edgeIsUnbundled ? (1 - ctrlptWeight) : ctrlptWeight;
+ var w2 = !swappedDirection || edgeIsUnbundled ? ctrlptWeight : (1 - ctrlptWeight);
+
+ var adjustedMidpt = {
+ x: midptSrcPts.x1 * w1 + midptSrcPts.x2 * w2,
+ y: midptSrcPts.y1 * w1 + midptSrcPts.y2 * w2
+ };
+
+ rs.ctrlpts.push(
+ adjustedMidpt.x + vectorNormInverse.x * distanceFromMidpoint,
+ adjustedMidpt.y + vectorNormInverse.y * distanceFromMidpoint
+ );
+ }
+
+ }
+
+ // find endpts for edge
+ this.findEndpoints( edge );
+
+ var badStart = !is.number( rs.startX ) || !is.number( rs.startY );
+ var badAStart = !is.number( rs.arrowStartX ) || !is.number( rs.arrowStartY );
+ var badEnd = !is.number( rs.endX ) || !is.number( rs.endY );
+ var badAEnd = !is.number( rs.arrowEndX ) || !is.number( rs.arrowEndY );
+
+ var minCpADistFactor = 3;
+ var arrowW = this.getArrowWidth( eStyle['width'].pfValue ) * this.arrowShapeHeight;
+ var minCpADist = minCpADistFactor * arrowW;
+
+ if( rs.edgeType === 'bezier' ){
+ var startACpDist = math.distance( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.startX, y: rs.startY } );
+ var closeStartACp = startACpDist < minCpADist;
+ var endACpDist = math.distance( { x: rs.ctrlpts[0], y: rs.ctrlpts[1] }, { x: rs.endX, y: rs.endY } );
+ var closeEndACp = endACpDist < minCpADist;
+
+ var overlapping = false;
+
+ if( badStart || badAStart || closeStartACp ){
+ overlapping = true;
+
+ // project control point along line from src centre to outside the src shape
+ // (otherwise intersection will yield nothing)
+ var cpD = { // delta
+ x: rs.ctrlpts[0] - srcPos.x,
+ y: rs.ctrlpts[1] - srcPos.y
+ };
+ var cpL = Math.sqrt( cpD.x*cpD.x + cpD.y*cpD.y ); // length of line
+ var cpM = { // normalised delta
+ x: cpD.x / cpL,
+ y: cpD.y / cpL
+ };
+ var radius = Math.max(srcW, srcH);
+ var cpProj = { // *2 radius guarantees outside shape
+ x: rs.ctrlpts[0] + cpM.x * 2 * radius,
+ y: rs.ctrlpts[1] + cpM.y * 2 * radius
+ };
+
+ var srcCtrlPtIntn = srcShape.intersectLine(
+ srcPos.x,
+ srcPos.y,
+ srcW,
+ srcH,
+ cpProj.x,
+ cpProj.y,
+ 0
+ );
+
+ if( closeStartACp ){
+ rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - startACpDist);
+ rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - startACpDist);
+ } else {
+ rs.ctrlpts[0] = srcCtrlPtIntn[0] + cpM.x * minCpADist;
+ rs.ctrlpts[1] = srcCtrlPtIntn[1] + cpM.y * minCpADist;
+ }
+ }
+
+ if( badEnd || badAEnd || closeEndACp ){
+ overlapping = true;
+
+ // project control point along line from tgt centre to outside the tgt shape
+ // (otherwise intersection will yield nothing)
+ var cpD = { // delta
+ x: rs.ctrlpts[0] - tgtPos.x,
+ y: rs.ctrlpts[1] - tgtPos.y
+ };
+ var cpL = Math.sqrt( cpD.x*cpD.x + cpD.y*cpD.y ); // length of line
+ var cpM = { // normalised delta
+ x: cpD.x / cpL,
+ y: cpD.y / cpL
+ };
+ var radius = Math.max(srcW, srcH);
+ var cpProj = { // *2 radius guarantees outside shape
+ x: rs.ctrlpts[0] + cpM.x * 2 * radius,
+ y: rs.ctrlpts[1] + cpM.y * 2 * radius
+ };
+
+ var tgtCtrlPtIntn = tgtShape.intersectLine(
+ tgtPos.x,
+ tgtPos.y,
+ tgtW,
+ tgtH,
+ cpProj.x,
+ cpProj.y,
+ 0
+ );
+
+ if( closeEndACp ){
+ rs.ctrlpts[0] = rs.ctrlpts[0] + cpM.x * (minCpADist - endACpDist);
+ rs.ctrlpts[1] = rs.ctrlpts[1] + cpM.y * (minCpADist - endACpDist);
+ } else {
+ rs.ctrlpts[0] = tgtCtrlPtIntn[0] + cpM.x * minCpADist;
+ rs.ctrlpts[1] = tgtCtrlPtIntn[1] + cpM.y * minCpADist;
+ }
+
+ }
+
+ if( overlapping ){
+ // recalc endpts
+ this.findEndpoints( edge );
+ }
+
+ }
+
+ if( rs.edgeType === 'multibezier' || rs.edgeType === 'bezier' || rs.edgeType === 'self' || rs.edgeType === 'compound' ){
+ rs.allpts = [];
+
+ rs.allpts.push( rs.startX, rs.startY );
+
+ for( var b = 0; b+1 < rs.ctrlpts.length; b += 2 ){
+ // ctrl pt itself
+ rs.allpts.push( rs.ctrlpts[b], rs.ctrlpts[b+1] );
+
+ // the midpt between ctrlpts as intermediate destination pts
+ if( b + 3 < rs.ctrlpts.length ){
+ rs.allpts.push( (rs.ctrlpts[b] + rs.ctrlpts[b+2])/2, (rs.ctrlpts[b+1] + rs.ctrlpts[b+3])/2 );
+ }
+ }
+
+ rs.allpts.push( rs.endX, rs.endY );
+
+ var m, mt;
+ if( rs.edgeType === 'bezier' ){
+ rs.midX = math.qbezierAt( rs.arrowStartX, rs.ctrlpts[0], rs.arrowEndX, 0.5 );
+ rs.midY = math.qbezierAt( rs.arrowStartY, rs.ctrlpts[1], rs.arrowEndY, 0.5 );
+ } else if( rs.ctrlpts.length/2 % 2 === 0 ){
+ m = rs.allpts.length/2 - 1;
+
+ rs.midX = rs.allpts[m];
+ rs.midY = rs.allpts[m+1];
+ } else {
+ m = rs.allpts.length/2 - 3;
+ mt = 0.5;
+
+ rs.midX = math.qbezierAt( rs.allpts[m], rs.allpts[m+2], rs.allpts[m+4], mt );
+ rs.midY = math.qbezierAt( rs.allpts[m+1], rs.allpts[m+3], rs.allpts[m+5], mt );
+ }
+
+ } else if( rs.edgeType === 'straight' ){
+ // need to calc these after endpts
+ rs.allpts = [ rs.startX, rs.startY, rs.endX, rs.endY ];
+
+ // default midpt for labels etc
+ rs.midX = ( rs.arrowStartX + rs.arrowEndX )/2;
+ rs.midY = ( rs.arrowStartY + rs.arrowEndY )/2;
+
+ } else if( rs.edgeType === 'segments' ){
+ rs.allpts = [];
+ rs.allpts.push( rs.startX, rs.startY );
+ rs.allpts.push.apply( rs.allpts, rs.segpts );
+ rs.allpts.push( rs.endX, rs.endY );
+
+ if( rs.segpts.length % 4 === 0 ){
+ var i2 = rs.segpts.length / 2;
+ var i1 = i2 - 2;
+
+ rs.midX = ( rs.segpts[i1] + rs.segpts[i2] ) / 2;
+ rs.midY = ( rs.segpts[i1+1] + rs.segpts[i2+1] ) / 2;
+ } else {
+ var i1 = rs.segpts.length / 2 - 1;
+
+ rs.midX = rs.segpts[i1];
+ rs.midY = rs.segpts[i1+1];
+ }
+
+
+ }
+
+ this.projectLines( edge );
+ this.calculateArrowAngles( edge );
+ this.recalculateEdgeLabelProjection( edge );
+
+ }
+ }
+
+ for( var i = 0; i < haystackEdges.length; i++ ){
+ var edge = haystackEdges[i];
+ var _p = edge._private;
+ var style = _p.style;
+ var rscratch = _p.rscratch;
+ var rs = rscratch;
+
+ if( !rscratch.haystack ){
+ var angle = Math.random() * 2 * Math.PI;
+
+ rscratch.source = {
+ x: Math.cos(angle),
+ y: Math.sin(angle)
+ };
+
+ var angle = Math.random() * 2 * Math.PI;
+
+ rscratch.target = {
+ x: Math.cos(angle),
+ y: Math.sin(angle)
+ };
+
+ }
+
+ var src = _p.source;
+ var tgt = _p.target;
+ var srcPos = src._private.position;
+ var tgtPos = tgt._private.position;
+ var srcW = src.width();
+ var tgtW = tgt.width();
+ var srcH = src.height();
+ var tgtH = tgt.height();
+ var radius = style['haystack-radius'].value;
+ var halfRadius = radius/2; // b/c have to half width/height
+
+ rs.haystackPts = rs.allpts = [
+ rs.source.x * srcW * halfRadius + srcPos.x,
+ rs.source.y * srcH * halfRadius + srcPos.y,
+ rs.target.x * tgtW * halfRadius + tgtPos.x,
+ rs.target.y * tgtH * halfRadius + tgtPos.y
+ ];
+
+ rs.midX = (rs.allpts[0] + rs.allpts[2])/2;
+ rs.midY = (rs.allpts[1] + rs.allpts[3])/2;
+
+ // always override as haystack in case set to different type previously
+ rscratch.edgeType = 'haystack';
+ rscratch.haystack = true;
+
+ this.projectLines( edge );
+ this.calculateArrowAngles( edge );
+ this.recalculateEdgeLabelProjection( edge );
+ }
+
+ for( var i = 0 ; i < autorotateEdges.length; i++ ){
+ var edge = autorotateEdges[i];
+ var rs = edge._private.rscratch;
+
+ rs.labelAngle = Math.atan( rs.midDispY / rs.midDispX );
+ }
+
+ return hashTable;
+};
+
+var getAngleFromDisp = function( dispX, dispY ){
+ return Math.atan2( dispY, dispX ) - Math.PI/2;
+};
+
+BRp.calculateArrowAngles = function( edge ){
+ var rs = edge._private.rscratch;
+ var isHaystack = rs.edgeType === 'haystack';
+ var isMultibezier = rs.edgeType === 'multibezier';
+ var isSegments = rs.edgeType === 'segments';
+ var isCompound = rs.edgeType === 'compound';
+ var isSelf = rs.edgeType === 'self';
+
+ // Displacement gives direction for arrowhead orientation
+ var dispX, dispY;
+ var startX, startY, endX, endY;
+
+ var srcPos = edge.source().position();
+ var tgtPos = edge.target().position();
+
+ if( isHaystack ){
+ startX = rs.haystackPts[0];
+ startY = rs.haystackPts[1];
+ endX = rs.haystackPts[2];
+ endY = rs.haystackPts[3];
+ } else {
+ startX = rs.arrowStartX;
+ startY = rs.arrowStartY;
+ endX = rs.arrowEndX;
+ endY = rs.arrowEndY;
+ }
+
+ // source
+ //
+
+ dispX = srcPos.x - startX;
+ dispY = srcPos.y - startY;
+
+ rs.srcArrowAngle = getAngleFromDisp( dispX, dispY );
+
+ // mid target
+ //
+
+ var midX = rs.midX;
+ var midY = rs.midY;
+
+ if( isHaystack ){
+ midX = ( startX + endX )/2;
+ midY = ( startY + endY )/2;
+ }
+
+ dispX = endX - startX;
+ dispY = endY - startY;
+
+ if( isSelf ){
+ dispX = -1;
+ dispY = 1;
+ } else if( isSegments ){
+ var pts = rs.allpts;
+
+ if( pts.length / 2 % 2 === 0 ){
+ var i2 = pts.length / 2;
+ var i1 = i2 - 2;
+
+ dispX = ( pts[i2] - pts[i1] );
+ dispY = ( pts[i2+1] - pts[i1+1] );
+ } else {
+ var i2 = pts.length / 2 - 1;
+ var i1 = i2 - 2;
+ var i3 = i2 + 2;
+
+ dispX = ( pts[i2] - pts[i1] );
+ dispY = ( pts[i2+1] - pts[i1+1] );
+ }
+ } else if( isMultibezier || isCompound ){
+ var pts = rs.allpts;
+ var cpts = rs.ctrlpts;
+ var bp0x, bp0y;
+ var bp1x, bp1y;
+
+ if( cpts.length / 2 % 2 === 0 ){
+ var p0 = pts.length / 2 - 1; // startpt
+ var ic = p0 + 2;
+ var p1 = ic + 2;
+
+ bp0x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.0 );
+ bp0y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.0 );
+
+ bp1x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.0001 );
+ bp1y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.0001 );
+ } else {
+ var ic = pts.length / 2 - 1; // ctrpt
+ var p0 = ic - 2; // startpt
+ var p1 = ic + 2; // endpt
+
+ bp0x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.4999 );
+ bp0y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.4999 );
+
+ bp1x = math.qbezierAt( pts[p0], pts[ic], pts[p1], 0.5 );
+ bp1y = math.qbezierAt( pts[p0+1], pts[ic+1], pts[p1+1], 0.5 );
+ }
+
+ dispX = ( bp1x - bp0x );
+ dispY = ( bp1y - bp0y );
+ }
+
+ rs.midtgtArrowAngle = getAngleFromDisp( dispX, dispY );
+
+ rs.midDispX = dispX;
+ rs.midDispY = dispY;
+
+ // mid source
+ //
+
+ dispX *= -1;
+ dispY *= -1;
+
+ if( isSegments ){
+ var pts = rs.allpts;
+
+ if( pts.length / 2 % 2 === 0 ){
+ // already ok
+ } else {
+ var i2 = pts.length / 2 - 1;
+ var i3 = i2 + 2;
+
+ dispX = -( pts[i3] - pts[i2] );
+ dispY = -( pts[i3+1] - pts[i2+1] );
+ }
+ }
+
+ rs.midsrcArrowAngle = getAngleFromDisp( dispX, dispY );
+
+ // target
+ //
+
+ dispX = tgtPos.x - endX;
+ dispY = tgtPos.y - endY;
+
+ rs.tgtArrowAngle = getAngleFromDisp( dispX, dispY );
+};
+
+
+BRp.findEndpoints = function( edge ){
+ var r = this;
+ var intersect;
+
+ var source = edge.source()[0];
+ var target = edge.target()[0];
+
+ var src_p = source._private;
+ var tgt_p = target._private;
+
+ var srcPos = src_p.position;
+ var tgtPos = tgt_p.position;
+
+ var tgtArShape = edge._private.style['target-arrow-shape'].value;
+ var srcArShape = edge._private.style['source-arrow-shape'].value;
+
+ var rs = edge._private.rscratch;
+
+ var et = rs.edgeType;
+ var bezier = et === 'bezier' || et === 'multibezier' || et === 'self' || et === 'compound';
+ var multi = et !== 'bezier';
+ var lines = et === 'straight' || et === 'segments';
+ var segments = et === 'segments';
+
+ var p1, p2;
+
+ if( bezier ){
+ var cpStart = [ rs.ctrlpts[0], rs.ctrlpts[1] ];
+ var cpEnd = multi ? [ rs.ctrlpts[rs.ctrlpts.length - 2], rs.ctrlpts[rs.ctrlpts.length - 1] ] : cpStart;
+
+ p1 = cpEnd;
+ p2 = cpStart;
+ } else if( lines ){
+ var srcArrowFromPt = !segments ? [ tgtPos.x, tgtPos.y ] : rs.segpts.slice( 0, 2 );
+ var tgtArrowFromPt = !segments ? [ srcPos.x, srcPos.y ] : rs.segpts.slice( rs.segpts.length - 2 );
+
+ p1 = tgtArrowFromPt;
+ p2 = srcArrowFromPt;
+ }
+
+ intersect = r.nodeShapes[this.getNodeShape(target)].intersectLine(
+ tgtPos.x,
+ tgtPos.y,
+ target.outerWidth(),
+ target.outerHeight(),
+ p1[0],
+ p1[1],
+ 0
+ );
+
+ var arrowEnd = math.shortenIntersection(intersect, p1,
+ r.arrowShapes[tgtArShape].spacing(edge));
+ var edgeEnd = math.shortenIntersection(intersect, p1,
+ r.arrowShapes[tgtArShape].gap(edge));
+
+ rs.endX = edgeEnd[0];
+ rs.endY = edgeEnd[1];
+
+ rs.arrowEndX = arrowEnd[0];
+ rs.arrowEndY = arrowEnd[1];
+
+ intersect = r.nodeShapes[this.getNodeShape(source)].intersectLine(
+ srcPos.x,
+ srcPos.y,
+ source.outerWidth(),
+ source.outerHeight(),
+ p2[0],
+ p2[1],
+ 0
+ );
+
+ var arrowStart = math.shortenIntersection(
+ intersect, p2,
+ r.arrowShapes[srcArShape].spacing(edge)
+ );
+ var edgeStart = math.shortenIntersection(
+ intersect, p2,
+ r.arrowShapes[srcArShape].gap(edge)
+ );
+
+ rs.startX = edgeStart[0];
+ rs.startY = edgeStart[1];
+
+ rs.arrowStartX = arrowStart[0];
+ rs.arrowStartY = arrowStart[1];
+
+ if( lines ){
+ if( !is.number(rs.startX) || !is.number(rs.startY) || !is.number(rs.endX) || !is.number(rs.endY) ){
+ rs.badLine = true;
+ } else {
+ rs.badLine = false;
+ }
+ }
+};
+
+BRp.getArrowWidth = BRp.getArrowHeight = function(edgeWidth) {
+ var cache = this.arrowWidthCache = this.arrowWidthCache || {};
+
+ var cachedVal = cache[edgeWidth];
+ if( cachedVal ){
+ return cachedVal;
+ }
+
+ cachedVal = Math.max(Math.pow(edgeWidth * 13.37, 0.9), 29);
+ cache[edgeWidth] = cachedVal;
+
+ return cachedVal;
+};
+
+module.exports = BRp;
+
+},{"../../../collection/zsort":29,"../../../is":77,"../../../math":79}],57:[function(_dereq_,module,exports){
+'use strict';
+
+var BRp = {};
+
+BRp.getCachedImage = function(url, onLoad) {
+ var r = this;
+ var imageCache = r.imageCache = r.imageCache || {};
+
+ if( imageCache[url] && imageCache[url].image ){
+ return imageCache[url].image;
+ }
+
+ var cache = imageCache[url] = imageCache[url] || {};
+
+ var image = cache.image = new Image();
+ image.addEventListener('load', onLoad);
+ image.src = url;
+
+ return image;
+};
+
+module.exports = BRp;
+
+},{}],58:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../../is');
+var util = _dereq_('../../../util');
+
+var BaseRenderer = function(){};
+var BR = BaseRenderer;
+var BRp = BR.prototype;
+
+BRp.clientFunctions = [ 'redrawHint', 'render', 'renderTo', 'matchCanvasSize', 'nodeShapeImpl', 'arrowShapeImpl' ];
+
+BRp.init = function( options ){
+ var r = this;
+
+ r.options = options;
+
+ r.cy = options.cy;
+
+ r.container = options.cy.container();
+
+ r.selection = [undefined, undefined, undefined, undefined, 0]; // Coordinates for selection box, plus enabled flag
+
+ //--Pointer-related data
+ r.hoverData = {down: null, last: null,
+ downTime: null, triggerMode: null,
+ dragging: false,
+ initialPan: [null, null], capture: false};
+
+ r.dragData = {possibleDragElements: []};
+
+ r.touchData = {
+ start: null, capture: false,
+
+ // These 3 fields related to tap, taphold events
+ startPosition: [null, null, null, null, null, null],
+ singleTouchStartTime: null,
+ singleTouchMoved: true,
+
+ now: [null, null, null, null, null, null],
+ earlier: [null, null, null, null, null, null]
+ };
+
+ r.redraws = 0;
+ r.showFps = options.showFps;
+
+ r.hideEdgesOnViewport = options.hideEdgesOnViewport;
+ r.hideLabelsOnViewport = options.hideLabelsOnViewport;
+ r.textureOnViewport = options.textureOnViewport;
+ r.wheelSensitivity = options.wheelSensitivity;
+ r.motionBlurEnabled = options.motionBlur; // on by default
+ r.forcedPixelRatio = options.pixelRatio;
+ r.motionBlur = true; // for initial kick off
+ r.motionBlurOpacity = options.motionBlurOpacity;
+ r.motionBlurTransparency = 1 - r.motionBlurOpacity;
+ r.motionBlurPxRatio = 1;
+ r.mbPxRBlurry = 1; //0.8;
+ r.minMbLowQualFrames = 4;
+ r.fullQualityMb = false;
+ r.clearedForMotionBlur = [];
+ r.desktopTapThreshold = options.desktopTapThreshold;
+ r.desktopTapThreshold2 = options.desktopTapThreshold * options.desktopTapThreshold;
+ r.touchTapThreshold = options.touchTapThreshold;
+ r.touchTapThreshold2 = options.touchTapThreshold * options.touchTapThreshold;
+ r.tapholdDuration = 500;
+
+ r.bindings = [];
+
+ r.registerNodeShapes();
+ r.registerArrowShapes();
+ r.load();
+};
+
+BRp.notify = function(params) {
+ var types;
+ var r = this;
+
+ if( is.array( params.type ) ){
+ types = params.type;
+
+ } else {
+ types = [ params.type ];
+ }
+
+ for( var i = 0; i < types.length; i++ ){
+ var type = types[i];
+
+ switch( type ){
+ case 'destroy':
+ r.destroy();
+ return;
+
+ case 'add':
+ case 'remove':
+ case 'load':
+ r.updateElementsCache();
+ break;
+
+ case 'viewport':
+ r.redrawHint('select', true);
+ break;
+
+ case 'style':
+ r.updateCachedZSortedEles();
+ break;
+ }
+
+ if( type === 'load' || type === 'resize' ){
+ r.invalidateContainerClientCoordsCache();
+ r.matchCanvasSize(r.container);
+ }
+ } // for
+
+ r.redrawHint('eles', true);
+ r.redrawHint('drag', true);
+
+ this.startRenderLoop();
+
+ this.redraw();
+};
+
+BRp.destroy = function(){
+ this.destroyed = true;
+
+ this.cy.stopAnimationLoop();
+
+ for( var i = 0; i < this.bindings.length; i++ ){
+ var binding = this.bindings[i];
+ var b = binding;
+
+ b.target.removeEventListener(b.event, b.handler, b.useCapture);
+ }
+
+ if( this.removeObserver ){
+ this.removeObserver.disconnect();
+ }
+
+ if( this.labelCalcDiv ){
+ try{
+ document.body.removeChild(this.labelCalcDiv);
+ } catch(e){
+ // ie10 issue #1014
+ }
+ }
+};
+
+[
+ _dereq_('./arrow-shapes'),
+ _dereq_('./cached-eles'),
+ _dereq_('./coord-ele-math'),
+ _dereq_('./images'),
+ _dereq_('./load-listeners'),
+ _dereq_('./node-shapes'),
+ _dereq_('./redraw')
+].forEach(function( props ){
+ util.extend( BRp, props );
+});
+
+module.exports = BR;
+
+},{"../../../is":77,"../../../util":94,"./arrow-shapes":54,"./cached-eles":55,"./coord-ele-math":56,"./images":57,"./load-listeners":59,"./node-shapes":60,"./redraw":61}],59:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../../is');
+var util = _dereq_('../../../util');
+var Event = _dereq_('../../../event');
+var Collection = _dereq_('../../../collection');
+
+var BRp = {};
+
+BRp.registerBinding = function(target, event, handler, useCapture){
+ this.bindings.push({
+ target: target,
+ event: event,
+ handler: handler,
+ useCapture: useCapture
+ });
+
+ target.addEventListener(event, handler, useCapture);
+};
+
+BRp.nodeIsDraggable = function(node) {
+ if (node._private.style['opacity'].value !== 0
+ && node._private.style['visibility'].value == 'visible'
+ && node._private.style['display'].value == 'element'
+ && !node.locked()
+ && node.grabbable() ) {
+
+ return true;
+ }
+
+ return false;
+};
+
+BRp.load = function() {
+ var r = this;
+
+ var triggerEvents = function( target, names, e, props ){
+ if( target == null ){
+ target = r.cy;
+ }
+
+ for( var i = 0; i < names.length; i++ ){
+ var name = names[i];
+
+ var event = Event( e, util.extend({ type: name }, props) );
+ target.trigger( event );
+ }
+ };
+
+ var isMultSelKeyDown = function( e ){
+ return e.shiftKey || e.metaKey || e.ctrlKey; // maybe e.altKey
+ };
+
+ var getDragListIds = function(opts){
+ var listHasId;
+
+ if( opts.addToList && r.cy.hasCompoundNodes() ){ // only needed for compound graphs
+ if( !opts.addToList.hasId ){ // build ids lookup if doesn't already exist
+ opts.addToList.hasId = {};
+
+ for( var i = 0; i < opts.addToList.length; i++ ){
+ var ele = opts.addToList[i];
+
+ opts.addToList.hasId[ ele.id() ] = true;
+ }
+ }
+
+ listHasId = opts.addToList.hasId;
+ }
+
+ return listHasId || {};
+ };
+
+ // helper function to determine which child nodes and inner edges
+ // of a compound node to be dragged as well as the grabbed and selected nodes
+ var addDescendantsToDrag = function(node, opts){
+ if( !node._private.cy.hasCompoundNodes() ){
+ return;
+ }
+
+ if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do
+
+ var listHasId = getDragListIds( opts );
+
+ var innerNodes = node.descendants();
+
+ for( var i = 0; i < innerNodes.size(); i++ ){
+ var iNode = innerNodes[i];
+ var _p = iNode._private;
+
+ if( opts.inDragLayer ){
+ _p.rscratch.inDragLayer = true;
+ }
+
+ if( opts.addToList && !listHasId[ iNode.id() ] ){
+ opts.addToList.push( iNode );
+ listHasId[ iNode.id() ] = true;
+
+ _p.grabbed = true;
+ }
+
+ var edges = _p.edges;
+ for( var j = 0; opts.inDragLayer && j < edges.length; j++ ){
+ edges[j]._private.rscratch.inDragLayer = true;
+ }
+ }
+ };
+
+ // adds the given nodes, and its edges to the drag layer
+ var addNodeToDrag = function(node, opts){
+
+ var _p = node._private;
+ var listHasId = getDragListIds( opts );
+
+ if( opts.inDragLayer ){
+ _p.rscratch.inDragLayer = true;
+ }
+
+ if( opts.addToList && !listHasId[ node.id() ] ){
+ opts.addToList.push( node );
+ listHasId[ node.id() ] = true;
+
+ _p.grabbed = true;
+ }
+
+ var edges = _p.edges;
+ for( var i = 0; opts.inDragLayer && i < edges.length; i++ ){
+ edges[i]._private.rscratch.inDragLayer = true;
+ }
+
+ addDescendantsToDrag( node, opts ); // always add to drag
+
+ // also add nodes and edges related to the topmost ancestor
+ updateAncestorsInDragLayer( node, {
+ inDragLayer: opts.inDragLayer
+ } );
+ };
+
+ var freeDraggedElements = function( draggedElements ){
+ if( !draggedElements ){ return; }
+
+ for (var i=0; i < draggedElements.length; i++) {
+
+ var dEi_p = draggedElements[i]._private;
+
+ if(dEi_p.group === 'nodes') {
+ dEi_p.rscratch.inDragLayer = false;
+ dEi_p.grabbed = false;
+
+ var sEdges = dEi_p.edges;
+ for( var j = 0; j < sEdges.length; j++ ){ sEdges[j]._private.rscratch.inDragLayer = false; }
+
+ // for compound nodes, also remove related nodes and edges from the drag layer
+ updateAncestorsInDragLayer(draggedElements[i], { inDragLayer: false });
+
+ } else if( dEi_p.group === 'edges' ){
+ dEi_p.rscratch.inDragLayer = false;
+ }
+
+ }
+ };
+
+ // helper function to determine which ancestor nodes and edges should go
+ // to the drag layer (or should be removed from drag layer).
+ var updateAncestorsInDragLayer = function(node, opts) {
+
+ if( opts.inDragLayer == null && opts.addToList == null ){ return; } // nothing to do
+
+ // find top-level parent
+ var parent = node;
+
+ if( !node._private.cy.hasCompoundNodes() ){
+ return;
+ }
+
+ while( parent.parent().nonempty() ){
+ parent = parent.parent()[0];
+ }
+
+ // no parent node: no nodes to add to the drag layer
+ if( parent == node ){
+ return;
+ }
+
+ var nodes = parent.descendants()
+ .merge( parent )
+ .unmerge( node )
+ .unmerge( node.descendants() )
+ ;
+
+ var edges = nodes.connectedEdges();
+
+ var listHasId = getDragListIds( opts );
+
+ for( var i = 0; i < nodes.size(); i++ ){
+ if( opts.inDragLayer !== undefined ){
+ nodes[i]._private.rscratch.inDragLayer = opts.inDragLayer;
+ }
+
+ if( opts.addToList && !listHasId[ nodes[i].id() ] ){
+ opts.addToList.push( nodes[i] );
+ listHasId[ nodes[i].id() ] = true;
+
+ nodes[i]._private.grabbed = true;
+ }
+ }
+
+ for( var j = 0; opts.inDragLayer !== undefined && j < edges.length; j++ ) {
+ edges[j]._private.rscratch.inDragLayer = opts.inDragLayer;
+ }
+ };
+
+ if( typeof MutationObserver !== 'undefined' ){
+ r.removeObserver = new MutationObserver(function( mutns ){
+ for( var i = 0; i < mutns.length; i++ ){
+ var mutn = mutns[i];
+ var rNodes = mutn.removedNodes;
+
+ if( rNodes ){ for( var j = 0; j < rNodes.length; j++ ){
+ var rNode = rNodes[j];
+
+ if( rNode === r.container ){
+ r.destroy();
+ break;
+ }
+ } }
+ }
+ });
+
+ if( r.container.parentNode ){
+ r.removeObserver.observe( r.container.parentNode, { childList: true } );
+ }
+ } else {
+ r.registerBinding(r.container, 'DOMNodeRemoved', function(e){
+ r.destroy();
+ });
+ }
+
+
+
+ // auto resize
+ r.registerBinding(window, 'resize', util.debounce( function(e) {
+ r.invalidateContainerClientCoordsCache();
+
+ r.matchCanvasSize(r.container);
+ r.redrawHint('eles', true);
+ r.redraw();
+ }, 100 ) );
+
+ var invalCtnrBBOnScroll = function(domEle){
+ r.registerBinding(domEle, 'scroll', function(e){
+ r.invalidateContainerClientCoordsCache();
+ } );
+ };
+
+ var bbCtnr = r.cy.container();
+
+ for( ;; ){
+
+ invalCtnrBBOnScroll( bbCtnr );
+
+ if( bbCtnr.parentNode ){
+ bbCtnr = bbCtnr.parentNode;
+ } else {
+ break;
+ }
+
+ }
+
+ // stop right click menu from appearing on cy
+ r.registerBinding(r.container, 'contextmenu', function(e){
+ e.preventDefault();
+ });
+
+ var inBoxSelection = function(){
+ return r.selection[4] !== 0;
+ };
+
+ // Primary key
+ r.registerBinding(r.container, 'mousedown', function(e) {
+ e.preventDefault();
+ r.hoverData.capture = true;
+ r.hoverData.which = e.which;
+
+ var cy = r.cy;
+ var pos = r.projectIntoViewport(e.clientX, e.clientY);
+ var select = r.selection;
+ var near = r.findNearestElement(pos[0], pos[1], true, false);
+ var draggedElements = r.dragData.possibleDragElements;
+
+ r.hoverData.mdownPos = pos;
+
+ var checkForTaphold = function(){
+ r.hoverData.tapholdCancelled = false;
+
+ clearTimeout( r.hoverData.tapholdTimeout );
+
+ r.hoverData.tapholdTimeout = setTimeout(function(){
+
+ if( r.hoverData.tapholdCancelled ){
+ return;
+ } else {
+ var ele = r.hoverData.down;
+
+ if( ele ){
+ ele.trigger( Event(e, {
+ type: 'taphold',
+ cyPosition: { x: pos[0], y: pos[1] }
+ }) );
+ } else {
+ cy.trigger( Event(e, {
+ type: 'taphold',
+ cyPosition: { x: pos[0], y: pos[1] }
+ }) );
+ }
+ }
+
+ }, r.tapholdDuration);
+ };
+
+ // Right click button
+ if( e.which == 3 ){
+
+ r.hoverData.cxtStarted = true;
+
+ var cxtEvt = Event(e, {
+ type: 'cxttapstart',
+ cyPosition: { x: pos[0], y: pos[1] }
+ });
+
+ if( near ){
+ near.activate();
+ near.trigger( cxtEvt );
+
+ r.hoverData.down = near;
+ } else {
+ cy.trigger( cxtEvt );
+ }
+
+ r.hoverData.downTime = (new Date()).getTime();
+ r.hoverData.cxtDragged = false;
+
+ // Primary button
+ } else if (e.which == 1) {
+
+ if( near ){
+ near.activate();
+ }
+
+ // Element dragging
+ {
+ // If something is under the cursor and it is draggable, prepare to grab it
+ if (near != null) {
+
+ if( r.nodeIsDraggable(near) ){
+
+ var grabEvent = Event(e, {
+ type: 'grab',
+ cyPosition: { x: pos[0], y: pos[1] }
+ });
+
+ if ( near.isNode() && !near.selected() ){
+
+ draggedElements = r.dragData.possibleDragElements = [];
+ addNodeToDrag( near, { addToList: draggedElements } );
+
+ near.trigger(grabEvent);
+
+ } else if ( near.isNode() && near.selected() ){
+ draggedElements = r.dragData.possibleDragElements = [ ];
+
+ var selectedNodes = cy.$(function(){ return this.isNode() && this.selected(); });
+
+ for( var i = 0; i < selectedNodes.length; i++ ){
+
+ // Only add this selected node to drag if it is draggable, eg. has nonzero opacity
+ if( r.nodeIsDraggable( selectedNodes[i] ) ){
+ addNodeToDrag( selectedNodes[i], { addToList: draggedElements } );
+ }
+ }
+
+ near.trigger( grabEvent );
+ }
+
+ r.redrawHint('eles', true);
+ r.redrawHint('drag', true);
+
+ }
+
+ }
+
+ r.hoverData.down = near;
+ r.hoverData.downTime = (new Date()).getTime();
+ }
+
+ triggerEvents( near, ['mousedown', 'tapstart', 'vmousedown'], e, {
+ cyPosition: { x: pos[0], y: pos[1] }
+ } );
+
+ if ( near == null ) {
+ select[4] = 1;
+
+ r.data.bgActivePosistion = {
+ x: pos[0],
+ y: pos[1]
+ };
+
+ r.redrawHint('select', true);
+
+ r.redraw();
+ } else if( near.isEdge() ){
+ select[4] = 1; // for future pan
+ }
+
+ checkForTaphold();
+
+ }
+
+ // Initialize selection box coordinates
+ select[0] = select[2] = pos[0];
+ select[1] = select[3] = pos[1];
+
+ }, false);
+
+ r.registerBinding(window, 'mousemove', function(e) {
+ var preventDefault = false;
+ var capture = r.hoverData.capture;
+
+ // save cycles if mouse events aren't to be captured
+ if ( !capture ){
+ var containerPageCoords = r.findContainerClientCoords();
+
+ if (e.clientX > containerPageCoords[0] && e.clientX < containerPageCoords[0] + r.canvasWidth
+ && e.clientY > containerPageCoords[1] && e.clientY < containerPageCoords[1] + r.canvasHeight
+ ) {
+ // inside container bounds so OK
+ } else {
+ return;
+ }
+
+ var cyContainer = r.container;
+ var target = e.target;
+ var tParent = target.parentNode;
+ var containerIsTarget = false;
+
+ while( tParent ){
+ if( tParent === cyContainer ){
+ containerIsTarget = true;
+ break;
+ }
+
+ tParent = tParent.parentNode;
+ }
+
+ if( !containerIsTarget ){ return; } // if target is outisde cy container, then this event is not for us
+ }
+
+ var cy = r.cy;
+ var zoom = cy.zoom();
+ var pos = r.projectIntoViewport(e.clientX, e.clientY);
+ var select = r.selection;
+
+ var near = null;
+ if( !r.hoverData.draggingEles ){
+ near = r.findNearestElement(pos[0], pos[1], true, false);
+ }
+ var last = r.hoverData.last;
+ var down = r.hoverData.down;
+
+ var disp = [pos[0] - select[2], pos[1] - select[3]];
+
+ var draggedElements = r.dragData.possibleDragElements;
+
+ var dx = select[2] - select[0];
+ var dx2 = dx * dx;
+ var dy = select[3] - select[1];
+ var dy2 = dy * dy;
+ var dist2 = dx2 + dy2;
+ var rdist2 = dist2 * zoom * zoom;
+
+ var multSelKeyDown = isMultSelKeyDown( e );
+
+ r.hoverData.tapholdCancelled = true;
+
+ var updateDragDelta = function(){
+ var dragDelta = r.hoverData.dragDelta = r.hoverData.dragDelta || [];
+
+ if( dragDelta.length === 0 ){
+ dragDelta.push( disp[0] );
+ dragDelta.push( disp[1] );
+ } else {
+ dragDelta[0] += disp[0];
+ dragDelta[1] += disp[1];
+ }
+ };
+
+
+ preventDefault = true;
+
+ triggerEvents( near, ['mousemove', 'vmousemove', 'tapdrag'], e, {
+ cyPosition: { x: pos[0], y: pos[1] }
+ } );
+
+ // trigger context drag if rmouse down
+ if( r.hoverData.which === 3 ){
+ var cxtEvt = Event(e, {
+ type: 'cxtdrag',
+ cyPosition: { x: pos[0], y: pos[1] }
+ });
+
+ if( down ){
+ down.trigger( cxtEvt );
+ } else {
+ cy.trigger( cxtEvt );
+ }
+
+ r.hoverData.cxtDragged = true;
+
+ if( !r.hoverData.cxtOver || near !== r.hoverData.cxtOver ){
+
+ if( r.hoverData.cxtOver ){
+ r.hoverData.cxtOver.trigger( Event(e, {
+ type: 'cxtdragout',
+ cyPosition: { x: pos[0], y: pos[1] }
+ }) );
+ }
+
+ r.hoverData.cxtOver = near;
+
+ if( near ){
+ near.trigger( Event(e, {
+ type: 'cxtdragover',
+ cyPosition: { x: pos[0], y: pos[1] }
+ }) );
+ }
+
+ }
+
+ // Check if we are drag panning the entire graph
+ } else if (r.hoverData.dragging) {
+ preventDefault = true;
+
+ if( cy.panningEnabled() && cy.userPanningEnabled() ){
+ var deltaP;
+
+ if( r.hoverData.justStartedPan ){
+ var mdPos = r.hoverData.mdownPos;
+
+ deltaP = {
+ x: ( pos[0] - mdPos[0] ) * zoom,
+ y: ( pos[1] - mdPos[1] ) * zoom
+ };
+
+ r.hoverData.justStartedPan = false;
+
+ } else {
+ deltaP = {
+ x: disp[0] * zoom,
+ y: disp[1] * zoom
+ };
+
+ }
+
+ cy.panBy( deltaP );
+
+ r.hoverData.dragged = true;
+ }
+
+ // Needs reproject due to pan changing viewport
+ pos = r.projectIntoViewport(e.clientX, e.clientY);
+
+ // Checks primary button down & out of time & mouse not moved much
+ } else if(
+ select[4] == 1 && (down == null || down.isEdge())
+ ){
+
+ if( !r.hoverData.dragging && cy.boxSelectionEnabled() && ( multSelKeyDown || !cy.panningEnabled() || !cy.userPanningEnabled() ) ){
+ r.data.bgActivePosistion = undefined;
+ r.hoverData.selecting = true;
+
+ r.redrawHint('select', true);
+ r.redraw();
+
+ } else if( !r.hoverData.selecting && cy.panningEnabled() && cy.userPanningEnabled() ){
+ r.hoverData.dragging = true;
+ r.hoverData.justStartedPan = true;
+ select[4] = 0;
+
+ r.data.bgActivePosistion = {
+ x: pos[0],
+ y: pos[1]
+ };
+
+ r.redrawHint('select', true);
+ r.redraw();
+ }
+
+ if( down && down.isEdge() && down.active() ){ down.unactivate(); }
+
+ } else {
+ if( down && down.isEdge() && down.active() ){ down.unactivate(); }
+
+ if (near != last) {
+
+ if (last) {
+ triggerEvents( last, ['mouseout', 'tapdragout'], e, {
+ cyPosition: { x: pos[0], y: pos[1] }
+ } );
+ }
+
+ if (near) {
+ triggerEvents( near, ['mouseover', 'tapdragover'], e, {
+ cyPosition: { x: pos[0], y: pos[1] }
+ } );
+ }
+
+ r.hoverData.last = near;
+ }
+
+ if( down && down.isNode() && r.nodeIsDraggable(down) ){
+
+ if( rdist2 >= r.desktopTapThreshold2 ){ // then drag
+
+ var justStartedDrag = !r.dragData.didDrag;
+
+ if( justStartedDrag ) {
+ r.redrawHint('eles', true);
+ }
+
+ r.dragData.didDrag = true; // indicate that we actually did drag the node
+
+ var toTrigger = [];
+
+ for( var i = 0; i < draggedElements.length; i++ ){
+ var dEle = draggedElements[i];
+
+ // now, add the elements to the drag layer if not done already
+ if( !r.hoverData.draggingEles ){
+ addNodeToDrag( dEle, { inDragLayer: true } );
+ }
+
+ // Locked nodes not draggable, as well as non-visible nodes
+ if( dEle.isNode() && r.nodeIsDraggable(dEle) && dEle.grabbed() ){
+ var dPos = dEle._private.position;
+
+ toTrigger.push( dEle );
+
+ if( is.number(disp[0]) && is.number(disp[1]) ){
+ var updatePos = !dEle.isParent();
+
+ if( updatePos ){
+ dPos.x += disp[0];
+ dPos.y += disp[1];
+ }
+
+ if( justStartedDrag ){
+ var dragDelta = r.hoverData.dragDelta;
+
+ if( updatePos && is.number(dragDelta[0]) && is.number(dragDelta[1]) ){
+ dPos.x += dragDelta[0];
+ dPos.y += dragDelta[1];
+ }
+ }
+ }
+
+ }
+ }
+
+ r.hoverData.draggingEles = true;
+
+ var tcol = (Collection(cy, toTrigger));
+
+ tcol.updateCompoundBounds();
+ tcol.trigger('position drag');
+
+ r.redrawHint('drag', true);
+ r.redraw();
+
+ } else { // otherwise save drag delta for when we actually start dragging so the relative grab pos is constant
+ updateDragDelta();
+ }
+ }
+
+ // prevent the dragging from triggering text selection on the page
+ preventDefault = true;
+ }
+
+ select[2] = pos[0]; select[3] = pos[1];
+
+ if( preventDefault ){
+ if(e.stopPropagation) e.stopPropagation();
+ if(e.preventDefault) e.preventDefault();
+ return false;
+ }
+ }, false);
+
+ r.registerBinding(window, 'mouseup', function(e) {
+ var capture = r.hoverData.capture;
+ if (!capture) { return; }
+ r.hoverData.capture = false;
+
+ var cy = r.cy; var pos = r.projectIntoViewport(e.clientX, e.clientY); var select = r.selection;
+ var near = r.findNearestElement(pos[0], pos[1], true, false);
+ var draggedElements = r.dragData.possibleDragElements; var down = r.hoverData.down;
+ var multSelKeyDown = isMultSelKeyDown( e );
+
+ if( r.data.bgActivePosistion ){
+ r.redrawHint('select', true);
+ r.redraw();
+ }
+
+ r.hoverData.tapholdCancelled = true;
+
+ r.data.bgActivePosistion = undefined; // not active bg now
+
+ if( down ){
+ down.unactivate();
+ }
+
+ if( r.hoverData.which === 3 ){
+ var cxtEvt = Event(e, {
+ type: 'cxttapend',
+ cyPosition: { x: pos[0], y: pos[1] }
+ });
+
+ if( down ){
+ down.trigger( cxtEvt );
+ } else {
+ cy.trigger( cxtEvt );
+ }
+
+ if( !r.hoverData.cxtDragged ){
+ var cxtTap = Event(e, {
+ type: 'cxttap',
+ cyPosition: { x: pos[0], y: pos[1] }
+ });
+
+ if( down ){
+ down.trigger( cxtTap );
+ } else {
+ cy.trigger( cxtTap );
+ }
+ }
+
+ r.hoverData.cxtDragged = false;
+ r.hoverData.which = null;
+
+ } else if( r.hoverData.which === 1 ) {
+
+ // Deselect all elements if nothing is currently under the mouse cursor and we aren't dragging something
+ if ( (down == null) // not mousedown on node
+ && !r.dragData.didDrag // didn't move the node around
+ && !r.hoverData.selecting // not box selection
+ && !r.hoverData.dragged // didn't pan
+ && !isMultSelKeyDown( e )
+ ) {
+
+ cy.$(function(){
+ return this.selected();
+ }).unselect();
+
+ if (draggedElements.length > 0) {
+ r.redrawHint('eles', true);
+ }
+
+ r.dragData.possibleDragElements = draggedElements = [];
+ }
+
+ triggerEvents( near, ['mouseup', 'tapend', 'vmouseup'], e, {
+ cyPosition: { x: pos[0], y: pos[1] }
+ } );
+
+ if(
+ !r.dragData.didDrag // didn't move a node around
+ && !r.hoverData.dragged // didn't pan
+ ){
+ triggerEvents( near, ['click', 'tap', 'vclick'], e, {
+ cyPosition: { x: pos[0], y: pos[1] }
+ } );
+ }
+
+ // Single selection
+ if( near == down && !r.dragData.didDrag && !r.hoverData.selecting ){
+ if( near != null && near._private.selectable ){
+
+ if( r.hoverData.dragging ){
+ // if panning, don't change selection state
+ } else if( cy.selectionType() === 'additive' || multSelKeyDown ){
+ if( near.selected() ){
+ near.unselect();
+ } else {
+ near.select();
+ }
+ } else {
+ if( !multSelKeyDown ){
+ cy.$(':selected').unmerge( near ).unselect();
+ near.select();
+ }
+ }
+
+ r.redrawHint('eles', true);
+ }
+ }
+
+ if ( r.hoverData.selecting ) {
+ var newlySelected = [];
+ var box = r.getAllInBox( select[0], select[1], select[2], select[3] );
+
+ r.redrawHint('select', true);
+
+ if( box.length > 0 ) {
+ r.redrawHint('eles', true);
+ }
+
+ for( var i = 0; i < box.length; i++ ){
+ if( box[i]._private.selectable ){
+ newlySelected.push( box[i] );
+ }
+ }
+
+ var newlySelCol = Collection( cy, newlySelected );
+
+ if( cy.selectionType() === 'additive' ){
+ newlySelCol.select();
+ } else {
+ if( !multSelKeyDown ){
+ cy.$(':selected').unmerge( newlySelCol ).unselect();
+ }
+
+ newlySelCol.select();
+ }
+
+ // always need redraw in case eles unselectable
+ r.redraw();
+
+ }
+
+ // Cancel drag pan
+ if( r.hoverData.dragging ){
+ r.hoverData.dragging = false;
+
+ r.redrawHint('select', true);
+ r.redrawHint('eles', true);
+
+ r.redraw();
+ }
+
+ if (!select[4]) {
+
+
+ r.redrawHint('drag', true);
+ r.redrawHint('eles', true);
+
+ freeDraggedElements( draggedElements );
+
+ if( down ){ down.trigger('free'); }
+ }
+
+ } // else not right mouse
+
+ select[4] = 0; r.hoverData.down = null;
+
+ r.hoverData.cxtStarted = false;
+ r.hoverData.draggingEles = false;
+ r.hoverData.selecting = false;
+ r.dragData.didDrag = false;
+ r.hoverData.dragged = false;
+ r.hoverData.dragDelta = [];
+
+ }, false);
+
+ var wheelHandler = function(e) {
+
+
+ if( r.scrollingPage ){ return; } // while scrolling, ignore wheel-to-zoom
+
+ var cy = r.cy;
+ var pos = r.projectIntoViewport(e.clientX, e.clientY);
+ var rpos = [pos[0] * cy.zoom() + cy.pan().x,
+ pos[1] * cy.zoom() + cy.pan().y];
+
+ if( r.hoverData.draggingEles || r.hoverData.dragging || r.hoverData.cxtStarted || inBoxSelection() ){ // if pan dragging or cxt dragging, wheel movements make no zoom
+ e.preventDefault();
+ return;
+ }
+
+ if( cy.panningEnabled() && cy.userPanningEnabled() && cy.zoomingEnabled() && cy.userZoomingEnabled() ){
+ e.preventDefault();
+
+ r.data.wheelZooming = true;
+ clearTimeout( r.data.wheelTimeout );
+ r.data.wheelTimeout = setTimeout(function(){
+ r.data.wheelZooming = false;
+
+ r.redrawHint('eles', true);
+ r.redraw();
+ }, 150);
+
+ var diff = e.deltaY / -250 || e.wheelDeltaY / 1000 || e.wheelDelta / 1000;
+ diff = diff * r.wheelSensitivity;
+
+ var needsWheelFix = e.deltaMode === 1;
+ if( needsWheelFix ){ // fixes slow wheel events on ff/linux and ff/windows
+ diff *= 33;
+ }
+
+ cy.zoom({
+ level: cy.zoom() * Math.pow(10, diff),
+ renderedPosition: { x: rpos[0], y: rpos[1] }
+ });
+ }
+
+ };
+
+ // Functions to help with whether mouse wheel should trigger zooming
+ // --
+ r.registerBinding(r.container, 'wheel', wheelHandler, true);
+
+ // disable nonstandard wheel events
+ // r.registerBinding(r.container, 'mousewheel', wheelHandler, true);
+ // r.registerBinding(r.container, 'DOMMouseScroll', wheelHandler, true);
+ // r.registerBinding(r.container, 'MozMousePixelScroll', wheelHandler, true); // older firefox
+
+ r.registerBinding(window, 'scroll', function(e){
+ r.scrollingPage = true;
+
+ clearTimeout( r.scrollingPageTimeout );
+ r.scrollingPageTimeout = setTimeout(function(){
+ r.scrollingPage = false;
+ }, 250);
+ }, true);
+
+ // Functions to help with handling mouseout/mouseover on the Cytoscape container
+ // Handle mouseout on Cytoscape container
+ r.registerBinding(r.container, 'mouseout', function(e) {
+ var pos = r.projectIntoViewport(e.clientX, e.clientY);
+
+ r.cy.trigger(Event(e, {
+ type: 'mouseout',
+ cyPosition: { x: pos[0], y: pos[1] }
+ }));
+ }, false);
+
+ r.registerBinding(r.container, 'mouseover', function(e) {
+ var pos = r.projectIntoViewport(e.clientX, e.clientY);
+
+ r.cy.trigger(Event(e, {
+ type: 'mouseover',
+ cyPosition: { x: pos[0], y: pos[1] }
+ }));
+ }, false);
+
+ var f1x1, f1y1, f2x1, f2y1; // starting points for pinch-to-zoom
+ var distance1, distance1Sq; // initial distance between finger 1 and finger 2 for pinch-to-zoom
+ var center1, modelCenter1; // center point on start pinch to zoom
+ var offsetLeft, offsetTop;
+ var containerWidth, containerHeight;
+ var twoFingersStartInside;
+
+ var distance = function(x1, y1, x2, y2){
+ return Math.sqrt( (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) );
+ };
+
+ var distanceSq = function(x1, y1, x2, y2){
+ return (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1);
+ };
+
+ var touchstartHandler;
+ r.registerBinding(r.container, 'touchstart', touchstartHandler = function(e) {
+ r.touchData.capture = true;
+ r.data.bgActivePosistion = undefined;
+
+ var cy = r.cy;
+ var nodes = r.getCachedNodes();
+ var edges = r.getCachedEdges();
+ var now = r.touchData.now;
+ var earlier = r.touchData.earlier;
+
+ if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }
+ if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }
+ if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }
+
+
+ // record starting points for pinch-to-zoom
+ if( e.touches[1] ){
+
+ // anything in the set of dragged eles should be released
+ var release = function( eles ){
+ for( var i = 0; i < eles.length; i++ ){
+ eles[i]._private.grabbed = false;
+ eles[i]._private.rscratch.inDragLayer = false;
+ if( eles[i].active() ){ eles[i].unactivate(); }
+ }
+ };
+ release(nodes);
+ release(edges);
+
+ var offsets = r.findContainerClientCoords();
+ offsetLeft = offsets[0];
+ offsetTop = offsets[1];
+ containerWidth = offsets[2];
+ containerHeight = offsets[3];
+
+ f1x1 = e.touches[0].clientX - offsetLeft;
+ f1y1 = e.touches[0].clientY - offsetTop;
+
+ f2x1 = e.touches[1].clientX - offsetLeft;
+ f2y1 = e.touches[1].clientY - offsetTop;
+
+ twoFingersStartInside =
+ 0 <= f1x1 && f1x1 <= containerWidth
+ && 0 <= f2x1 && f2x1 <= containerWidth
+ && 0 <= f1y1 && f1y1 <= containerHeight
+ && 0 <= f2y1 && f2y1 <= containerHeight
+ ;
+
+ var pan = cy.pan();
+ var zoom = cy.zoom();
+
+ distance1 = distance( f1x1, f1y1, f2x1, f2y1 );
+ distance1Sq = distanceSq( f1x1, f1y1, f2x1, f2y1 );
+ center1 = [ (f1x1 + f2x1)/2, (f1y1 + f2y1)/2 ];
+ modelCenter1 = [
+ (center1[0] - pan.x) / zoom,
+ (center1[1] - pan.y) / zoom
+ ];
+
+ // consider context tap
+ var cxtDistThreshold = 200;
+ var cxtDistThresholdSq = cxtDistThreshold * cxtDistThreshold;
+ if( distance1Sq < cxtDistThresholdSq && !e.touches[2] ){
+
+ var near1 = r.findNearestElement(now[0], now[1], true, true);
+ var near2 = r.findNearestElement(now[2], now[3], true, true);
+
+ if( near1 && near1.isNode() ){
+ near1.activate().trigger( Event(e, {
+ type: 'cxttapstart',
+ cyPosition: { x: now[0], y: now[1] }
+ }) );
+ r.touchData.start = near1;
+
+ } else if( near2 && near2.isNode() ){
+ near2.activate().trigger( Event(e, {
+ type: 'cxttapstart',
+ cyPosition: { x: now[0], y: now[1] }
+ }) );
+ r.touchData.start = near2;
+
+ } else {
+ cy.trigger( Event(e, {
+ type: 'cxttapstart',
+ cyPosition: { x: now[0], y: now[1] }
+ }) );
+ r.touchData.start = null;
+ }
+
+ if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }
+ r.touchData.cxt = true;
+ r.touchData.cxtDragged = false;
+ r.data.bgActivePosistion = undefined;
+
+ r.redraw();
+ return;
+
+ }
+
+ }
+
+ if (e.touches[2]) {
+
+ } else if (e.touches[1]) {
+
+ } else if (e.touches[0]) {
+ var near = r.findNearestElement(now[0], now[1], true, true);
+
+ if (near != null) {
+ near.activate();
+
+ r.touchData.start = near;
+
+ if( near.isNode() && r.nodeIsDraggable(near) ){
+
+ var draggedEles = r.dragData.touchDragEles = [];
+
+ r.redrawHint('eles', true);
+ r.redrawHint('drag', true);
+
+ if( near.selected() ){
+ // reset drag elements, since near will be added again
+
+ var selectedNodes = cy.$(function(){
+ return this.isNode() && this.selected();
+ });
+
+ for( var k = 0; k < selectedNodes.length; k++ ){
+ var selectedNode = selectedNodes[k];
+
+ if( r.nodeIsDraggable(selectedNode) ){
+ addNodeToDrag( selectedNode, { addToList: draggedEles } );
+ }
+ }
+ } else {
+ addNodeToDrag( near, { addToList: draggedEles } );
+ }
+
+ near.trigger( Event(e, {
+ type: 'grab',
+ cyPosition: { x: now[0], y: now[1] }
+ }) );
+ }
+ }
+
+ triggerEvents( near, ['touchstart', 'tapstart', 'vmousedown'], e, {
+ cyPosition: { x: now[0], y: now[1] }
+ } );
+
+ if (near == null) {
+ r.data.bgActivePosistion = {
+ x: pos[0],
+ y: pos[1]
+ };
+
+ r.redrawHint('select', true);
+ r.redraw();
+ }
+
+
+ // Tap, taphold
+ // -----
+
+ for (var i=0; i<now.length; i++) {
+ earlier[i] = now[i];
+ r.touchData.startPosition[i] = now[i];
+ }
+
+ r.touchData.singleTouchMoved = false;
+ r.touchData.singleTouchStartTime = +new Date();
+
+ clearTimeout( r.touchData.tapholdTimeout );
+ r.touchData.tapholdTimeout = setTimeout(function() {
+ if(
+ r.touchData.singleTouchMoved === false
+ && !r.pinching // if pinching, then taphold unselect shouldn't take effect
+ ){
+ triggerEvents( r.touchData.start, ['taphold'], e, {
+ cyPosition: { x: now[0], y: now[1] }
+ } );
+
+ if (!r.touchData.start) {
+ cy.$(':selected').unselect();
+ }
+
+ }
+ }, r.tapholdDuration);
+ }
+
+ }, false);
+
+ var touchmoveHandler;
+ r.registerBinding(window, 'touchmove', touchmoveHandler = function(e) {
+
+ var select = r.selection;
+ var capture = r.touchData.capture;
+ var cy = r.cy;
+ var now = r.touchData.now; var earlier = r.touchData.earlier;
+ var zoom = cy.zoom();
+
+ if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }
+ if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }
+ if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }
+
+ var disp = []; for (var j=0;j<now.length;j++) { disp[j] = now[j] - earlier[j]; }
+ var startPos = r.touchData.startPosition;
+ var dx = now[0] - startPos[0];
+ var dx2 = dx * dx;
+ var dy = now[1] - startPos[1];
+ var dy2 = dy * dy;
+ var dist2 = dx2 + dy2;
+ var rdist2 = dist2 * zoom * zoom;
+
+ // context swipe cancelling
+ if( capture && r.touchData.cxt ){
+ e.preventDefault();
+
+ var f1x2 = e.touches[0].clientX - offsetLeft, f1y2 = e.touches[0].clientY - offsetTop;
+ var f2x2 = e.touches[1].clientX - offsetLeft, f2y2 = e.touches[1].clientY - offsetTop;
+ // var distance2 = distance( f1x2, f1y2, f2x2, f2y2 );
+ var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 );
+ var factorSq = distance2Sq / distance1Sq;
+
+ var distThreshold = 150;
+ var distThresholdSq = distThreshold * distThreshold;
+ var factorThreshold = 1.5;
+ var factorThresholdSq = factorThreshold * factorThreshold;
+
+ // cancel ctx gestures if the distance b/t the fingers increases
+ if( factorSq >= factorThresholdSq || distance2Sq >= distThresholdSq ){
+ r.touchData.cxt = false;
+ if( r.touchData.start ){ r.touchData.start.unactivate(); r.touchData.start = null; }
+ r.data.bgActivePosistion = undefined;
+ r.redrawHint('select', true);
+
+ var cxtEvt = Event(e, {
+ type: 'cxttapend',
+ cyPosition: { x: now[0], y: now[1] }
+ });
+ if( r.touchData.start ){
+ r.touchData.start.trigger( cxtEvt );
+ } else {
+ cy.trigger( cxtEvt );
+ }
+ }
+
+ }
+
+ // context swipe
+ if( capture && r.touchData.cxt ){
+ var cxtEvt = Event(e, {
+ type: 'cxtdrag',
+ cyPosition: { x: now[0], y: now[1] }
+ });
+ r.data.bgActivePosistion = undefined;
+ r.redrawHint('select', true);
+
+ if( r.touchData.start ){
+ r.touchData.start.trigger( cxtEvt );
+ } else {
+ cy.trigger( cxtEvt );
+ }
+
+ if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }
+ r.touchData.cxtDragged = true;
+
+ var near = r.findNearestElement(now[0], now[1], true, true);
+
+ if( !r.touchData.cxtOver || near !== r.touchData.cxtOver ){
+
+ if( r.touchData.cxtOver ){
+ r.touchData.cxtOver.trigger( Event(e, {
+ type: 'cxtdragout',
+ cyPosition: { x: now[0], y: now[1] }
+ }) );
+ }
+
+ r.touchData.cxtOver = near;
+
+ if( near ){
+ near.trigger( Event(e, {
+ type: 'cxtdragover',
+ cyPosition: { x: now[0], y: now[1] }
+ }) );
+
+ }
+
+ }
+
+ // box selection
+ } else if( capture && e.touches[2] && cy.boxSelectionEnabled() ){
+ e.preventDefault();
+
+ r.data.bgActivePosistion = undefined;
+
+ this.lastThreeTouch = +new Date();
+ r.touchData.selecting = true;
+
+ r.redrawHint('select', true);
+
+ if( !select || select.length === 0 || select[0] === undefined ){
+ select[0] = (now[0] + now[2] + now[4])/3;
+ select[1] = (now[1] + now[3] + now[5])/3;
+ select[2] = (now[0] + now[2] + now[4])/3 + 1;
+ select[3] = (now[1] + now[3] + now[5])/3 + 1;
+ } else {
+ select[2] = (now[0] + now[2] + now[4])/3;
+ select[3] = (now[1] + now[3] + now[5])/3;
+ }
+
+ select[4] = 1;
+ r.touchData.selecting = true;
+
+ r.redraw();
+
+ // pinch to zoom
+ } else if ( capture && e.touches[1] && cy.zoomingEnabled() && cy.panningEnabled() && cy.userZoomingEnabled() && cy.userPanningEnabled() ) { // two fingers => pinch to zoom
+ e.preventDefault();
+
+ r.data.bgActivePosistion = undefined;
+ r.redrawHint('select', true);
+
+ var draggedEles = r.dragData.touchDragEles;
+ if( draggedEles ){
+ r.redrawHint('drag', true);
+
+ for( var i = 0; i < draggedEles.length; i++ ){
+ draggedEles[i]._private.grabbed = false;
+ draggedEles[i]._private.rscratch.inDragLayer = false;
+ }
+ }
+
+ // (x2, y2) for fingers 1 and 2
+ var f1x2 = e.touches[0].clientX - offsetLeft, f1y2 = e.touches[0].clientY - offsetTop;
+ var f2x2 = e.touches[1].clientX - offsetLeft, f2y2 = e.touches[1].clientY - offsetTop;
+
+
+ var distance2 = distance( f1x2, f1y2, f2x2, f2y2 );
+ // var distance2Sq = distanceSq( f1x2, f1y2, f2x2, f2y2 );
+ // var factor = Math.sqrt( distance2Sq ) / Math.sqrt( distance1Sq );
+ var factor = distance2 / distance1;
+
+ if( factor != 1 && twoFingersStartInside){
+ // delta finger1
+ var df1x = f1x2 - f1x1;
+ var df1y = f1y2 - f1y1;
+
+ // delta finger 2
+ var df2x = f2x2 - f2x1;
+ var df2y = f2y2 - f2y1;
+
+ // translation is the normalised vector of the two fingers movement
+ // i.e. so pinching cancels out and moving together pans
+ var tx = (df1x + df2x)/2;
+ var ty = (df1y + df2y)/2;
+
+ // adjust factor by the speed multiplier
+ // var speed = 1.5;
+ // if( factor > 1 ){
+ // factor = (factor - 1) * speed + 1;
+ // } else {
+ // factor = 1 - (1 - factor) * speed;
+ // }
+
+ // now calculate the zoom
+ var zoom1 = cy.zoom();
+ var zoom2 = zoom1 * factor;
+ var pan1 = cy.pan();
+
+ // the model center point converted to the current rendered pos
+ var ctrx = modelCenter1[0] * zoom1 + pan1.x;
+ var ctry = modelCenter1[1] * zoom1 + pan1.y;
+
+ var pan2 = {
+ x: -zoom2/zoom1 * (ctrx - pan1.x - tx) + ctrx,
+ y: -zoom2/zoom1 * (ctry - pan1.y - ty) + ctry
+ };
+
+ // remove dragged eles
+ if( r.touchData.start ){
+ var draggedEles = r.dragData.touchDragEles;
+
+ if( draggedEles ){ for( var i = 0; i < draggedEles.length; i++ ){
+ var dEi_p = draggedEles[i]._private;
+
+ dEi_p.grabbed = false;
+ dEi_p.rscratch.inDragLayer = false;
+ } }
+
+ var start_p = r.touchData.start._private;
+ start_p.active = false;
+ start_p.grabbed = false;
+ start_p.rscratch.inDragLayer = false;
+
+ r.redrawHint('drag', true);
+
+ r.touchData.start
+ .trigger('free')
+ .trigger('unactivate')
+ ;
+ }
+
+ cy.viewport({
+ zoom: zoom2,
+ pan: pan2,
+ cancelOnFailedZoom: true
+ });
+
+ distance1 = distance2;
+ f1x1 = f1x2;
+ f1y1 = f1y2;
+ f2x1 = f2x2;
+ f2y1 = f2y2;
+
+ r.pinching = true;
+ }
+
+ // Re-project
+ if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }
+ if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }
+ if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }
+
+ } else if (e.touches[0]) {
+ var start = r.touchData.start;
+ var last = r.touchData.last;
+ var near = near || r.findNearestElement(now[0], now[1], true, true);
+
+ if( start != null ){
+ e.preventDefault();
+ }
+
+ // dragging nodes
+ if( start != null && start._private.group == 'nodes' && r.nodeIsDraggable(start) ){
+
+ if( rdist2 >= r.touchTapThreshold2 ){ // then dragging can happen
+ var draggedEles = r.dragData.touchDragEles;
+ var justStartedDrag = !r.dragData.didDrag;
+
+ for( var k = 0; k < draggedEles.length; k++ ){
+ var draggedEle = draggedEles[k];
+
+ if( justStartedDrag ){
+ addNodeToDrag( draggedEle, { inDragLayer: true } );
+ }
+
+ if( r.nodeIsDraggable(draggedEle) && draggedEle.isNode() && draggedEle.grabbed() ){
+ r.dragData.didDrag = true;
+ var dPos = draggedEle._private.position;
+ var updatePos = !draggedEle.isParent();
+
+ if( updatePos && is.number(disp[0]) && is.number(disp[1]) ){
+ dPos.x += disp[0];
+ dPos.y += disp[1];
+ }
+
+ if( justStartedDrag ){
+ r.redrawHint('eles', true);
+
+ var dragDelta = r.touchData.dragDelta;
+
+ if( updatePos && is.number(dragDelta[0]) && is.number(dragDelta[1]) ){
+ dPos.x += dragDelta[0];
+ dPos.y += dragDelta[1];
+ }
+
+ }
+ }
+ }
+
+ var tcol = Collection(cy, draggedEles);
+
+ tcol.updateCompoundBounds();
+ tcol.trigger('position drag');
+
+ r.hoverData.draggingEles = true;
+
+ r.redrawHint('drag', true);
+
+ if(
+ r.touchData.startPosition[0] == earlier[0]
+ && r.touchData.startPosition[1] == earlier[1]
+ ){
+
+ r.redrawHint('eles', true);
+ }
+
+ r.redraw();
+ } else { // otherise keep track of drag delta for later
+ var dragDelta = r.touchData.dragDelta = r.touchData.dragDelta || [];
+
+ if( dragDelta.length === 0 ){
+ dragDelta.push( disp[0] );
+ dragDelta.push( disp[1] );
+ } else {
+ dragDelta[0] += disp[0];
+ dragDelta[1] += disp[1];
+ }
+ }
+ }
+
+ // touchmove
+ {
+ triggerEvents( (start || near), ['touchmove', 'tapdrag', 'vmousemove'], e, {
+ cyPosition: { x: now[0], y: now[1] }
+ } );
+
+ if (near != last) {
+ if (last) { last.trigger(Event(e, { type: 'tapdragout', cyPosition: { x: now[0], y: now[1] } })); }
+ if (near) { near.trigger(Event(e, { type: 'tapdragover', cyPosition: { x: now[0], y: now[1] } })); }
+ }
+
+ r.touchData.last = near;
+ }
+
+ // check to cancel taphold
+ for (var i=0;i<now.length;i++) {
+ if( now[i]
+ && r.touchData.startPosition[i]
+ && rdist2 > r.touchTapThreshold2 ){
+
+ r.touchData.singleTouchMoved = true;
+ }
+ }
+
+ // panning
+ if(
+ capture
+ && ( start == null || start.isEdge() )
+ && cy.panningEnabled() && cy.userPanningEnabled()
+ ){
+
+ e.preventDefault();
+
+ if( r.swipePanning ){
+ cy.panBy({
+ x: disp[0] * zoom,
+ y: disp[1] * zoom
+ });
+
+ } else if( rdist2 >= r.touchTapThreshold2 ){
+ r.swipePanning = true;
+
+ cy.panBy({
+ x: dx * zoom,
+ y: dy * zoom
+ });
+
+ if( start ){
+ start.unactivate();
+
+ if( !r.data.bgActivePosistion ){
+ r.data.bgActivePosistion = {
+ x: now[0],
+ y: now[1]
+ };
+ }
+
+ r.redrawHint('select', true);
+
+ r.touchData.start = null;
+ }
+ }
+
+ // Re-project
+ var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY);
+ now[0] = pos[0]; now[1] = pos[1];
+ }
+ }
+
+ for (var j=0; j<now.length; j++) { earlier[j] = now[j]; }
+ //r.redraw();
+
+ }, false);
+
+ var touchcancelHandler;
+ r.registerBinding(window, 'touchcancel', touchcancelHandler = function(e) {
+ var start = r.touchData.start;
+
+ r.touchData.capture = false;
+
+ if( start ){
+ start.unactivate();
+ }
+ });
+
+ var touchendHandler;
+ r.registerBinding(window, 'touchend', touchendHandler = function(e) {
+ var start = r.touchData.start;
+
+ var capture = r.touchData.capture;
+
+ if( capture ){
+ r.touchData.capture = false;
+
+ e.preventDefault();
+ } else {
+ return;
+ }
+
+ var select = r.selection;
+
+ r.swipePanning = false;
+ r.hoverData.draggingEles = false;
+
+ var cy = r.cy;
+ var zoom = cy.zoom();
+ var now = r.touchData.now;
+ var earlier = r.touchData.earlier;
+
+ if (e.touches[0]) { var pos = r.projectIntoViewport(e.touches[0].clientX, e.touches[0].clientY); now[0] = pos[0]; now[1] = pos[1]; }
+ if (e.touches[1]) { var pos = r.projectIntoViewport(e.touches[1].clientX, e.touches[1].clientY); now[2] = pos[0]; now[3] = pos[1]; }
+ if (e.touches[2]) { var pos = r.projectIntoViewport(e.touches[2].clientX, e.touches[2].clientY); now[4] = pos[0]; now[5] = pos[1]; }
+
+ if( start ){
+ start.unactivate();
+ }
+
+ var ctxTapend;
+ if( r.touchData.cxt ){
+ ctxTapend = Event(e, {
+ type: 'cxttapend',
+ cyPosition: { x: now[0], y: now[1] }
+ });
+
+ if( start ){
+ start.trigger( ctxTapend );
+ } else {
+ cy.trigger( ctxTapend );
+ }
+
+ if( !r.touchData.cxtDragged ){
+ var ctxTap = Event(e, {
+ type: 'cxttap',
+ cyPosition: { x: now[0], y: now[1] }
+ });
+
+ if( start ){
+ start.trigger( ctxTap );
+ } else {
+ cy.trigger( ctxTap );
+ }
+
+ }
+
+ if( r.touchData.start ){ r.touchData.start._private.grabbed = false; }
+ r.touchData.cxt = false;
+ r.touchData.start = null;
+
+ r.redraw();
+ return;
+ }
+
+ // no more box selection if we don't have three fingers
+ if( !e.touches[2] && cy.boxSelectionEnabled() && r.touchData.selecting ){
+ r.touchData.selecting = false;
+
+ var newlySelected = [];
+ var box = r.getAllInBox( select[0], select[1], select[2], select[3] );
+
+ select[0] = undefined;
+ select[1] = undefined;
+ select[2] = undefined;
+ select[3] = undefined;
+ select[4] = 0;
+
+ r.redrawHint('select', true);
+
+ for( var i = 0; i< box.length; i++ ) {
+ if( box[i]._private.selectable ){
+ newlySelected.push( box[i] );
+ }
+ }
+
+ var newlySelCol = Collection( cy, newlySelected );
+
+ newlySelCol.select();
+
+ if( newlySelCol.length > 0 ) {
+ r.redrawHint('eles', true);
+ } else {
+ r.redraw();
+ }
+ }
+
+ var updateStartStyle = false;
+
+ if( start != null ){
+ start._private.active = false;
+ updateStartStyle = true;
+ start.unactivate();
+ }
+
+ if (e.touches[2]) {
+ r.data.bgActivePosistion = undefined;
+ r.redrawHint('select', true);
+ } else if (e.touches[1]) {
+
+ } else if (e.touches[0]) {
+
+ // Last touch released
+ } else if (!e.touches[0]) {
+
+ r.data.bgActivePosistion = undefined;
+ r.redrawHint('select', true);
+
+ var draggedEles = r.dragData.touchDragEles;
+
+ if (start != null ) {
+
+ var startWasGrabbed = start._private.grabbed;
+
+ freeDraggedElements( draggedEles );
+
+ r.redrawHint('drag', true);
+ r.redrawHint('eles', true);
+
+ if( startWasGrabbed ){
+ start.trigger('free');
+ }
+
+ triggerEvents( start, ['touchend', 'tapend', 'vmouseup'], e, {
+ cyPosition: { x: now[0], y: now[1] }
+ } );
+
+ start.unactivate();
+
+ r.touchData.start = null;
+
+ } else {
+ var near = r.findNearestElement(now[0], now[1], true, true);
+
+ triggerEvents( near, ['touchend', 'tapend', 'vmouseup'], e, {
+ cyPosition: { x: now[0], y: now[1] }
+ } );
+
+ }
+
+ var dx = r.touchData.startPosition[0] - now[0];
+ var dx2 = dx * dx;
+ var dy = r.touchData.startPosition[1] - now[1];
+ var dy2 = dy * dy;
+ var dist2 = dx2 + dy2;
+ var rdist2 = dist2 * zoom * zoom;
+
+ // Prepare to select the currently touched node, only if it hasn't been dragged past a certain distance
+ if (start != null
+ && !r.dragData.didDrag // didn't drag nodes around
+ && start._private.selectable
+ && rdist2 < r.touchTapThreshold2
+ && !r.pinching // pinch to zoom should not affect selection
+ ) {
+
+ if( cy.selectionType() === 'single' ){
+ cy.$(':selected').unmerge( start ).unselect();
+ start.select();
+ } else {
+ if( start.selected() ){
+ start.unselect();
+ } else {
+ start.select();
+ }
+ }
+
+ updateStartStyle = true;
+
+
+ r.redrawHint('eles', true);
+ }
+
+ // Tap event, roughly same as mouse click event for touch
+ if( !r.touchData.singleTouchMoved ){
+ triggerEvents( start, ['tap', 'vclick'], e, {
+ cyPosition: { x: now[0], y: now[1] }
+ } );
+ }
+
+ r.touchData.singleTouchMoved = true;
+ }
+
+ for( var j = 0; j < now.length; j++ ){ earlier[j] = now[j]; }
+
+ r.dragData.didDrag = false; // reset for next mousedown
+
+ if( e.touches.length === 0 ){
+ r.touchData.dragDelta = [];
+ }
+
+ if( updateStartStyle && start ){
+ start.updateStyle(false);
+ }
+
+ if( e.touches.length < 2 ){
+ r.pinching = false;
+ r.redrawHint('eles', true);
+ r.redraw();
+ }
+
+ //r.redraw();
+
+ }, false);
+
+ // fallback compatibility layer for ms pointer events
+ if( typeof TouchEvent === 'undefined' ){
+
+ var pointers = [];
+
+ var makeTouch = function( e ){
+ return {
+ clientX: e.clientX,
+ clientY: e.clientY,
+ force: 1,
+ identifier: e.pointerId,
+ pageX: e.pageX,
+ pageY: e.pageY,
+ radiusX: e.width/2,
+ radiusY: e.height/2,
+ screenX: e.screenX,
+ screenY: e.screenY,
+ target: e.target
+ };
+ };
+
+ var makePointer = function( e ){
+ return {
+ event: e,
+ touch: makeTouch(e)
+ };
+ };
+
+ var addPointer = function( e ){
+ pointers.push( makePointer(e) );
+ };
+
+ var removePointer = function( e ){
+ for( var i = 0; i < pointers.length; i++ ){
+ var p = pointers[i];
+
+ if( p.event.pointerId === e.pointerId ){
+ pointers.splice( i, 1 );
+ return;
+ }
+ }
+ };
+
+ var updatePointer = function( e ){
+ var p = pointers.filter(function( p ){
+ return p.event.pointerId === e.pointerId;
+ })[0];
+
+ p.event = e;
+ p.touch = makeTouch(e);
+ };
+
+ var addTouchesToEvent = function( e ){
+ e.touches = pointers.map(function( p ){
+ return p.touch;
+ });
+ };
+
+ r.registerBinding(r.container, 'pointerdown', function(e){
+ if( e.pointerType === 'mouse' ){ return; } // mouse already handled
+
+ e.preventDefault();
+
+ addPointer( e );
+
+ addTouchesToEvent( e );
+ touchstartHandler( e );
+ });
+
+ r.registerBinding(r.container, 'pointerup', function(e){
+ if( e.pointerType === 'mouse' ){ return; } // mouse already handled
+
+ removePointer( e );
+
+ addTouchesToEvent( e );
+ touchendHandler( e );
+ });
+
+ r.registerBinding(r.container, 'pointercancel', function(e){
+ if( e.pointerType === 'mouse' ){ return; } // mouse already handled
+
+ removePointer( e );
+
+ addTouchesToEvent( e );
+ touchcancelHandler( e );
+ });
+
+ r.registerBinding(r.container, 'pointermove', function(e){
+ if( e.pointerType === 'mouse' ){ return; } // mouse already handled
+
+ e.preventDefault();
+
+ updatePointer( e );
+
+ addTouchesToEvent( e );
+ touchmoveHandler( e );
+ });
+
+ }
+};
+
+module.exports = BRp;
+
+},{"../../../collection":23,"../../../event":42,"../../../is":77,"../../../util":94}],60:[function(_dereq_,module,exports){
+'use strict';
+
+var math = _dereq_('../../../math');
+
+var BRp = {};
+
+BRp.registerNodeShapes = function(){
+ var nodeShapes = this.nodeShapes = {};
+ var renderer = this;
+
+ nodeShapes['ellipse'] = {
+ name: 'ellipse',
+
+ draw: function( context, centerX, centerY, width, height ){
+ renderer.nodeShapeImpl( this.name )( context, centerX, centerY, width, height );
+ },
+
+ intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){
+ return math.intersectLineEllipse(
+ x, y,
+ nodeX,
+ nodeY,
+ width / 2 + padding,
+ height / 2 + padding)
+ ;
+ },
+
+ checkPoint: function( x, y, padding, width, height, centerX, centerY ){
+ x -= centerX;
+ y -= centerY;
+
+ x /= (width / 2 + padding);
+ y /= (height / 2 + padding);
+
+ return x*x + y*y <= 1;
+ }
+ };
+
+ function generatePolygon( name, points ){
+ return ( nodeShapes[name] = {
+ name: name,
+
+ points: points,
+
+ draw: function( context, centerX, centerY, width, height ){
+ renderer.nodeShapeImpl('polygon')( context, centerX, centerY, width, height, this.points );
+ },
+
+ intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){
+ return math.polygonIntersectLine(
+ x, y,
+ this.points,
+ nodeX,
+ nodeY,
+ width / 2, height / 2,
+ padding)
+ ;
+ },
+
+ checkPoint: function( x, y, padding, width, height, centerX, centerY ){
+ return math.pointInsidePolygon(x, y, nodeShapes[name].points,
+ centerX, centerY, width, height, [0, -1], padding)
+ ;
+ }
+ } );
+ }
+
+ generatePolygon( 'triangle', math.generateUnitNgonPointsFitToSquare(3, 0) );
+
+ generatePolygon( 'square', math.generateUnitNgonPointsFitToSquare(4, 0) );
+ nodeShapes['rectangle'] = nodeShapes['square'];
+
+ nodeShapes['roundrectangle'] = {
+ name: 'roundrectangle',
+
+ points: math.generateUnitNgonPointsFitToSquare(4, 0),
+
+ draw: function( context, centerX, centerY, width, height ){
+ renderer.nodeShapeImpl( this.name )( context, centerX, centerY, width, height );
+ },
+
+ intersectLine: function( nodeX, nodeY, width, height, x, y, padding ){
+ return math.roundRectangleIntersectLine(
+ x, y,
+ nodeX,
+ nodeY,
+ width, height,
+ padding)
+ ;
+ },
+
+ // Looks like the width passed into this function is actually the total width / 2
+ checkPoint: function(
+ x, y, padding, width, height, centerX, centerY ){
+
+ var cornerRadius = math.getRoundRectangleRadius(width, height);
+
+ // Check hBox
+ if (math.pointInsidePolygon(x, y, this.points,
+ centerX, centerY, width, height - 2 * cornerRadius, [0, -1], padding) ){
+ return true;
+ }
+
+ // Check vBox
+ if (math.pointInsidePolygon(x, y, this.points,
+ centerX, centerY, width - 2 * cornerRadius, height, [0, -1], padding) ){
+ return true;
+ }
+
+ var checkInEllipse = function( x, y, centerX, centerY, width, height, padding ){
+ x -= centerX;
+ y -= centerY;
+
+ x /= (width / 2 + padding);
+ y /= (height / 2 + padding);
+
+ return (x*x + y*y <= 1);
+ };
+
+
+ // Check top left quarter circle
+ if (checkInEllipse(x, y,
+ centerX - width / 2 + cornerRadius,
+ centerY - height / 2 + cornerRadius,
+ cornerRadius * 2, cornerRadius * 2, padding) ){
+
+ return true;
+ }
+
+ // Check top right quarter circle
+ if (checkInEllipse(x, y,
+ centerX + width / 2 - cornerRadius,
+ centerY - height / 2 + cornerRadius,
+ cornerRadius * 2, cornerRadius * 2, padding) ){
+
+ return true;
+ }
+
+ // Check bottom right quarter circle
+ if (checkInEllipse(x, y,
+ centerX + width / 2 - cornerRadius,
+ centerY + height / 2 - cornerRadius,
+ cornerRadius * 2, cornerRadius * 2, padding) ){
+
+ return true;
+ }
+
+ // Check bottom left quarter circle
+ if (checkInEllipse(x, y,
+ centerX - width / 2 + cornerRadius,
+ centerY + height / 2 - cornerRadius,
+ cornerRadius * 2, cornerRadius * 2, padding) ){
+
+ return true;
+ }
+
+ return false;
+ }
+ };
+
+ generatePolygon( 'diamond', [
+ 0, 1,
+ 1, 0,
+ 0, -1,
+ -1, 0
+ ] );
+
+ generatePolygon( 'pentagon', math.generateUnitNgonPointsFitToSquare(5, 0) );
+
+ generatePolygon( 'hexagon', math.generateUnitNgonPointsFitToSquare(6, 0) );
+
+ generatePolygon( 'heptagon', math.generateUnitNgonPointsFitToSquare(7, 0) );
+
+ generatePolygon( 'octagon', math.generateUnitNgonPointsFitToSquare(8, 0) );
+
+ var star5Points = new Array(20);
+ {
+ var outerPoints = math.generateUnitNgonPoints(5, 0);
+ var innerPoints = math.generateUnitNgonPoints(5, Math.PI / 5);
+
+ // Outer radius is 1; inner radius of star is smaller
+ var innerRadius = 0.5 * (3 - Math.sqrt(5));
+ innerRadius *= 1.57;
+
+ for (var i=0;i<innerPoints.length/2;i++ ){
+ innerPoints[i*2] *= innerRadius;
+ innerPoints[i*2+1] *= innerRadius;
+ }
+
+ for (var i=0;i<20/4;i++ ){
+ star5Points[i*4] = outerPoints[i*2];
+ star5Points[i*4+1] = outerPoints[i*2+1];
+
+ star5Points[i*4+2] = innerPoints[i*2];
+ star5Points[i*4+3] = innerPoints[i*2+1];
+ }
+ }
+
+ star5Points = math.fitPolygonToSquare( star5Points );
+
+ generatePolygon( 'star', star5Points );
+
+ generatePolygon( 'vee', [
+ -1, -1,
+ 0, -0.333,
+ 1, -1,
+ 0, 1
+ ] );
+
+ generatePolygon( 'rhomboid', [
+ -1, -1,
+ 0.333, -1,
+ 1, 1,
+ -0.333, 1
+ ] );
+
+ nodeShapes.makePolygon = function( points ){
+
+ // use caching on user-specified polygons so they are as fast as native shapes
+
+ var key = points.join('$');
+ var name = 'polygon-' + key;
+ var shape;
+
+ if( (shape = nodeShapes[name]) ){ // got cached shape
+ return shape;
+ }
+
+ // create and cache new shape
+ return generatePolygon( name, points );
+ };
+
+};
+
+module.exports = BRp;
+
+},{"../../../math":79}],61:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../../../util');
+
+var BRp = {};
+
+BRp.timeToRender = function(){
+ return this.redrawTotalTime / this.redrawCount;
+};
+
+var minRedrawLimit = 1000/60; // people can't see much better than 60fps
+var maxRedrawLimit = 1000; // don't cap max b/c it's more important to be responsive than smooth
+
+BRp.redraw = function( options ){
+ options = options || util.staticEmptyObject();
+
+ var r = this;
+ var forcedContext = options.forcedContext;
+
+ if( r.averageRedrawTime === undefined ){ r.averageRedrawTime = 0; }
+ if( r.lastRedrawTime === undefined ){ r.lastRedrawTime = 0; }
+
+ var redrawLimit = r.lastRedrawTime; // estimate the ideal redraw limit based on how fast we can draw
+ redrawLimit = minRedrawLimit > redrawLimit ? minRedrawLimit : redrawLimit;
+ redrawLimit = redrawLimit < maxRedrawLimit ? redrawLimit : maxRedrawLimit;
+
+ if( r.lastDrawTime === undefined ){ r.lastDrawTime = 0; }
+
+ var nowTime = Date.now();
+ var timeElapsed = nowTime - r.lastDrawTime;
+ var callAfterLimit = timeElapsed >= redrawLimit;
+
+ if( !forcedContext ){
+ if( !callAfterLimit || r.currentlyDrawing ){
+ r.skipFrame = true;
+ return;
+ }
+ }
+
+ r.requestedFrame = true;
+ r.currentlyDrawing = true;
+ r.renderOptions = options;
+};
+
+BRp.startRenderLoop = function(){
+ var r = this;
+
+ var renderFn = function(){
+ if( r.destroyed ){ return; }
+
+ if( r.requestedFrame && !r.skipFrame ){
+ var startTime = util.performanceNow();
+
+ r.render( r.renderOptions );
+
+ var endTime = r.lastRedrawTime = util.performanceNow();
+
+ if( r.averageRedrawTime === undefined ){
+ r.averageRedrawTime = endTime - startTime;
+ }
+
+ if( r.redrawCount === undefined ){
+ r.redrawCount = 0;
+ }
+
+ r.redrawCount++;
+
+ if( r.redrawTotalTime === undefined ){
+ r.redrawTotalTime = 0;
+ }
+
+ var duration = endTime - startTime;
+
+ r.redrawTotalTime += duration;
+ r.lastRedrawTime = duration;
+
+ // use a weighted average with a bias from the previous average so we don't spike so easily
+ r.averageRedrawTime = r.averageRedrawTime/2 + duration/2;
+
+ r.requestedFrame = false;
+ }
+
+ r.skipFrame = false;
+
+ util.requestAnimationFrame( renderFn );
+ };
+
+ util.requestAnimationFrame( renderFn );
+
+};
+
+module.exports = BRp;
+
+},{"../../../util":94}],62:[function(_dereq_,module,exports){
+'use strict';
+
+var CRp = {};
+
+var impl;
+
+CRp.arrowShapeImpl = function( name ){
+ return ( impl || (impl = {
+ 'polygon': function( context, points ){
+ for( var i = 0; i < points.length; i++ ){
+ var pt = points[i];
+
+ context.lineTo( pt.x, pt.y );
+ }
+ },
+
+ 'triangle-backcurve': function( context, points, controlPoint ){
+ var firstPt;
+
+ for( var i = 0; i < points.length; i++ ){
+ var pt = points[i];
+
+ if( i === 0 ){
+ firstPt = pt;
+ }
+
+ context.lineTo( pt.x, pt.y );
+ }
+
+ context.quadraticCurveTo( controlPoint.x, controlPoint.y, firstPt.x, firstPt.y );
+ },
+
+ 'triangle-tee': function( context, trianglePoints, teePoints ){
+ var triPts = trianglePoints;
+ for( var i = 0; i < triPts.length; i++ ){
+ var pt = triPts[i];
+
+ context.lineTo( pt.x, pt.y );
+ }
+
+ var teePts = teePoints;
+ var firstTeePt = teePoints[0];
+ context.moveTo( firstTeePt.x, firstTeePt.y );
+
+ for( var i = 0; i < teePts.length; i++ ){
+ var pt = teePts[i];
+
+ context.lineTo( pt.x, pt.y );
+ }
+ },
+
+ 'circle': function( context, rx, ry, r ){
+ context.arc(rx, ry, r, 0, Math.PI * 2, false);
+ }
+ }) )[ name ];
+};
+
+module.exports = CRp;
+
+},{}],63:[function(_dereq_,module,exports){
+'use strict';
+
+var CRp = {};
+
+CRp.drawEdge = function(context, edge, drawOverlayInstead) {
+ var rs = edge._private.rscratch;
+ var usePaths = this.usePaths();
+
+ // if bezier ctrl pts can not be calculated, then die
+ if( rs.badBezier || rs.badLine || isNaN( rs.allpts[0] ) ){ // iNaN in case edge is impossible and browser bugs (e.g. safari)
+ return;
+ }
+
+ var style = edge._private.style;
+
+ // Edge line width
+ if (style['width'].pfValue <= 0) {
+ return;
+ }
+
+ var overlayPadding = style['overlay-padding'].pfValue;
+ var overlayOpacity = style['overlay-opacity'].value;
+ var overlayColor = style['overlay-color'].value;
+
+ // Edge color & opacity
+ if( drawOverlayInstead ){
+
+ if( overlayOpacity === 0 ){ // exit early if no overlay
+ return;
+ }
+
+ this.strokeStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);
+ context.lineCap = 'round';
+
+ if( rs.edgeType == 'self' && !usePaths ){
+ context.lineCap = 'butt';
+ }
+
+ } else {
+ var lineColor = style['line-color'].value;
+
+ this.strokeStyle(context, lineColor[0], lineColor[1], lineColor[2], style.opacity.value);
+
+ context.lineCap = 'butt';
+ }
+
+ var edgeWidth = style['width'].pfValue + (drawOverlayInstead ? 2 * overlayPadding : 0);
+ var lineStyle = drawOverlayInstead ? 'solid' : style['line-style'].value;
+ context.lineWidth = edgeWidth;
+
+ var shadowBlur = style['shadow-blur'].pfValue;
+ var shadowOpacity = style['shadow-opacity'].value;
+ var shadowColor = style['shadow-color'].value;
+ var shadowOffsetX = style['shadow-offset-x'].pfValue;
+ var shadowOffsetY = style['shadow-offset-y'].pfValue;
+
+ this.shadowStyle(context, shadowColor, drawOverlayInstead ? 0 : shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);
+
+ this.drawEdgePath(
+ edge,
+ context,
+ rs.allpts,
+ lineStyle,
+ edgeWidth
+ );
+
+ this.drawArrowheads(context, edge, drawOverlayInstead);
+
+ this.shadowStyle(context, 'transparent', 0); // reset for next guy
+
+};
+
+
+CRp.drawEdgePath = function(edge, context, pts, type, width) {
+ var rs = edge._private.rscratch;
+ var canvasCxt = context;
+ var path;
+ var pathCacheHit = false;
+ var usePaths = this.usePaths();
+
+ if( usePaths ){
+ var pathCacheKey = pts.join('$');
+ var keyMatches = rs.pathCacheKey && rs.pathCacheKey === pathCacheKey;
+
+ if( keyMatches ){
+ path = context = rs.pathCache;
+ pathCacheHit = true;
+ } else {
+ path = context = new Path2D();
+ rs.pathCacheKey = pathCacheKey;
+ rs.pathCache = path;
+ }
+ }
+
+ if( canvasCxt.setLineDash ){ // for very outofdate browsers
+ switch( type ){
+ case 'dotted':
+ canvasCxt.setLineDash([ 1, 1 ]);
+ break;
+
+ case 'dashed':
+ canvasCxt.setLineDash([ 6, 3 ]);
+ break;
+
+ case 'solid':
+ canvasCxt.setLineDash([ ]);
+ break;
+ }
+ }
+
+ if( !pathCacheHit ){
+ if( context.beginPath ){ context.beginPath(); }
+ context.moveTo( pts[0], pts[1] );
+
+ switch( rs.edgeType ){
+ case 'bezier':
+ case 'self':
+ case 'compound':
+ case 'multibezier':
+ if( !rs.badBezier ){
+ for( var i = 2; i + 3 < pts.length; i += 4 ){
+ context.quadraticCurveTo( pts[i], pts[i+1], pts[i+2], pts[i+3] );
+ }
+ }
+ break;
+
+ case 'straight':
+ case 'segments':
+ case 'haystack':
+ if( !rs.badLine ){
+ for( var i = 2; i + 1 < pts.length; i += 2 ){
+ context.lineTo( pts[i], pts[i+1] );
+ }
+ }
+ break;
+ }
+ }
+
+ context = canvasCxt;
+ if( usePaths ){
+ context.stroke( path );
+ } else {
+ context.stroke();
+ }
+
+ // reset any line dashes
+ if( context.setLineDash ){ // for very outofdate browsers
+ context.setLineDash([ ]);
+ }
+
+};
+
+CRp.drawArrowheads = function(context, edge, drawOverlayInstead) {
+ if( drawOverlayInstead ){ return; } // don't do anything for overlays
+
+ var rs = edge._private.rscratch;
+ var isHaystack = rs.edgeType === 'haystack';
+
+ if( !isHaystack ){
+ this.drawArrowhead( context, edge, 'source', rs.arrowStartX, rs.arrowStartY, rs.srcArrowAngle );
+ }
+
+ this.drawArrowhead( context, edge, 'mid-target', rs.midX, rs.midY, rs.midtgtArrowAngle );
+
+ this.drawArrowhead( context, edge, 'mid-source', rs.midX, rs.midY, rs.midsrcArrowAngle );
+
+ if( !isHaystack ){
+ this.drawArrowhead( context, edge, 'target', rs.arrowEndX, rs.arrowEndY, rs.tgtArrowAngle );
+ }
+};
+
+CRp.drawArrowhead = function( context, edge, prefix, x, y, angle ){
+ if( isNaN(x) || x == null || isNaN(y) || y == null || isNaN(angle) || angle == null ){ return; }
+
+ var self = this;
+ var style = edge._private.style;
+ var arrowShape = style[prefix + '-arrow-shape'].value;
+
+ if( arrowShape === 'none' ){
+ return;
+ }
+
+ var gco = context.globalCompositeOperation;
+
+ var arrowClearFill = style[prefix + '-arrow-fill'].value === 'hollow' ? 'both' : 'filled';
+ var arrowFill = style[prefix + '-arrow-fill'].value;
+
+ if( arrowShape === 'half-triangle-overshot' ){
+ arrowFill = 'hollow';
+ arrowClearFill = 'hollow';
+ }
+
+ if( style.opacity.value !== 1 || arrowFill === 'hollow' ){ // then extra clear is needed
+ context.globalCompositeOperation = 'destination-out';
+
+ self.fillStyle(context, 255, 255, 255, 1);
+ self.strokeStyle(context, 255, 255, 255, 1);
+
+ self.drawArrowShape( edge, prefix, context,
+ arrowClearFill, style['width'].pfValue, style[prefix + '-arrow-shape'].value,
+ x, y, angle
+ );
+
+ context.globalCompositeOperation = gco;
+ } // otherwise, the opaque arrow clears it for free :)
+
+ var color = style[prefix + '-arrow-color'].value;
+ self.fillStyle(context, color[0], color[1], color[2], style.opacity.value);
+ self.strokeStyle(context, color[0], color[1], color[2], style.opacity.value);
+
+ self.drawArrowShape( edge, prefix, context,
+ arrowFill, style['width'].pfValue, style[prefix + '-arrow-shape'].value,
+ x, y, angle
+ );
+};
+
+CRp.drawArrowShape = function(edge, arrowType, context, fill, edgeWidth, shape, x, y, angle) {
+ var r = this;
+ var usePaths = this.usePaths();
+ var rs = edge._private.rscratch;
+ var pathCacheHit = false;
+ var path;
+ var canvasContext = context;
+ var translation = { x: x, y: y };
+ var size = this.getArrowWidth( edgeWidth );
+ var shapeImpl = r.arrowShapes[shape];
+
+ if( usePaths ){
+ var pathCacheKey = size + '$' + shape + '$' + angle + '$' + x + '$' + y;
+ rs.arrowPathCacheKey = rs.arrowPathCacheKey || {};
+ rs.arrowPathCache = rs.arrowPathCache || {};
+
+ var alreadyCached = rs.arrowPathCacheKey[arrowType] === pathCacheKey;
+ if( alreadyCached ){
+ path = context = rs.arrowPathCache[arrowType];
+ pathCacheHit = true;
+ } else {
+ path = context = new Path2D();
+ rs.arrowPathCacheKey[arrowType] = pathCacheKey;
+ rs.arrowPathCache[arrowType] = path;
+ }
+ }
+
+ if( context.beginPath ){ context.beginPath(); }
+
+ if( !pathCacheHit ){
+ shapeImpl.draw(context, size, angle, translation);
+ }
+
+ if( !shapeImpl.leavePathOpen && context.closePath ){
+ context.closePath();
+ }
+
+ context = canvasContext;
+
+ if( fill === 'filled' || fill === 'both' ){
+ if( usePaths ){
+ context.fill( path );
+ } else {
+ context.fill();
+ }
+ }
+
+ if( fill === 'hollow' || fill === 'both' ){
+ context.lineWidth = ( shapeImpl.matchEdgeWidth ? edgeWidth : 1 );
+ context.lineJoin = 'miter';
+
+ if( usePaths ){
+ context.stroke( path );
+ } else {
+ context.stroke();
+ }
+
+ }
+};
+
+module.exports = CRp;
+
+},{}],64:[function(_dereq_,module,exports){
+'use strict';
+
+var CRp = {};
+
+CRp.safeDrawImage = function( context, img, ix, iy, iw, ih, x, y, w, h ){
+ var r = this;
+
+ try {
+ context.drawImage( img, ix, iy, iw, ih, x, y, w, h );
+ } catch(e){
+ r.data.canvasNeedsRedraw[r.NODE] = true;
+ r.data.canvasNeedsRedraw[r.DRAG] = true;
+
+ r.drawingImage = true;
+
+ r.redraw();
+ }
+};
+
+CRp.drawInscribedImage = function(context, img, node) {
+ var r = this;
+ var nodeX = node._private.position.x;
+ var nodeY = node._private.position.y;
+ var style = node._private.style;
+ var fit = style['background-fit'].value;
+ var xPos = style['background-position-x'];
+ var yPos = style['background-position-y'];
+ var repeat = style['background-repeat'].value;
+ var nodeW = node.width();
+ var nodeH = node.height();
+ var rs = node._private.rscratch;
+ var clip = style['background-clip'].value;
+ var shouldClip = clip === 'node';
+ var imgOpacity = style['background-image-opacity'].value;
+
+ var imgW = img.width || img.cachedW;
+ var imgH = img.height || img.cachedH;
+
+ // workaround for broken browsers like ie
+ if( null == imgW || null == imgH ){
+ document.body.appendChild( img );
+
+ imgW = img.cachedW = img.width || img.offsetWidth;
+ imgH = img.cachedH = img.height || img.offsetHeight;
+
+ document.body.removeChild( img );
+ }
+
+ var w = imgW;
+ var h = imgH;
+
+ var bgW = style['background-width'];
+ if( bgW.value !== 'auto' ){
+ if( bgW.units === '%' ){
+ w = bgW.value/100 * nodeW;
+ } else {
+ w = bgW.pfValue;
+ }
+ }
+
+ var bgH = style['background-height'];
+ if( bgH.value !== 'auto' ){
+ if( bgH.units === '%' ){
+ h = bgH.value/100 * nodeH;
+ } else {
+ h = bgH.pfValue;
+ }
+ }
+
+ if( w === 0 || h === 0 ){
+ return; // no point in drawing empty image (and chrome is broken in this case)
+ }
+
+ if( fit === 'contain' ){
+ var scale = Math.min( nodeW/w, nodeH/h );
+
+ w *= scale;
+ h *= scale;
+
+ } else if( fit === 'cover' ){
+ var scale = Math.max( nodeW/w, nodeH/h );
+
+ w *= scale;
+ h *= scale;
+ }
+
+ var x = (nodeX - nodeW/2); // left
+ if( xPos.units === '%' ){
+ x += (nodeW - w) * xPos.value/100;
+ } else {
+ x += xPos.pfValue;
+ }
+
+ var y = (nodeY - nodeH/2); // top
+ if( yPos.units === '%' ){
+ y += (nodeH - h) * yPos.value/100;
+ } else {
+ y += yPos.pfValue;
+ }
+
+ if( rs.pathCache ){
+ x -= nodeX;
+ y -= nodeY;
+
+ nodeX = 0;
+ nodeY = 0;
+ }
+
+ var gAlpha = context.globalAlpha;
+
+ context.globalAlpha = imgOpacity;
+
+ if( repeat === 'no-repeat' ){
+
+ if( shouldClip ){
+ context.save();
+
+ if( rs.pathCache ){
+ context.clip( rs.pathCache );
+ } else {
+ r.nodeShapes[r.getNodeShape(node)].draw(
+ context,
+ nodeX, nodeY,
+ nodeW, nodeH);
+
+ context.clip();
+ }
+ }
+
+ r.safeDrawImage( context, img, 0, 0, imgW, imgH, x, y, w, h );
+
+ if( shouldClip ){
+ context.restore();
+ }
+ } else {
+ var pattern = context.createPattern( img, repeat );
+ context.fillStyle = pattern;
+
+ r.nodeShapes[r.getNodeShape(node)].draw(
+ context,
+ nodeX, nodeY,
+ nodeW, nodeH);
+
+ context.translate(x, y);
+ context.fill();
+ context.translate(-x, -y);
+ }
+
+ context.globalAlpha = gAlpha;
+
+};
+
+module.exports = CRp;
+
+},{}],65:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../../is');
+
+var CRp = {};
+
+// Draw edge text
+CRp.drawEdgeText = function(context, edge) {
+ var text = edge._private.style['label'].strValue;
+
+ if( !text || text.match(/^\s+$/) ){
+ return;
+ }
+
+ if( this.hideEdgesOnViewport && (this.dragData.didDrag || this.pinching || this.hoverData.dragging || this.data.wheel || this.swipePanning) ){ return; } // save cycles on pinching
+
+ var computedSize = edge._private.style['font-size'].pfValue * edge.cy().zoom();
+ var minSize = edge._private.style['min-zoomed-font-size'].pfValue;
+
+ if( computedSize < minSize ){
+ return;
+ }
+
+ // Calculate text draw position
+
+ context.textAlign = 'center';
+ context.textBaseline = 'middle';
+
+ var rs = edge._private.rscratch;
+ if( !is.number( rs.labelX ) || !is.number( rs.labelY ) ){ return; } // no pos => label can't be rendered
+
+ var style = edge._private.style;
+ var autorotate = style['edge-text-rotation'].strValue === 'autorotate';
+ var theta;
+
+ if( autorotate ){
+ theta = rs.labelAngle;
+
+ context.translate(rs.labelX, rs.labelY);
+ context.rotate(theta);
+
+ this.drawText(context, edge, 0, 0);
+
+ context.rotate(-theta);
+ context.translate(-rs.labelX, -rs.labelY);
+ } else {
+ this.drawText(context, edge, rs.labelX, rs.labelY);
+ }
+
+};
+
+// Draw node text
+CRp.drawNodeText = function(context, node) {
+ var text = node._private.style['label'].strValue;
+
+ if ( !text || text.match(/^\s+$/) ) {
+ return;
+ }
+
+ var computedSize = node._private.style['font-size'].pfValue * node.cy().zoom();
+ var minSize = node._private.style['min-zoomed-font-size'].pfValue;
+
+ if( computedSize < minSize ){
+ return;
+ }
+
+ // this.recalculateNodeLabelProjection( node );
+
+ var textHalign = node._private.style['text-halign'].strValue;
+ var textValign = node._private.style['text-valign'].strValue;
+ var rs = node._private.rscratch;
+ if( !is.number( rs.labelX ) || !is.number( rs.labelY ) ){ return; } // no pos => label can't be rendered
+
+ switch( textHalign ){
+ case 'left':
+ context.textAlign = 'right';
+ break;
+
+ case 'right':
+ context.textAlign = 'left';
+ break;
+
+ default: // e.g. center
+ context.textAlign = 'center';
+ }
+
+ switch( textValign ){
+ case 'top':
+ context.textBaseline = 'bottom';
+ break;
+
+ case 'bottom':
+ context.textBaseline = 'top';
+ break;
+
+ default: // e.g. center
+ context.textBaseline = 'middle';
+ }
+
+ this.drawText(context, node, rs.labelX, rs.labelY);
+};
+
+CRp.getFontCache = function(context){
+ var cache;
+
+ this.fontCaches = this.fontCaches || [];
+
+ for( var i = 0; i < this.fontCaches.length; i++ ){
+ cache = this.fontCaches[i];
+
+ if( cache.context === context ){
+ return cache;
+ }
+ }
+
+ cache = {
+ context: context
+ };
+ this.fontCaches.push(cache);
+
+ return cache;
+};
+
+// set up canvas context with font
+// returns transformed text string
+CRp.setupTextStyle = function( context, element ){
+ // Font style
+ var parentOpacity = element.effectiveOpacity();
+ var style = element._private.style;
+ var labelStyle = style['font-style'].strValue;
+ var labelSize = style['font-size'].pfValue + 'px';
+ var labelFamily = style['font-family'].strValue;
+ var labelWeight = style['font-weight'].strValue;
+ var opacity = style['text-opacity'].value * style['opacity'].value * parentOpacity;
+ var outlineOpacity = style['text-outline-opacity'].value * opacity;
+ var color = style['color'].value;
+ var outlineColor = style['text-outline-color'].value;
+ var shadowBlur = style['text-shadow-blur'].pfValue;
+ var shadowOpacity = style['text-shadow-opacity'].value;
+ var shadowColor = style['text-shadow-color'].value;
+ var shadowOffsetX = style['text-shadow-offset-x'].pfValue;
+ var shadowOffsetY = style['text-shadow-offset-y'].pfValue;
+
+ var fontCacheKey = element._private.fontKey;
+ var cache = this.getFontCache(context);
+
+ if( cache.key !== fontCacheKey ){
+ context.font = labelStyle + ' ' + labelWeight + ' ' + labelSize + ' ' + labelFamily;
+
+ cache.key = fontCacheKey;
+ }
+
+ var text = this.getLabelText( element );
+
+ // Calculate text draw position based on text alignment
+
+ // so text outlines aren't jagged
+ context.lineJoin = 'round';
+
+ this.fillStyle(context, color[0], color[1], color[2], opacity);
+
+ this.strokeStyle(context, outlineColor[0], outlineColor[1], outlineColor[2], outlineOpacity);
+
+ this.shadowStyle(context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);
+
+ return text;
+};
+
+function roundRect(ctx, x, y, width, height, radius) {
+ var radius = radius || 5;
+ ctx.beginPath();
+ ctx.moveTo(x + radius, y);
+ ctx.lineTo(x + width - radius, y);
+ ctx.quadraticCurveTo(x + width, y, x + width, y + radius);
+ ctx.lineTo(x + width, y + height - radius);
+ ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
+ ctx.lineTo(x + radius, y + height);
+ ctx.quadraticCurveTo(x, y + height, x, y + height - radius);
+ ctx.lineTo(x, y + radius);
+ ctx.quadraticCurveTo(x, y, x + radius, y);
+ ctx.closePath();
+ ctx.fill();
+}
+
+// Draw text
+CRp.drawText = function(context, element, textX, textY) {
+ var _p = element._private;
+ var style = _p.style;
+ var rstyle = _p.rstyle;
+ var rscratch = _p.rscratch;
+ var parentOpacity = element.effectiveOpacity();
+ if( parentOpacity === 0 || style['text-opacity'].value === 0){ return; }
+
+ var text = this.setupTextStyle( context, element );
+ var halign = style['text-halign'].value;
+ var valign = style['text-valign'].value;
+
+ if( element.isEdge() ){
+ halign = 'center';
+ valign = 'center';
+ }
+
+ if( element.isNode() ){
+ var pLeft = style['padding-left'].pfValue;
+ var pRight = style['padding-right'].pfValue;
+ var pTop = style['padding-top'].pfValue;
+ var pBottom = style['padding-bottom'].pfValue;
+
+ textX += pLeft/2;
+ textX -= pRight/2;
+
+ textY += pTop/2;
+ textY -= pBottom/2;
+ }
+
+ if ( text != null && !isNaN(textX) && !isNaN(textY)) {
+ var backgroundOpacity = style['text-background-opacity'].value;
+ var borderOpacity = style['text-border-opacity'].value;
+ var textBorderWidth = style['text-border-width'].pfValue;
+
+ if( backgroundOpacity > 0 || (textBorderWidth > 0 && borderOpacity > 0) ){
+ var margin = 4 + textBorderWidth/2;
+
+ if (element.isNode()) {
+ //Move textX, textY to include the background margins
+ if (valign === 'top') {
+ textY -= margin;
+ } else if (valign === 'bottom') {
+ textY += margin;
+ }
+ if (halign === 'left') {
+ textX -= margin;
+ } else if (halign === 'right') {
+ textX += margin;
+ }
+ }
+
+ var bgWidth = rstyle.labelWidth;
+ var bgHeight = rstyle.labelHeight;
+ var bgX = textX;
+
+ if (halign) {
+ if (halign == 'center') {
+ bgX = bgX - bgWidth / 2;
+ } else if (halign == 'left') {
+ bgX = bgX- bgWidth;
+ }
+ }
+
+ var bgY = textY;
+
+ if (element.isNode()) {
+ if (valign == 'top') {
+ bgY = bgY - bgHeight;
+ } else if (valign == 'center') {
+ bgY = bgY- bgHeight / 2;
+ }
+ } else {
+ bgY = bgY - bgHeight / 2;
+ }
+
+ if (style['edge-text-rotation'].strValue === 'autorotate') {
+ textY = 0;
+ bgWidth += 4;
+ bgX = textX - bgWidth / 2;
+ bgY = textY - bgHeight / 2;
+ } else {
+ // Adjust with border width & margin
+ bgX -= margin;
+ bgY -= margin;
+ bgHeight += margin*2;
+ bgWidth += margin*2;
+ }
+
+ if( backgroundOpacity > 0 ){
+ var textFill = context.fillStyle;
+ var textBackgroundColor = style['text-background-color'].value;
+
+ context.fillStyle = 'rgba(' + textBackgroundColor[0] + ',' + textBackgroundColor[1] + ',' + textBackgroundColor[2] + ',' + backgroundOpacity * parentOpacity + ')';
+ var styleShape = style['text-background-shape'].strValue;
+ if (styleShape == 'roundrectangle') {
+ roundRect(context, bgX, bgY, bgWidth, bgHeight, 2);
+ } else {
+ context.fillRect(bgX,bgY,bgWidth,bgHeight);
+ }
+ context.fillStyle = textFill;
+ }
+
+ if( textBorderWidth > 0 && borderOpacity > 0 ){
+ var textStroke = context.strokeStyle;
+ var textLineWidth = context.lineWidth;
+ var textBorderColor = style['text-border-color'].value;
+ var textBorderStyle = style['text-border-style'].value;
+
+ context.strokeStyle = 'rgba(' + textBorderColor[0] + ',' + textBorderColor[1] + ',' + textBorderColor[2] + ',' + borderOpacity * parentOpacity + ')';
+ context.lineWidth = textBorderWidth;
+
+ if( context.setLineDash ){ // for very outofdate browsers
+ switch( textBorderStyle ){
+ case 'dotted':
+ context.setLineDash([ 1, 1 ]);
+ break;
+ case 'dashed':
+ context.setLineDash([ 4, 2 ]);
+ break;
+ case 'double':
+ context.lineWidth = textBorderWidth/4; // 50% reserved for white between the two borders
+ context.setLineDash([ ]);
+ break;
+ case 'solid':
+ context.setLineDash([ ]);
+ break;
+ }
+ }
+
+ context.strokeRect(bgX,bgY,bgWidth,bgHeight);
+
+ if( textBorderStyle === 'double' ){
+ var whiteWidth = textBorderWidth/2;
+
+ context.strokeRect(bgX+whiteWidth,bgY+whiteWidth,bgWidth-whiteWidth*2,bgHeight-whiteWidth*2);
+ }
+
+ if( context.setLineDash ){ // for very outofdate browsers
+ context.setLineDash([ ]);
+ }
+ context.lineWidth = textLineWidth;
+ context.strokeStyle = textStroke;
+ }
+
+ }
+
+ var lineWidth = 2 * style['text-outline-width'].pfValue; // *2 b/c the stroke is drawn centred on the middle
+
+ if( lineWidth > 0 ){
+ context.lineWidth = lineWidth;
+ }
+
+ if( style['text-wrap'].value === 'wrap' ){
+ var lines = rscratch.labelWrapCachedLines;
+ var lineHeight = rstyle.labelHeight / lines.length;
+
+ switch( valign ){
+ case 'top':
+ textY -= (lines.length - 1) * lineHeight;
+ break;
+
+ case 'bottom':
+ // nothing required
+ break;
+
+ default:
+ case 'center':
+ textY -= (lines.length - 1) * lineHeight / 2;
+ }
+
+ for( var l = 0; l < lines.length; l++ ){
+ if( lineWidth > 0 ){
+ context.strokeText( lines[l], textX, textY );
+ }
+
+ context.fillText( lines[l], textX, textY );
+
+ textY += lineHeight;
+ }
+
+ } else {
+ if( lineWidth > 0 ){
+ context.strokeText( text, textX, textY );
+ }
+
+ context.fillText( text, textX, textY );
+ }
+
+
+ this.shadowStyle(context, 'transparent', 0); // reset for next guy
+ }
+};
+
+
+module.exports = CRp;
+
+},{"../../../is":77}],66:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../../is');
+
+var CRp = {};
+
+// Draw node
+CRp.drawNode = function(context, node, drawOverlayInstead) {
+
+ var r = this;
+ var nodeWidth, nodeHeight;
+ var style = node._private.style;
+ var rs = node._private.rscratch;
+ var _p = node._private;
+ var pos = _p.position;
+
+ if( !is.number(pos.x) || !is.number(pos.y) ){
+ return; // can't draw node with undefined position
+ }
+
+ var usePaths = this.usePaths();
+ var canvasContext = context;
+ var path;
+ var pathCacheHit = false;
+
+ var overlayPadding = style['overlay-padding'].pfValue;
+ var overlayOpacity = style['overlay-opacity'].value;
+ var overlayColor = style['overlay-color'].value;
+
+ if( drawOverlayInstead && overlayOpacity === 0 ){ // exit early if drawing overlay but none to draw
+ return;
+ }
+
+ var parentOpacity = node.effectiveOpacity();
+ if( parentOpacity === 0 ){ return; }
+
+ nodeWidth = node.width() + style['padding-left'].pfValue + style['padding-right'].pfValue;
+ nodeHeight = node.height() + style['padding-top'].pfValue + style['padding-bottom'].pfValue;
+
+ context.lineWidth = style['border-width'].pfValue;
+
+ if( drawOverlayInstead === undefined || !drawOverlayInstead ){
+
+ var url = style['background-image'].value[2] ||
+ style['background-image'].value[1];
+ var image;
+
+ if (url !== undefined) {
+
+ // get image, and if not loaded then ask to redraw when later loaded
+ image = this.getCachedImage(url, function(){
+ r.data.canvasNeedsRedraw[r.NODE] = true;
+ r.data.canvasNeedsRedraw[r.DRAG] = true;
+
+ r.drawingImage = true;
+
+ r.redraw();
+ });
+
+ var prevBging = _p.backgrounding;
+ _p.backgrounding = !image.complete;
+
+ if( prevBging !== _p.backgrounding ){ // update style b/c :backgrounding state changed
+ node.updateStyle( false );
+ }
+ }
+
+ // Node color & opacity
+
+ var bgColor = style['background-color'].value;
+ var borderColor = style['border-color'].value;
+ var borderStyle = style['border-style'].value;
+
+ this.fillStyle(context, bgColor[0], bgColor[1], bgColor[2], style['background-opacity'].value * parentOpacity);
+
+ this.strokeStyle(context, borderColor[0], borderColor[1], borderColor[2], style['border-opacity'].value * parentOpacity);
+
+ var shadowBlur = style['shadow-blur'].pfValue;
+ var shadowOpacity = style['shadow-opacity'].value;
+ var shadowColor = style['shadow-color'].value;
+ var shadowOffsetX = style['shadow-offset-x'].pfValue;
+ var shadowOffsetY = style['shadow-offset-y'].pfValue;
+
+ this.shadowStyle(context, shadowColor, shadowOpacity, shadowBlur, shadowOffsetX, shadowOffsetY);
+
+ context.lineJoin = 'miter'; // so borders are square with the node shape
+
+ if( context.setLineDash ){ // for very outofdate browsers
+ switch( borderStyle ){
+ case 'dotted':
+ context.setLineDash([ 1, 1 ]);
+ break;
+
+ case 'dashed':
+ context.setLineDash([ 4, 2 ]);
+ break;
+
+ case 'solid':
+ case 'double':
+ context.setLineDash([ ]);
+ break;
+ }
+ }
+
+
+ var styleShape = style['shape'].strValue;
+
+ if( usePaths ){
+ var pathCacheKey = styleShape + '$' + nodeWidth +'$' + nodeHeight;
+
+ context.translate( pos.x, pos.y );
+
+ if( rs.pathCacheKey === pathCacheKey ){
+ path = context = rs.pathCache;
+ pathCacheHit = true;
+ } else {
+ path = context = new Path2D();
+ rs.pathCacheKey = pathCacheKey;
+ rs.pathCache = path;
+ }
+ }
+
+ if( !pathCacheHit ){
+
+ var npos = pos;
+
+ if( usePaths ){
+ npos = {
+ x: 0,
+ y: 0
+ };
+ }
+
+ r.nodeShapes[this.getNodeShape(node)].draw(
+ context,
+ npos.x,
+ npos.y,
+ nodeWidth,
+ nodeHeight);
+ }
+
+ context = canvasContext;
+
+ if( usePaths ){
+ context.fill( path );
+ } else {
+ context.fill();
+ }
+
+ this.shadowStyle(context, 'transparent', 0); // reset for next guy
+
+ if (url !== undefined) {
+ if( image.complete ){
+ this.drawInscribedImage(context, image, node);
+ }
+ }
+
+ var darkness = style['background-blacken'].value;
+ var borderWidth = style['border-width'].pfValue;
+
+ if( this.hasPie(node) ){
+ this.drawPie( context, node, parentOpacity );
+
+ // redraw path for blacken and border
+ if( darkness !== 0 || borderWidth !== 0 ){
+
+ if( !usePaths ){
+ r.nodeShapes[this.getNodeShape(node)].draw(
+ context,
+ pos.x,
+ pos.y,
+ nodeWidth,
+ nodeHeight);
+ }
+ }
+ }
+
+ if( darkness > 0 ){
+ this.fillStyle(context, 0, 0, 0, darkness);
+
+ if( usePaths ){
+ context.fill( path );
+ } else {
+ context.fill();
+ }
+
+ } else if( darkness < 0 ){
+ this.fillStyle(context, 255, 255, 255, -darkness);
+
+ if( usePaths ){
+ context.fill( path );
+ } else {
+ context.fill();
+ }
+ }
+
+ // Border width, draw border
+ if (borderWidth > 0) {
+
+ if( usePaths ){
+ context.stroke( path );
+ } else {
+ context.stroke();
+ }
+
+ if( borderStyle === 'double' ){
+ context.lineWidth = style['border-width'].pfValue/3;
+
+ var gco = context.globalCompositeOperation;
+ context.globalCompositeOperation = 'destination-out';
+
+ if( usePaths ){
+ context.stroke( path );
+ } else {
+ context.stroke();
+ }
+
+ context.globalCompositeOperation = gco;
+ }
+
+ }
+
+ if( usePaths ){
+ context.translate( -pos.x, -pos.y );
+ }
+
+ // reset in case we changed the border style
+ if( context.setLineDash ){ // for very outofdate browsers
+ context.setLineDash([ ]);
+ }
+
+ // draw the overlay
+ } else {
+
+ if( overlayOpacity > 0 ){
+ this.fillStyle(context, overlayColor[0], overlayColor[1], overlayColor[2], overlayOpacity);
+
+ r.nodeShapes['roundrectangle'].draw(
+ context,
+ node._private.position.x,
+ node._private.position.y,
+ nodeWidth + overlayPadding * 2,
+ nodeHeight + overlayPadding * 2
+ );
+
+ context.fill();
+ }
+ }
+
+};
+
+// does the node have at least one pie piece?
+CRp.hasPie = function(node){
+ node = node[0]; // ensure ele ref
+
+ return node._private.hasPie;
+};
+
+CRp.drawPie = function( context, node, nodeOpacity ){
+ node = node[0]; // ensure ele ref
+
+ var _p = node._private;
+ var cyStyle = node.cy().style();
+ var style = _p.style;
+ var pieSize = style['pie-size'];
+ var nodeW = node.width();
+ var nodeH = node.height();
+ var x = _p.position.x;
+ var y = _p.position.y;
+ var radius = Math.min( nodeW, nodeH ) / 2; // must fit in node
+ var lastPercent = 0; // what % to continue drawing pie slices from on [0, 1]
+ var usePaths = this.usePaths();
+
+ if( usePaths ){
+ x = 0;
+ y = 0;
+ }
+
+ if( pieSize.units === '%' ){
+ radius = radius * pieSize.value / 100;
+ } else if( pieSize.pfValue !== undefined ){
+ radius = pieSize.pfValue / 2;
+ }
+
+ for( var i = 1; i <= cyStyle.pieBackgroundN; i++ ){ // 1..N
+ var size = style['pie-' + i + '-background-size'].value;
+ var color = style['pie-' + i + '-background-color'].value;
+ var opacity = style['pie-' + i + '-background-opacity'].value * nodeOpacity;
+ var percent = size / 100; // map integer range [0, 100] to [0, 1]
+
+ // percent can't push beyond 1
+ if( percent + lastPercent > 1 ){
+ percent = 1 - lastPercent;
+ }
+
+ var angleStart = 1.5 * Math.PI + 2 * Math.PI * lastPercent; // start at 12 o'clock and go clockwise
+ var angleDelta = 2 * Math.PI * percent;
+ var angleEnd = angleStart + angleDelta;
+
+ // ignore if
+ // - zero size
+ // - we're already beyond the full circle
+ // - adding the current slice would go beyond the full circle
+ if( size === 0 || lastPercent >= 1 || lastPercent + percent > 1 ){
+ continue;
+ }
+
+ context.beginPath();
+ context.moveTo(x, y);
+ context.arc( x, y, radius, angleStart, angleEnd );
+ context.closePath();
+
+ this.fillStyle(context, color[0], color[1], color[2], opacity);
+
+ context.fill();
+
+ lastPercent += percent;
+ }
+
+};
+
+
+module.exports = CRp;
+
+},{"../../../is":77}],67:[function(_dereq_,module,exports){
+'use strict';
+
+var CRp = {};
+
+var util = _dereq_('../../../util');
+var math = _dereq_('../../../math');
+
+var motionBlurDelay = 100;
+
+// var isFirefox = typeof InstallTrigger !== 'undefined';
+
+CRp.getPixelRatio = function(){
+ var context = this.data.contexts[0];
+
+ if( this.forcedPixelRatio != null ){
+ return this.forcedPixelRatio;
+ }
+
+ var backingStore = context.backingStorePixelRatio ||
+ context.webkitBackingStorePixelRatio ||
+ context.mozBackingStorePixelRatio ||
+ context.msBackingStorePixelRatio ||
+ context.oBackingStorePixelRatio ||
+ context.backingStorePixelRatio || 1;
+
+ return (window.devicePixelRatio || 1) / backingStore;
+};
+
+CRp.paintCache = function(context){
+ var caches = this.paintCaches = this.paintCaches || [];
+ var needToCreateCache = true;
+ var cache;
+
+ for(var i = 0; i < caches.length; i++ ){
+ cache = caches[i];
+
+ if( cache.context === context ){
+ needToCreateCache = false;
+ break;
+ }
+ }
+
+ if( needToCreateCache ){
+ cache = {
+ context: context
+ };
+ caches.push( cache );
+ }
+
+ return cache;
+};
+
+CRp.fillStyle = function(context, r, g, b, a){
+ context.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
+
+ // turn off for now, seems context does its own caching
+
+ // var cache = this.paintCache(context);
+
+ // var fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
+
+ // if( cache.fillStyle !== fillStyle ){
+ // context.fillStyle = cache.fillStyle = fillStyle;
+ // }
+};
+
+CRp.strokeStyle = function(context, r, g, b, a){
+ context.strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
+
+ // turn off for now, seems context does its own caching
+
+ // var cache = this.paintCache(context);
+
+ // var strokeStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')';
+
+ // if( cache.strokeStyle !== strokeStyle ){
+ // context.strokeStyle = cache.strokeStyle = strokeStyle;
+ // }
+};
+
+CRp.shadowStyle = function(context, color, opacity, blur, offsetX, offsetY){
+ var zoom = this.cy.zoom();
+
+ var cache = this.paintCache(context);
+
+ // don't make expensive changes to the shadow style if it's not used
+ if( cache.shadowOpacity === 0 && opacity === 0 ){
+ return;
+ }
+
+ cache.shadowOpacity = opacity;
+
+ if (opacity > 0) {
+ context.shadowBlur = blur * zoom;
+ context.shadowColor = "rgba(" + color[0] + "," + color[1] + "," + color[2] + "," + opacity + ")";
+ context.shadowOffsetX = offsetX * zoom;
+ context.shadowOffsetY = offsetY * zoom;
+ } else {
+ context.shadowBlur = 0;
+ context.shadowColor = "transparent";
+ }
+};
+
+// Resize canvas
+CRp.matchCanvasSize = function(container) {
+ var r = this;
+ var data = r.data;
+ var width = container.clientWidth;
+ var height = container.clientHeight;
+ var pixelRatio = r.getPixelRatio();
+ var mbPxRatio = r.motionBlurPxRatio;
+
+ if(
+ container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_NODE] ||
+ container === r.data.bufferCanvases[r.MOTIONBLUR_BUFFER_DRAG]
+ ){
+ pixelRatio = mbPxRatio;
+ }
+
+ var canvasWidth = width * pixelRatio;
+ var canvasHeight = height * pixelRatio;
+ var canvas;
+
+ if( canvasWidth === r.canvasWidth && canvasHeight === r.canvasHeight ){
+ return; // save cycles if same
+ }
+
+ r.fontCaches = null; // resizing resets the style
+
+ var canvasContainer = data.canvasContainer;
+ canvasContainer.style.width = width + 'px';
+ canvasContainer.style.height = height + 'px';
+
+ for (var i = 0; i < r.CANVAS_LAYERS; i++) {
+
+ canvas = data.canvases[i];
+
+ if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {
+
+ canvas.width = canvasWidth;
+ canvas.height = canvasHeight;
+
+ canvas.style.width = width + 'px';
+ canvas.style.height = height + 'px';
+ }
+ }
+
+ for (var i = 0; i < r.BUFFER_COUNT; i++) {
+
+ canvas = data.bufferCanvases[i];
+
+ if (canvas.width !== canvasWidth || canvas.height !== canvasHeight) {
+
+ canvas.width = canvasWidth;
+ canvas.height = canvasHeight;
+
+ canvas.style.width = width + 'px';
+ canvas.style.height = height + 'px';
+ }
+ }
+
+ r.textureMult = 1;
+ if( pixelRatio <= 1 ){
+ canvas = data.bufferCanvases[ r.TEXTURE_BUFFER ];
+
+ r.textureMult = 2;
+ canvas.width = canvasWidth * r.textureMult;
+ canvas.height = canvasHeight * r.textureMult;
+ }
+
+ r.canvasWidth = canvasWidth;
+ r.canvasHeight = canvasHeight;
+
+};
+
+CRp.renderTo = function( cxt, zoom, pan, pxRatio ){
+ this.render({
+ forcedContext: cxt,
+ forcedZoom: zoom,
+ forcedPan: pan,
+ drawAllLayers: true,
+ forcedPxRatio: pxRatio
+ });
+};
+
+CRp.render = function( options ) {
+ options = options || util.staticEmptyObject();
+
+ var forcedContext = options.forcedContext;
+ var drawAllLayers = options.drawAllLayers;
+ var drawOnlyNodeLayer = options.drawOnlyNodeLayer;
+ var forcedZoom = options.forcedZoom;
+ var forcedPan = options.forcedPan;
+ var r = this;
+ var pixelRatio = options.forcedPxRatio === undefined ? this.getPixelRatio() : options.forcedPxRatio;
+ var cy = r.cy; var data = r.data;
+ var needDraw = data.canvasNeedsRedraw;
+ var textureDraw = r.textureOnViewport && !forcedContext && (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming);
+ var motionBlur = options.motionBlur !== undefined ? options.motionBlur : r.motionBlur;
+ var mbPxRatio = r.motionBlurPxRatio;
+ var hasCompoundNodes = cy.hasCompoundNodes();
+ var inNodeDragGesture = r.hoverData.draggingEles;
+ var inBoxSelection = r.hoverData.selecting || r.touchData.selecting ? true : false;
+ motionBlur = motionBlur && !forcedContext && r.motionBlurEnabled && !inBoxSelection;
+ var motionBlurFadeEffect = motionBlur;
+
+ if( !forcedContext && r.motionBlurTimeout ){
+ clearTimeout( r.motionBlurTimeout );
+ }
+
+ if( motionBlur ){
+ if( r.mbFrames == null ){
+ r.mbFrames = 0;
+ }
+
+ if( !r.drawingImage ){ // image loading frames don't count towards motion blur blurry frames
+ r.mbFrames++;
+ }
+
+ if( r.mbFrames < 3 ){ // need several frames before even high quality motionblur
+ motionBlurFadeEffect = false;
+ }
+
+ // go to lower quality blurry frames when several m/b frames have been rendered (avoids flashing)
+ if( r.mbFrames > r.minMbLowQualFrames ){
+ //r.fullQualityMb = false;
+ r.motionBlurPxRatio = r.mbPxRBlurry;
+ }
+ }
+
+ if( r.clearingMotionBlur ){
+ r.motionBlurPxRatio = 1;
+ }
+
+ // b/c drawToContext() may be async w.r.t. redraw(), keep track of last texture frame
+ // because a rogue async texture frame would clear needDraw
+ if( r.textureDrawLastFrame && !textureDraw ){
+ needDraw[r.NODE] = true;
+ needDraw[r.SELECT_BOX] = true;
+ }
+
+ var edges = r.getCachedEdges();
+ var coreStyle = cy.style()._private.coreStyle;
+
+ var zoom = cy.zoom();
+ var effectiveZoom = forcedZoom !== undefined ? forcedZoom : zoom;
+ var pan = cy.pan();
+ var effectivePan = {
+ x: pan.x,
+ y: pan.y
+ };
+
+ var vp = {
+ zoom: zoom,
+ pan: {
+ x: pan.x,
+ y: pan.y
+ }
+ };
+ var prevVp = r.prevViewport;
+ var viewportIsDiff = prevVp === undefined || vp.zoom !== prevVp.zoom || vp.pan.x !== prevVp.pan.x || vp.pan.y !== prevVp.pan.y;
+
+ // we want the low quality motionblur only when the viewport is being manipulated etc (where it's not noticed)
+ if( !viewportIsDiff && !(inNodeDragGesture && !hasCompoundNodes) ){
+ r.motionBlurPxRatio = 1;
+ }
+
+ if( forcedPan ){
+ effectivePan = forcedPan;
+ }
+
+ // apply pixel ratio
+
+ effectiveZoom *= pixelRatio;
+ effectivePan.x *= pixelRatio;
+ effectivePan.y *= pixelRatio;
+
+ var eles = {
+ drag: {
+ nodes: [],
+ edges: [],
+ eles: []
+ },
+ nondrag: {
+ nodes: [],
+ edges: [],
+ eles: []
+ }
+ };
+
+ function mbclear( context, x, y, w, h ){
+ var gco = context.globalCompositeOperation;
+
+ context.globalCompositeOperation = 'destination-out';
+ r.fillStyle( context, 255, 255, 255, r.motionBlurTransparency );
+ context.fillRect(x, y, w, h);
+
+ context.globalCompositeOperation = gco;
+ }
+
+ function setContextTransform(context, clear){
+ var ePan, eZoom, w, h;
+
+ if( !r.clearingMotionBlur && (context === data.bufferContexts[r.MOTIONBLUR_BUFFER_NODE] || context === data.bufferContexts[r.MOTIONBLUR_BUFFER_DRAG]) ){
+ ePan = {
+ x: pan.x * mbPxRatio,
+ y: pan.y * mbPxRatio
+ };
+
+ eZoom = zoom * mbPxRatio;
+
+ w = r.canvasWidth * mbPxRatio;
+ h = r.canvasHeight * mbPxRatio;
+ } else {
+ ePan = effectivePan;
+ eZoom = effectiveZoom;
+
+ w = r.canvasWidth;
+ h = r.canvasHeight;
+ }
+
+ context.setTransform(1, 0, 0, 1, 0, 0);
+
+ if( clear === 'motionBlur' ){
+ mbclear(context, 0, 0, w, h);
+ } else if( !forcedContext && (clear === undefined || clear) ){
+ context.clearRect(0, 0, w, h);
+ }
+
+ if( !drawAllLayers ){
+ context.translate( ePan.x, ePan.y );
+ context.scale( eZoom, eZoom );
+ }
+ if( forcedPan ){
+ context.translate( forcedPan.x, forcedPan.y );
+ }
+ if( forcedZoom ){
+ context.scale( forcedZoom, forcedZoom );
+ }
+ }
+
+ if( !textureDraw ){
+ r.textureDrawLastFrame = false;
+ }
+
+ if( textureDraw ){
+ r.textureDrawLastFrame = true;
+
+ var bb;
+
+ if( !r.textureCache ){
+ r.textureCache = {};
+
+ bb = r.textureCache.bb = cy.elements().boundingBox();
+
+ r.textureCache.texture = r.data.bufferCanvases[ r.TEXTURE_BUFFER ];
+
+ var cxt = r.data.bufferContexts[ r.TEXTURE_BUFFER ];
+
+ cxt.setTransform(1, 0, 0, 1, 0, 0);
+ cxt.clearRect(0, 0, r.canvasWidth * r.textureMult, r.canvasHeight * r.textureMult);
+
+ r.render({
+ forcedContext: cxt,
+ drawOnlyNodeLayer: true,
+ forcedPxRatio: pixelRatio * r.textureMult
+ });
+
+ var vp = r.textureCache.viewport = {
+ zoom: cy.zoom(),
+ pan: cy.pan(),
+ width: r.canvasWidth,
+ height: r.canvasHeight
+ };
+
+ vp.mpan = {
+ x: (0 - vp.pan.x)/vp.zoom,
+ y: (0 - vp.pan.y)/vp.zoom
+ };
+ }
+
+ needDraw[r.DRAG] = false;
+ needDraw[r.NODE] = false;
+
+ var context = data.contexts[r.NODE];
+
+ var texture = r.textureCache.texture;
+ var vp = r.textureCache.viewport;
+ bb = r.textureCache.bb;
+
+ context.setTransform(1, 0, 0, 1, 0, 0);
+
+ if( motionBlur ){
+ mbclear(context, 0, 0, vp.width, vp.height);
+ } else {
+ context.clearRect(0, 0, vp.width, vp.height);
+ }
+
+ var outsideBgColor = coreStyle['outside-texture-bg-color'].value;
+ var outsideBgOpacity = coreStyle['outside-texture-bg-opacity'].value;
+ r.fillStyle( context, outsideBgColor[0], outsideBgColor[1], outsideBgColor[2], outsideBgOpacity );
+ context.fillRect( 0, 0, vp.width, vp.height );
+
+ var zoom = cy.zoom();
+
+ setContextTransform( context, false );
+
+ context.clearRect( vp.mpan.x, vp.mpan.y, vp.width/vp.zoom/pixelRatio, vp.height/vp.zoom/pixelRatio );
+ context.drawImage( texture, vp.mpan.x, vp.mpan.y, vp.width/vp.zoom/pixelRatio, vp.height/vp.zoom/pixelRatio );
+
+ } else if( r.textureOnViewport && !forcedContext ){ // clear the cache since we don't need it
+ r.textureCache = null;
+ }
+
+ var vpManip = (r.pinching || r.hoverData.dragging || r.swipePanning || r.data.wheelZooming || r.hoverData.draggingEles);
+ var hideEdges = r.hideEdgesOnViewport && vpManip;
+ var hideLabels = r.hideLabelsOnViewport && vpManip;
+
+ if (needDraw[r.DRAG] || needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer) {
+ if( hideEdges ){
+ } else {
+ r.findEdgeControlPoints(edges);
+ }
+
+ var zEles = r.getCachedZSortedEles();
+ var extent = cy.extent();
+
+ for (var i = 0; i < zEles.length; i++) {
+ var ele = zEles[i];
+ var list;
+ var bb = forcedContext ? null : ele.boundingBox();
+ var insideExtent = forcedContext ? true : math.boundingBoxesIntersect( extent, bb );
+
+ if( !insideExtent ){ continue; } // no need to render
+
+ if ( ele._private.rscratch.inDragLayer ) {
+ list = eles.drag;
+ } else {
+ list = eles.nondrag;
+ }
+
+ list.eles.push( ele );
+ }
+
+ }
+
+
+ function drawElements( list, context ){
+ var eles = list.eles;
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+
+ if( ele.isNode() ){
+ r.drawNode(context, ele);
+
+ if( !hideLabels ){
+ r.drawNodeText(context, ele);
+ }
+
+ r.drawNode(context, ele, true);
+ } else if( !hideEdges ) {
+ r.drawEdge(context, ele);
+
+ if( !hideLabels ){
+ r.drawEdgeText(context, ele);
+ }
+
+ r.drawEdge(context, ele, true);
+ }
+
+
+ }
+
+ }
+
+ var needMbClear = [];
+
+ needMbClear[r.NODE] = !needDraw[r.NODE] && motionBlur && !r.clearedForMotionBlur[r.NODE] || r.clearingMotionBlur;
+ if( needMbClear[r.NODE] ){ r.clearedForMotionBlur[r.NODE] = true; }
+
+ needMbClear[r.DRAG] = !needDraw[r.DRAG] && motionBlur && !r.clearedForMotionBlur[r.DRAG] || r.clearingMotionBlur;
+ if( needMbClear[r.DRAG] ){ r.clearedForMotionBlur[r.DRAG] = true; }
+
+ if( needDraw[r.NODE] || drawAllLayers || drawOnlyNodeLayer || needMbClear[r.NODE] ){
+ var useBuffer = motionBlur && !needMbClear[r.NODE] && mbPxRatio !== 1;
+ var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_NODE ] : data.contexts[r.NODE] );
+ var clear = motionBlur && !useBuffer ? 'motionBlur' : undefined;
+
+ setContextTransform( context, clear );
+ drawElements(eles.nondrag, context);
+
+ if( !drawAllLayers && !motionBlur ){
+ needDraw[r.NODE] = false;
+ }
+ }
+
+ if ( !drawOnlyNodeLayer && (needDraw[r.DRAG] || drawAllLayers || needMbClear[r.DRAG]) ) {
+ var useBuffer = motionBlur && !needMbClear[r.DRAG] && mbPxRatio !== 1;
+ var context = forcedContext || ( useBuffer ? r.data.bufferContexts[ r.MOTIONBLUR_BUFFER_DRAG ] : data.contexts[r.DRAG] );
+
+ setContextTransform( context, motionBlur && !useBuffer ? 'motionBlur' : undefined );
+ drawElements(eles.drag, context);
+
+ if( !drawAllLayers && !motionBlur ){
+ needDraw[r.DRAG] = false;
+ }
+ }
+
+ if( r.showFps || (!drawOnlyNodeLayer && (needDraw[r.SELECT_BOX] && !drawAllLayers)) ) {
+ var context = forcedContext || data.contexts[r.SELECT_BOX];
+
+ setContextTransform( context );
+
+ if( r.selection[4] == 1 && ( r.hoverData.selecting || r.touchData.selecting ) ){
+ var zoom = r.cy.zoom();
+ var borderWidth = coreStyle['selection-box-border-width'].value / zoom;
+
+ context.lineWidth = borderWidth;
+ context.fillStyle = "rgba("
+ + coreStyle['selection-box-color'].value[0] + ","
+ + coreStyle['selection-box-color'].value[1] + ","
+ + coreStyle['selection-box-color'].value[2] + ","
+ + coreStyle['selection-box-opacity'].value + ")";
+
+ context.fillRect(
+ r.selection[0],
+ r.selection[1],
+ r.selection[2] - r.selection[0],
+ r.selection[3] - r.selection[1]);
+
+ if (borderWidth > 0) {
+ context.strokeStyle = "rgba("
+ + coreStyle['selection-box-border-color'].value[0] + ","
+ + coreStyle['selection-box-border-color'].value[1] + ","
+ + coreStyle['selection-box-border-color'].value[2] + ","
+ + coreStyle['selection-box-opacity'].value + ")";
+
+ context.strokeRect(
+ r.selection[0],
+ r.selection[1],
+ r.selection[2] - r.selection[0],
+ r.selection[3] - r.selection[1]);
+ }
+ }
+
+ if( data.bgActivePosistion && !r.hoverData.selecting ){
+ var zoom = r.cy.zoom();
+ var pos = data.bgActivePosistion;
+
+ context.fillStyle = "rgba("
+ + coreStyle['active-bg-color'].value[0] + ","
+ + coreStyle['active-bg-color'].value[1] + ","
+ + coreStyle['active-bg-color'].value[2] + ","
+ + coreStyle['active-bg-opacity'].value + ")";
+
+ context.beginPath();
+ context.arc(pos.x, pos.y, coreStyle['active-bg-size'].pfValue / zoom, 0, 2 * Math.PI);
+ context.fill();
+ }
+
+ var timeToRender = r.lastRedrawTime;
+ if( r.showFps && timeToRender ){
+ timeToRender = Math.round( timeToRender );
+ var fps = Math.round(1000/timeToRender);
+
+ context.setTransform(1, 0, 0, 1, 0, 0);
+
+ context.fillStyle = 'rgba(255, 0, 0, 0.75)';
+ context.strokeStyle = 'rgba(255, 0, 0, 0.75)';
+ context.lineWidth = 1;
+ context.fillText( '1 frame = ' + timeToRender + ' ms = ' + fps + ' fps', 0, 20);
+
+ var maxFps = 60;
+ context.strokeRect(0, 30, 250, 20);
+ context.fillRect(0, 30, 250 * Math.min(fps/maxFps, 1), 20);
+ }
+
+ if( !drawAllLayers ){
+ needDraw[r.SELECT_BOX] = false;
+ }
+ }
+
+ // motionblur: blit rendered blurry frames
+ if( motionBlur && mbPxRatio !== 1 ){
+ var cxtNode = data.contexts[r.NODE];
+ var txtNode = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_NODE ];
+
+ var cxtDrag = data.contexts[r.DRAG];
+ var txtDrag = r.data.bufferCanvases[ r.MOTIONBLUR_BUFFER_DRAG ];
+
+ var drawMotionBlur = function( cxt, txt, needClear ){
+ cxt.setTransform(1, 0, 0, 1, 0, 0);
+
+ if( needClear || !motionBlurFadeEffect ){
+ cxt.clearRect( 0, 0, r.canvasWidth, r.canvasHeight );
+ } else {
+ mbclear( cxt, 0, 0, r.canvasWidth, r.canvasHeight );
+ }
+
+ var pxr = mbPxRatio;
+
+ cxt.drawImage(
+ txt, // img
+ 0, 0, // sx, sy
+ r.canvasWidth * pxr, r.canvasHeight * pxr, // sw, sh
+ 0, 0, // x, y
+ r.canvasWidth, r.canvasHeight // w, h
+ );
+ };
+
+ if( needDraw[r.NODE] || needMbClear[r.NODE] ){
+ drawMotionBlur( cxtNode, txtNode, needMbClear[r.NODE] );
+ needDraw[r.NODE] = false;
+ }
+
+ if( needDraw[r.DRAG] || needMbClear[r.DRAG] ){
+ drawMotionBlur( cxtDrag, txtDrag, needMbClear[r.DRAG] );
+ needDraw[r.DRAG] = false;
+ }
+ }
+
+ r.currentlyDrawing = false;
+
+ r.prevViewport = vp;
+
+ if( r.clearingMotionBlur ){
+ r.clearingMotionBlur = false;
+ r.motionBlurCleared = true;
+ r.motionBlur = true;
+ }
+
+ if( motionBlur ){
+ r.motionBlurTimeout = setTimeout(function(){
+ r.motionBlurTimeout = null;
+
+ r.clearedForMotionBlur[r.NODE] = false;
+ r.clearedForMotionBlur[r.DRAG] = false;
+ r.motionBlur = false;
+ r.clearingMotionBlur = !textureDraw;
+ r.mbFrames = 0;
+
+ needDraw[r.NODE] = true;
+ needDraw[r.DRAG] = true;
+
+ r.redraw();
+ }, motionBlurDelay);
+ }
+
+ r.drawingImage = false;
+
+
+ if( !forcedContext && !r.initrender ){
+ r.initrender = true;
+ cy.trigger('initrender');
+ }
+
+ if( !forcedContext ){
+ cy.triggerOnRender();
+ }
+
+};
+
+module.exports = CRp;
+
+},{"../../../math":79,"../../../util":94}],68:[function(_dereq_,module,exports){
+'use strict';
+
+ var math = _dereq_('../../../math');
+
+ var CRp = {};
+
+ // @O Polygon drawing
+ CRp.drawPolygonPath = function(
+ context, x, y, width, height, points) {
+
+ var halfW = width / 2;
+ var halfH = height / 2;
+
+ if( context.beginPath ){ context.beginPath(); }
+
+ context.moveTo( x + halfW * points[0], y + halfH * points[1] );
+
+ for (var i = 1; i < points.length / 2; i++) {
+ context.lineTo( x + halfW * points[i * 2], y + halfH * points[i * 2 + 1] );
+ }
+
+ context.closePath();
+ };
+
+ // Round rectangle drawing
+ CRp.drawRoundRectanglePath = function(
+ context, x, y, width, height, radius) {
+
+ var halfWidth = width / 2;
+ var halfHeight = height / 2;
+ var cornerRadius = math.getRoundRectangleRadius(width, height);
+
+ if( context.beginPath ){ context.beginPath(); }
+
+ // Start at top middle
+ context.moveTo(x, y - halfHeight);
+ // Arc from middle top to right side
+ context.arcTo(x + halfWidth, y - halfHeight, x + halfWidth, y, cornerRadius);
+ // Arc from right side to bottom
+ context.arcTo(x + halfWidth, y + halfHeight, x, y + halfHeight, cornerRadius);
+ // Arc from bottom to left side
+ context.arcTo(x - halfWidth, y + halfHeight, x - halfWidth, y, cornerRadius);
+ // Arc from left side to topBorder
+ context.arcTo(x - halfWidth, y - halfHeight, x, y - halfHeight, cornerRadius);
+ // Join line
+ context.lineTo(x, y - halfHeight);
+
+
+ context.closePath();
+ };
+
+ var sin0 = Math.sin(0);
+ var cos0 = Math.cos(0);
+
+ var sin = {};
+ var cos = {};
+
+ var ellipseStepSize = Math.PI / 40;
+
+ for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ) {
+ sin[i] = Math.sin(i);
+ cos[i] = Math.cos(i);
+ }
+
+ CRp.drawEllipsePath = function(context, centerX, centerY, width, height){
+ if( context.beginPath ){ context.beginPath(); }
+
+ if( context.ellipse ){
+ context.ellipse( centerX, centerY, width/2, height/2, 0, 0, 2*Math.PI );
+ } else {
+ var xPos, yPos;
+ var rw = width/2;
+ var rh = height/2;
+ for (var i = 0 * Math.PI; i < 2 * Math.PI; i += ellipseStepSize ) {
+ xPos = centerX - (rw * sin[i]) * sin0 + (rw * cos[i]) * cos0;
+ yPos = centerY + (rh * cos[i]) * sin0 + (rh * sin[i]) * cos0;
+
+ if (i === 0) {
+ context.moveTo(xPos, yPos);
+ } else {
+ context.lineTo(xPos, yPos);
+ }
+ }
+ }
+
+ context.closePath();
+ };
+
+module.exports = CRp;
+
+},{"../../../math":79}],69:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../../../is');
+
+var CRp = {};
+
+CRp.createBuffer = function(w, h) {
+ var buffer = document.createElement('canvas');
+ buffer.width = w;
+ buffer.height = h;
+
+ return [buffer, buffer.getContext('2d')];
+};
+
+CRp.bufferCanvasImage = function( options ){
+ var cy = this.cy;
+ var bb = cy.elements().boundingBox();
+ var width = options.full ? Math.ceil(bb.w) : this.container.clientWidth;
+ var height = options.full ? Math.ceil(bb.h) : this.container.clientHeight;
+ var scale = 1;
+
+ if( options.scale !== undefined ){
+ width *= options.scale;
+ height *= options.scale;
+
+ scale = options.scale;
+ } else if( is.number(options.maxWidth) || is.number(options.maxHeight) ){
+ var maxScaleW = Infinity;
+ var maxScaleH = Infinity;
+
+ if( is.number(options.maxWidth) ){
+ maxScaleW = scale * options.maxWidth / width;
+ }
+
+ if( is.number(options.maxHeight) ){
+ maxScaleH = scale * options.maxHeight / height;
+ }
+
+ scale = Math.min( maxScaleW, maxScaleH );
+
+ width *= scale;
+ height *= scale;
+ }
+
+ var buffCanvas = document.createElement('canvas');
+
+ buffCanvas.width = width;
+ buffCanvas.height = height;
+
+ buffCanvas.style.width = width + 'px';
+ buffCanvas.style.height = height + 'px';
+
+ var buffCxt = buffCanvas.getContext('2d');
+
+ // Rasterize the layers, but only if container has nonzero size
+ if (width > 0 && height > 0) {
+
+ buffCxt.clearRect( 0, 0, width, height );
+
+ if( options.bg ){
+ buffCxt.fillStyle = options.bg;
+ buffCxt.rect( 0, 0, width, height );
+ buffCxt.fill();
+ }
+
+ buffCxt.globalCompositeOperation = 'source-over';
+
+ if( options.full ){ // draw the full bounds of the graph
+ this.render({
+ forcedContext: buffCxt,
+ drawAllLayers: true,
+ forcedZoom: scale,
+ forcedPan: { x: -bb.x1*scale, y: -bb.y1*scale },
+ forcedPxRatio: 1
+ });
+ } else { // draw the current view
+ var cyPan = cy.pan();
+ var pan = {
+ x: cyPan.x * scale,
+ y: cyPan.y * scale
+ };
+ var zoom = cy.zoom() * scale;
+
+ this.render({
+ forcedContext: buffCxt,
+ drawAllLayers: true,
+ forcedZoom: zoom,
+ forcedPan: pan,
+ forcedPxRatio: 1
+ });
+ }
+ }
+
+ return buffCanvas;
+};
+
+CRp.png = function( options ){
+ return this.bufferCanvasImage( options ).toDataURL('image/png');
+};
+
+CRp.jpg = function( options ){
+ return this.bufferCanvasImage( options ).toDataURL('image/jpeg');
+};
+
+module.exports = CRp;
+
+},{"../../../is":77}],70:[function(_dereq_,module,exports){
+/*
+The canvas renderer was written by Yue Dong.
+
+Modifications tracked on Github.
+*/
+
+'use strict';
+
+var util = _dereq_('../../../util');
+var is = _dereq_('../../../is');
+
+var CR = CanvasRenderer;
+var CRp = CanvasRenderer.prototype;
+
+CRp.CANVAS_LAYERS = 3;
+//
+CRp.SELECT_BOX = 0;
+CRp.DRAG = 1;
+CRp.NODE = 2;
+
+CRp.BUFFER_COUNT = 3;
+//
+CRp.TEXTURE_BUFFER = 0;
+CRp.MOTIONBLUR_BUFFER_NODE = 1;
+CRp.MOTIONBLUR_BUFFER_DRAG = 2;
+
+function CanvasRenderer(options) {
+ var r = this;
+
+ r.data = {
+ canvases: new Array(CRp.CANVAS_LAYERS),
+ contexts: new Array(CRp.CANVAS_LAYERS),
+ canvasNeedsRedraw: new Array(CRp.CANVAS_LAYERS),
+
+ bufferCanvases: new Array(CRp.BUFFER_COUNT),
+ bufferContexts: new Array(CRp.CANVAS_LAYERS)
+ };
+
+ r.data.canvasContainer = document.createElement('div');
+ var containerStyle = r.data.canvasContainer.style;
+ r.data.canvasContainer.setAttribute('style', '-webkit-tap-highlight-color: rgba(0,0,0,0);');
+ containerStyle.position = 'relative';
+ containerStyle.zIndex = '0';
+ containerStyle.overflow = 'hidden';
+
+ var container = options.cy.container();
+ container.appendChild( r.data.canvasContainer );
+ container.setAttribute('style', ( container.getAttribute('style') || '' ) + '-webkit-tap-highlight-color: rgba(0,0,0,0);');
+
+ for (var i = 0; i < CRp.CANVAS_LAYERS; i++) {
+ var canvas = r.data.canvases[i] = document.createElement('canvas');
+ r.data.contexts[i] = canvas.getContext('2d');
+ canvas.setAttribute( 'style', '-webkit-user-select: none; -moz-user-select: -moz-none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); outline-style: none;' + ( is.ms() ? ' -ms-touch-action: none; touch-action: none; ' : '' ) );
+ canvas.style.position = 'absolute';
+ canvas.setAttribute('data-id', 'layer' + i);
+ canvas.style.zIndex = String(CRp.CANVAS_LAYERS - i);
+ r.data.canvasContainer.appendChild(canvas);
+
+ r.data.canvasNeedsRedraw[i] = false;
+ }
+ r.data.topCanvas = r.data.canvases[0];
+
+ r.data.canvases[CRp.NODE].setAttribute('data-id', 'layer' + CRp.NODE + '-node');
+ r.data.canvases[CRp.SELECT_BOX].setAttribute('data-id', 'layer' + CRp.SELECT_BOX + '-selectbox');
+ r.data.canvases[CRp.DRAG].setAttribute('data-id', 'layer' + CRp.DRAG + '-drag');
+
+ for (var i = 0; i < CRp.BUFFER_COUNT; i++) {
+ r.data.bufferCanvases[i] = document.createElement('canvas');
+ r.data.bufferContexts[i] = r.data.bufferCanvases[i].getContext('2d');
+ r.data.bufferCanvases[i].style.position = 'absolute';
+ r.data.bufferCanvases[i].setAttribute('data-id', 'buffer' + i);
+ r.data.bufferCanvases[i].style.zIndex = String(-i - 1);
+ r.data.bufferCanvases[i].style.visibility = 'hidden';
+ //r.data.canvasContainer.appendChild(r.data.bufferCanvases[i]);
+ }
+
+ r.pathsEnabled = true;
+}
+
+CRp.redrawHint = function( group, bool ){
+ var r = this;
+
+ switch( group ){
+ case 'eles':
+ r.data.canvasNeedsRedraw[ CRp.NODE ] = bool;
+ break;
+ case 'drag':
+ r.data.canvasNeedsRedraw[ CRp.DRAG ] = bool;
+ break;
+ case 'select':
+ r.data.canvasNeedsRedraw[ CRp.SELECT_BOX ] = bool;
+ break;
+ }
+};
+
+// whether to use Path2D caching for drawing
+var pathsImpld = typeof Path2D !== 'undefined';
+
+CRp.path2dEnabled = function( on ){
+ if( on === undefined ){
+ return this.pathsEnabled;
+ }
+
+ this.pathsEnabled = on ? true : false;
+};
+
+CRp.usePaths = function(){
+ return pathsImpld && this.pathsEnabled;
+};
+
+[
+ _dereq_('./arrow-shapes'),
+ _dereq_('./drawing-edges'),
+ _dereq_('./drawing-images'),
+ _dereq_('./drawing-label-text'),
+ _dereq_('./drawing-nodes'),
+ _dereq_('./drawing-redraw'),
+ _dereq_('./drawing-shapes'),
+ _dereq_('./export-image'),
+ _dereq_('./node-shapes')
+].forEach(function( props ){
+ util.extend( CRp, props );
+});
+
+module.exports = CR;
+
+},{"../../../is":77,"../../../util":94,"./arrow-shapes":62,"./drawing-edges":63,"./drawing-images":64,"./drawing-label-text":65,"./drawing-nodes":66,"./drawing-redraw":67,"./drawing-shapes":68,"./export-image":69,"./node-shapes":71}],71:[function(_dereq_,module,exports){
+'use strict';
+
+var CRp = {};
+
+var impl;
+
+CRp.nodeShapeImpl = function( name ){
+ var self = this;
+
+ return ( impl || (impl = {
+ 'ellipse': function( context, centerX, centerY, width, height ){
+ self.drawEllipsePath( context, centerX, centerY, width, height );
+ },
+
+ 'polygon': function( context, centerX, centerY, width, height, points ){
+ self.drawPolygonPath( context, centerX, centerY, width, height, points );
+ },
+
+ 'roundrectangle': function( context, centerX, centerY, width, height ){
+ self.drawRoundRectanglePath( context, centerX, centerY, width, height, 10 );
+ }
+ }) )[ name ];
+};
+
+module.exports = CRp;
+
+},{}],72:[function(_dereq_,module,exports){
+'use strict';
+
+module.exports = [
+ { name: 'null', impl: _dereq_('./null') },
+ { name: 'base', impl: _dereq_('./base') },
+ { name: 'canvas', impl: _dereq_('./canvas') }
+];
+
+},{"./base":58,"./canvas":70,"./null":73}],73:[function(_dereq_,module,exports){
+'use strict';
+
+function NullRenderer(options){
+ this.options = options;
+ this.notifications = 0; // for testing
+}
+
+var noop = function(){};
+
+NullRenderer.prototype = {
+ recalculateRenderedStyle: noop,
+ notify: function(){ this.notifications++; },
+ init: noop
+};
+
+module.exports = NullRenderer;
+
+},{}],74:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('./is');
+var util = _dereq_('./util');
+var Thread = _dereq_('./thread');
+var Promise = _dereq_('./promise');
+var define = _dereq_('./define');
+
+var Fabric = function( N ){
+ if( !(this instanceof Fabric) ){
+ return new Fabric( N );
+ }
+
+ this._private = {
+ pass: []
+ };
+
+ var defN = 4;
+
+ if( is.number(N) ){
+ // then use the specified number of threads
+ } if( typeof navigator !== 'undefined' && navigator.hardwareConcurrency != null ){
+ N = navigator.hardwareConcurrency;
+ } else {
+ try{
+ N = _dereq_('os').cpus().length;
+ } catch( err ){
+ N = defN;
+ }
+ } // TODO could use an estimation here but would the additional expense be worth it?
+
+ for( var i = 0; i < N; i++ ){
+ this[i] = new Thread();
+ }
+
+ this.length = N;
+};
+
+var fabfn = Fabric.prototype; // short alias
+
+util.extend(fabfn, {
+
+ instanceString: function(){ return 'fabric'; },
+
+ // require fn in all threads
+ require: function( fn, as ){
+ for( var i = 0; i < this.length; i++ ){
+ var thread = this[i];
+
+ thread.require( fn, as );
+ }
+
+ return this;
+ },
+
+ // get a random thread
+ random: function(){
+ var i = Math.round( (this.length - 1) * Math.random() );
+ var thread = this[i];
+
+ return thread;
+ },
+
+ // run on random thread
+ run: function( fn ){
+ var pass = this._private.pass.shift();
+
+ return this.random().pass( pass ).run( fn );
+ },
+
+ // sends a random thread a message
+ message: function( m ){
+ return this.random().message( m );
+ },
+
+ // send all threads a message
+ broadcast: function( m ){
+ for( var i = 0; i < this.length; i++ ){
+ var thread = this[i];
+
+ thread.message( m );
+ }
+
+ return this; // chaining
+ },
+
+ // stop all threads
+ stop: function(){
+ for( var i = 0; i < this.length; i++ ){
+ var thread = this[i];
+
+ thread.stop();
+ }
+
+ return this; // chaining
+ },
+
+ // pass data to be used with .spread() etc.
+ pass: function( data ){
+ var pass = this._private.pass;
+
+ if( is.array(data) ){
+ pass.push( data );
+ } else {
+ throw 'Only arrays may be used with fabric.pass()';
+ }
+
+ return this; // chaining
+ },
+
+ spreadSize: function(){
+ var subsize = Math.ceil( this._private.pass[0].length / this.length );
+
+ subsize = Math.max( 1, subsize ); // don't pass less than one ele to each thread
+
+ return subsize;
+ },
+
+ // split the data into slices to spread the data equally among threads
+ spread: function( fn ){
+ var self = this;
+ var _p = self._private;
+ var subsize = self.spreadSize(); // number of pass eles to handle in each thread
+ var pass = _p.pass.shift().concat([]); // keep a copy
+ var runPs = [];
+
+ for( var i = 0; i < this.length; i++ ){
+ var thread = this[i];
+ var slice = pass.splice( 0, subsize );
+
+ var runP = thread.pass( slice ).run( fn );
+
+ runPs.push( runP );
+
+ var doneEarly = pass.length === 0;
+ if( doneEarly ){ break; }
+ }
+
+ return Promise.all( runPs ).then(function( thens ){
+ var postpass = [];
+ var p = 0;
+
+ // fill postpass with the total result joined from all threads
+ for( var i = 0; i < thens.length; i++ ){
+ var then = thens[i]; // array result from thread i
+
+ for( var j = 0; j < then.length; j++ ){
+ var t = then[j]; // array element
+
+ postpass[ p++ ] = t;
+ }
+ }
+
+ return postpass;
+ });
+ },
+
+ // parallel version of array.map()
+ map: function( fn ){
+ var self = this;
+
+ self.require( fn, '_$_$_fabmap' );
+
+ return self.spread(function( split ){
+ var mapped = [];
+ var origResolve = resolve; // jshint ignore:line
+
+ resolve = function( val ){ // jshint ignore:line
+ mapped.push( val );
+ };
+
+ for( var i = 0; i < split.length; i++ ){
+ var oldLen = mapped.length;
+ var ret = _$_$_fabmap( split[i] ); // jshint ignore:line
+ var nothingInsdByResolve = oldLen === mapped.length;
+
+ if( nothingInsdByResolve ){
+ mapped.push( ret );
+ }
+ }
+
+ resolve = origResolve; // jshint ignore:line
+
+ return mapped;
+ });
+
+ },
+
+ // parallel version of array.filter()
+ filter: function( fn ){
+ var _p = this._private;
+ var pass = _p.pass[0];
+
+ return this.map( fn ).then(function( include ){
+ var ret = [];
+
+ for( var i = 0; i < pass.length; i++ ){
+ var datum = pass[i];
+ var incDatum = include[i];
+
+ if( incDatum ){
+ ret.push( datum );
+ }
+ }
+
+ return ret;
+ });
+ },
+
+ // sorts the passed array using a divide and conquer strategy
+ sort: function( cmp ){
+ var self = this;
+ var P = this._private.pass[0].length;
+ var subsize = this.spreadSize();
+
+ cmp = cmp || function( a, b ){ // default comparison function
+ if( a < b ){
+ return -1;
+ } else if( a > b ){
+ return 1;
+ }
+
+ return 0;
+ };
+
+ self.require( cmp, '_$_$_cmp' );
+
+ return self.spread(function( split ){ // sort each split normally
+ var sortedSplit = split.sort( _$_$_cmp ); // jshint ignore:line
+ resolve( sortedSplit ); // jshint ignore:line
+
+ }).then(function( joined ){
+ // do all the merging in the main thread to minimise data transfer
+
+ // TODO could do merging in separate threads but would incur add'l cost of data transfer
+ // for each level of the merge
+
+ var merge = function( i, j, max ){
+ // don't overflow array
+ j = Math.min( j, P );
+ max = Math.min( max, P );
+
+ // left and right sides of merge
+ var l = i;
+ var r = j;
+
+ var sorted = [];
+
+ for( var k = l; k < max; k++ ){
+
+ var eleI = joined[i];
+ var eleJ = joined[j];
+
+ if( i < r && ( j >= max || cmp(eleI, eleJ) <= 0 ) ){
+ sorted.push( eleI );
+ i++;
+ } else {
+ sorted.push( eleJ );
+ j++;
+ }
+
+ }
+
+ // in the array proper, put the sorted values
+ for( var k = 0; k < sorted.length; k++ ){ // kth sorted item
+ var index = l + k;
+
+ joined[ index ] = sorted[k];
+ }
+ };
+
+ for( var splitL = subsize; splitL < P; splitL *= 2 ){ // merge until array is "split" as 1
+
+ for( var i = 0; i < P; i += 2*splitL ){
+ merge( i, i + splitL, i + 2*splitL );
+ }
+
+ }
+
+ return joined;
+ });
+ }
+
+
+});
+
+var defineRandomPasser = function( opts ){
+ opts = opts || {};
+
+ return function( fn, arg1 ){
+ var pass = this._private.pass.shift();
+
+ return this.random().pass( pass )[ opts.threadFn ]( fn, arg1 );
+ };
+};
+
+util.extend(fabfn, {
+ randomMap: defineRandomPasser({ threadFn: 'map' }),
+
+ reduce: defineRandomPasser({ threadFn: 'reduce' }),
+
+ reduceRight: defineRandomPasser({ threadFn: 'reduceRight' })
+});
+
+// aliases
+var fn = fabfn;
+fn.promise = fn.run;
+fn.terminate = fn.halt = fn.stop;
+fn.include = fn.require;
+
+// pull in event apis
+util.extend(fabfn, {
+ on: define.on(),
+ one: define.on({ unbindSelfOnTrigger: true }),
+ off: define.off(),
+ trigger: define.trigger()
+});
+
+define.eventAliasesOn( fabfn );
+
+module.exports = Fabric;
+
+},{"./define":41,"./is":77,"./promise":80,"./thread":92,"./util":94,"os":undefined}],75:[function(_dereq_,module,exports){
+'use strict';
+/* jshint ignore:start */
+
+// Generated by CoffeeScript 1.8.0
+(function() {
+ var Heap, defaultCmp, floor, heapify, heappop, heappush, heappushpop, heapreplace, insort, min, nlargest, nsmallest, updateItem, _siftdown, _siftup;
+
+ floor = Math.floor, min = Math.min;
+
+
+ /*
+ Default comparison function to be used
+ */
+
+ defaultCmp = function(x, y) {
+ if (x < y) {
+ return -1;
+ }
+ if (x > y) {
+ return 1;
+ }
+ return 0;
+ };
+
+
+ /*
+ Insert item x in list a, and keep it sorted assuming a is sorted.
+
+ If x is already in a, insert it to the right of the rightmost x.
+
+ Optional args lo (default 0) and hi (default a.length) bound the slice
+ of a to be searched.
+ */
+
+ insort = function(a, x, lo, hi, cmp) {
+ var mid;
+ if (lo == null) {
+ lo = 0;
+ }
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ if (lo < 0) {
+ throw new Error('lo must be non-negative');
+ }
+ if (hi == null) {
+ hi = a.length;
+ }
+ while (lo < hi) {
+ mid = floor((lo + hi) / 2);
+ if (cmp(x, a[mid]) < 0) {
+ hi = mid;
+ } else {
+ lo = mid + 1;
+ }
+ }
+ return ([].splice.apply(a, [lo, lo - lo].concat(x)), x);
+ };
+
+
+ /*
+ Push item onto heap, maintaining the heap invariant.
+ */
+
+ heappush = function(array, item, cmp) {
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ array.push(item);
+ return _siftdown(array, 0, array.length - 1, cmp);
+ };
+
+
+ /*
+ Pop the smallest item off the heap, maintaining the heap invariant.
+ */
+
+ heappop = function(array, cmp) {
+ var lastelt, returnitem;
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ lastelt = array.pop();
+ if (array.length) {
+ returnitem = array[0];
+ array[0] = lastelt;
+ _siftup(array, 0, cmp);
+ } else {
+ returnitem = lastelt;
+ }
+ return returnitem;
+ };
+
+
+ /*
+ Pop and return the current smallest value, and add the new item.
+
+ This is more efficient than heappop() followed by heappush(), and can be
+ more appropriate when using a fixed size heap. Note that the value
+ returned may be larger than item! That constrains reasonable use of
+ this routine unless written as part of a conditional replacement:
+ if item > array[0]
+ item = heapreplace(array, item)
+ */
+
+ heapreplace = function(array, item, cmp) {
+ var returnitem;
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ returnitem = array[0];
+ array[0] = item;
+ _siftup(array, 0, cmp);
+ return returnitem;
+ };
+
+
+ /*
+ Fast version of a heappush followed by a heappop.
+ */
+
+ heappushpop = function(array, item, cmp) {
+ var _ref;
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ if (array.length && cmp(array[0], item) < 0) {
+ _ref = [array[0], item], item = _ref[0], array[0] = _ref[1];
+ _siftup(array, 0, cmp);
+ }
+ return item;
+ };
+
+
+ /*
+ Transform list into a heap, in-place, in O(array.length) time.
+ */
+
+ heapify = function(array, cmp) {
+ var i, _i, _j, _len, _ref, _ref1, _results, _results1;
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ _ref1 = (function() {
+ _results1 = [];
+ for (var _j = 0, _ref = floor(array.length / 2); 0 <= _ref ? _j < _ref : _j > _ref; 0 <= _ref ? _j++ : _j--){ _results1.push(_j); }
+ return _results1;
+ }).apply(this).reverse();
+ _results = [];
+ for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
+ i = _ref1[_i];
+ _results.push(_siftup(array, i, cmp));
+ }
+ return _results;
+ };
+
+
+ /*
+ Update the position of the given item in the heap.
+ This function should be called every time the item is being modified.
+ */
+
+ updateItem = function(array, item, cmp) {
+ var pos;
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ pos = array.indexOf(item);
+ if (pos === -1) {
+ return;
+ }
+ _siftdown(array, 0, pos, cmp);
+ return _siftup(array, pos, cmp);
+ };
+
+
+ /*
+ Find the n largest elements in a dataset.
+ */
+
+ nlargest = function(array, n, cmp) {
+ var elem, result, _i, _len, _ref;
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ result = array.slice(0, n);
+ if (!result.length) {
+ return result;
+ }
+ heapify(result, cmp);
+ _ref = array.slice(n);
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ elem = _ref[_i];
+ heappushpop(result, elem, cmp);
+ }
+ return result.sort(cmp).reverse();
+ };
+
+
+ /*
+ Find the n smallest elements in a dataset.
+ */
+
+ nsmallest = function(array, n, cmp) {
+ var elem, i, los, result, _i, _j, _len, _ref, _ref1, _results;
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ if (n * 10 <= array.length) {
+ result = array.slice(0, n).sort(cmp);
+ if (!result.length) {
+ return result;
+ }
+ los = result[result.length - 1];
+ _ref = array.slice(n);
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ elem = _ref[_i];
+ if (cmp(elem, los) < 0) {
+ insort(result, elem, 0, null, cmp);
+ result.pop();
+ los = result[result.length - 1];
+ }
+ }
+ return result;
+ }
+ heapify(array, cmp);
+ _results = [];
+ for (i = _j = 0, _ref1 = min(n, array.length); 0 <= _ref1 ? _j < _ref1 : _j > _ref1; i = 0 <= _ref1 ? ++_j : --_j) {
+ _results.push(heappop(array, cmp));
+ }
+ return _results;
+ };
+
+ _siftdown = function(array, startpos, pos, cmp) {
+ var newitem, parent, parentpos;
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ newitem = array[pos];
+ while (pos > startpos) {
+ parentpos = (pos - 1) >> 1;
+ parent = array[parentpos];
+ if (cmp(newitem, parent) < 0) {
+ array[pos] = parent;
+ pos = parentpos;
+ continue;
+ }
+ break;
+ }
+ return array[pos] = newitem;
+ };
+
+ _siftup = function(array, pos, cmp) {
+ var childpos, endpos, newitem, rightpos, startpos;
+ if (cmp == null) {
+ cmp = defaultCmp;
+ }
+ endpos = array.length;
+ startpos = pos;
+ newitem = array[pos];
+ childpos = 2 * pos + 1;
+ while (childpos < endpos) {
+ rightpos = childpos + 1;
+ if (rightpos < endpos && !(cmp(array[childpos], array[rightpos]) < 0)) {
+ childpos = rightpos;
+ }
+ array[pos] = array[childpos];
+ pos = childpos;
+ childpos = 2 * pos + 1;
+ }
+ array[pos] = newitem;
+ return _siftdown(array, startpos, pos, cmp);
+ };
+
+ Heap = (function() {
+ Heap.push = heappush;
+
+ Heap.pop = heappop;
+
+ Heap.replace = heapreplace;
+
+ Heap.pushpop = heappushpop;
+
+ Heap.heapify = heapify;
+
+ Heap.updateItem = updateItem;
+
+ Heap.nlargest = nlargest;
+
+ Heap.nsmallest = nsmallest;
+
+ function Heap(cmp) {
+ this.cmp = cmp != null ? cmp : defaultCmp;
+ this.nodes = [];
+ }
+
+ Heap.prototype.push = function(x) {
+ return heappush(this.nodes, x, this.cmp);
+ };
+
+ Heap.prototype.pop = function() {
+ return heappop(this.nodes, this.cmp);
+ };
+
+ Heap.prototype.peek = function() {
+ return this.nodes[0];
+ };
+
+ Heap.prototype.contains = function(x) {
+ return this.nodes.indexOf(x) !== -1;
+ };
+
+ Heap.prototype.replace = function(x) {
+ return heapreplace(this.nodes, x, this.cmp);
+ };
+
+ Heap.prototype.pushpop = function(x) {
+ return heappushpop(this.nodes, x, this.cmp);
+ };
+
+ Heap.prototype.heapify = function() {
+ return heapify(this.nodes, this.cmp);
+ };
+
+ Heap.prototype.updateItem = function(x) {
+ return updateItem(this.nodes, x, this.cmp);
+ };
+
+ Heap.prototype.clear = function() {
+ return this.nodes = [];
+ };
+
+ Heap.prototype.empty = function() {
+ return this.nodes.length === 0;
+ };
+
+ Heap.prototype.size = function() {
+ return this.nodes.length;
+ };
+
+ Heap.prototype.clone = function() {
+ var heap;
+ heap = new Heap();
+ heap.nodes = this.nodes.slice(0);
+ return heap;
+ };
+
+ Heap.prototype.toArray = function() {
+ return this.nodes.slice(0);
+ };
+
+ Heap.prototype.insert = Heap.prototype.push;
+
+ Heap.prototype.top = Heap.prototype.peek;
+
+ Heap.prototype.front = Heap.prototype.peek;
+
+ Heap.prototype.has = Heap.prototype.contains;
+
+ Heap.prototype.copy = Heap.prototype.clone;
+
+ return Heap;
+
+ })();
+
+ (function(root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ return define([], factory);
+ } else if (typeof exports === 'object') {
+ return module.exports = factory();
+ } else {
+ return root.Heap = factory();
+ }
+ })(this, function() {
+ return Heap;
+ });
+
+}).call(this);
+
+/* jshint ignore:end */
+
+},{}],76:[function(_dereq_,module,exports){
+'use strict';
+
+var window = _dereq_('./window');
+var is = _dereq_('./is');
+var Core = _dereq_('./core');
+var extension = _dereq_('./extension');
+var registerJquery = _dereq_('./jquery-plugin');
+var Stylesheet = _dereq_('./stylesheet');
+var Thread = _dereq_('./thread');
+var Fabric = _dereq_('./fabric');
+
+var cytoscape = function( options ){ // jshint ignore:line
+ // if no options specified, use default
+ if( options === undefined ){
+ options = {};
+ }
+
+ // create instance
+ if( is.plainObject( options ) ){
+ return new Core( options );
+ }
+
+ // allow for registration of extensions
+ else if( is.string( options ) ) {
+ return extension.apply(extension, arguments);
+ }
+};
+
+// replaced by build system
+cytoscape.version = '2.5.1';
+
+// try to register w/ jquery
+if( window && window.jQuery ){
+ registerJquery( window.jQuery, cytoscape );
+}
+
+// expose register api
+cytoscape.registerJquery = function( jQuery ){
+ registerJquery( jQuery, cytoscape );
+};
+
+// expose public apis (mostly for extensions)
+cytoscape.stylesheet = cytoscape.Stylesheet = Stylesheet;
+cytoscape.thread = cytoscape.Thread = Thread;
+cytoscape.fabric = cytoscape.Fabric = Fabric;
+
+module.exports = cytoscape;
+
+},{"./core":34,"./extension":43,"./fabric":74,"./is":77,"./jquery-plugin":78,"./stylesheet":91,"./thread":92,"./window":100}],77:[function(_dereq_,module,exports){
+'use strict';
+
+var window = _dereq_('./window');
+var navigator = window ? window.navigator : null;
+
+var typeofstr = typeof '';
+var typeofobj = typeof {};
+var typeoffn = typeof function(){};
+var typeofhtmlele = typeof HTMLElement;
+
+var instanceStr = function( obj ){
+ return obj && obj.instanceString && is.fn( obj.instanceString ) ? obj.instanceString() : null;
+};
+
+var is = {
+ defined: function(obj){
+ return obj != null; // not undefined or null
+ },
+
+ string: function(obj){
+ return obj != null && typeof obj == typeofstr;
+ },
+
+ fn: function(obj){
+ return obj != null && typeof obj === typeoffn;
+ },
+
+ array: function(obj){
+ return Array.isArray ? Array.isArray(obj) : obj != null && obj instanceof Array;
+ },
+
+ plainObject: function(obj){
+ return obj != null && typeof obj === typeofobj && !is.array(obj) && obj.constructor === Object;
+ },
+
+ object: function(obj){
+ return obj != null && typeof obj === typeofobj;
+ },
+
+ number: function(obj){
+ return obj != null && typeof obj === typeof 1 && !isNaN(obj);
+ },
+
+ integer: function( obj ){
+ return is.number(obj) && Math.floor(obj) === obj;
+ },
+
+ bool: function(obj){
+ return obj != null && typeof obj === typeof true;
+ },
+
+ htmlElement: function(obj){
+ if( 'undefined' === typeofhtmlele ){
+ return undefined;
+ } else {
+ return null != obj && obj instanceof HTMLElement;
+ }
+ },
+
+ elementOrCollection: function(obj){
+ return is.element(obj) || is.collection(obj);
+ },
+
+ element: function(obj){
+ return instanceStr(obj) === 'collection' && obj._private.single;
+ },
+
+ collection: function(obj){
+ return instanceStr(obj) === 'collection' && !obj._private.single;
+ },
+
+ core: function(obj){
+ return instanceStr(obj) === 'core';
+ },
+
+ style: function(obj){
+ return instanceStr(obj) === 'style';
+ },
+
+ stylesheet: function(obj){
+ return instanceStr(obj) === 'stylesheet';
+ },
+
+ event: function(obj){
+ return instanceStr(obj) === 'event';
+ },
+
+ thread: function(obj){
+ return instanceStr(obj) === 'thread';
+ },
+
+ fabric: function(obj){
+ return instanceStr(obj) === 'fabric';
+ },
+
+ emptyString: function(obj){
+ if( !obj ){ // null is empty
+ return true;
+ } else if( is.string(obj) ){
+ if( obj === '' || obj.match(/^\s+$/) ){
+ return true; // empty string is empty
+ }
+ }
+
+ return false; // otherwise, we don't know what we've got
+ },
+
+ nonemptyString: function(obj){
+ if( obj && is.string(obj) && obj !== '' && !obj.match(/^\s+$/) ){
+ return true;
+ }
+
+ return false;
+ },
+
+ domElement: function(obj){
+ if( typeof HTMLElement === 'undefined' ){
+ return false; // we're not in a browser so it doesn't matter
+ } else {
+ return obj instanceof HTMLElement;
+ }
+ },
+
+ boundingBox: function(obj){
+ return is.plainObject(obj) &&
+ is.number(obj.x1) && is.number(obj.x2) &&
+ is.number(obj.y1) && is.number(obj.y2)
+ ;
+ },
+
+ promise: function(obj){
+ return is.object(obj) && is.fn(obj.then);
+ },
+
+ touch: function(){
+ return window && ( ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch );
+ },
+
+ gecko: function(){
+ return typeof InstallTrigger !== 'undefined' || ('MozAppearance' in document.documentElement.style);
+ },
+
+ webkit: function(){
+ return typeof webkitURL !== 'undefined' || ('WebkitAppearance' in document.documentElement.style);
+ },
+
+ chromium: function(){
+ return typeof chrome !== 'undefined';
+ },
+
+ khtml: function(){
+ return navigator && navigator.vendor.match(/kde/i); // probably a better way to detect this...
+ },
+
+ khtmlEtc: function(){
+ return is.khtml() || is.webkit() || is.chromium();
+ },
+
+ ms: function(){
+ return navigator && navigator.userAgent.match(/msie|trident|edge/i); // probably a better way to detect this...
+ },
+
+ windows: function(){
+ return navigator && navigator.appVersion.match(/Win/i);
+ },
+
+ mac: function(){
+ return navigator && navigator.appVersion.match(/Mac/i);
+ },
+
+ linux: function(){
+ return navigator && navigator.appVersion.match(/Linux/i);
+ },
+
+ unix: function(){
+ return navigator && navigator.appVersion.match(/X11/i);
+ }
+};
+
+module.exports = is;
+
+},{"./window":100}],78:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('./is');
+
+var cyReg = function( $ele ){
+ var d = $ele[0]._cyreg = $ele[0]._cyreg || {};
+
+ return d;
+};
+
+var registerJquery = function( $, cytoscape ){
+ if( !$ ){ return; } // no jquery => don't need this
+
+ if( $.fn.cytoscape ){ return; } // already registered
+
+ // allow calls on a jQuery selector by proxying calls to $.cytoscape
+ // e.g. $("#foo").cytoscape(options) => $.cytoscape(options) on #foo
+ $.fn.cytoscape = function(opts){
+ var $this = $(this);
+
+ // get object
+ if( opts === 'get' ){
+ return cyReg( $this ).cy;
+ }
+
+ // bind to ready
+ else if( is.fn(opts) ){
+
+ var ready = opts;
+ var cy = cyReg( $this ).cy;
+
+ if( cy && cy.isReady() ){ // already ready so just trigger now
+ cy.trigger('ready', [], ready);
+
+ } else { // not yet ready, so add to readies list
+ var data = cyReg( $this );
+ var readies = data.readies = data.readies || [];
+
+ readies.push( ready );
+ }
+
+ }
+
+ // proxy to create instance
+ else if( is.plainObject(opts) ){
+ return $this.each(function(){
+ var options = $.extend({}, opts, {
+ container: $(this)[0]
+ });
+
+ cytoscape(options);
+ });
+ }
+ };
+
+ // allow access to the global cytoscape object under jquery for legacy reasons
+ $.cytoscape = cytoscape;
+
+ // use short alias (cy) if not already defined
+ if( $.fn.cy == null && $.cy == null ){
+ $.fn.cy = $.fn.cytoscape;
+ $.cy = $.cytoscape;
+ }
+};
+
+module.exports = registerJquery;
+
+},{"./is":77}],79:[function(_dereq_,module,exports){
+'use strict';
+
+var math = {};
+
+math.signum = function(x){
+ if( x > 0 ){
+ return 1;
+ } else if( x < 0 ){
+ return -1;
+ } else {
+ return 0;
+ }
+};
+
+math.distance = function( p1, p2 ){
+ return Math.sqrt( math.sqDistance(p1, p2) );
+};
+
+math.sqDistance = function( p1, p2 ){
+ var dx = p2.x - p1.x;
+ var dy = p2.y - p1.y;
+
+ return dx*dx + dy*dy;
+};
+
+// from http://en.wikipedia.org/wiki/Bézier_curve#Quadratic_curves
+math.qbezierAt = function(p0, p1, p2, t){
+ return (1 - t)*(1 - t)*p0 + 2*(1 - t)*t*p1 + t*t*p2;
+};
+
+math.qbezierPtAt = function(p0, p1, p2, t){
+ return {
+ x: math.qbezierAt( p0.x, p1.x, p2.x, t ),
+ y: math.qbezierAt( p0.y, p1.y, p2.y, t )
+ };
+};
+
+// makes a full bb (x1, y1, x2, y2, w, h) from implicit params
+math.makeBoundingBox = function( bb ){
+ if( bb.x1 != null && bb.y1 != null ){
+ if( bb.x2 != null && bb.y2 != null && bb.x2 >= bb.x1 && bb.y2 >= bb.y1 ){
+ return {
+ x1: bb.x1,
+ y1: bb.y1,
+ x2: bb.x2,
+ y2: bb.y2,
+ w: bb.x2 - bb.x1,
+ h: bb.y2 - bb.y1
+ };
+ } else if( bb.w != null && bb.h != null && bb.w >= 0 && bb.h >= 0 ){
+ return {
+ x1: bb.x1,
+ y1: bb.y1,
+ x2: bb.x1 + bb.w,
+ y2: bb.y1 + bb.h,
+ w: bb.w,
+ h: bb.h
+ };
+ }
+ }
+};
+
+math.boundingBoxesIntersect = function( bb1, bb2 ){
+ // case: one bb to right of other
+ if( bb1.x1 > bb2.x2 ){ return false; }
+ if( bb2.x1 > bb1.x2 ){ return false; }
+
+ // case: one bb to left of other
+ if( bb1.x2 < bb2.x1 ){ return false; }
+ if( bb2.x2 < bb1.x1 ){ return false; }
+
+ // case: one bb above other
+ if( bb1.y2 < bb2.y1 ){ return false; }
+ if( bb2.y2 < bb1.y1 ){ return false; }
+
+ // case: one bb below other
+ if( bb1.y1 > bb2.y2 ){ return false; }
+ if( bb2.y1 > bb1.y2 ){ return false; }
+
+ // otherwise, must have some overlap
+ return true;
+};
+
+math.inBoundingBox = function( bb, x, y ){
+ return bb.x1 <= x && x <= bb.x2 && bb.y1 <= y && y <= bb.y2;
+};
+
+math.pointInBoundingBox = function( bb, pt ){
+ return this.inBoundingBox( bb, pt.x, pt.y );
+};
+
+math.roundRectangleIntersectLine = function(
+ x, y, nodeX, nodeY, width, height, padding) {
+
+ var cornerRadius = this.getRoundRectangleRadius(width, height);
+
+ var halfWidth = width / 2;
+ var halfHeight = height / 2;
+
+ // Check intersections with straight line segments
+ var straightLineIntersections;
+
+ // Top segment, left to right
+ {
+ var topStartX = nodeX - halfWidth + cornerRadius - padding;
+ var topStartY = nodeY - halfHeight - padding;
+ var topEndX = nodeX + halfWidth - cornerRadius + padding;
+ var topEndY = topStartY;
+
+ straightLineIntersections = this.finiteLinesIntersect(
+ x, y, nodeX, nodeY, topStartX, topStartY, topEndX, topEndY, false);
+
+ if (straightLineIntersections.length > 0) {
+ return straightLineIntersections;
+ }
+ }
+
+ // Right segment, top to bottom
+ {
+ var rightStartX = nodeX + halfWidth + padding;
+ var rightStartY = nodeY - halfHeight + cornerRadius - padding;
+ var rightEndX = rightStartX;
+ var rightEndY = nodeY + halfHeight - cornerRadius + padding;
+
+ straightLineIntersections = this.finiteLinesIntersect(
+ x, y, nodeX, nodeY, rightStartX, rightStartY, rightEndX, rightEndY, false);
+
+ if (straightLineIntersections.length > 0) {
+ return straightLineIntersections;
+ }
+ }
+
+ // Bottom segment, left to right
+ {
+ var bottomStartX = nodeX - halfWidth + cornerRadius - padding;
+ var bottomStartY = nodeY + halfHeight + padding;
+ var bottomEndX = nodeX + halfWidth - cornerRadius + padding;
+ var bottomEndY = bottomStartY;
+
+ straightLineIntersections = this.finiteLinesIntersect(
+ x, y, nodeX, nodeY, bottomStartX, bottomStartY, bottomEndX, bottomEndY, false);
+
+ if (straightLineIntersections.length > 0) {
+ return straightLineIntersections;
+ }
+ }
+
+ // Left segment, top to bottom
+ {
+ var leftStartX = nodeX - halfWidth - padding;
+ var leftStartY = nodeY - halfHeight + cornerRadius - padding;
+ var leftEndX = leftStartX;
+ var leftEndY = nodeY + halfHeight - cornerRadius + padding;
+
+ straightLineIntersections = this.finiteLinesIntersect(
+ x, y, nodeX, nodeY, leftStartX, leftStartY, leftEndX, leftEndY, false);
+
+ if (straightLineIntersections.length > 0) {
+ return straightLineIntersections;
+ }
+ }
+
+ // Check intersections with arc segments
+ var arcIntersections;
+
+ // Top Left
+ {
+ var topLeftCenterX = nodeX - halfWidth + cornerRadius;
+ var topLeftCenterY = nodeY - halfHeight + cornerRadius;
+ arcIntersections = this.intersectLineCircle(
+ x, y, nodeX, nodeY,
+ topLeftCenterX, topLeftCenterY, cornerRadius + padding);
+
+ // Ensure the intersection is on the desired quarter of the circle
+ if (arcIntersections.length > 0
+ && arcIntersections[0] <= topLeftCenterX
+ && arcIntersections[1] <= topLeftCenterY) {
+ return [arcIntersections[0], arcIntersections[1]];
+ }
+ }
+
+ // Top Right
+ {
+ var topRightCenterX = nodeX + halfWidth - cornerRadius;
+ var topRightCenterY = nodeY - halfHeight + cornerRadius;
+ arcIntersections = this.intersectLineCircle(
+ x, y, nodeX, nodeY,
+ topRightCenterX, topRightCenterY, cornerRadius + padding);
+
+ // Ensure the intersection is on the desired quarter of the circle
+ if (arcIntersections.length > 0
+ && arcIntersections[0] >= topRightCenterX
+ && arcIntersections[1] <= topRightCenterY) {
+ return [arcIntersections[0], arcIntersections[1]];
+ }
+ }
+
+ // Bottom Right
+ {
+ var bottomRightCenterX = nodeX + halfWidth - cornerRadius;
+ var bottomRightCenterY = nodeY + halfHeight - cornerRadius;
+ arcIntersections = this.intersectLineCircle(
+ x, y, nodeX, nodeY,
+ bottomRightCenterX, bottomRightCenterY, cornerRadius + padding);
+
+ // Ensure the intersection is on the desired quarter of the circle
+ if (arcIntersections.length > 0
+ && arcIntersections[0] >= bottomRightCenterX
+ && arcIntersections[1] >= bottomRightCenterY) {
+ return [arcIntersections[0], arcIntersections[1]];
+ }
+ }
+
+ // Bottom Left
+ {
+ var bottomLeftCenterX = nodeX - halfWidth + cornerRadius;
+ var bottomLeftCenterY = nodeY + halfHeight - cornerRadius;
+ arcIntersections = this.intersectLineCircle(
+ x, y, nodeX, nodeY,
+ bottomLeftCenterX, bottomLeftCenterY, cornerRadius + padding);
+
+ // Ensure the intersection is on the desired quarter of the circle
+ if (arcIntersections.length > 0
+ && arcIntersections[0] <= bottomLeftCenterX
+ && arcIntersections[1] >= bottomLeftCenterY) {
+ return [arcIntersections[0], arcIntersections[1]];
+ }
+ }
+
+ return []; // if nothing
+};
+
+math.inLineVicinity = function(x, y, lx1, ly1, lx2, ly2, tolerance){
+ var t = tolerance;
+
+ var x1 = Math.min(lx1, lx2);
+ var x2 = Math.max(lx1, lx2);
+ var y1 = Math.min(ly1, ly2);
+ var y2 = Math.max(ly1, ly2);
+
+ return x1 - t <= x && x <= x2 + t
+ && y1 - t <= y && y <= y2 + t;
+};
+
+math.inBezierVicinity = function(
+ x, y, x1, y1, x2, y2, x3, y3, tolerance) {
+
+ var bb = {
+ x1: Math.min( x1, x3, x2 ) - tolerance,
+ x2: Math.max( x1, x3, x2 ) + tolerance,
+ y1: Math.min( y1, y3, y2 ) - tolerance,
+ y2: Math.max( y1, y3, y2 ) + tolerance
+ };
+
+ // if outside the rough bounding box for the bezier, then it can't be a hit
+ if( x < bb.x1 || x > bb.x2 || y < bb.y1 || y > bb.y2 ){
+ // console.log('bezier out of rough bb')
+ return false;
+ } else {
+ // console.log('do more expensive check');
+ return true;
+ }
+
+};
+
+math.solveCubic = function(a, b, c, d, result) {
+
+ // Solves a cubic function, returns root in form [r1, i1, r2, i2, r3, i3], where
+ // r is the real component, i is the imaginary component
+
+ // An implementation of the Cardano method from the year 1545
+ // http://en.wikipedia.org/wiki/Cubic_function#The_nature_of_the_roots
+
+ b /= a;
+ c /= a;
+ d /= a;
+
+ var discriminant, q, r, dum1, s, t, term1, r13;
+
+ q = (3.0 * c - (b * b)) / 9.0;
+ r = -(27.0 * d) + b * (9.0 * c - 2.0 * (b * b));
+ r /= 54.0;
+
+ discriminant = q * q * q + r * r;
+ result[1] = 0;
+ term1 = (b / 3.0);
+
+ if (discriminant > 0) {
+ s = r + Math.sqrt(discriminant);
+ s = ((s < 0) ? -Math.pow(-s, (1.0 / 3.0)) : Math.pow(s, (1.0 / 3.0)));
+ t = r - Math.sqrt(discriminant);
+ t = ((t < 0) ? -Math.pow(-t, (1.0 / 3.0)) : Math.pow(t, (1.0 / 3.0)));
+ result[0] = -term1 + s + t;
+ term1 += (s + t) / 2.0;
+ result[4] = result[2] = -term1;
+ term1 = Math.sqrt(3.0) * (-t + s) / 2;
+ result[3] = term1;
+ result[5] = -term1;
+ return;
+ }
+
+ result[5] = result[3] = 0;
+
+ if (discriminant === 0) {
+ r13 = ((r < 0) ? -Math.pow(-r, (1.0 / 3.0)) : Math.pow(r, (1.0 / 3.0)));
+ result[0] = -term1 + 2.0 * r13;
+ result[4] = result[2] = -(r13 + term1);
+ return;
+ }
+
+ q = -q;
+ dum1 = q * q * q;
+ dum1 = Math.acos(r / Math.sqrt(dum1));
+ r13 = 2.0 * Math.sqrt(q);
+ result[0] = -term1 + r13 * Math.cos(dum1 / 3.0);
+ result[2] = -term1 + r13 * Math.cos((dum1 + 2.0 * Math.PI) / 3.0);
+ result[4] = -term1 + r13 * Math.cos((dum1 + 4.0 * Math.PI) / 3.0);
+
+ return;
+};
+
+math.sqDistanceToQuadraticBezier = function(
+ x, y, x1, y1, x2, y2, x3, y3) {
+
+ // Find minimum distance by using the minimum of the distance
+ // function between the given point and the curve
+
+ // This gives the coefficients of the resulting cubic equation
+ // whose roots tell us where a possible minimum is
+ // (Coefficients are divided by 4)
+
+ var a = 1.0 * x1*x1 - 4*x1*x2 + 2*x1*x3 + 4*x2*x2 - 4*x2*x3 + x3*x3
+ + y1*y1 - 4*y1*y2 + 2*y1*y3 + 4*y2*y2 - 4*y2*y3 + y3*y3;
+
+ var b = 1.0 * 9*x1*x2 - 3*x1*x1 - 3*x1*x3 - 6*x2*x2 + 3*x2*x3
+ + 9*y1*y2 - 3*y1*y1 - 3*y1*y3 - 6*y2*y2 + 3*y2*y3;
+
+ var c = 1.0 * 3*x1*x1 - 6*x1*x2 + x1*x3 - x1*x + 2*x2*x2 + 2*x2*x - x3*x
+ + 3*y1*y1 - 6*y1*y2 + y1*y3 - y1*y + 2*y2*y2 + 2*y2*y - y3*y;
+
+ var d = 1.0 * x1*x2 - x1*x1 + x1*x - x2*x
+ + y1*y2 - y1*y1 + y1*y - y2*y;
+
+ // debug("coefficients: " + a / a + ", " + b / a + ", " + c / a + ", " + d / a);
+
+ var roots = [];
+
+ // Use the cubic solving algorithm
+ this.solveCubic(a, b, c, d, roots);
+
+ var zeroThreshold = 0.0000001;
+
+ var params = [];
+
+ for (var index = 0; index < 6; index += 2) {
+ if (Math.abs(roots[index + 1]) < zeroThreshold
+ && roots[index] >= 0
+ && roots[index] <= 1.0) {
+ params.push(roots[index]);
+ }
+ }
+
+ params.push(1.0);
+ params.push(0.0);
+
+ var minDistanceSquared = -1;
+ var closestParam;
+
+ var curX, curY, distSquared;
+ for (var i = 0; i < params.length; i++) {
+ curX = Math.pow(1.0 - params[i], 2.0) * x1
+ + 2.0 * (1 - params[i]) * params[i] * x2
+ + params[i] * params[i] * x3;
+
+ curY = Math.pow(1 - params[i], 2.0) * y1
+ + 2 * (1.0 - params[i]) * params[i] * y2
+ + params[i] * params[i] * y3;
+
+ distSquared = Math.pow(curX - x, 2) + Math.pow(curY - y, 2);
+ // debug('distance for param ' + params[i] + ": " + Math.sqrt(distSquared));
+ if (minDistanceSquared >= 0) {
+ if (distSquared < minDistanceSquared) {
+ minDistanceSquared = distSquared;
+ closestParam = params[i];
+ }
+ } else {
+ minDistanceSquared = distSquared;
+ closestParam = params[i];
+ }
+ }
+
+ return minDistanceSquared;
+};
+
+math.sqDistanceToFiniteLine = function(x, y, x1, y1, x2, y2) {
+ var offset = [x - x1, y - y1];
+ var line = [x2 - x1, y2 - y1];
+
+ var lineSq = line[0] * line[0] + line[1] * line[1];
+ var hypSq = offset[0] * offset[0] + offset[1] * offset[1];
+
+ var dotProduct = offset[0] * line[0] + offset[1] * line[1];
+ var adjSq = dotProduct * dotProduct / lineSq;
+
+ if (dotProduct < 0) {
+ return hypSq;
+ }
+
+ if (adjSq > lineSq) {
+ return (x - x2) * (x - x2) + (y - y2) * (y - y2);
+ }
+
+ return hypSq - adjSq;
+};
+
+math.pointInsidePolygonPoints = function(x, y, points){
+ var x1, y1, x2, y2;
+ var y3;
+
+ // Intersect with vertical line through (x, y)
+ var up = 0;
+ var down = 0;
+ for (var i = 0; i < points.length / 2; i++) {
+
+ x1 = points[i * 2];
+ y1 = points[i * 2 + 1];
+
+ if (i + 1 < points.length / 2) {
+ x2 = points[(i + 1) * 2];
+ y2 = points[(i + 1) * 2 + 1];
+ } else {
+ x2 = points[(i + 1 - points.length / 2) * 2];
+ y2 = points[(i + 1 - points.length / 2) * 2 + 1];
+ }
+
+ if (x1 == x && x2 == x) {
+
+ } else if ((x1 >= x && x >= x2)
+ || (x1 <= x && x <= x2)) {
+
+ y3 = (x - x1) / (x2 - x1) * (y2 - y1) + y1;
+
+ if (y3 > y) {
+ up++;
+ }
+
+ if (y3 < y) {
+ down++;
+ }
+
+ } else {
+ continue;
+ }
+
+ }
+
+ if (up % 2 === 0) {
+ return false;
+ } else {
+ return true;
+ }
+};
+
+math.pointInsidePolygon = function(
+ x, y, basePoints, centerX, centerY, width, height, direction, padding) {
+
+ //var direction = arguments[6];
+ var transformedPoints = new Array(basePoints.length);
+
+ // Gives negative angle
+ var angle;
+
+ if( direction[0] != null ){
+ angle = Math.atan(direction[1] / direction[0]);
+
+ if (direction[0] < 0) {
+ angle = angle + Math.PI / 2;
+ } else {
+ angle = -angle - Math.PI / 2;
+ }
+ } else {
+ angle = direction;
+ }
+
+ var cos = Math.cos(-angle);
+ var sin = Math.sin(-angle);
+
+ // console.log("base: " + basePoints);
+ for (var i = 0; i < transformedPoints.length / 2; i++) {
+ transformedPoints[i * 2] =
+ width / 2 * (basePoints[i * 2] * cos
+ - basePoints[i * 2 + 1] * sin);
+
+ transformedPoints[i * 2 + 1] =
+ height / 2 * (basePoints[i * 2 + 1] * cos
+ + basePoints[i * 2] * sin);
+
+ transformedPoints[i * 2] += centerX;
+ transformedPoints[i * 2 + 1] += centerY;
+ }
+
+ var points;
+
+ if (padding > 0) {
+ var expandedLineSet = this.expandPolygon(
+ transformedPoints,
+ -padding);
+
+ points = this.joinLines(expandedLineSet);
+ } else {
+ points = transformedPoints;
+ }
+
+ return math.pointInsidePolygonPoints( x, y, points );
+};
+
+math.joinLines = function(lineSet) {
+
+ var vertices = new Array(lineSet.length / 2);
+
+ var currentLineStartX, currentLineStartY, currentLineEndX, currentLineEndY;
+ var nextLineStartX, nextLineStartY, nextLineEndX, nextLineEndY;
+
+ for (var i = 0; i < lineSet.length / 4; i++) {
+ currentLineStartX = lineSet[i * 4];
+ currentLineStartY = lineSet[i * 4 + 1];
+ currentLineEndX = lineSet[i * 4 + 2];
+ currentLineEndY = lineSet[i * 4 + 3];
+
+ if (i < lineSet.length / 4 - 1) {
+ nextLineStartX = lineSet[(i + 1) * 4];
+ nextLineStartY = lineSet[(i + 1) * 4 + 1];
+ nextLineEndX = lineSet[(i + 1) * 4 + 2];
+ nextLineEndY = lineSet[(i + 1) * 4 + 3];
+ } else {
+ nextLineStartX = lineSet[0];
+ nextLineStartY = lineSet[1];
+ nextLineEndX = lineSet[2];
+ nextLineEndY = lineSet[3];
+ }
+
+ var intersection = this.finiteLinesIntersect(
+ currentLineStartX, currentLineStartY,
+ currentLineEndX, currentLineEndY,
+ nextLineStartX, nextLineStartY,
+ nextLineEndX, nextLineEndY,
+ true);
+
+ vertices[i * 2] = intersection[0];
+ vertices[i * 2 + 1] = intersection[1];
+ }
+
+ return vertices;
+};
+
+math.expandPolygon = function(points, pad) {
+
+ var expandedLineSet = new Array(points.length * 2);
+
+ var currentPointX, currentPointY, nextPointX, nextPointY;
+
+ for (var i = 0; i < points.length / 2; i++) {
+ currentPointX = points[i * 2];
+ currentPointY = points[i * 2 + 1];
+
+ if (i < points.length / 2 - 1) {
+ nextPointX = points[(i + 1) * 2];
+ nextPointY = points[(i + 1) * 2 + 1];
+ } else {
+ nextPointX = points[0];
+ nextPointY = points[1];
+ }
+
+ // Current line: [currentPointX, currentPointY] to [nextPointX, nextPointY]
+
+ // Assume CCW polygon winding
+
+ var offsetX = (nextPointY - currentPointY);
+ var offsetY = -(nextPointX - currentPointX);
+
+ // Normalize
+ var offsetLength = Math.sqrt(offsetX * offsetX + offsetY * offsetY);
+ var normalizedOffsetX = offsetX / offsetLength;
+ var normalizedOffsetY = offsetY / offsetLength;
+
+ expandedLineSet[i * 4] = currentPointX + normalizedOffsetX * pad;
+ expandedLineSet[i * 4 + 1] = currentPointY + normalizedOffsetY * pad;
+ expandedLineSet[i * 4 + 2] = nextPointX + normalizedOffsetX * pad;
+ expandedLineSet[i * 4 + 3] = nextPointY + normalizedOffsetY * pad;
+ }
+
+ return expandedLineSet;
+};
+
+math.intersectLineEllipse = function(
+ x, y, centerX, centerY, ellipseWradius, ellipseHradius) {
+
+ var dispX = centerX - x;
+ var dispY = centerY - y;
+
+ dispX /= ellipseWradius;
+ dispY /= ellipseHradius;
+
+ var len = Math.sqrt(dispX * dispX + dispY * dispY);
+
+ var newLength = len - 1;
+
+ if (newLength < 0) {
+ return [];
+ }
+
+ var lenProportion = newLength / len;
+
+ return [(centerX - x) * lenProportion + x, (centerY - y) * lenProportion + y];
+};
+
+// Returns intersections of increasing distance from line's start point
+math.intersectLineCircle = function(
+ x1, y1, x2, y2, centerX, centerY, radius) {
+
+ // Calculate d, direction vector of line
+ var d = [x2 - x1, y2 - y1]; // Direction vector of line
+ var c = [centerX, centerY]; // Center of circle
+ var f = [x1 - centerX, y1 - centerY];
+
+ var a = d[0] * d[0] + d[1] * d[1];
+ var b = 2 * (f[0] * d[0] + f[1] * d[1]);
+ var c = (f[0] * f[0] + f[1] * f[1]) - radius * radius ;
+
+ var discriminant = b*b-4*a*c;
+
+ if (discriminant < 0) {
+ return [];
+ }
+
+ var t1 = (-b + Math.sqrt(discriminant)) / (2 * a);
+ var t2 = (-b - Math.sqrt(discriminant)) / (2 * a);
+
+ var tMin = Math.min(t1, t2);
+ var tMax = Math.max(t1, t2);
+ var inRangeParams = [];
+
+ if (tMin >= 0 && tMin <= 1) {
+ inRangeParams.push(tMin);
+ }
+
+ if (tMax >= 0 && tMax <= 1) {
+ inRangeParams.push(tMax);
+ }
+
+ if (inRangeParams.length === 0) {
+ return [];
+ }
+
+ var nearIntersectionX = inRangeParams[0] * d[0] + x1;
+ var nearIntersectionY = inRangeParams[0] * d[1] + y1;
+
+ if (inRangeParams.length > 1) {
+
+ if (inRangeParams[0] == inRangeParams[1]) {
+ return [nearIntersectionX, nearIntersectionY];
+ } else {
+
+ var farIntersectionX = inRangeParams[1] * d[0] + x1;
+ var farIntersectionY = inRangeParams[1] * d[1] + y1;
+
+ return [nearIntersectionX, nearIntersectionY, farIntersectionX, farIntersectionY];
+ }
+
+ } else {
+ return [nearIntersectionX, nearIntersectionY];
+ }
+
+};
+
+math.findCircleNearPoint = function(centerX, centerY,
+ radius, farX, farY) {
+
+ var displacementX = farX - centerX;
+ var displacementY = farY - centerY;
+ var distance = Math.sqrt(displacementX * displacementX
+ + displacementY * displacementY);
+
+ var unitDisplacementX = displacementX / distance;
+ var unitDisplacementY = displacementY / distance;
+
+ return [centerX + unitDisplacementX * radius,
+ centerY + unitDisplacementY * radius];
+};
+
+math.findMaxSqDistanceToOrigin = function(points) {
+ var maxSqDistance = 0.000001;
+ var sqDistance;
+
+ for (var i = 0; i < points.length / 2; i++) {
+
+ sqDistance = points[i * 2] * points[i * 2]
+ + points[i * 2 + 1] * points[i * 2 + 1];
+
+ if (sqDistance > maxSqDistance) {
+ maxSqDistance = sqDistance;
+ }
+ }
+
+ return maxSqDistance;
+};
+
+math.finiteLinesIntersect = function(
+ x1, y1, x2, y2, x3, y3, x4, y4, infiniteLines) {
+
+ var ua_t = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
+ var ub_t = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);
+ var u_b = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
+
+ if (u_b !== 0) {
+ var ua = ua_t / u_b;
+ var ub = ub_t / u_b;
+
+ if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
+ return [x1 + ua * (x2 - x1), y1 + ua * (y2 - y1)];
+
+ } else {
+ if (!infiniteLines) {
+ return [];
+ } else {
+ return [x1 + ua * (x2 - x1), y1 + ua * (y2 - y1)];
+ }
+ }
+ } else {
+ if (ua_t === 0 || ub_t === 0) {
+
+ // Parallel, coincident lines. Check if overlap
+
+ // Check endpoint of second line
+ if ([x1, x2, x4].sort()[1] === x4) {
+ return [x4, y4];
+ }
+
+ // Check start point of second line
+ if ([x1, x2, x3].sort()[1] === x3) {
+ return [x3, y3];
+ }
+
+ // Endpoint of first line
+ if ([x3, x4, x2].sort()[1] === x2) {
+ return [x2, y2];
+ }
+
+ return [];
+ } else {
+
+ // Parallel, non-coincident
+ return [];
+ }
+ }
+};
+
+math.polygonIntersectLine = function(
+ x, y, basePoints, centerX, centerY, width, height, padding) {
+
+ var intersections = [];
+ var intersection;
+
+ var transformedPoints = new Array(basePoints.length);
+
+ for (var i = 0; i < transformedPoints.length / 2; i++) {
+ transformedPoints[i * 2] = basePoints[i * 2] * width + centerX;
+ transformedPoints[i * 2 + 1] = basePoints[i * 2 + 1] * height + centerY;
+ }
+
+ var points;
+
+ if (padding > 0) {
+ var expandedLineSet = math.expandPolygon(
+ transformedPoints,
+ -padding);
+
+ points = math.joinLines(expandedLineSet);
+ } else {
+ points = transformedPoints;
+ }
+ // var points = transformedPoints;
+
+ var currentX, currentY, nextX, nextY;
+
+ for (var i = 0; i < points.length / 2; i++) {
+
+ currentX = points[i * 2];
+ currentY = points[i * 2 + 1];
+
+ if (i < points.length / 2 - 1) {
+ nextX = points[(i + 1) * 2];
+ nextY = points[(i + 1) * 2 + 1];
+ } else {
+ nextX = points[0];
+ nextY = points[1];
+ }
+
+ intersection = this.finiteLinesIntersect(
+ x, y, centerX, centerY,
+ currentX, currentY,
+ nextX, nextY);
+
+ if (intersection.length !== 0) {
+ intersections.push(intersection[0], intersection[1]);
+ }
+ }
+
+ return intersections;
+};
+
+math.shortenIntersection = function(
+ intersection, offset, amount) {
+
+ var disp = [intersection[0] - offset[0], intersection[1] - offset[1]];
+
+ var length = Math.sqrt(disp[0] * disp[0] + disp[1] * disp[1]);
+
+ var lenRatio = (length - amount) / length;
+
+ if (lenRatio < 0) {
+ lenRatio = 0.00001;
+ }
+
+ return [offset[0] + lenRatio * disp[0], offset[1] + lenRatio * disp[1]];
+};
+
+math.generateUnitNgonPointsFitToSquare = function(sides, rotationRadians) {
+ var points = math.generateUnitNgonPoints(sides, rotationRadians);
+ points = math.fitPolygonToSquare(points);
+
+ return points;
+};
+
+math.fitPolygonToSquare = function(points){
+ var x, y;
+ var sides = points.length/2;
+ var minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
+
+ for (var i = 0; i < sides; i++) {
+ x = points[2 * i];
+ y = points[2 * i + 1];
+
+ minX = Math.min( minX, x );
+ maxX = Math.max( maxX, x );
+ minY = Math.min( minY, y );
+ maxY = Math.max( maxY, y );
+ }
+
+ // stretch factors
+ var sx = 2 / (maxX - minX);
+ var sy = 2 / (maxY - minY);
+
+ for (var i = 0; i < sides; i++){
+ x = points[2 * i] = points[2 * i] * sx;
+ y = points[2 * i + 1] = points[2 * i + 1] * sy;
+
+ minX = Math.min( minX, x );
+ maxX = Math.max( maxX, x );
+ minY = Math.min( minY, y );
+ maxY = Math.max( maxY, y );
+ }
+
+ if( minY < -1 ){
+ for (var i = 0; i < sides; i++){
+ y = points[2 * i + 1] = points[2 * i + 1] + (-1 -minY);
+ }
+ }
+
+ return points;
+};
+
+math.generateUnitNgonPoints = function(sides, rotationRadians) {
+
+ var increment = 1.0 / sides * 2 * Math.PI;
+ var startAngle = sides % 2 === 0 ?
+ Math.PI / 2.0 + increment / 2.0 : Math.PI / 2.0;
+ // console.log(nodeShapes['square']);
+ startAngle += rotationRadians;
+
+ var points = new Array(sides * 2);
+
+ var currentAngle, x, y;
+ for (var i = 0; i < sides; i++) {
+ currentAngle = i * increment + startAngle;
+
+ x = points[2 * i] = Math.cos(currentAngle);// * (1 + i/2);
+ y = points[2 * i + 1] = Math.sin(-currentAngle);// * (1 + i/2);
+ }
+
+ return points;
+};
+
+math.getRoundRectangleRadius = function(width, height) {
+
+ // Set the default radius, unless half of width or height is smaller than default
+ return Math.min(width / 4, height / 4, 8);
+};
+
+module.exports = math;
+
+},{}],80:[function(_dereq_,module,exports){
+// internal, minimal Promise impl s.t. apis can return promises in old envs
+// based on thenable (http://github.com/rse/thenable)
+
+'use strict';
+
+/* promise states [Promises/A+ 2.1] */
+var STATE_PENDING = 0; /* [Promises/A+ 2.1.1] */
+var STATE_FULFILLED = 1; /* [Promises/A+ 2.1.2] */
+var STATE_REJECTED = 2; /* [Promises/A+ 2.1.3] */
+
+/* promise object constructor */
+var api = function (executor) {
+ /* optionally support non-constructor/plain-function call */
+ if (!(this instanceof api))
+ return new api(executor);
+
+ /* initialize object */
+ this.id = "Thenable/1.0.7";
+ this.state = STATE_PENDING; /* initial state */
+ this.fulfillValue = undefined; /* initial value */ /* [Promises/A+ 1.3, 2.1.2.2] */
+ this.rejectReason = undefined; /* initial reason */ /* [Promises/A+ 1.5, 2.1.3.2] */
+ this.onFulfilled = []; /* initial handlers */
+ this.onRejected = []; /* initial handlers */
+
+ /* provide optional information-hiding proxy */
+ this.proxy = {
+ then: this.then.bind(this)
+ };
+
+ /* support optional executor function */
+ if (typeof executor === "function")
+ executor.call(this, this.fulfill.bind(this), this.reject.bind(this));
+};
+
+/* promise API methods */
+api.prototype = {
+ /* promise resolving methods */
+ fulfill: function (value) { return deliver(this, STATE_FULFILLED, "fulfillValue", value); },
+ reject: function (value) { return deliver(this, STATE_REJECTED, "rejectReason", value); },
+
+ /* "The then Method" [Promises/A+ 1.1, 1.2, 2.2] */
+ then: function (onFulfilled, onRejected) {
+ var curr = this;
+ var next = new api(); /* [Promises/A+ 2.2.7] */
+ curr.onFulfilled.push(
+ resolver(onFulfilled, next, "fulfill")); /* [Promises/A+ 2.2.2/2.2.6] */
+ curr.onRejected.push(
+ resolver(onRejected, next, "reject" )); /* [Promises/A+ 2.2.3/2.2.6] */
+ execute(curr);
+ return next.proxy; /* [Promises/A+ 2.2.7, 3.3] */
+ }
+};
+
+/* deliver an action */
+var deliver = function (curr, state, name, value) {
+ if (curr.state === STATE_PENDING) {
+ curr.state = state; /* [Promises/A+ 2.1.2.1, 2.1.3.1] */
+ curr[name] = value; /* [Promises/A+ 2.1.2.2, 2.1.3.2] */
+ execute(curr);
+ }
+ return curr;
+};
+
+/* execute all handlers */
+var execute = function (curr) {
+ if (curr.state === STATE_FULFILLED)
+ execute_handlers(curr, "onFulfilled", curr.fulfillValue);
+ else if (curr.state === STATE_REJECTED)
+ execute_handlers(curr, "onRejected", curr.rejectReason);
+};
+
+/* execute particular set of handlers */
+var execute_handlers = function (curr, name, value) {
+ /* global setImmediate: true */
+ /* global setTimeout: true */
+
+ /* short-circuit processing */
+ if (curr[name].length === 0)
+ return;
+
+ /* iterate over all handlers, exactly once */
+ var handlers = curr[name];
+ curr[name] = []; /* [Promises/A+ 2.2.2.3, 2.2.3.3] */
+ var func = function () {
+ for (var i = 0; i < handlers.length; i++)
+ handlers[i](value); /* [Promises/A+ 2.2.5] */
+ };
+
+ /* execute procedure asynchronously */ /* [Promises/A+ 2.2.4, 3.1] */
+ if (typeof setImmediate === "function")
+ setImmediate(func);
+ else
+ setTimeout(func, 0);
+};
+
+/* generate a resolver function */
+var resolver = function (cb, next, method) {
+ return function (value) {
+ if (typeof cb !== "function") /* [Promises/A+ 2.2.1, 2.2.7.3, 2.2.7.4] */
+ next[method].call(next, value); /* [Promises/A+ 2.2.7.3, 2.2.7.4] */
+ else {
+ var result;
+ try { result = cb(value); } /* [Promises/A+ 2.2.2.1, 2.2.3.1, 2.2.5, 3.2] */
+ catch (e) {
+ next.reject(e); /* [Promises/A+ 2.2.7.2] */
+ return;
+ }
+ resolve(next, result); /* [Promises/A+ 2.2.7.1] */
+ }
+ };
+};
+
+/* "Promise Resolution Procedure" */ /* [Promises/A+ 2.3] */
+var resolve = function (promise, x) {
+ /* sanity check arguments */ /* [Promises/A+ 2.3.1] */
+ if (promise === x || promise.proxy === x) {
+ promise.reject(new TypeError("cannot resolve promise with itself"));
+ return;
+ }
+
+ /* surgically check for a "then" method
+ (mainly to just call the "getter" of "then" only once) */
+ var then;
+ if ((typeof x === "object" && x !== null) || typeof x === "function") {
+ try { then = x.then; } /* [Promises/A+ 2.3.3.1, 3.5] */
+ catch (e) {
+ promise.reject(e); /* [Promises/A+ 2.3.3.2] */
+ return;
+ }
+ }
+
+ /* handle own Thenables [Promises/A+ 2.3.2]
+ and similar "thenables" [Promises/A+ 2.3.3] */
+ if (typeof then === "function") {
+ var resolved = false;
+ try {
+ /* call retrieved "then" method */ /* [Promises/A+ 2.3.3.3] */
+ then.call(x,
+ /* resolvePromise */ /* [Promises/A+ 2.3.3.3.1] */
+ function (y) {
+ if (resolved) return; resolved = true; /* [Promises/A+ 2.3.3.3.3] */
+ if (y === x) /* [Promises/A+ 3.6] */
+ promise.reject(new TypeError("circular thenable chain"));
+ else
+ resolve(promise, y);
+ },
+
+ /* rejectPromise */ /* [Promises/A+ 2.3.3.3.2] */
+ function (r) {
+ if (resolved) return; resolved = true; /* [Promises/A+ 2.3.3.3.3] */
+ promise.reject(r);
+ }
+ );
+ }
+ catch (e) {
+ if (!resolved) /* [Promises/A+ 2.3.3.3.3] */
+ promise.reject(e); /* [Promises/A+ 2.3.3.3.4] */
+ }
+ return;
+ }
+
+ /* handle other values */
+ promise.fulfill(x); /* [Promises/A+ 2.3.4, 2.3.3.4] */
+};
+
+// use native promises where possible
+var Promise = typeof Promise === 'undefined' ? api : Promise;
+
+// so we always have Promise.all()
+Promise.all = Promise.all || function( ps ){
+ return new Promise(function( resolveAll, rejectAll ){
+ var vals = new Array( ps.length );
+ var doneCount = 0;
+
+ var fulfill = function( i, val ){
+ vals[i] = val;
+ doneCount++;
+
+ if( doneCount === ps.length ){
+ resolveAll( vals );
+ }
+ };
+
+ for( var i = 0; i < ps.length; i++ ){
+ (function( i ){
+ var p = ps[i];
+ var isPromise = p.then != null;
+
+ if( isPromise ){
+ p.then(function( val ){
+ fulfill( i, val );
+ }, function( err ){
+ rejectAll( err );
+ });
+ } else {
+ var val = p;
+ fulfill( i, val );
+ }
+ })( i );
+ }
+
+ });
+};
+
+module.exports = Promise;
+
+},{}],81:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('./is');
+var util = _dereq_('./util');
+
+var Selector = function( onlyThisGroup, selector ){
+
+ if( !(this instanceof Selector) ){
+ return new Selector(onlyThisGroup, selector);
+ }
+
+ if( selector === undefined && onlyThisGroup !== undefined ){
+ selector = onlyThisGroup;
+ onlyThisGroup = undefined;
+ }
+
+ var self = this;
+
+ self._private = {
+ selectorText: null,
+ invalid: true
+ };
+
+ if( !selector || ( is.string(selector) && selector.match(/^\s*$/) ) ){
+
+ if( onlyThisGroup == null ){
+ // ignore
+ self.length = 0;
+ } else {
+ self[0] = newQuery();
+ self[0].group = onlyThisGroup;
+ self.length = 1;
+ }
+
+ } else if( is.elementOrCollection( selector ) ){
+ var collection = selector.collection();
+
+ self[0] = newQuery();
+ self[0].collection = collection;
+ self.length = 1;
+
+ } else if( is.fn( selector ) ) {
+ self[0] = newQuery();
+ self[0].filter = selector;
+ self.length = 1;
+
+ } else if( is.string( selector ) ){
+
+ // the current subject in the query
+ var currentSubject = null;
+
+ // storage for parsed queries
+ var newQuery = function(){
+ return {
+ classes: [],
+ colonSelectors: [],
+ data: [],
+ group: null,
+ ids: [],
+ meta: [],
+
+ // fake selectors
+ collection: null, // a collection to match against
+ filter: null, // filter function
+
+ // these are defined in the upward direction rather than down (e.g. child)
+ // because we need to go up in Selector.filter()
+ parent: null, // parent query obj
+ ancestor: null, // ancestor query obj
+ subject: null, // defines subject in compound query (subject query obj; points to self if subject)
+
+ // use these only when subject has been defined
+ child: null,
+ descendant: null
+ };
+ };
+
+ // tokens in the query language
+ var tokens = {
+ metaChar: '[\\!\\"\\#\\$\\%\\&\\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]', // chars we need to escape in var names, etc
+ comparatorOp: '=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=', // binary comparison op (used in data selectors)
+ boolOp: '\\?|\\!|\\^', // boolean (unary) operators (used in data selectors)
+ string: '"(?:\\\\"|[^"])+"' + '|' + "'(?:\\\\'|[^'])+'", // string literals (used in data selectors) -- doublequotes | singlequotes
+ number: util.regex.number, // number literal (used in data selectors) --- e.g. 0.1234, 1234, 12e123
+ meta: 'degree|indegree|outdegree', // allowed metadata fields (i.e. allowed functions to use from Collection)
+ separator: '\\s*,\\s*', // queries are separated by commas, e.g. edge[foo = 'bar'], node.someClass
+ descendant: '\\s+',
+ child: '\\s+>\\s+',
+ subject: '\\$'
+ };
+ tokens.variable = '(?:[\\w-]|(?:\\\\'+ tokens.metaChar +'))+'; // a variable name
+ tokens.value = tokens.string + '|' + tokens.number; // a value literal, either a string or number
+ tokens.className = tokens.variable; // a class name (follows variable conventions)
+ tokens.id = tokens.variable; // an element id (follows variable conventions)
+
+ // when a token like a variable has escaped meta characters, we need to clean the backslashes out
+ // so that values get compared properly in Selector.filter()
+ var cleanMetaChars = function(str){
+ return str.replace(new RegExp('\\\\(' + tokens.metaChar + ')', 'g'), function(match, $1, offset, original){
+ return $1;
+ });
+ };
+
+ // add @ variants to comparatorOp
+ var ops = tokens.comparatorOp.split('|');
+ for( var i = 0; i < ops.length; i++ ){
+ var op = ops[i];
+ tokens.comparatorOp += '|@' + op;
+ }
+
+ // add ! variants to comparatorOp
+ var ops = tokens.comparatorOp.split('|');
+ for( var i = 0; i < ops.length; i++ ){
+ var op = ops[i];
+
+ if( op.indexOf('!') >= 0 ){ continue; } // skip ops that explicitly contain !
+ if( op === '=' ){ continue; } // skip = b/c != is explicitly defined
+
+ tokens.comparatorOp += '|\\!' + op;
+ }
+
+ // NOTE: add new expression syntax here to have it recognised by the parser;
+ // - a query contains all adjacent (i.e. no separator in between) expressions;
+ // - the current query is stored in self[i] --- you can use the reference to `this` in the populate function;
+ // - you need to check the query objects in Selector.filter() for it actually filter properly, but that's pretty straight forward
+ // - when you add something here, also add to Selector.toString()
+ var exprs = [
+ {
+ name: 'group',
+ query: true,
+ regex: '(node|edge|\\*)',
+ populate: function( group ){
+ this.group = group == "*" ? group : group + 's';
+ }
+ },
+
+ {
+ name: 'state',
+ query: true,
+ // NB: if one colon selector is a substring of another from its start, place the longer one first
+ // e.g. :foobar|:foo
+ regex: '(:selected|:unselected|:locked|:unlocked|:visible|:hidden|:transparent|:grabbed|:free|:removed|:inside|:grabbable|:ungrabbable|:animated|:unanimated|:selectable|:unselectable|:orphan|:nonorphan|:parent|:child|:loop|:simple|:active|:inactive|:touch|:backgrounding|:nonbackgrounding)',
+ populate: function( state ){
+ this.colonSelectors.push( state );
+ }
+ },
+
+ {
+ name: 'id',
+ query: true,
+ regex: '\\#('+ tokens.id +')',
+ populate: function( id ){
+ this.ids.push( cleanMetaChars(id) );
+ }
+ },
+
+ {
+ name: 'className',
+ query: true,
+ regex: '\\.('+ tokens.className +')',
+ populate: function( className ){
+ this.classes.push( cleanMetaChars(className) );
+ }
+ },
+
+ {
+ name: 'dataExists',
+ query: true,
+ regex: '\\[\\s*('+ tokens.variable +')\\s*\\]',
+ populate: function( variable ){
+ this.data.push({
+ field: cleanMetaChars(variable)
+ });
+ }
+ },
+
+ {
+ name: 'dataCompare',
+ query: true,
+ regex: '\\[\\s*('+ tokens.variable +')\\s*('+ tokens.comparatorOp +')\\s*('+ tokens.value +')\\s*\\]',
+ populate: function( variable, comparatorOp, value ){
+ var valueIsString = new RegExp('^' + tokens.string + '$').exec(value) != null;
+
+ if( valueIsString ){
+ value = value.substring(1, value.length - 1);
+ } else {
+ value = parseFloat(value);
+ }
+
+ this.data.push({
+ field: cleanMetaChars(variable),
+ operator: comparatorOp,
+ value: value
+ });
+ }
+ },
+
+ {
+ name: 'dataBool',
+ query: true,
+ regex: '\\[\\s*('+ tokens.boolOp +')\\s*('+ tokens.variable +')\\s*\\]',
+ populate: function( boolOp, variable ){
+ this.data.push({
+ field: cleanMetaChars(variable),
+ operator: boolOp
+ });
+ }
+ },
+
+ {
+ name: 'metaCompare',
+ query: true,
+ regex: '\\[\\[\\s*('+ tokens.meta +')\\s*('+ tokens.comparatorOp +')\\s*('+ tokens.number +')\\s*\\]\\]',
+ populate: function( meta, comparatorOp, number ){
+ this.meta.push({
+ field: cleanMetaChars(meta),
+ operator: comparatorOp,
+ value: parseFloat(number)
+ });
+ }
+ },
+
+ {
+ name: 'nextQuery',
+ separator: true,
+ regex: tokens.separator,
+ populate: function(){
+ // go on to next query
+ self[++i] = newQuery();
+ currentSubject = null;
+ }
+ },
+
+ {
+ name: 'child',
+ separator: true,
+ regex: tokens.child,
+ populate: function(){
+ // this query is the parent of the following query
+ var childQuery = newQuery();
+ childQuery.parent = this;
+ childQuery.subject = currentSubject;
+
+ // we're now populating the child query with expressions that follow
+ self[i] = childQuery;
+ }
+ },
+
+ {
+ name: 'descendant',
+ separator: true,
+ regex: tokens.descendant,
+ populate: function(){
+ // this query is the ancestor of the following query
+ var descendantQuery = newQuery();
+ descendantQuery.ancestor = this;
+ descendantQuery.subject = currentSubject;
+
+ // we're now populating the descendant query with expressions that follow
+ self[i] = descendantQuery;
+ }
+ },
+
+ {
+ name: 'subject',
+ modifier: true,
+ regex: tokens.subject,
+ populate: function(){
+ if( currentSubject != null && this.subject != this ){
+ util.error('Redefinition of subject in selector `' + selector + '`');
+ return false;
+ }
+
+ currentSubject = this;
+ this.subject = this;
+ }
+
+ }
+ ];
+
+ self._private.selectorText = selector;
+ var remaining = selector;
+ var i = 0;
+
+ // of all the expressions, find the first match in the remaining text
+ var consumeExpr = function( expectation ){
+ var expr;
+ var match;
+ var name;
+
+ for( var j = 0; j < exprs.length; j++ ){
+ var e = exprs[j];
+ var n = e.name;
+
+ // ignore this expression if it doesn't meet the expectation function
+ if( is.fn( expectation ) && !expectation(n, e) ){ continue; }
+
+ var m = remaining.match(new RegExp( '^' + e.regex ));
+
+ if( m != null ){
+ match = m;
+ expr = e;
+ name = n;
+
+ var consumed = m[0];
+ remaining = remaining.substring( consumed.length );
+
+ break; // we've consumed one expr, so we can return now
+ }
+ }
+
+ return {
+ expr: expr,
+ match: match,
+ name: name
+ };
+ };
+
+ // consume all leading whitespace
+ var consumeWhitespace = function(){
+ var match = remaining.match(/^\s+/);
+
+ if( match ){
+ var consumed = match[0];
+ remaining = remaining.substring( consumed.length );
+ }
+ };
+
+ self[0] = newQuery(); // get started
+
+ consumeWhitespace(); // get rid of leading whitespace
+ for(;;){
+ var check = consumeExpr();
+
+ if( check.expr == null ){
+ util.error('The selector `'+ selector +'`is invalid');
+ return;
+ } else {
+ var args = [];
+ for(var j = 1; j < check.match.length; j++){
+ args.push( check.match[j] );
+ }
+
+ // let the token populate the selector object (i.e. in self[i])
+ var ret = check.expr.populate.apply( self[i], args );
+
+ if( ret === false ){ return; } // exit if population failed
+ }
+
+ // we're done when there's nothing left to parse
+ if( remaining.match(/^\s*$/) ){
+ break;
+ }
+ }
+
+ self.length = i + 1;
+
+ // adjust references for subject
+ for(var j = 0; j < self.length; j++){
+ var query = self[j];
+
+ if( query.subject != null ){
+ // go up the tree until we reach the subject
+ for(;;){
+ if( query.subject == query ){ break; } // done if subject is self
+
+ if( query.parent != null ){ // swap parent/child reference
+ var parent = query.parent;
+ var child = query;
+
+ child.parent = null;
+ parent.child = child;
+
+ query = parent; // go up the tree
+ } else if( query.ancestor != null ){ // swap ancestor/descendant
+ var ancestor = query.ancestor;
+ var descendant = query;
+
+ descendant.ancestor = null;
+ ancestor.descendant = descendant;
+
+ query = ancestor; // go up the tree
+ } else {
+ util.error('When adjusting references for the selector `'+ query +'`, neither parent nor ancestor was found');
+ break;
+ }
+ } // for
+
+ self[j] = query.subject; // subject should be the root query
+ } // if
+ } // for
+
+ // make sure for each query that the subject group matches the implicit group if any
+ if( onlyThisGroup != null ){
+ for(var j = 0; j < self.length; j++){
+ if( self[j].group != null && self[j].group != onlyThisGroup ){
+ util.error('Group `'+ self[j].group +'` conflicts with implicit group `'+ onlyThisGroup +'` in selector `'+ selector +'`');
+ return;
+ }
+
+ self[j].group = onlyThisGroup; // set to implicit group
+ }
+ }
+
+ } else {
+ util.error('A selector must be created from a string; found ' + selector);
+ return;
+ }
+
+ self._private.invalid = false;
+
+};
+
+var selfn = Selector.prototype;
+
+selfn.size = function(){
+ return this.length;
+};
+
+selfn.eq = function(i){
+ return this[i];
+};
+
+var queryMatches = function(query, element){
+ // check group
+ if( query.group != null && query.group != '*' && query.group != element._private.group ){
+ return false;
+ }
+
+ var cy = element.cy();
+
+ // check colon selectors
+ var allColonSelectorsMatch = true;
+ for(var k = 0; k < query.colonSelectors.length; k++){
+ var sel = query.colonSelectors[k];
+
+ switch(sel){
+ case ':selected':
+ allColonSelectorsMatch = element.selected();
+ break;
+ case ':unselected':
+ allColonSelectorsMatch = !element.selected();
+ break;
+ case ':selectable':
+ allColonSelectorsMatch = element.selectable();
+ break;
+ case ':unselectable':
+ allColonSelectorsMatch = !element.selectable();
+ break;
+ case ':locked':
+ allColonSelectorsMatch = element.locked();
+ break;
+ case ':unlocked':
+ allColonSelectorsMatch = !element.locked();
+ break;
+ case ':visible':
+ allColonSelectorsMatch = element.visible();
+ break;
+ case ':hidden':
+ allColonSelectorsMatch = !element.visible();
+ break;
+ case ':transparent':
+ allColonSelectorsMatch = element.transparent();
+ break;
+ case ':grabbed':
+ allColonSelectorsMatch = element.grabbed();
+ break;
+ case ':free':
+ allColonSelectorsMatch = !element.grabbed();
+ break;
+ case ':removed':
+ allColonSelectorsMatch = element.removed();
+ break;
+ case ':inside':
+ allColonSelectorsMatch = !element.removed();
+ break;
+ case ':grabbable':
+ allColonSelectorsMatch = element.grabbable();
+ break;
+ case ':ungrabbable':
+ allColonSelectorsMatch = !element.grabbable();
+ break;
+ case ':animated':
+ allColonSelectorsMatch = element.animated();
+ break;
+ case ':unanimated':
+ allColonSelectorsMatch = !element.animated();
+ break;
+ case ':parent':
+ allColonSelectorsMatch = element.isNode() && element.children().nonempty();
+ break;
+ case ':child':
+ case ':nonorphan':
+ allColonSelectorsMatch = element.isNode() && element.parent().nonempty();
+ break;
+ case ':orphan':
+ allColonSelectorsMatch = element.isNode() && element.parent().empty();
+ break;
+ case ':loop':
+ allColonSelectorsMatch = element.isEdge() && element.data('source') === element.data('target');
+ break;
+ case ':simple':
+ allColonSelectorsMatch = element.isEdge() && element.data('source') !== element.data('target');
+ break;
+ case ':active':
+ allColonSelectorsMatch = element.active();
+ break;
+ case ':inactive':
+ allColonSelectorsMatch = !element.active();
+ break;
+ case ':touch':
+ allColonSelectorsMatch = is.touch();
+ break;
+ case ':backgrounding':
+ allColonSelectorsMatch = element.backgrounding();
+ break;
+ case ':nonbackgrounding':
+ allColonSelectorsMatch = !element.backgrounding();
+ break;
+ }
+
+ if( !allColonSelectorsMatch ) break;
+ }
+ if( !allColonSelectorsMatch ) return false;
+
+ // check id
+ var allIdsMatch = true;
+ for(var k = 0; k < query.ids.length; k++){
+ var id = query.ids[k];
+ var actualId = element._private.data.id;
+
+ allIdsMatch = allIdsMatch && (id == actualId);
+
+ if( !allIdsMatch ) break;
+ }
+ if( !allIdsMatch ) return false;
+
+ // check classes
+ var allClassesMatch = true;
+ for(var k = 0; k < query.classes.length; k++){
+ var cls = query.classes[k];
+
+ allClassesMatch = allClassesMatch && element.hasClass(cls);
+
+ if( !allClassesMatch ) break;
+ }
+ if( !allClassesMatch ) return false;
+
+ // generic checking for data/metadata
+ var operandsMatch = function(params){
+ var allDataMatches = true;
+ for(var k = 0; k < query[params.name].length; k++){
+ var data = query[params.name][k];
+ var operator = data.operator;
+ var value = data.value;
+ var field = data.field;
+ var matches;
+
+ if( operator != null && value != null ){
+
+ var fieldVal = params.fieldValue(field);
+ var fieldStr = !is.string(fieldVal) && !is.number(fieldVal) ? '' : '' + fieldVal;
+ var valStr = '' + value;
+
+ var caseInsensitive = false;
+ if( operator.indexOf('@') >= 0 ){
+ fieldStr = fieldStr.toLowerCase();
+ valStr = valStr.toLowerCase();
+
+ operator = operator.replace('@', '');
+ caseInsensitive = true;
+ }
+
+ var notExpr = false;
+ var handledNotExpr = false;
+ if( operator.indexOf('!') >= 0 ){
+ operator = operator.replace('!', '');
+ notExpr = true;
+ }
+
+ // if we're doing a case insensitive comparison, then we're using a STRING comparison
+ // even if we're comparing numbers
+ if( caseInsensitive ){
+ value = valStr.toLowerCase();
+ fieldVal = fieldStr.toLowerCase();
+ }
+
+ switch(operator){
+ case '*=':
+ matches = fieldStr.search(valStr) >= 0;
+ break;
+ case '$=':
+ matches = new RegExp(valStr + '$').exec(fieldStr) != null;
+ break;
+ case '^=':
+ matches = new RegExp('^' + valStr).exec(fieldStr) != null;
+ break;
+ case '=':
+ matches = fieldVal === value;
+ break;
+ case '!=':
+ matches = fieldVal !== value;
+ break;
+ case '>':
+ matches = !notExpr ? fieldVal > value : fieldVal <= value;
+ handledNotExpr = true;
+ break;
+ case '>=':
+ matches = !notExpr ? fieldVal >= value : fieldVal < value;
+ handledNotExpr = true;
+ break;
+ case '<':
+ matches = !notExpr ? fieldVal < value : fieldVal >= value;
+ handledNotExpr = true;
+ break;
+ case '<=':
+ matches = !notExpr ? fieldVal <= value : fieldVal > value;
+ handledNotExpr = true;
+ break;
+ default:
+ matches = false;
+ break;
+
+ }
+ } else if( operator != null ){
+ switch(operator){
+ case '?':
+ matches = params.fieldTruthy(field);
+ break;
+ case '!':
+ matches = !params.fieldTruthy(field);
+ break;
+ case '^':
+ matches = params.fieldUndefined(field);
+ break;
+ }
+ } else {
+ matches = !params.fieldUndefined(field);
+ }
+
+ if( notExpr && !handledNotExpr ){
+ matches = !matches;
+ handledNotExpr = true;
+ }
+
+ if( !matches ){
+ allDataMatches = false;
+ break;
+ }
+ } // for
+
+ return allDataMatches;
+ }; // operandsMatch
+
+ // check data matches
+ var allDataMatches = operandsMatch({
+ name: 'data',
+ fieldValue: function(field){
+ return element._private.data[field];
+ },
+ fieldRef: function(field){
+ return 'element._private.data.' + field;
+ },
+ fieldUndefined: function(field){
+ return element._private.data[field] === undefined;
+ },
+ fieldTruthy: function(field){
+ if( element._private.data[field] ){
+ return true;
+ }
+ return false;
+ }
+ });
+
+ if( !allDataMatches ){
+ return false;
+ }
+
+ // check metadata matches
+ var allMetaMatches = operandsMatch({
+ name: 'meta',
+ fieldValue: function(field){
+ return element[field]();
+ },
+ fieldRef: function(field){
+ return 'element.' + field + '()';
+ },
+ fieldUndefined: function(field){
+ return element[field]() == null;
+ },
+ fieldTruthy: function(field){
+ if( element[field]() ){
+ return true;
+ }
+ return false;
+ }
+ });
+
+ if( !allMetaMatches ){
+ return false;
+ }
+
+ // check collection
+ if( query.collection != null ){
+ var matchesAny = query.collection._private.ids[ element.id() ] != null;
+
+ if( !matchesAny ){
+ return false;
+ }
+ }
+
+ // check filter function
+ if( query.filter != null && element.collection().filter( query.filter ).size() === 0 ){
+ return false;
+ }
+
+
+ // check parent/child relations
+ var confirmRelations = function( query, elements ){
+ if( query != null ){
+ var matches = false;
+
+ if( !cy.hasCompoundNodes() ){
+ return false;
+ }
+
+ elements = elements(); // make elements functional so we save cycles if query == null
+
+ // query must match for at least one element (may be recursive)
+ for(var i = 0; i < elements.length; i++){
+ if( queryMatches( query, elements[i] ) ){
+ matches = true;
+ break;
+ }
+ }
+
+ return matches;
+ } else {
+ return true;
+ }
+ };
+
+ if (! confirmRelations(query.parent, function(){
+ return element.parent();
+ }) ){ return false; }
+
+ if (! confirmRelations(query.ancestor, function(){
+ return element.parents();
+ }) ){ return false; }
+
+ if (! confirmRelations(query.child, function(){
+ return element.children();
+ }) ){ return false; }
+
+ if (! confirmRelations(query.descendant, function(){
+ return element.descendants();
+ }) ){ return false; }
+
+ // we've reached the end, so we've matched everything for this query
+ return true;
+}; // queryMatches
+
+// filter an existing collection
+selfn.filter = function(collection){
+ var self = this;
+ var cy = collection.cy();
+
+ // don't bother trying if it's invalid
+ if( self._private.invalid ){
+ return cy.collection();
+ }
+
+ var selectorFunction = function(i, element){
+ for(var j = 0; j < self.length; j++){
+ var query = self[j];
+
+ if( queryMatches(query, element) ){
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ if( self._private.selectorText == null ){
+ selectorFunction = function(){ return true; };
+ }
+
+ var filteredCollection = collection.filter( selectorFunction );
+
+ return filteredCollection;
+}; // filter
+
+// does selector match a single element?
+selfn.matches = function(ele){
+ var self = this;
+
+ // don't bother trying if it's invalid
+ if( self._private.invalid ){
+ return false;
+ }
+
+ for(var j = 0; j < self.length; j++){
+ var query = self[j];
+
+ if( queryMatches(query, ele) ){
+ return true;
+ }
+ }
+
+ return false;
+}; // filter
+
+// ith query to string
+selfn.toString = selfn.selector = function(){
+
+ var str = '';
+
+ var clean = function(obj, isValue){
+ if( is.string(obj) ){
+ return isValue ? '"' + obj + '"' : obj;
+ }
+ return '';
+ };
+
+ var queryToString = function(query){
+ var str = '';
+
+ if( query.subject === query ){
+ str += '$';
+ }
+
+ var group = clean(query.group);
+ str += group.substring(0, group.length - 1);
+
+ for(var j = 0; j < query.data.length; j++){
+ var data = query.data[j];
+
+ if( data.value ){
+ str += '[' + data.field + clean(data.operator) + clean(data.value, true) + ']';
+ } else {
+ str += '[' + clean(data.operator) + data.field + ']';
+ }
+ }
+
+ for(var j = 0; j < query.meta.length; j++){
+ var meta = query.meta[j];
+ str += '[[' + meta.field + clean(meta.operator) + clean(meta.value, true) + ']]';
+ }
+
+ for(var j = 0; j < query.colonSelectors.length; j++){
+ var sel = query.colonSelectors[i];
+ str += sel;
+ }
+
+ for(var j = 0; j < query.ids.length; j++){
+ var sel = '#' + query.ids[i];
+ str += sel;
+ }
+
+ for(var j = 0; j < query.classes.length; j++){
+ var sel = '.' + query.classes[j];
+ str += sel;
+ }
+
+ if( query.parent != null ){
+ str = queryToString( query.parent ) + ' > ' + str;
+ }
+
+ if( query.ancestor != null ){
+ str = queryToString( query.ancestor ) + ' ' + str;
+ }
+
+ if( query.child != null ){
+ str += ' > ' + queryToString( query.child );
+ }
+
+ if( query.descendant != null ){
+ str += ' ' + queryToString( query.descendant );
+ }
+
+ return str;
+ };
+
+ for(var i = 0; i < this.length; i++){
+ var query = this[i];
+
+ str += queryToString( query );
+
+ if( this.length > 1 && i < this.length - 1 ){
+ str += ', ';
+ }
+ }
+
+ return str;
+};
+
+module.exports = Selector;
+
+},{"./is":77,"./util":94}],82:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+var is = _dereq_('../is');
+
+var styfn = {};
+
+// (potentially expensive calculation)
+// apply the style to the element based on
+// - its bypass
+// - what selectors match it
+styfn.apply = function( eles ){
+ var self = this;
+
+ if( self._private.newStyle ){ // clear style caches
+ this._private.contextStyles = {};
+ this._private.propDiffs = {};
+ }
+
+ for( var ie = 0; ie < eles.length; ie++ ){
+ var ele = eles[ie];
+ var cxtMeta = self.getContextMeta( ele );
+ var cxtStyle = self.getContextStyle( cxtMeta );
+ var app = self.applyContextStyle( cxtMeta, cxtStyle, ele );
+
+ self.updateTransitions( ele, app.diffProps );
+ self.updateStyleHints( ele );
+
+ } // for elements
+
+ self._private.newStyle = false;
+};
+
+styfn.getPropertiesDiff = function( oldCxtKey, newCxtKey ){
+ var self = this;
+ var cache = self._private.propDiffs = self._private.propDiffs || {};
+ var dualCxtKey = oldCxtKey + '-' + newCxtKey;
+ var cachedVal = cache[dualCxtKey];
+
+ if( cachedVal ){
+ return cachedVal;
+ }
+
+ var diffProps = [];
+ var addedProp = {};
+
+ for( var i = 0; i < self.length; i++ ){
+ var cxt = self[i];
+ var oldHasCxt = oldCxtKey[i] === 't';
+ var newHasCxt = newCxtKey[i] === 't';
+ var cxtHasDiffed = oldHasCxt !== newHasCxt;
+ var cxtHasMappedProps = cxt.mappedProperties.length > 0;
+
+ if( cxtHasDiffed || cxtHasMappedProps ){
+ var props;
+
+ if( cxtHasDiffed && cxtHasMappedProps ){
+ props = cxt.properties; // suffices b/c mappedProperties is a subset of properties
+ } else if( cxtHasDiffed ){
+ props = cxt.properties; // need to check them all
+ } else if( cxtHasMappedProps ){
+ props = cxt.mappedProperties; // only need to check mapped
+ }
+
+ for( var j = 0; j < props.length; j++ ){
+ var prop = props[j];
+ var name = prop.name;
+
+ // if a later context overrides this property, then the fact that this context has switched/diffed doesn't matter
+ // (semi expensive check since it makes this function O(n^2) on context length, but worth it since overall result
+ // is cached)
+ var laterCxtOverrides = false;
+ for( var k = i + 1; k < self.length; k++ ){
+ var laterCxt = self[k];
+ var hasLaterCxt = newCxtKey[k] === 't';
+
+ if( !hasLaterCxt ){ continue; } // can't override unless the context is active
+
+ laterCxtOverrides = laterCxt.properties[ prop.name ] != null;
+
+ if( laterCxtOverrides ){ break; } // exit early as long as one later context overrides
+ }
+
+ if( !addedProp[name] && !laterCxtOverrides ){
+ addedProp[name] = true;
+ diffProps.push( name );
+ }
+ } // for props
+ } // if
+
+ } // for contexts
+
+ cache[ dualCxtKey ] = diffProps;
+ return diffProps;
+};
+
+styfn.getContextMeta = function( ele ){
+ var self = this;
+ var cxtKey = '';
+ var diffProps;
+ var prevKey = ele._private.styleCxtKey || '';
+
+ if( self._private.newStyle ){
+ prevKey = ''; // since we need to apply all style if a fresh stylesheet
+ }
+
+ // get the cxt key
+ for( var i = 0; i < self.length; i++ ){
+ var context = self[i];
+ var contextSelectorMatches = context.selector && context.selector.matches( ele ); // NB: context.selector may be null for 'core'
+
+ if( contextSelectorMatches ){
+ cxtKey += 't';
+ } else {
+ cxtKey += 'f';
+ }
+ } // for context
+
+ diffProps = self.getPropertiesDiff( prevKey, cxtKey );
+
+ ele._private.styleCxtKey = cxtKey;
+
+ return {
+ key: cxtKey,
+ diffPropNames: diffProps
+ };
+};
+
+// gets a computed ele style object based on matched contexts
+styfn.getContextStyle = function( cxtMeta ){
+ var cxtKey = cxtMeta.key;
+ var self = this;
+ var cxtStyles = this._private.contextStyles = this._private.contextStyles || {};
+
+ // if already computed style, returned cached copy
+ if( cxtStyles[cxtKey] ){ return cxtStyles[cxtKey]; }
+
+ var style = {
+ _private: {
+ key: cxtKey
+ }
+ };
+
+ for( var i = 0; i < self.length; i++ ){
+ var cxt = self[i];
+ var hasCxt = cxtKey[i] === 't';
+
+ if( !hasCxt ){ continue; }
+
+ for( var j = 0; j < cxt.properties.length; j++ ){
+ var prop = cxt.properties[j];
+ var styProp = style[ prop.name ] = prop;
+
+ styProp.context = cxt;
+ }
+ }
+
+ cxtStyles[cxtKey] = style;
+ return style;
+};
+
+styfn.applyContextStyle = function( cxtMeta, cxtStyle, ele ){
+ var self = this;
+ var diffProps = cxtMeta.diffPropNames;
+ var retDiffProps = {};
+
+ for( var i = 0; i < diffProps.length; i++ ){
+ var diffPropName = diffProps[i];
+ var cxtProp = cxtStyle[ diffPropName ];
+ var eleProp = ele._private.style[ diffPropName ];
+
+ // save cycles when the context prop doesn't need to be applied
+ if( !cxtProp || eleProp === cxtProp ){ continue; }
+
+ var retDiffProp = retDiffProps[ diffPropName ] = {
+ prev: eleProp
+ };
+
+ self.applyParsedProperty( ele, cxtProp );
+
+ retDiffProp.next = ele._private.style[ diffPropName ];
+
+ if( retDiffProp.next && retDiffProp.next.bypass ){
+ retDiffProp.next = retDiffProp.next.bypassed;
+ }
+ }
+
+ return {
+ diffProps: retDiffProps
+ };
+};
+
+styfn.updateStyleHints = function(ele){
+ var _p = ele._private;
+ var self = this;
+ var style = _p.style;
+
+ if( ele.removed() ){ return; }
+
+ // set whether has pie or not; for greater efficiency
+ var hasPie = false;
+ if( _p.group === 'nodes' && self._private.hasPie ){
+ for( var i = 1; i <= self.pieBackgroundN; i++ ){ // 1..N
+ var size = _p.style['pie-' + i + '-background-size'].value;
+
+ if( size > 0 ){
+ hasPie = true;
+ break;
+ }
+ }
+ }
+
+ _p.hasPie = hasPie;
+
+ var transform = style['text-transform'].strValue;
+ var content = style['label'].strValue;
+ var fStyle = style['font-style'].strValue;
+ var size = style['font-size'].pfValue + 'px';
+ var family = style['font-family'].strValue;
+ // var variant = style['font-variant'].strValue;
+ var weight = style['font-weight'].strValue;
+ var valign = style['text-valign'].strValue;
+ var halign = style['text-valign'].strValue;
+ var oWidth = style['text-outline-width'].pfValue;
+ var wrap = style['text-wrap'].strValue;
+ var wrapW = style['text-max-width'].pfValue;
+ _p.labelKey = fStyle +'$'+ size +'$'+ family +'$'+ weight +'$'+ content +'$'+ transform +'$'+ valign +'$'+ halign +'$'+ oWidth + '$' + wrap + '$' + wrapW;
+ _p.fontKey = fStyle +'$'+ weight +'$'+ size +'$'+ family;
+
+ var width = style['width'].pfValue;
+ var height = style['height'].pfValue;
+ var borderW = style['border-width'].pfValue;
+ _p.boundingBoxKey = width +'$'+ height +'$'+ borderW;
+
+ if( ele._private.group === 'edges' ){
+ var cpss = style['control-point-step-size'].pfValue;
+ var cpd = style['control-point-distances'] ? style['control-point-distances'].pfValue.join('_') : undefined;
+ var cpw = style['control-point-weights'].value.join('_');
+ var curve = style['curve-style'].strValue;
+
+ _p.boundingBoxKey += '$'+ cpss +'$'+ cpd +'$'+ cpw +'$'+ curve;
+ }
+
+ _p.styleKey = Date.now();
+};
+
+// apply a property to the style (for internal use)
+// returns whether application was successful
+//
+// now, this function flattens the property, and here's how:
+//
+// for parsedProp:{ bypass: true, deleteBypass: true }
+// no property is generated, instead the bypass property in the
+// element's style is replaced by what's pointed to by the `bypassed`
+// field in the bypass property (i.e. restoring the property the
+// bypass was overriding)
+//
+// for parsedProp:{ mapped: truthy }
+// the generated flattenedProp:{ mapping: prop }
+//
+// for parsedProp:{ bypass: true }
+// the generated flattenedProp:{ bypassed: parsedProp }
+styfn.applyParsedProperty = function( ele, parsedProp ){
+ var self = this;
+ var prop = parsedProp;
+ var style = ele._private.style;
+ var fieldVal, flatProp;
+ var types = self.types;
+ var type = self.properties[ prop.name ].type;
+ var propIsBypass = prop.bypass;
+ var origProp = style[ prop.name ];
+ var origPropIsBypass = origProp && origProp.bypass;
+ var _p = ele._private;
+
+ // can't apply auto to width or height unless it's a parent node
+ if( (parsedProp.name === 'height' || parsedProp.name === 'width') && ele.isNode() ){
+ if( parsedProp.value === 'auto' && !ele.isParent() ){
+ return false;
+ } else if( parsedProp.value !== 'auto' && ele.isParent() ){
+ prop = parsedProp = this.parse( parsedProp.name, 'auto', propIsBypass );
+ }
+ }
+
+ // check if we need to delete the current bypass
+ if( propIsBypass && prop.deleteBypass ){ // then this property is just here to indicate we need to delete
+ var currentProp = style[ prop.name ];
+
+ // can only delete if the current prop is a bypass and it points to the property it was overriding
+ if( !currentProp ){
+ return true; // property is already not defined
+ } else if( currentProp.bypass && currentProp.bypassed ){ // then replace the bypass property with the original
+
+ // because the bypassed property was already applied (and therefore parsed), we can just replace it (no reapplying necessary)
+ style[ prop.name ] = currentProp.bypassed;
+ return true;
+
+ } else {
+ return false; // we're unsuccessful deleting the bypass
+ }
+ }
+
+ var printMappingErr = function(){
+ util.error('Do not assign mappings to elements without corresponding data (e.g. ele `'+ ele.id() +'` for property `'+ prop.name +'` with data field `'+ prop.field +'`); try a `['+ prop.field +']` selector to limit scope to elements with `'+ prop.field +'` defined');
+ };
+
+ // put the property in the style objects
+ switch( prop.mapped ){ // flatten the property if mapped
+ case types.mapData:
+ case types.mapLayoutData:
+ case types.mapScratch:
+
+ var isLayout = prop.mapped === types.mapLayoutData;
+ var isScratch = prop.mapped === types.mapScratch;
+
+ // flatten the field (e.g. data.foo.bar)
+ var fields = prop.field.split(".");
+ var fieldVal;
+
+ if( isScratch || isLayout ){
+ fieldVal = _p.scratch;
+ } else {
+ fieldVal = _p.data;
+ }
+
+ for( var i = 0; i < fields.length && fieldVal; i++ ){
+ var field = fields[i];
+ fieldVal = fieldVal[ field ];
+ }
+
+ var percent;
+ if( !is.number(fieldVal) ){ // then keep the mapping but assume 0% for now
+ percent = 0;
+ } else {
+ percent = (fieldVal - prop.fieldMin) / (prop.fieldMax - prop.fieldMin);
+ }
+
+ // make sure to bound percent value
+ if( percent < 0 ){
+ percent = 0;
+ } else if( percent > 1 ){
+ percent = 1;
+ }
+
+ if( type.color ){
+ var r1 = prop.valueMin[0];
+ var r2 = prop.valueMax[0];
+ var g1 = prop.valueMin[1];
+ var g2 = prop.valueMax[1];
+ var b1 = prop.valueMin[2];
+ var b2 = prop.valueMax[2];
+ var a1 = prop.valueMin[3] == null ? 1 : prop.valueMin[3];
+ var a2 = prop.valueMax[3] == null ? 1 : prop.valueMax[3];
+
+ var clr = [
+ Math.round( r1 + (r2 - r1)*percent ),
+ Math.round( g1 + (g2 - g1)*percent ),
+ Math.round( b1 + (b2 - b1)*percent ),
+ Math.round( a1 + (a2 - a1)*percent )
+ ];
+
+ flatProp = { // colours are simple, so just create the flat property instead of expensive string parsing
+ bypass: prop.bypass, // we're a bypass if the mapping property is a bypass
+ name: prop.name,
+ value: clr,
+ strValue: 'rgb(' + clr[0] + ', ' + clr[1] + ', ' + clr[2] + ')'
+ };
+
+ } else if( type.number ){
+ var calcValue = prop.valueMin + (prop.valueMax - prop.valueMin) * percent;
+ flatProp = this.parse( prop.name, calcValue, prop.bypass, true );
+
+ } else {
+ return false; // can only map to colours and numbers
+ }
+
+ if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself
+ flatProp = this.parse( prop.name, origProp.strValue, prop.bypass, true );
+ }
+
+ if( !flatProp ){ printMappingErr(); }
+ flatProp.mapping = prop; // keep a reference to the mapping
+ prop = flatProp; // the flattened (mapped) property is the one we want
+
+ break;
+
+ // direct mapping
+ case types.data:
+ case types.layoutData:
+ case types.scratch:
+ var isLayout = prop.mapped === types.layoutData;
+ var isScratch = prop.mapped === types.scratch;
+
+ // flatten the field (e.g. data.foo.bar)
+ var fields = prop.field.split(".");
+ var fieldVal;
+
+ if( isScratch || isLayout ){
+ fieldVal = _p.scratch;
+ } else {
+ fieldVal = _p.data;
+ }
+
+ if( fieldVal ){ for( var i = 0; i < fields.length; i++ ){
+ var field = fields[i];
+ fieldVal = fieldVal[ field ];
+ } }
+
+ flatProp = this.parse( prop.name, fieldVal, prop.bypass, true );
+
+ if( !flatProp ){ // if we can't flatten the property, then use the origProp so we still keep the mapping itself
+ var flatPropVal = origProp ? origProp.strValue : '';
+
+ flatProp = this.parse( prop.name, flatPropVal, prop.bypass, true );
+ }
+
+ if( !flatProp ){ printMappingErr(); }
+ flatProp.mapping = prop; // keep a reference to the mapping
+ prop = flatProp; // the flattened (mapped) property is the one we want
+
+ break;
+
+ case types.fn:
+ var fn = prop.value;
+ var fnRetVal = fn( ele );
+
+ flatProp = this.parse( prop.name, fnRetVal, prop.bypass, true );
+ flatProp.mapping = prop; // keep a reference to the mapping
+ prop = flatProp; // the flattened (mapped) property is the one we want
+
+ break;
+
+ case undefined:
+ break; // just set the property
+
+ default:
+ return false; // not a valid mapping
+ }
+
+ // if the property is a bypass property, then link the resultant property to the original one
+ if( propIsBypass ){
+ if( origPropIsBypass ){ // then this bypass overrides the existing one
+ prop.bypassed = origProp.bypassed; // steal bypassed prop from old bypass
+ } else { // then link the orig prop to the new bypass
+ prop.bypassed = origProp;
+ }
+
+ style[ prop.name ] = prop; // and set
+
+ } else { // prop is not bypass
+ if( origPropIsBypass ){ // then keep the orig prop (since it's a bypass) and link to the new prop
+ origProp.bypassed = prop;
+ } else { // then just replace the old prop with the new one
+ style[ prop.name ] = prop;
+ }
+ }
+
+ return true;
+};
+
+// updates the visual style for all elements (useful for manual style modification after init)
+styfn.update = function(){
+ var cy = this._private.cy;
+ var eles = cy.elements();
+
+ eles.updateStyle();
+};
+
+// just update the functional properties (i.e. mappings) in the elements'
+// styles (less expensive than recalculation)
+styfn.updateMappers = function( eles ){
+ var self = this;
+
+ for( var i = 0; i < eles.length; i++ ){ // for each ele
+ var ele = eles[i];
+ var style = ele._private.style;
+
+ for( var j = 0; j < self.properties.length; j++ ){ // for each prop
+ var prop = self.properties[j];
+ var propInStyle = style[ prop.name ];
+
+ if( propInStyle && propInStyle.mapping ){
+ var mapping = propInStyle.mapping;
+ this.applyParsedProperty( ele, mapping ); // reapply the mapping property
+ }
+ }
+
+ this.updateStyleHints( ele );
+ }
+};
+
+// diffProps : { name => { prev, next } }
+styfn.updateTransitions = function( ele, diffProps, isBypass ){
+ var self = this;
+ var _p = ele._private;
+ var style = _p.style;
+ var props = style['transition-property'].value;
+ var duration = style['transition-duration'].pfValue;
+ var delay = style['transition-delay'].pfValue;
+ var css = {};
+
+ if( props.length > 0 && duration > 0 ){
+
+ // build up the style to animate towards
+ var anyPrev = false;
+ for( var i = 0; i < props.length; i++ ){
+ var prop = props[i];
+ var styProp = style[ prop ];
+ var diffProp = diffProps[ prop ];
+
+ if( !diffProp ){ continue; }
+
+ var prevProp = diffProp.prev;
+ var fromProp = prevProp;
+ var toProp = diffProp.next != null ? diffProp.next : styProp;
+ var diff = false;
+ var initVal;
+ var initDt = 0.000001; // delta time % value for initVal (allows animating out of init zero opacity)
+
+ if( !fromProp ){ continue; }
+
+ // consider px values
+ if( is.number( fromProp.pfValue ) && is.number( toProp.pfValue ) ){
+ diff = toProp.pfValue - fromProp.pfValue; // nonzero is truthy
+ initVal = fromProp.pfValue + initDt * diff;
+
+ // consider numerical values
+ } else if( is.number( fromProp.value ) && is.number( toProp.value ) ){
+ diff = toProp.value - fromProp.value; // nonzero is truthy
+ initVal = fromProp.value + initDt * diff;
+
+ // consider colour values
+ } else if( is.array( fromProp.value ) && is.array( toProp.value ) ){
+ diff = fromProp.value[0] !== toProp.value[0]
+ || fromProp.value[1] !== toProp.value[1]
+ || fromProp.value[2] !== toProp.value[2]
+ ;
+
+ initVal = fromProp.strValue;
+ }
+
+ // the previous value is good for an animation only if it's different
+ if( diff ){
+ css[ prop ] = toProp.strValue; // to val
+ this.applyBypass( ele, prop, initVal ); // from val
+ anyPrev = true;
+ }
+
+ } // end if props allow ani
+
+ // can't transition if there's nothing previous to transition from
+ if( !anyPrev ){ return; }
+
+ _p.transitioning = true;
+
+ ele.stop();
+
+ if( delay > 0 ){
+ ele.delay( delay );
+ }
+
+ ele.animate({
+ css: css
+ }, {
+ duration: duration,
+ easing: style['transition-timing-function'].value,
+ queue: false,
+ complete: function(){
+ if( !isBypass ){
+ self.removeBypasses( ele, props );
+ }
+
+ _p.transitioning = false;
+ }
+ });
+
+ } else if( _p.transitioning ){
+ ele.stop();
+
+ this.removeBypasses( ele, props );
+
+ _p.transitioning = false;
+ }
+};
+
+module.exports = styfn;
+
+},{"../is":77,"../util":94}],83:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+var util = _dereq_('../util');
+
+var styfn = {};
+
+// bypasses are applied to an existing style on an element, and just tacked on temporarily
+// returns true iff application was successful for at least 1 specified property
+styfn.applyBypass = function( eles, name, value, updateTransitions ){
+ var self = this;
+ var props = [];
+ var isBypass = true;
+
+ // put all the properties (can specify one or many) in an array after parsing them
+ if( name === "*" || name === "**" ){ // apply to all property names
+
+ if( value !== undefined ){
+ for( var i = 0; i < self.properties.length; i++ ){
+ var prop = self.properties[i];
+ var name = prop.name;
+
+ var parsedProp = this.parse(name, value, true);
+
+ if( parsedProp ){
+ props.push( parsedProp );
+ }
+ }
+ }
+
+ } else if( is.string(name) ){ // then parse the single property
+ var parsedProp = this.parse(name, value, true);
+
+ if( parsedProp ){
+ props.push( parsedProp );
+ }
+ } else if( is.plainObject(name) ){ // then parse each property
+ var specifiedProps = name;
+ updateTransitions = value;
+
+ for( var i = 0; i < self.properties.length; i++ ){
+ var prop = self.properties[i];
+ var name = prop.name;
+ var value = specifiedProps[ name ];
+
+ if( value === undefined ){ // try camel case name too
+ value = specifiedProps[ util.dash2camel(name) ];
+ }
+
+ if( value !== undefined ){
+ var parsedProp = this.parse(name, value, true);
+
+ if( parsedProp ){
+ props.push( parsedProp );
+ }
+ }
+ }
+ } else { // can't do anything without well defined properties
+ return false;
+ }
+
+ // we've failed if there are no valid properties
+ if( props.length === 0 ){ return false; }
+
+ // now, apply the bypass properties on the elements
+ var ret = false; // return true if at least one succesful bypass applied
+ for( var i = 0; i < eles.length; i++ ){ // for each ele
+ var ele = eles[i];
+ var style = ele._private.style;
+ var diffProps = {};
+ var diffProp;
+
+ for( var j = 0; j < props.length; j++ ){ // for each prop
+ var prop = props[j];
+
+ if( updateTransitions ){
+ var prevProp = style[ prop.name ];
+ diffProp = diffProps[ prop.name ] = { prev: prevProp };
+ }
+
+ ret = this.applyParsedProperty( ele, prop ) || ret;
+
+ if( updateTransitions ){
+ diffProp.next = style[ prop.name ];
+ }
+
+ } // for props
+
+ if( ret ){
+ this.updateStyleHints( ele );
+ }
+
+ if( updateTransitions ){
+ this.updateTransitions( ele, diffProps, isBypass );
+ }
+ } // for eles
+
+ return ret;
+};
+
+// only useful in specific cases like animation
+styfn.overrideBypass = function( eles, name, value ){
+ name = util.camel2dash(name);
+
+ for( var i = 0; i < eles.length; i++ ){
+ var ele = eles[i];
+ var prop = ele._private.style[ name ];
+ var type = this.properties[ name ].type;
+ var isColor = type.color;
+ var isMulti = type.mutiple;
+
+ if( !prop.bypass ){ // need a bypass if one doesn't exist
+ this.applyBypass( ele, name, value );
+ continue;
+ }
+
+ prop.value = value;
+
+ if( prop.pfValue != null ){
+ prop.pfValue = value;
+ }
+
+ if( isColor ){
+ prop.strValue = 'rgb(' + value.join(',') + ')';
+ } else if( isMulti ){
+ prop.strValue = value.join(' ');
+ } else {
+ prop.strValue = '' + value;
+ }
+ }
+};
+
+styfn.removeAllBypasses = function( eles, updateTransitions ){
+ return this.removeBypasses( eles, this.propertyNames, updateTransitions );
+};
+
+styfn.removeBypasses = function( eles, props, updateTransitions ){
+ var isBypass = true;
+
+ for( var j = 0; j < eles.length; j++ ){
+ var ele = eles[j];
+ var diffProps = {};
+ var style = ele._private.style;
+
+ for( var i = 0; i < props.length; i++ ){
+ var name = props[i];
+ var prop = this.properties[ name ];
+ var value = ''; // empty => remove bypass
+ var parsedProp = this.parse(name, value, true);
+ var prevProp = style[ prop.name ];
+ var diffProp = diffProps[ prop.name ] = { prev: prevProp };
+
+ this.applyParsedProperty(ele, parsedProp);
+
+ diffProp.next = style[ prop.name ];
+ } // for props
+
+ this.updateStyleHints( ele );
+
+ if( updateTransitions ){
+ this.updateTransitions( ele, diffProps, isBypass );
+ }
+ } // for eles
+};
+
+module.exports = styfn;
+
+},{"../is":77,"../util":94}],84:[function(_dereq_,module,exports){
+'use strict';
+
+var window = _dereq_('../window');
+
+var styfn = {};
+
+// gets what an em size corresponds to in pixels relative to a dom element
+styfn.getEmSizeInPixels = function(){
+ var px = this.containerCss('font-size');
+
+ if( px != null ){
+ return parseFloat( px );
+ } else {
+ return 1; // for headless
+ }
+};
+
+// gets css property from the core container
+styfn.containerCss = function( propName ){
+ var cy = this._private.cy;
+ var domElement = cy.container();
+
+ if( window && domElement && window.getComputedStyle ){
+ return window.getComputedStyle(domElement).getPropertyValue( propName );
+ }
+};
+
+module.exports = styfn;
+
+},{"../window":100}],85:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+var is = _dereq_('../is');
+
+var styfn = {};
+
+// gets the rendered style for an element
+styfn.getRenderedStyle = function( ele ){
+ return this.getRawStyle( ele, true );
+};
+
+// gets the raw style for an element
+styfn.getRawStyle = function( ele, isRenderedVal ){
+ var self = this;
+ var ele = ele[0]; // insure it's an element
+
+ if( ele ){
+ var rstyle = {};
+
+ for( var i = 0; i < self.properties.length; i++ ){
+ var prop = self.properties[i];
+ var val = self.getStylePropertyValue( ele, prop.name, isRenderedVal );
+
+ if( val ){
+ rstyle[ prop.name ] = val;
+ rstyle[ util.dash2camel(prop.name) ] = val;
+ }
+ }
+
+ return rstyle;
+ }
+};
+
+styfn.getStylePropertyValue = function( ele, propName, isRenderedVal ){
+ var self = this;
+ var ele = ele[0]; // insure it's an element
+
+ if( ele ){
+ var style = ele._private.style;
+ var prop = self.properties[ propName ];
+ var type = prop.type;
+ var styleProp = style[ prop.name ];
+ var zoom = ele.cy().zoom();
+
+ if( styleProp ){
+ var units = styleProp.units ? type.implicitUnits || 'px' : null;
+ var val = units ? [].concat( styleProp.pfValue ).map(function( pfValue ){
+ return ( pfValue * (isRenderedVal ? zoom : 1) ) + units;
+ }).join(' ') : styleProp.strValue;
+
+ return val;
+ }
+ }
+};
+
+// gets the value style for an element (useful for things like animations)
+styfn.getValueStyle = function( ele ){
+ var self = this;
+ var rstyle = {};
+ var style;
+ var isEle = is.element(ele);
+
+ if( isEle ){
+ style = ele._private.style;
+ } else {
+ style = ele; // just passed the style itself
+ }
+
+ if( style ){
+ for( var i = 0; i < self.properties.length; i++ ){
+ var prop = self.properties[i];
+ var styleProp = style[ prop.name ] || style[ util.dash2camel(prop.name) ];
+
+ if( styleProp !== undefined ){ // then make a prop of it
+ if( is.plainObject( styleProp ) ){
+ styleProp = this.parse( prop.name, styleProp.strValue );
+ } else {
+ styleProp = this.parse( prop.name, styleProp );
+ }
+ }
+
+ if( styleProp ){
+ rstyle[ prop.name ] = styleProp;
+ rstyle[ util.dash2camel(prop.name) ] = styleProp;
+ }
+ }
+ }
+
+ return rstyle;
+};
+
+styfn.getPropsList = function( propsObj ){
+ var self = this;
+ var rstyle = [];
+ var style = propsObj;
+ var props = self.properties;
+
+ if( style ){
+ for( var name in style ){
+ var val = style[name];
+ var prop = props[name] || props[ util.camel2dash(name) ];
+ var styleProp = this.parse( prop.name, val );
+
+ rstyle.push( styleProp );
+ }
+ }
+
+ return rstyle;
+};
+
+module.exports = styfn;
+
+},{"../is":77,"../util":94}],86:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+var util = _dereq_('../util');
+var Selector = _dereq_('../selector');
+
+var Style = function( cy ){
+
+ if( !(this instanceof Style) ){
+ return new Style(cy);
+ }
+
+ if( !is.core(cy) ){
+ util.error('A style must have a core reference');
+ return;
+ }
+
+ this._private = {
+ cy: cy,
+ coreStyle: {},
+ newStyle: true
+ };
+
+ this.length = 0;
+
+ this.addDefaultStylesheet();
+};
+
+var styfn = Style.prototype;
+
+styfn.instanceString = function(){
+ return 'style';
+};
+
+// remove all contexts
+styfn.clear = function(){
+ for( var i = 0; i < this.length; i++ ){
+ this[i] = undefined;
+ }
+ this.length = 0;
+ this._private.newStyle = true;
+
+ return this; // chaining
+};
+
+styfn.resetToDefault = function(){
+ this.clear();
+ this.addDefaultStylesheet();
+
+ return this;
+};
+
+// builds a style object for the 'core' selector
+styfn.core = function(){
+ return this._private.coreStyle;
+};
+
+// create a new context from the specified selector string and switch to that context
+styfn.selector = function( selectorStr ){
+ // 'core' is a special case and does not need a selector
+ var selector = selectorStr === 'core' ? null : new Selector( selectorStr );
+
+ var i = this.length++; // new context means new index
+ this[i] = {
+ selector: selector,
+ properties: [],
+ mappedProperties: [],
+ index: i
+ };
+
+ return this; // chaining
+};
+
+// add one or many css rules to the current context
+styfn.css = function(){
+ var self = this;
+ var args = arguments;
+
+ switch( args.length ){
+ case 1:
+ var map = args[0];
+
+ for( var i = 0; i < self.properties.length; i++ ){
+ var prop = self.properties[i];
+ var mapVal = map[ prop.name ];
+
+ if( mapVal === undefined ){
+ mapVal = map[ util.dash2camel(prop.name) ];
+ }
+
+ if( mapVal !== undefined ){
+ this.cssRule( prop.name, mapVal );
+ }
+ }
+
+ break;
+
+ case 2:
+ this.cssRule( args[0], args[1] );
+ break;
+
+ default:
+ break; // do nothing if args are invalid
+ }
+
+ return this; // chaining
+};
+styfn.style = styfn.css;
+
+// add a single css rule to the current context
+styfn.cssRule = function( name, value ){
+ // name-value pair
+ var property = this.parse( name, value );
+
+ // add property to current context if valid
+ if( property ){
+ var i = this.length - 1;
+ this[i].properties.push( property );
+ this[i].properties[ property.name ] = property; // allow access by name as well
+
+ if( property.name.match(/pie-(\d+)-background-size/) && property.value ){
+ this._private.hasPie = true;
+ }
+
+ if( property.mapped ){
+ this[i].mappedProperties.push( property );
+ }
+
+ // add to core style if necessary
+ var currentSelectorIsCore = !this[i].selector;
+ if( currentSelectorIsCore ){
+ this._private.coreStyle[ property.name ] = property;
+ }
+ }
+
+ return this; // chaining
+};
+
+// static function
+Style.fromJson = function( cy, json ){
+ var style = new Style( cy );
+
+ style.fromJson( json );
+
+ return style;
+};
+
+Style.fromString = function( cy, string ){
+ return new Style( cy ).fromString( string );
+};
+
+[
+ _dereq_('./apply'),
+ _dereq_('./bypass'),
+ _dereq_('./container'),
+ _dereq_('./get-for-ele'),
+ _dereq_('./json'),
+ _dereq_('./string-sheet'),
+ _dereq_('./properties'),
+ _dereq_('./parse')
+].forEach(function( props ){
+ util.extend( styfn, props );
+});
+
+
+Style.types = styfn.types;
+Style.properties = styfn.properties;
+
+module.exports = Style;
+
+},{"../is":77,"../selector":81,"../util":94,"./apply":82,"./bypass":83,"./container":84,"./get-for-ele":85,"./json":87,"./parse":88,"./properties":89,"./string-sheet":90}],87:[function(_dereq_,module,exports){
+'use strict';
+
+var styfn = {};
+
+styfn.applyFromJson = function( json ){
+ var style = this;
+
+ for( var i = 0; i < json.length; i++ ){
+ var context = json[i];
+ var selector = context.selector;
+ var props = context.style || context.css;
+
+ style.selector( selector ); // apply selector
+
+ for( var name in props ){
+ var value = props[name];
+
+ style.css( name, value ); // apply property
+ }
+ }
+
+ return style;
+};
+
+// accessible cy.style() function
+styfn.fromJson = function( json ){
+ var style = this;
+
+ style.resetToDefault();
+ style.applyFromJson( json );
+
+ return style;
+};
+
+// get json from cy.style() api
+styfn.json = function(){
+ var json = [];
+
+ for( var i = this.defaultLength; i < this.length; i++ ){
+ var cxt = this[i];
+ var selector = cxt.selector;
+ var props = cxt.properties;
+ var css = {};
+
+ for( var j = 0; j < props.length; j++ ){
+ var prop = props[j];
+ css[ prop.name ] = prop.strValue;
+ }
+
+ json.push({
+ selector: !selector ? 'core' : selector.toString(),
+ style: css
+ });
+ }
+
+ return json;
+};
+
+module.exports = styfn;
+
+},{}],88:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+var is = _dereq_('../is');
+
+var styfn = {};
+
+// a caching layer for property parsing
+styfn.parse = function( name, value, propIsBypass, propIsFlat ){
+ var argHash = [ name, value, propIsBypass, propIsFlat ].join('$');
+ var propCache = this.propCache = this.propCache || {};
+ var ret;
+ var impl = parseImpl.bind( this );
+
+ if( !(ret = propCache[argHash]) ){
+ ret = propCache[argHash] = impl( name, value, propIsBypass, propIsFlat );
+ }
+
+ // always need a copy since props are mutated later in their lifecycles
+ ret = util.copy( ret );
+
+ if( ret ){
+ ret.value = util.copy( ret.value ); // because it could be an array, e.g. colour
+ }
+
+ return ret;
+};
+
+// parse a property; return null on invalid; return parsed property otherwise
+// fields :
+// - name : the name of the property
+// - value : the parsed, native-typed value of the property
+// - strValue : a string value that represents the property value in valid css
+// - bypass : true iff the property is a bypass property
+var parseImpl = function( name, value, propIsBypass, propIsFlat ){
+ var self = this;
+
+ name = util.camel2dash( name ); // make sure the property name is in dash form (e.g. 'property-name' not 'propertyName')
+
+ var property = self.properties[ name ];
+ var passedValue = value;
+ var types = self.types;
+
+ if( !property ){ return null; } // return null on property of unknown name
+ if( value === undefined || value === null ){ return null; } // can't assign null
+
+ // the property may be an alias
+ if( property.alias ){
+ property = property.pointsTo;
+ name = property.name;
+ }
+
+ var valueIsString = is.string(value);
+ if( valueIsString ){ // trim the value to make parsing easier
+ value = value.trim();
+ }
+
+ var type = property.type;
+ if( !type ){ return null; } // no type, no luck
+
+ // check if bypass is null or empty string (i.e. indication to delete bypass property)
+ if( propIsBypass && (value === '' || value === null) ){
+ return {
+ name: name,
+ value: value,
+ bypass: true,
+ deleteBypass: true
+ };
+ }
+
+ // check if value is a function used as a mapper
+ if( is.fn(value) ){
+ return {
+ name: name,
+ value: value,
+ strValue: 'fn',
+ mapped: types.fn,
+ bypass: propIsBypass
+ };
+ }
+
+ // check if value is mapped
+ var data, mapData, layoutData, mapLayoutData, scratch, mapScratch;
+ if( !valueIsString || propIsFlat ){
+ // then don't bother to do the expensive regex checks
+
+ } else if(
+ ( data = new RegExp( types.data.regex ).exec( value ) ) ||
+ ( layoutData = new RegExp( types.layoutData.regex ).exec( value ) ) ||
+ ( scratch = new RegExp( types.scratch.regex ).exec( value ) )
+ ){
+ if( propIsBypass ){ return false; } // mappers not allowed in bypass
+
+ var mapped;
+ if( data ){
+ mapped = types.data;
+ } else if( layoutData ){
+ mapped = types.layoutData;
+ } else {
+ mapped = types.scratch;
+ }
+
+ data = data || layoutData || scratch;
+
+ return {
+ name: name,
+ value: data,
+ strValue: '' + value,
+ mapped: mapped,
+ field: data[1],
+ bypass: propIsBypass
+ };
+
+ } else if(
+ ( mapData = new RegExp( types.mapData.regex ).exec( value ) ) ||
+ ( mapLayoutData = new RegExp( types.mapLayoutData.regex ).exec( value ) ) ||
+ ( mapScratch = new RegExp( types.mapScratch.regex ).exec( value ) )
+ ){
+ if( propIsBypass ){ return false; } // mappers not allowed in bypass
+ if( type.multiple ){ return false; } // impossible to map to num
+
+ var mapped;
+ if( mapData ){
+ mapped = types.mapData;
+ } else if( mapLayoutData ){
+ mapped = types.mapLayoutData;
+ } else {
+ mapped = types.mapScratch;
+ }
+
+ mapData = mapData || mapLayoutData || mapScratch;
+
+ // we can map only if the type is a colour or a number
+ if( !(type.color || type.number) ){ return false; }
+
+ var valueMin = this.parse( name, mapData[4] ); // parse to validate
+ if( !valueMin || valueMin.mapped ){ return false; } // can't be invalid or mapped
+
+ var valueMax = this.parse( name, mapData[5] ); // parse to validate
+ if( !valueMax || valueMax.mapped ){ return false; } // can't be invalid or mapped
+
+ // check if valueMin and valueMax are the same
+ if( valueMin.value === valueMax.value ){
+ return false; // can't make much of a mapper without a range
+
+ } else if( type.color ){
+ var c1 = valueMin.value;
+ var c2 = valueMax.value;
+
+ var same = c1[0] === c2[0] // red
+ && c1[1] === c2[1] // green
+ && c1[2] === c2[2] // blue
+ && ( // optional alpha
+ c1[3] === c2[3] // same alpha outright
+ || (
+ (c1[3] == null || c1[3] === 1) // full opacity for colour 1?
+ &&
+ (c2[3] == null || c2[3] === 1) // full opacity for colour 2?
+ )
+ )
+ ;
+
+ if( same ){ return false; } // can't make a mapper without a range
+ }
+
+ return {
+ name: name,
+ value: mapData,
+ strValue: '' + value,
+ mapped: mapped,
+ field: mapData[1],
+ fieldMin: parseFloat( mapData[2] ), // min & max are numeric
+ fieldMax: parseFloat( mapData[3] ),
+ valueMin: valueMin.value,
+ valueMax: valueMax.value,
+ bypass: propIsBypass
+ };
+ }
+
+ if( type.multiple && !propIsFlat ){
+ var vals;
+
+ if( valueIsString ){
+ vals = value.split(/\s+/);
+ } else if( is.array(value) ){
+ vals = value;
+ } else {
+ vals = [ value ];
+ }
+
+ if( type.evenMultiple && vals.length % 2 !== 0 ){ return null; }
+
+ var valArr = vals.map(function( v ){
+ var p = self.parse( name, v, propIsBypass, true );
+
+ if( p.pfValue != null ){
+ return p.pfValue;
+ } else {
+ return p.value;
+ }
+ });
+
+ return {
+ name: name,
+ value: valArr,
+ pfValue: valArr,
+ strValue: valArr.join(' '),
+ bypass: propIsBypass,
+ units: type.number && !type.unitless ? type.implicitUnits || 'px' : undefined
+ };
+ }
+
+ // several types also allow enums
+ var checkEnums = function(){
+ for( var i = 0; i < type.enums.length; i++ ){
+ var en = type.enums[i];
+
+ if( en === value ){
+ return {
+ name: name,
+ value: value,
+ strValue: '' + value,
+ bypass: propIsBypass
+ };
+ }
+ }
+
+ return null;
+ };
+
+ // check the type and return the appropriate object
+ if( type.number ){
+ var units;
+ var implicitUnits = 'px'; // not set => px
+
+ if( type.units ){ // use specified units if set
+ units = type.units;
+ }
+
+ if( type.implicitUnits ){
+ implicitUnits = type.implicitUnits;
+ }
+
+ if( !type.unitless ){
+ if( valueIsString ){
+ var unitsRegex = 'px|em' + (type.allowPercent ? '|\\%' : '');
+ if( units ){ unitsRegex = units; } // only allow explicit units if so set
+ var match = value.match( '^(' + util.regex.number + ')(' + unitsRegex + ')?' + '$' );
+
+ if( match ){
+ value = match[1];
+ units = match[2] || implicitUnits;
+ }
+
+ } else if( !units || type.implicitUnits ) {
+ units = implicitUnits; // implicitly px if unspecified
+ }
+ }
+
+ value = parseFloat( value );
+
+ // if not a number and enums not allowed, then the value is invalid
+ if( isNaN(value) && type.enums === undefined ){
+ return null;
+ }
+
+ // check if this number type also accepts special keywords in place of numbers
+ // (i.e. `left`, `auto`, etc)
+ if( isNaN(value) && type.enums !== undefined ){
+ value = passedValue;
+
+ return checkEnums();
+ }
+
+ // check if value must be an integer
+ if( type.integer && !is.integer(value) ){
+ return null;
+ }
+
+ // check value is within range
+ if( (type.min !== undefined && value < type.min)
+ || (type.max !== undefined && value > type.max)
+ ){
+ return null;
+ }
+
+ var ret = {
+ name: name,
+ value: value,
+ strValue: '' + value + (units ? units : ''),
+ units: units,
+ bypass: propIsBypass
+ };
+
+ // normalise value in pixels
+ if( type.unitless || (units !== 'px' && units !== 'em') ){
+ ret.pfValue = value;
+ } else {
+ ret.pfValue = ( units === 'px' || !units ? (value) : (this.getEmSizeInPixels() * value) );
+ }
+
+ // normalise value in ms
+ if( units === 'ms' || units === 's' ){
+ ret.pfValue = units === 'ms' ? value : 1000 * value;
+ }
+
+ // normalise value in rad
+ if( units === 'deg' || units === 'rad' ){
+ ret.pfValue = units === 'rad' ? value : value * Math.PI/180;
+ }
+
+ return ret;
+
+ } else if( type.propList ) {
+
+ var props = [];
+ var propsStr = '' + value;
+
+ if( propsStr === 'none' ){
+ // leave empty
+
+ } else { // go over each prop
+
+ var propsSplit = propsStr.split(',');
+ for( var i = 0; i < propsSplit.length; i++ ){
+ var propName = propsSplit[i].trim();
+
+ if( self.properties[propName] ){
+ props.push( propName );
+ }
+ }
+
+ if( props.length === 0 ){ return null; }
+ }
+
+ return {
+ name: name,
+ value: props,
+ strValue: props.length === 0 ? 'none' : props.join(', '),
+ bypass: propIsBypass
+ };
+
+ } else if( type.color ){
+ var tuple = util.color2tuple( value );
+
+ if( !tuple ){ return null; }
+
+ return {
+ name: name,
+ value: tuple,
+ strValue: '' + value,
+ bypass: propIsBypass,
+ roundValue: true
+ };
+
+ } else if( type.regex || type.regexes ){
+
+ // first check enums
+ if( type.enums ){
+ var enumProp = checkEnums();
+
+ if( enumProp ){ return enumProp; }
+ }
+
+ var regexes = type.regexes ? type.regexes : [ type.regex ];
+
+ for( var i = 0; i < regexes.length; i++ ){
+ var regex = new RegExp( regexes[i] ); // make a regex from the type string
+ var m = regex.exec( value );
+
+ if( m ){ // regex matches
+ return {
+ name: name,
+ value: m,
+ strValue: '' + value,
+ bypass: propIsBypass
+ };
+
+ }
+ }
+
+ return null; // didn't match any
+
+ } else if( type.string ){
+ // just return
+ return {
+ name: name,
+ value: value,
+ strValue: '' + value,
+ bypass: propIsBypass
+ };
+
+ } else if( type.enums ){ // check enums last because it's a combo type in others
+ return checkEnums();
+
+ } else {
+ return null; // not a type we can handle
+ }
+
+};
+
+module.exports = styfn;
+
+},{"../is":77,"../util":94}],89:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+
+var styfn = {};
+
+(function(){
+ var number = util.regex.number;
+ var rgba = util.regex.rgbaNoBackRefs;
+ var hsla = util.regex.hslaNoBackRefs;
+ var hex3 = util.regex.hex3;
+ var hex6 = util.regex.hex6;
+ var data = function( prefix ){ return '^' + prefix + '\\s*\\(\\s*([\\w\\.]+)\\s*\\)$'; };
+ var mapData = function( prefix ){
+ var mapArg = number + '|\\w+|' + rgba + '|' + hsla + '|' + hex3 + '|' + hex6;
+ return '^' + prefix + '\\s*\\(([\\w\\.]+)\\s*\\,\\s*(' + number + ')\\s*\\,\\s*(' + number + ')\\s*,\\s*(' + mapArg + ')\\s*\\,\\s*(' + mapArg + ')\\)$';
+ };
+
+ // each visual style property has a type and needs to be validated according to it
+ styfn.types = {
+ time: { number: true, min: 0, units: 's|ms', implicitUnits: 'ms' },
+ percent: { number: true, min: 0, max: 100, units: '%', implicitUnits: '%' },
+ zeroOneNumber: { number: true, min: 0, max: 1, unitless: true },
+ nOneOneNumber: { number: true, min: -1, max: 1, unitless: true },
+ nonNegativeInt: { number: true, min: 0, integer: true, unitless: true },
+ position: { enums: ['parent', 'origin'] },
+ nodeSize: { number: true, min: 0, enums: ['auto', 'label'] },
+ number: { number: true, unitless: true },
+ numbers: { number: true, unitless: true, multiple: true },
+ size: { number: true, min: 0 },
+ bidirectionalSize: { number: true }, // allows negative
+ bidirectionalSizes: { number: true, multiple: true }, // allows negative
+ bgSize: { number: true, min: 0, allowPercent: true },
+ bgWH: { number: true, min: 0, allowPercent: true, enums: ['auto'] },
+ bgPos: { number: true, allowPercent: true },
+ bgRepeat: { enums: ['repeat', 'repeat-x', 'repeat-y', 'no-repeat'] },
+ bgFit: { enums: ['none', 'contain', 'cover'] },
+ bgClip: { enums: ['none', 'node'] },
+ color: { color: true },
+ bool: { enums: ['yes', 'no'] },
+ lineStyle: { enums: ['solid', 'dotted', 'dashed'] },
+ borderStyle: { enums: ['solid', 'dotted', 'dashed', 'double'] },
+ curveStyle: { enums: ['bezier', 'unbundled-bezier', 'haystack', 'segments'] },
+ fontFamily: { regex: '^([\\w- \\"]+(?:\\s*,\\s*[\\w- \\"]+)*)$' },
+ fontVariant: { enums: ['small-caps', 'normal'] },
+ fontStyle: { enums: ['italic', 'normal', 'oblique'] },
+ fontWeight: { enums: ['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '800', '900', 100, 200, 300, 400, 500, 600, 700, 800, 900] },
+ textDecoration: { enums: ['none', 'underline', 'overline', 'line-through'] },
+ textTransform: { enums: ['none', 'uppercase', 'lowercase'] },
+ textWrap: { enums: ['none', 'wrap'] },
+ textBackgroundShape: { enums: ['rectangle', 'roundrectangle']},
+ nodeShape: { enums: ['rectangle', 'roundrectangle', 'ellipse', 'triangle', 'square', 'pentagon', 'hexagon', 'heptagon', 'octagon', 'star', 'diamond', 'vee', 'rhomboid', 'polygon'] },
+ compoundIncludeLabels: { enums: ['include', 'exclude'] },
+ arrowShape: { enums: ['tee', 'triangle', 'triangle-tee', 'triangle-backcurve', 'half-triangle-overshot', 'vee', 'square', 'circle', 'diamond', 'none'] },
+ arrowFill: { enums: ['filled', 'hollow'] },
+ display: { enums: ['element', 'none'] },
+ visibility: { enums: ['hidden', 'visible'] },
+ valign: { enums: ['top', 'center', 'bottom'] },
+ halign: { enums: ['left', 'center', 'right'] },
+ text: { string: true },
+ data: { mapping: true, regex: data('data') },
+ layoutData: { mapping: true, regex: data('layoutData') },
+ scratch: { mapping: true, regex: data('scratch') },
+ mapData: { mapping: true, regex: mapData('mapData') },
+ mapLayoutData: { mapping: true, regex: mapData('mapLayoutData') },
+ mapScratch: { mapping: true, regex: mapData('mapScratch') },
+ fn: { mapping: true, fn: true },
+ url: { regex: '^url\\s*\\(\\s*([^\\s]+)\\s*\\s*\\)|none|(.+)$' },
+ propList: { propList: true },
+ angle: { number: true, units: 'deg|rad', implicitUnits: 'rad' },
+ textRotation: { enums: ['none', 'autorotate'] },
+ polygonPointList: { number: true, multiple: true, evenMultiple: true, min: -1, max: 1, unitless: true },
+ easing: {
+ regexes: [
+ '^(spring)\\s*\\(\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*\\)$',
+ '^(cubic-bezier)\\s*\\(\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*,\\s*(' + number + ')\\s*\\)$'
+ ],
+ enums: [
+ 'linear',
+ 'ease', 'ease-in', 'ease-out', 'ease-in-out',
+ 'ease-in-sine', 'ease-out-sine', 'ease-in-out-sine',
+ 'ease-in-quad', 'ease-out-quad', 'ease-in-out-quad',
+ 'ease-in-cubic', 'ease-out-cubic', 'ease-in-out-cubic',
+ 'ease-in-quart', 'ease-out-quart', 'ease-in-out-quart',
+ 'ease-in-quint', 'ease-out-quint', 'ease-in-out-quint',
+ 'ease-in-expo', 'ease-out-expo', 'ease-in-out-expo',
+ 'ease-in-circ', 'ease-out-circ', 'ease-in-out-circ'
+ ]
+ }
+ };
+
+ // define visual style properties
+ var t = styfn.types;
+ var props = styfn.properties = [
+ // labels
+ { name: 'text-valign', type: t.valign },
+ { name: 'text-halign', type: t.halign },
+ { name: 'color', type: t.color },
+ { name: 'label', type: t.text },
+ { name: 'text-outline-color', type: t.color },
+ { name: 'text-outline-width', type: t.size },
+ { name: 'text-outline-opacity', type: t.zeroOneNumber },
+ { name: 'text-opacity', type: t.zeroOneNumber },
+ { name: 'text-background-color', type: t.color },
+ { name: 'text-background-opacity', type: t.zeroOneNumber },
+ { name: 'text-border-opacity', type: t.zeroOneNumber },
+ { name: 'text-border-color', type: t.color },
+ { name: 'text-border-width', type: t.size },
+ { name: 'text-border-style', type: t.borderStyle },
+ { name: 'text-background-shape', type: t.textBackgroundShape},
+ // { name: 'text-decoration', type: t.textDecoration }, // not supported in canvas
+ { name: 'text-transform', type: t.textTransform },
+ { name: 'text-wrap', type: t.textWrap },
+ { name: 'text-max-width', type: t.size },
+ { name: 'text-events', type: t.bool },
+
+ // { name: 'text-rotation', type: t.angle }, // TODO disabled b/c rotation breaks bounding boxes
+ { name: 'font-family', type: t.fontFamily },
+ { name: 'font-style', type: t.fontStyle },
+ // { name: 'font-variant', type: t.fontVariant }, // not useful
+ { name: 'font-weight', type: t.fontWeight },
+ { name: 'font-size', type: t.size },
+ { name: 'min-zoomed-font-size', type: t.size },
+ { name: 'edge-text-rotation', type: t.textRotation },
+
+ // behaviour
+ { name: 'events', type: t.bool },
+
+ // visibility
+ { name: 'display', type: t.display },
+ { name: 'visibility', type: t.visibility },
+ { name: 'opacity', type: t.zeroOneNumber },
+ { name: 'z-index', type: t.nonNegativeInt },
+
+ // overlays
+ { name: 'overlay-padding', type: t.size },
+ { name: 'overlay-color', type: t.color },
+ { name: 'overlay-opacity', type: t.zeroOneNumber },
+
+ // shadows
+ { name: 'shadow-blur', type: t.size },
+ { name: 'shadow-color', type: t.color },
+ { name: 'shadow-opacity', type: t.zeroOneNumber },
+ { name: 'shadow-offset-x', type: t.bidirectionalSize },
+ { name: 'shadow-offset-y', type: t.bidirectionalSize },
+
+ // label shadows
+ { name: 'text-shadow-blur', type: t.size },
+ { name: 'text-shadow-color', type: t.color },
+ { name: 'text-shadow-opacity', type: t.zeroOneNumber },
+ { name: 'text-shadow-offset-x', type: t.bidirectionalSize },
+ { name: 'text-shadow-offset-y', type: t.bidirectionalSize },
+
+ // transition anis
+ { name: 'transition-property', type: t.propList },
+ { name: 'transition-duration', type: t.time },
+ { name: 'transition-delay', type: t.time },
+ { name: 'transition-timing-function', type: t.easing },
+
+ // node body
+ { name: 'height', type: t.nodeSize },
+ { name: 'width', type: t.nodeSize },
+ { name: 'shape', type: t.nodeShape },
+ { name: 'shape-polygon-points', type: t.polygonPointList },
+ { name: 'background-color', type: t.color },
+ { name: 'background-opacity', type: t.zeroOneNumber },
+ { name: 'background-blacken', type: t.nOneOneNumber },
+ { name: 'padding-left', type: t.size },
+ { name: 'padding-right', type: t.size },
+ { name: 'padding-top', type: t.size },
+ { name: 'padding-bottom', type: t.size },
+
+ // node border
+ { name: 'border-color', type: t.color },
+ { name: 'border-opacity', type: t.zeroOneNumber },
+ { name: 'border-width', type: t.size },
+ { name: 'border-style', type: t.borderStyle },
+
+ // node background images
+ { name: 'background-image', type: t.url },
+ { name: 'background-image-opacity', type: t.zeroOneNumber },
+ { name: 'background-position-x', type: t.bgPos },
+ { name: 'background-position-y', type: t.bgPos },
+ { name: 'background-repeat', type: t.bgRepeat },
+ { name: 'background-fit', type: t.bgFit },
+ { name: 'background-clip', type: t.bgClip },
+ { name: 'background-width', type: t.bgWH },
+ { name: 'background-height', type: t.bgWH },
+
+ // compound props
+ { name: 'position', type: t.position },
+ { name: 'compound-sizing-wrt-labels', type: t.compoundIncludeLabels },
+
+ // edge line
+ { name: 'line-style', type: t.lineStyle },
+ { name: 'line-color', type: t.color },
+ { name: 'curve-style', type: t.curveStyle },
+ { name: 'haystack-radius', type: t.zeroOneNumber },
+ { name: 'control-point-step-size', type: t.size },
+ { name: 'control-point-distances', type: t.bidirectionalSizes },
+ { name: 'control-point-weights', type: t.numbers },
+ { name: 'segment-distances', type: t.bidirectionalSizes },
+ { name: 'segment-weights', type: t.numbers },
+
+ // these are just for the core
+ { name: 'selection-box-color', type: t.color },
+ { name: 'selection-box-opacity', type: t.zeroOneNumber },
+ { name: 'selection-box-border-color', type: t.color },
+ { name: 'selection-box-border-width', type: t.size },
+ { name: 'active-bg-color', type: t.color },
+ { name: 'active-bg-opacity', type: t.zeroOneNumber },
+ { name: 'active-bg-size', type: t.size },
+ { name: 'outside-texture-bg-color', type: t.color },
+ { name: 'outside-texture-bg-opacity', type: t.zeroOneNumber }
+ ];
+
+ // define aliases
+ var aliases = styfn.aliases = [
+ { name: 'content', pointsTo: 'label' },
+ { name: 'control-point-distance', pointsTo: 'control-point-distances' },
+ { name: 'control-point-weight', pointsTo: 'control-point-weights' }
+ ];
+
+ // pie backgrounds for nodes
+ styfn.pieBackgroundN = 16; // because the pie properties are numbered, give access to a constant N (for renderer use)
+ props.push({ name: 'pie-size', type: t.bgSize });
+ for( var i = 1; i <= styfn.pieBackgroundN; i++ ){
+ props.push({ name: 'pie-'+i+'-background-color', type: t.color });
+ props.push({ name: 'pie-'+i+'-background-size', type: t.percent });
+ props.push({ name: 'pie-'+i+'-background-opacity', type: t.zeroOneNumber });
+ }
+
+ // edge arrows
+ var arrowPrefixes = styfn.arrowPrefixes = ['source', 'mid-source', 'target', 'mid-target'];
+ [
+ { name: 'arrow-shape', type: t.arrowShape },
+ { name: 'arrow-color', type: t.color },
+ { name: 'arrow-fill', type: t.arrowFill }
+ ].forEach(function( prop ){
+ arrowPrefixes.forEach(function( prefix ){
+ var name = prefix + '-' + prop.name;
+ var type = prop.type;
+
+ props.push({ name: name, type: type });
+ });
+ }, {});
+
+ // list of property names
+ styfn.propertyNames = props.map(function(p){ return p.name; });
+
+ // allow access of properties by name ( e.g. style.properties.height )
+ for( var i = 0; i < props.length; i++ ){
+ var prop = props[i];
+
+ props[ prop.name ] = prop; // allow lookup by name
+ }
+
+ // map aliases
+ for( var i = 0; i < aliases.length; i++ ){
+ var alias = aliases[i];
+ var pointsToProp = props[ alias.pointsTo ];
+ var aliasProp = {
+ name: alias.name,
+ alias: true,
+ pointsTo: pointsToProp
+ };
+
+ // add alias prop for parsing
+ props.push( aliasProp );
+
+ props[ alias.name ] = aliasProp; // allow lookup by name
+ }
+})();
+
+// adds the default stylesheet to the current style
+styfn.addDefaultStylesheet = function(){
+ // fill the style with the default stylesheet
+ this
+ .selector('node, edge') // common properties
+ .css( util.extend( {
+ 'events': 'yes',
+ 'text-events': 'no',
+ 'text-valign': 'top',
+ 'text-halign': 'center',
+ 'color': '#000',
+ 'text-outline-color': '#000',
+ 'text-outline-width': 0,
+ 'text-outline-opacity': 1,
+ 'text-opacity': 1,
+ 'text-decoration': 'none',
+ 'text-transform': 'none',
+ 'text-wrap': 'none',
+ 'text-max-width': 9999,
+ 'text-background-color': '#000',
+ 'text-background-opacity': 0,
+ 'text-border-opacity': 0,
+ 'text-border-width': 0,
+ 'text-border-style': 'solid',
+ 'text-border-color':'#000',
+ 'text-background-shape':'rectangle',
+ 'font-family': 'Helvetica Neue, Helvetica, sans-serif',
+ 'font-style': 'normal',
+ // 'font-variant': fontVariant,
+ 'font-weight': 'normal',
+ 'font-size': 16,
+ 'min-zoomed-font-size': 0,
+ 'edge-text-rotation': 'none',
+ 'visibility': 'visible',
+ 'display': 'element',
+ 'opacity': 1,
+ 'z-index': 0,
+ 'label': '',
+ 'overlay-opacity': 0,
+ 'overlay-color': '#000',
+ 'overlay-padding': 10,
+ 'shadow-opacity': 0,
+ 'shadow-color': '#000',
+ 'shadow-blur': 10,
+ 'shadow-offset-x': 0,
+ 'shadow-offset-y': 0,
+ 'text-shadow-opacity': 0,
+ 'text-shadow-color': '#000',
+ 'text-shadow-blur': 5,
+ 'text-shadow-offset-x': 0,
+ 'text-shadow-offset-y': 0,
+ 'transition-property': 'none',
+ 'transition-duration': 0,
+ 'transition-delay': 0,
+ 'transition-timing-function': 'linear',
+
+ // node props
+ 'background-blacken': 0,
+ 'background-color': '#888',
+ 'background-opacity': 1,
+ 'background-image': 'none',
+ 'background-image-opacity': 1,
+ 'background-position-x': '50%',
+ 'background-position-y': '50%',
+ 'background-repeat': 'no-repeat',
+ 'background-fit': 'none',
+ 'background-clip': 'node',
+ 'background-width': 'auto',
+ 'background-height': 'auto',
+ 'border-color': '#000',
+ 'border-opacity': 1,
+ 'border-width': 0,
+ 'border-style': 'solid',
+ 'height': 30,
+ 'width': 30,
+ 'shape': 'ellipse',
+ 'shape-polygon-points': '-1, -1, 1, -1, 1, 1, -1, 1',
+
+ // compound props
+ 'padding-top': 0,
+ 'padding-bottom': 0,
+ 'padding-left': 0,
+ 'padding-right': 0,
+ 'position': 'origin',
+ 'compound-sizing-wrt-labels': 'include',
+ }, {
+ // node pie bg
+ 'pie-size': '100%'
+ }, [
+ { name: 'pie-{{i}}-background-color', value: 'black' },
+ { name: 'pie-{{i}}-background-size', value: '0%' },
+ { name: 'pie-{{i}}-background-opacity', value: 1 }
+ ].reduce(function( css, prop ){
+ for( var i = 1; i <= styfn.pieBackgroundN; i++ ){
+ var name = prop.name.replace('{{i}}', i);
+ var val = prop.value;
+
+ css[ name ] = val;
+ }
+
+ return css;
+ }, {}), {
+ // edge props
+ 'line-style': 'solid',
+ 'line-color': '#ddd',
+ 'control-point-step-size': 40,
+ 'control-point-weights': 0.5,
+ 'segment-weights': 0.25,
+ 'segment-distances': 20,
+ 'curve-style': 'bezier',
+ 'haystack-radius': 0.8
+ }, [
+ { name: 'arrow-shape', value: 'none' },
+ { name: 'arrow-color', value: '#ddd' },
+ { name: 'arrow-fill', value: 'filled' }
+ ].reduce(function( css, prop ){
+ styfn.arrowPrefixes.forEach(function( prefix ){
+ var name = prefix + '-' + prop.name;
+ var val = prop.value;
+
+ css[ name ] = val;
+ });
+
+ return css;
+ }, {}) ) )
+ .selector('$node > node') // compound (parent) node properties
+ .css({
+ 'width': 'auto',
+ 'height': 'auto',
+ 'shape': 'rectangle',
+ 'padding-top': 10,
+ 'padding-right': 10,
+ 'padding-left': 10,
+ 'padding-bottom': 10
+ })
+ .selector('edge') // just edge properties
+ .css({
+ 'width': 1
+ })
+ .selector(':active')
+ .css({
+ 'overlay-color': 'black',
+ 'overlay-padding': 10,
+ 'overlay-opacity': 0.25
+ })
+ .selector('core') // just core properties
+ .css({
+ 'selection-box-color': '#ddd',
+ 'selection-box-opacity': 0.65,
+ 'selection-box-border-color': '#aaa',
+ 'selection-box-border-width': 1,
+ 'active-bg-color': 'black',
+ 'active-bg-opacity': 0.15,
+ 'active-bg-size': 30,
+ 'outside-texture-bg-color': '#000',
+ 'outside-texture-bg-opacity': 0.125
+ })
+ ;
+
+ this.defaultLength = this.length;
+};
+
+module.exports = styfn;
+
+},{"../util":94}],90:[function(_dereq_,module,exports){
+'use strict';
+
+var util = _dereq_('../util');
+var Selector = _dereq_('../selector');
+
+var styfn = {};
+
+styfn.applyFromString = function( string ){
+ var self = this;
+ var style = this;
+ var remaining = '' + string;
+ var selAndBlockStr;
+ var blockRem;
+ var propAndValStr;
+
+ // remove comments from the style string
+ remaining = remaining.replace(/[/][*](\s|.)+?[*][/]/g, '');
+
+ function removeSelAndBlockFromRemaining(){
+ // remove the parsed selector and block from the remaining text to parse
+ if( remaining.length > selAndBlockStr.length ){
+ remaining = remaining.substr( selAndBlockStr.length );
+ } else {
+ remaining = '';
+ }
+ }
+
+ function removePropAndValFromRem(){
+ // remove the parsed property and value from the remaining block text to parse
+ if( blockRem.length > propAndValStr.length ){
+ blockRem = blockRem.substr( propAndValStr.length );
+ } else {
+ blockRem = '';
+ }
+ }
+
+ while(true){
+ var nothingLeftToParse = remaining.match(/^\s*$/);
+ if( nothingLeftToParse ){ break; }
+
+ var selAndBlock = remaining.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);
+
+ if( !selAndBlock ){
+ util.error('Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining);
+ break;
+ }
+
+ selAndBlockStr = selAndBlock[0];
+
+ // parse the selector
+ var selectorStr = selAndBlock[1];
+ if( selectorStr !== 'core' ){
+ var selector = new Selector( selectorStr );
+ if( selector._private.invalid ){
+ util.error('Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr);
+
+ // skip this selector and block
+ removeSelAndBlockFromRemaining();
+ continue;
+ }
+ }
+
+ // parse the block of properties and values
+ var blockStr = selAndBlock[2];
+ var invalidBlock = false;
+ blockRem = blockStr;
+ var props = [];
+
+ while(true){
+ var nothingLeftToParse = blockRem.match(/^\s*$/);
+ if( nothingLeftToParse ){ break; }
+
+ var propAndVal = blockRem.match(/^\s*(.+?)\s*:\s*(.+?)\s*;/);
+
+ if( !propAndVal ){
+ util.error('Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr);
+ invalidBlock = true;
+ break;
+ }
+
+ propAndValStr = propAndVal[0];
+ var propStr = propAndVal[1];
+ var valStr = propAndVal[2];
+
+ var prop = self.properties[ propStr ];
+ if( !prop ){
+ util.error('Skipping property: Invalid property name in: ' + propAndValStr);
+
+ // skip this property in the block
+ removePropAndValFromRem();
+ continue;
+ }
+
+ var parsedProp = style.parse( propStr, valStr );
+
+ if( !parsedProp ){
+ util.error('Skipping property: Invalid property definition in: ' + propAndValStr);
+
+ // skip this property in the block
+ removePropAndValFromRem();
+ continue;
+ }
+
+ props.push({
+ name: propStr,
+ val: valStr
+ });
+ removePropAndValFromRem();
+ }
+
+ if( invalidBlock ){
+ removeSelAndBlockFromRemaining();
+ break;
+ }
+
+ // put the parsed block in the style
+ style.selector( selectorStr );
+ for( var i = 0; i < props.length; i++ ){
+ var prop = props[i];
+ style.css( prop.name, prop.val );
+ }
+
+ removeSelAndBlockFromRemaining();
+ }
+
+ return style;
+};
+
+styfn.fromString = function( string ){
+ var style = this;
+
+ style.resetToDefault();
+ style.applyFromString( string );
+
+ return style;
+};
+
+module.exports = styfn;
+
+},{"../selector":81,"../util":94}],91:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('./is');
+var util = _dereq_('./util');
+var Style = _dereq_('./style');
+
+// a dummy stylesheet object that doesn't need a reference to the core
+// (useful for init)
+var Stylesheet = function(){
+ if( !(this instanceof Stylesheet) ){
+ return new Stylesheet();
+ }
+
+ this.length = 0;
+};
+
+var sheetfn = Stylesheet.prototype;
+
+sheetfn.instanceString = function(){
+ return 'stylesheet';
+};
+
+// just store the selector to be parsed later
+sheetfn.selector = function( selector ){
+ var i = this.length++;
+
+ this[i] = {
+ selector: selector,
+ properties: []
+ };
+
+ return this; // chaining
+};
+
+// just store the property to be parsed later
+sheetfn.css = function( name, value ){
+ var i = this.length - 1;
+
+ if( is.string(name) ){
+ this[i].properties.push({
+ name: name,
+ value: value
+ });
+ } else if( is.plainObject(name) ){
+ var map = name;
+
+ for( var j = 0; j < Style.properties.length; j++ ){
+ var prop = Style.properties[j];
+ var mapVal = map[ prop.name ];
+
+ if( mapVal === undefined ){ // also try camel case name
+ mapVal = map[ util.dash2camel(prop.name) ];
+ }
+
+ if( mapVal !== undefined ){
+ var name = prop.name;
+ var value = mapVal;
+
+ this[i].properties.push({
+ name: name,
+ value: value
+ });
+ }
+ }
+ }
+
+ return this; // chaining
+};
+
+sheetfn.style = sheetfn.css;
+
+// generate a real style object from the dummy stylesheet
+sheetfn.generateStyle = function( cy ){
+ var style = new Style(cy);
+
+ for( var i = 0; i < this.length; i++ ){
+ var context = this[i];
+ var selector = context.selector;
+ var props = context.properties;
+
+ style.selector(selector); // apply selector
+
+ for( var j = 0; j < props.length; j++ ){
+ var prop = props[j];
+
+ style.css( prop.name, prop.value ); // apply property
+ }
+ }
+
+ return style;
+};
+
+module.exports = Stylesheet;
+
+},{"./is":77,"./style":86,"./util":94}],92:[function(_dereq_,module,exports){
+// cross-env thread/worker
+// NB : uses (heavyweight) processes on nodejs so best not to create too many threads
+
+'use strict';
+
+var window = _dereq_('./window');
+var util = _dereq_('./util');
+var Promise = _dereq_('./promise');
+var Event = _dereq_('./event');
+var define = _dereq_('./define');
+var is = _dereq_('./is');
+
+var Thread = function( opts ){
+ if( !(this instanceof Thread) ){
+ return new Thread( opts );
+ }
+
+ var _p = this._private = {
+ requires: [],
+ files: [],
+ queue: null,
+ pass: [],
+ disabled: false
+ };
+
+ if( is.plainObject(opts) ){
+ if( opts.disabled != null ){
+ _p.disabled = !!opts.disabled;
+ }
+ }
+
+};
+
+var thdfn = Thread.prototype; // short alias
+
+var stringifyFieldVal = function( val ){
+ var valStr = is.fn( val ) ? val.toString() : 'JSON.parse("' + JSON.stringify(val) + '")';
+
+ return valStr;
+};
+
+// allows for requires with prototypes and subobjs etc
+var fnAsRequire = function( fn ){
+ var req;
+ var fnName;
+
+ if( is.object(fn) && fn.fn ){ // manual fn
+ req = fnAs( fn.fn, fn.name );
+ fnName = fn.name;
+ fn = fn.fn;
+ } else if( is.fn(fn) ){ // auto fn
+ req = fn.toString();
+ fnName = fn.name;
+ } else if( is.string(fn) ){ // stringified fn
+ req = fn;
+ } else if( is.object(fn) ){ // plain object
+ if( fn.proto ){
+ req = '';
+ } else {
+ req = fn.name + ' = {};';
+ }
+
+ fnName = fn.name;
+ fn = fn.obj;
+ }
+
+ req += '\n';
+
+ var protoreq = function( val, subname ){
+ if( val.prototype ){
+ var protoNonempty = false;
+ for( var prop in val.prototype ){ protoNonempty = true; break; } // jshint ignore:line
+
+ if( protoNonempty ){
+ req += fnAsRequire( {
+ name: subname,
+ obj: val,
+ proto: true
+ }, val );
+ }
+ }
+ };
+
+ // pull in prototype
+ if( fn.prototype && fnName != null ){
+
+ for( var name in fn.prototype ){
+ var protoStr = '';
+
+ var val = fn.prototype[ name ];
+ var valStr = stringifyFieldVal( val );
+ var subname = fnName + '.prototype.' + name;
+
+ protoStr += subname + ' = ' + valStr + ';\n';
+
+ if( protoStr ){
+ req += protoStr;
+ }
+
+ protoreq( val, subname ); // subobject with prototype
+ }
+
+ }
+
+ // pull in properties for obj/fns
+ if( !is.string(fn) ){ for( var name in fn ){
+ var propsStr = '';
+
+ if( fn.hasOwnProperty(name) ){
+ var val = fn[ name ];
+ var valStr = stringifyFieldVal( val );
+ var subname = fnName + '["' + name + '"]';
+
+ propsStr += subname + ' = ' + valStr + ';\n';
+ }
+
+ if( propsStr ){
+ req += propsStr;
+ }
+
+ protoreq( val, subname ); // subobject with prototype
+ } }
+
+ return req;
+};
+
+var isPathStr = function( str ){
+ return is.string(str) && str.match(/\.js$/);
+};
+
+util.extend(thdfn, {
+
+ instanceString: function(){ return 'thread'; },
+
+ require: function( fn, as ){
+ var requires = this._private.requires;
+
+ if( isPathStr(fn) ){
+ this._private.files.push( fn );
+
+ return this;
+ }
+
+ if( as ){
+ if( is.fn(fn) ){
+ fn = { name: as, fn: fn };
+ } else {
+ fn = { name: as, obj: fn };
+ }
+ } else {
+ if( is.fn(fn) ){
+ if( !fn.name ){
+ throw 'The function name could not be automatically determined. Use thread.require( someFunction, "someFunction" )';
+ }
+
+ fn = { name: fn.name, fn: fn };
+ }
+ }
+
+ requires.push( fn );
+
+ return this; // chaining
+ },
+
+ pass: function( data ){
+ this._private.pass.push( data );
+
+ return this; // chaining
+ },
+
+ run: function( fn, pass ){ // fn used like main()
+ var self = this;
+ var _p = this._private;
+ pass = pass || _p.pass.shift();
+
+ if( _p.stopped ){
+ throw 'Attempted to run a stopped thread! Start a new thread or do not stop the existing thread and reuse it.';
+ }
+
+ if( _p.running ){
+ return ( _p.queue = _p.queue.then(function(){ // inductive step
+ return self.run( fn, pass );
+ }) );
+ }
+
+ var useWW = window != null && !_p.disabled;
+ var useNode = !window && typeof module !== 'undefined' && !_p.disabled;
+
+ self.trigger('run');
+
+ var runP = new Promise(function( resolve, reject ){
+
+ _p.running = true;
+
+ var threadTechAlreadyExists = _p.ran;
+
+ var fnImplStr = is.string( fn ) ? fn : fn.toString();
+
+ // worker code to exec
+ var fnStr = '\n' + ( _p.requires.map(function( r ){
+ return fnAsRequire( r );
+ }) ).concat( _p.files.map(function( f ){
+ if( useWW ){
+ var wwifyFile = function( file ){
+ if( file.match(/^\.\//) || file.match(/^\.\./) ){
+ return window.location.origin + window.location.pathname + file;
+ } else if( file.match(/^\//) ){
+ return window.location.origin + '/' + file;
+ }
+ return file;
+ };
+
+ return 'importScripts("' + wwifyFile(f) + '");';
+ } else if( useNode ) {
+ return 'eval( require("fs").readFileSync("' + f + '", { encoding: "utf8" }) );';
+ } else {
+ throw 'External file `' + f + '` can not be required without any threading technology.';
+ }
+ }) ).concat([
+ '( function(){',
+ 'var ret = (' + fnImplStr + ')(' + JSON.stringify(pass) + ');',
+ 'if( ret !== undefined ){ resolve(ret); }', // assume if ran fn returns defined value (incl. null), that we want to resolve to it
+ '} )()\n'
+ ]).join('\n');
+
+ // because we've now consumed the requires, empty the list so we don't dupe on next run()
+ _p.requires = [];
+ _p.files = [];
+
+ if( useWW ){
+ var fnBlob, fnUrl;
+
+ // add normalised thread api functions
+ if( !threadTechAlreadyExists ){
+ var fnPre = fnStr + '';
+
+ fnStr = [
+ 'function _ref_(o){ return eval(o); };',
+ 'function broadcast(m){ return message(m); };', // alias
+ 'function message(m){ postMessage(m); };',
+ 'function listen(fn){',
+ ' self.addEventListener("message", function(m){ ',
+ ' if( typeof m === "object" && (m.data.$$eval || m.data === "$$start") ){',
+ ' } else { ',
+ ' fn( m.data );',
+ ' }',
+ ' });',
+ '};',
+ 'self.addEventListener("message", function(m){ if( m.data.$$eval ){ eval( m.data.$$eval ); } });',
+ 'function resolve(v){ postMessage({ $$resolve: v }); };',
+ 'function reject(v){ postMessage({ $$reject: v }); };'
+ ].join('\n');
+
+ fnStr += fnPre;
+
+ fnBlob = new Blob([ fnStr ], {
+ type: 'application/javascript'
+ });
+ fnUrl = window.URL.createObjectURL( fnBlob );
+ }
+ // create webworker and let it exec the serialised code
+ var ww = _p.webworker = _p.webworker || new Worker( fnUrl );
+
+ if( threadTechAlreadyExists ){ // then just exec new run() code
+ ww.postMessage({
+ $$eval: fnStr
+ });
+ }
+
+ // worker messages => events
+ var cb;
+ ww.addEventListener('message', cb = function( m ){
+ var isObject = is.object(m) && is.object( m.data );
+
+ if( isObject && ('$$resolve' in m.data) ){
+ ww.removeEventListener('message', cb); // done listening b/c resolve()
+
+ resolve( m.data.$$resolve );
+ } else if( isObject && ('$$reject' in m.data) ){
+ ww.removeEventListener('message', cb); // done listening b/c reject()
+
+ reject( m.data.$$reject );
+ } else {
+ self.trigger( new Event(m, { type: 'message', message: m.data }) );
+ }
+ }, false);
+
+ if( !threadTechAlreadyExists ){
+ ww.postMessage('$$start'); // start up the worker
+ }
+
+ } else if( useNode ){
+ // create a new process
+
+ if( !_p.child ){
+ _p.child = ( _dereq_('child_process').fork( _dereq_('path').join(__dirname, 'thread-node-fork') ) );
+ }
+
+ var child = _p.child;
+
+ // child process messages => events
+ var cb;
+ child.on('message', cb = function( m ){
+ if( is.object(m) && ('$$resolve' in m) ){
+ child.removeListener('message', cb); // done listening b/c resolve()
+
+ resolve( m.$$resolve );
+ } else if( is.object(m) && ('$$reject' in m) ){
+ child.removeListener('message', cb); // done listening b/c reject()
+
+ reject( m.$$reject );
+ } else {
+ self.trigger( new Event({}, { type: 'message', message: m }) );
+ }
+ });
+
+ // ask the child process to eval the worker code
+ child.send({
+ $$eval: fnStr
+ });
+
+ } else { // use a fallback mechanism using a timeout
+
+ var promiseResolve = resolve;
+ var promiseReject = reject;
+
+ var timer = _p.timer = _p.timer || {
+
+ listeners: [],
+
+ exec: function(){
+ // as a string so it can't be mangled by minifiers and processors
+ fnStr = [
+ 'function _ref_(o){ return eval(o); };',
+ 'function broadcast(m){ return message(m); };',
+ 'function message(m){ self.trigger( new Event({}, { type: "message", message: m }) ); };',
+ 'function listen(fn){ timer.listeners.push( fn ); };',
+ 'function resolve(v){ promiseResolve(v); };',
+ 'function reject(v){ promiseReject(v); };'
+ ].join('\n') + fnStr;
+
+ // the .run() code
+ eval( fnStr ); // jshint ignore:line
+ },
+
+ message: function( m ){
+ var ls = timer.listeners;
+
+ for( var i = 0; i < ls.length; i++ ){
+ var fn = ls[i];
+
+ fn( m );
+ }
+ }
+
+ };
+
+ timer.exec();
+ }
+
+ }).then(function( v ){
+ _p.running = false;
+ _p.ran = true;
+
+ self.trigger('ran');
+
+ return v;
+ });
+
+ if( _p.queue == null ){
+ _p.queue = runP; // i.e. first step of inductive promise chain (for queue)
+ }
+
+ return runP;
+ },
+
+ // send the thread a message
+ message: function( m ){
+ var _p = this._private;
+
+ if( _p.webworker ){
+ _p.webworker.postMessage( m );
+ }
+
+ if( _p.child ){
+ _p.child.send( m );
+ }
+
+ if( _p.timer ){
+ _p.timer.message( m );
+ }
+
+ return this; // chaining
+ },
+
+ stop: function(){
+ var _p = this._private;
+
+ if( _p.webworker ){
+ _p.webworker.terminate();
+ }
+
+ if( _p.child ){
+ _p.child.kill();
+ }
+
+ if( _p.timer ){
+ // nothing we can do if we've run a timeout
+ }
+
+ _p.stopped = true;
+
+ return this.trigger('stop'); // chaining
+ },
+
+ stopped: function(){
+ return this._private.stopped;
+ }
+
+});
+
+// turns a stringified function into a (re)named function
+var fnAs = function( fn, name ){
+ var fnStr = fn.toString();
+ fnStr = fnStr.replace(/function\s*?\S*?\s*?\(/, 'function ' + name + '(');
+
+ return fnStr;
+};
+
+var defineFnal = function( opts ){
+ opts = opts || {};
+
+ return function fnalImpl( fn, arg1 ){
+ var fnStr = fnAs( fn, '_$_$_' + opts.name );
+
+ this.require( fnStr );
+
+ return this.run( [
+ 'function( data ){',
+ ' var origResolve = resolve;',
+ ' var res = [];',
+ ' ',
+ ' resolve = function( val ){',
+ ' res.push( val );',
+ ' };',
+ ' ',
+ ' var ret = data.' + opts.name + '( _$_$_' + opts.name + ( arguments.length > 1 ? ', ' + JSON.stringify(arg1) : '' ) + ' );',
+ ' ',
+ ' resolve = origResolve;',
+ ' resolve( res.length > 0 ? res : ret );',
+ '}'
+ ].join('\n') );
+ };
+};
+
+util.extend(thdfn, {
+ reduce: defineFnal({ name: 'reduce' }),
+
+ reduceRight: defineFnal({ name: 'reduceRight' }),
+
+ map: defineFnal({ name: 'map' })
+});
+
+// aliases
+var fn = thdfn;
+fn.promise = fn.run;
+fn.terminate = fn.halt = fn.stop;
+fn.include = fn.require;
+
+// pull in event apis
+util.extend(thdfn, {
+ on: define.on(),
+ one: define.on({ unbindSelfOnTrigger: true }),
+ off: define.off(),
+ trigger: define.trigger()
+});
+
+define.eventAliasesOn( thdfn );
+
+module.exports = Thread;
+
+},{"./define":41,"./event":42,"./is":77,"./promise":80,"./util":94,"./window":100,"child_process":undefined,"path":undefined}],93:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+
+module.exports = {
+ // get [r, g, b] from #abc or #aabbcc
+ hex2tuple: function( hex ){
+ if( !(hex.length === 4 || hex.length === 7) || hex[0] !== "#" ){ return; }
+
+ var shortHex = hex.length === 4;
+ var r, g, b;
+ var base = 16;
+
+ if( shortHex ){
+ r = parseInt( hex[1] + hex[1], base );
+ g = parseInt( hex[2] + hex[2], base );
+ b = parseInt( hex[3] + hex[3], base );
+ } else {
+ r = parseInt( hex[1] + hex[2], base );
+ g = parseInt( hex[3] + hex[4], base );
+ b = parseInt( hex[5] + hex[6], base );
+ }
+
+ return [r, g, b];
+ },
+
+ // get [r, g, b, a] from hsl(0, 0, 0) or hsla(0, 0, 0, 0)
+ hsl2tuple: function( hsl ){
+ var ret;
+ var h, s, l, a, r, g, b;
+ function hue2rgb(p, q, t){
+ if(t < 0) t += 1;
+ if(t > 1) t -= 1;
+ if(t < 1/6) return p + (q - p) * 6 * t;
+ if(t < 1/2) return q;
+ if(t < 2/3) return p + (q - p) * (2/3 - t) * 6;
+ return p;
+ }
+
+ var m = new RegExp("^" + this.regex.hsla + "$").exec(hsl);
+ if( m ){
+
+ // get hue
+ h = parseInt( m[1] );
+ if( h < 0 ){
+ h = ( 360 - (-1*h % 360) ) % 360;
+ } else if( h > 360 ){
+ h = h % 360;
+ }
+ h /= 360; // normalise on [0, 1]
+
+ s = parseFloat( m[2] );
+ if( s < 0 || s > 100 ){ return; } // saturation is [0, 100]
+ s = s/100; // normalise on [0, 1]
+
+ l = parseFloat( m[3] );
+ if( l < 0 || l > 100 ){ return; } // lightness is [0, 100]
+ l = l/100; // normalise on [0, 1]
+
+ a = m[4];
+ if( a !== undefined ){
+ a = parseFloat( a );
+
+ if( a < 0 || a > 1 ){ return; } // alpha is [0, 1]
+ }
+
+ // now, convert to rgb
+ // code from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
+ if( s === 0 ){
+ r = g = b = Math.round(l * 255); // achromatic
+ } else {
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ var p = 2 * l - q;
+ r = Math.round( 255 * hue2rgb(p, q, h + 1/3) );
+ g = Math.round( 255 * hue2rgb(p, q, h) );
+ b = Math.round( 255 * hue2rgb(p, q, h - 1/3) );
+ }
+
+ ret = [r, g, b, a];
+ }
+
+ return ret;
+ },
+
+ // get [r, g, b, a] from rgb(0, 0, 0) or rgba(0, 0, 0, 0)
+ rgb2tuple: function( rgb ){
+ var ret;
+
+ var m = new RegExp("^" + this.regex.rgba + "$").exec(rgb);
+ if( m ){
+ ret = [];
+
+ var isPct = [];
+ for( var i = 1; i <= 3; i++ ){
+ var channel = m[i];
+
+ if( channel[ channel.length - 1 ] === "%" ){
+ isPct[i] = true;
+ }
+ channel = parseFloat( channel );
+
+ if( isPct[i] ){
+ channel = channel/100 * 255; // normalise to [0, 255]
+ }
+
+ if( channel < 0 || channel > 255 ){ return; } // invalid channel value
+
+ ret.push( Math.floor(channel) );
+ }
+
+ var atLeastOneIsPct = isPct[1] || isPct[2] || isPct[3];
+ var allArePct = isPct[1] && isPct[2] && isPct[3];
+ if( atLeastOneIsPct && !allArePct ){ return; } // must all be percent values if one is
+
+ var alpha = m[4];
+ if( alpha !== undefined ){
+ alpha = parseFloat( alpha );
+
+ if( alpha < 0 || alpha > 1 ){ return; } // invalid alpha value
+
+ ret.push( alpha );
+ }
+ }
+
+ return ret;
+ },
+
+ colorname2tuple: function( color ){
+ return this.colors[ color.toLowerCase() ];
+ },
+
+ color2tuple: function( color ){
+ return ( is.array(color) ? color : null )
+ || this.colorname2tuple(color)
+ || this.hex2tuple(color)
+ || this.rgb2tuple(color)
+ || this.hsl2tuple(color);
+ },
+
+ colors: {
+ // special colour names
+ transparent: [0, 0, 0, 0], // NB alpha === 0
+
+ // regular colours
+ aliceblue: [240, 248, 255],
+ antiquewhite: [250, 235, 215],
+ aqua: [0, 255, 255],
+ aquamarine: [127, 255, 212],
+ azure: [240, 255, 255],
+ beige: [245, 245, 220],
+ bisque: [255, 228, 196],
+ black: [0, 0, 0],
+ blanchedalmond: [255, 235, 205],
+ blue: [0, 0, 255],
+ blueviolet: [138, 43, 226],
+ brown: [165, 42, 42],
+ burlywood: [222, 184, 135],
+ cadetblue: [95, 158, 160],
+ chartreuse: [127, 255, 0],
+ chocolate: [210, 105, 30],
+ coral: [255, 127, 80],
+ cornflowerblue: [100, 149, 237],
+ cornsilk: [255, 248, 220],
+ crimson: [220, 20, 60],
+ cyan: [0, 255, 255],
+ darkblue: [0, 0, 139],
+ darkcyan: [0, 139, 139],
+ darkgoldenrod: [184, 134, 11],
+ darkgray: [169, 169, 169],
+ darkgreen: [0, 100, 0],
+ darkgrey: [169, 169, 169],
+ darkkhaki: [189, 183, 107],
+ darkmagenta: [139, 0, 139],
+ darkolivegreen: [85, 107, 47],
+ darkorange: [255, 140, 0],
+ darkorchid: [153, 50, 204],
+ darkred: [139, 0, 0],
+ darksalmon: [233, 150, 122],
+ darkseagreen: [143, 188, 143],
+ darkslateblue: [72, 61, 139],
+ darkslategray: [47, 79, 79],
+ darkslategrey: [47, 79, 79],
+ darkturquoise: [0, 206, 209],
+ darkviolet: [148, 0, 211],
+ deeppink: [255, 20, 147],
+ deepskyblue: [0, 191, 255],
+ dimgray: [105, 105, 105],
+ dimgrey: [105, 105, 105],
+ dodgerblue: [30, 144, 255],
+ firebrick: [178, 34, 34],
+ floralwhite: [255, 250, 240],
+ forestgreen: [34, 139, 34],
+ fuchsia: [255, 0, 255],
+ gainsboro: [220, 220, 220],
+ ghostwhite: [248, 248, 255],
+ gold: [255, 215, 0],
+ goldenrod: [218, 165, 32],
+ gray: [128, 128, 128],
+ grey: [128, 128, 128],
+ green: [0, 128, 0],
+ greenyellow: [173, 255, 47],
+ honeydew: [240, 255, 240],
+ hotpink: [255, 105, 180],
+ indianred: [205, 92, 92],
+ indigo: [75, 0, 130],
+ ivory: [255, 255, 240],
+ khaki: [240, 230, 140],
+ lavender: [230, 230, 250],
+ lavenderblush: [255, 240, 245],
+ lawngreen: [124, 252, 0],
+ lemonchiffon: [255, 250, 205],
+ lightblue: [173, 216, 230],
+ lightcoral: [240, 128, 128],
+ lightcyan: [224, 255, 255],
+ lightgoldenrodyellow: [250, 250, 210],
+ lightgray: [211, 211, 211],
+ lightgreen: [144, 238, 144],
+ lightgrey: [211, 211, 211],
+ lightpink: [255, 182, 193],
+ lightsalmon: [255, 160, 122],
+ lightseagreen: [32, 178, 170],
+ lightskyblue: [135, 206, 250],
+ lightslategray: [119, 136, 153],
+ lightslategrey: [119, 136, 153],
+ lightsteelblue: [176, 196, 222],
+ lightyellow: [255, 255, 224],
+ lime: [0, 255, 0],
+ limegreen: [50, 205, 50],
+ linen: [250, 240, 230],
+ magenta: [255, 0, 255],
+ maroon: [128, 0, 0],
+ mediumaquamarine: [102, 205, 170],
+ mediumblue: [0, 0, 205],
+ mediumorchid: [186, 85, 211],
+ mediumpurple: [147, 112, 219],
+ mediumseagreen: [60, 179, 113],
+ mediumslateblue: [123, 104, 238],
+ mediumspringgreen: [0, 250, 154],
+ mediumturquoise: [72, 209, 204],
+ mediumvioletred: [199, 21, 133],
+ midnightblue: [25, 25, 112],
+ mintcream: [245, 255, 250],
+ mistyrose: [255, 228, 225],
+ moccasin: [255, 228, 181],
+ navajowhite: [255, 222, 173],
+ navy: [0, 0, 128],
+ oldlace: [253, 245, 230],
+ olive: [128, 128, 0],
+ olivedrab: [107, 142, 35],
+ orange: [255, 165, 0],
+ orangered: [255, 69, 0],
+ orchid: [218, 112, 214],
+ palegoldenrod: [238, 232, 170],
+ palegreen: [152, 251, 152],
+ paleturquoise: [175, 238, 238],
+ palevioletred: [219, 112, 147],
+ papayawhip: [255, 239, 213],
+ peachpuff: [255, 218, 185],
+ peru: [205, 133, 63],
+ pink: [255, 192, 203],
+ plum: [221, 160, 221],
+ powderblue: [176, 224, 230],
+ purple: [128, 0, 128],
+ red: [255, 0, 0],
+ rosybrown: [188, 143, 143],
+ royalblue: [65, 105, 225],
+ saddlebrown: [139, 69, 19],
+ salmon: [250, 128, 114],
+ sandybrown: [244, 164, 96],
+ seagreen: [46, 139, 87],
+ seashell: [255, 245, 238],
+ sienna: [160, 82, 45],
+ silver: [192, 192, 192],
+ skyblue: [135, 206, 235],
+ slateblue: [106, 90, 205],
+ slategray: [112, 128, 144],
+ slategrey: [112, 128, 144],
+ snow: [255, 250, 250],
+ springgreen: [0, 255, 127],
+ steelblue: [70, 130, 180],
+ tan: [210, 180, 140],
+ teal: [0, 128, 128],
+ thistle: [216, 191, 216],
+ tomato: [255, 99, 71],
+ turquoise: [64, 224, 208],
+ violet: [238, 130, 238],
+ wheat: [245, 222, 179],
+ white: [255, 255, 255],
+ whitesmoke: [245, 245, 245],
+ yellow: [255, 255, 0],
+ yellowgreen: [154, 205, 50]
+ }
+};
+
+},{"../is":77}],94:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+var math = _dereq_('../math');
+
+var util = {
+
+ falsify: function(){ return false; },
+
+ zeroify: function(){ return 0; },
+
+ noop: function(){},
+
+ /* jshint ignore:start */
+ error: function( msg ){
+ if( console.error ){
+ console.error.apply( console, arguments );
+
+ if( console.trace ){ console.trace(); }
+ } else {
+ console.log.apply( console, arguments );
+
+ if( console.trace ){ console.trace(); }
+ }
+ },
+ /* jshint ignore:end */
+
+ clone: function( obj ){
+ return this.extend( {}, obj );
+ },
+
+ // gets a shallow copy of the argument
+ copy: function( obj ){
+ if( obj == null ){
+ return obj;
+ } if( is.array(obj) ){
+ return obj.slice();
+ } else if( is.plainObject(obj) ){
+ return this.clone( obj );
+ } else {
+ return obj;
+ }
+ }
+
+};
+
+util.makeBoundingBox = math.makeBoundingBox.bind( math );
+
+util._staticEmptyObject = {};
+
+util.staticEmptyObject = function(){
+ return util._staticEmptyObject;
+};
+
+util.extend = Object.assign != null ? Object.assign : function( tgt ){
+ var args = arguments;
+
+ for( var i = 1; i < args.length; i++ ){
+ var obj = args[i];
+
+ for( var k in obj ){
+ tgt[k] = obj[k];
+ }
+ }
+
+ return tgt;
+};
+
+[
+ _dereq_('./colors'),
+ _dereq_('./maps'),
+ { memoize: _dereq_('./memoize') },
+ _dereq_('./regex'),
+ _dereq_('./strings'),
+ _dereq_('./timing')
+].forEach(function( req ){
+ util.extend( util, req );
+});
+
+module.exports = util;
+
+},{"../is":77,"../math":79,"./colors":93,"./maps":95,"./memoize":96,"./regex":97,"./strings":98,"./timing":99}],95:[function(_dereq_,module,exports){
+'use strict';
+
+var is = _dereq_('../is');
+
+module.exports = {
+ // has anything been set in the map
+ mapEmpty: function( map ){
+ var empty = true;
+
+ if( map != null ){
+ for(var i in map){ // jshint ignore:line
+ empty = false;
+ break;
+ }
+ }
+
+ return empty;
+ },
+
+ // pushes to the array at the end of a map (map may not be built)
+ pushMap: function( options ){
+ var array = this.getMap(options);
+
+ if( array == null ){ // if empty, put initial array
+ this.setMap( this.extend({}, options, {
+ value: [ options.value ]
+ }) );
+ } else {
+ array.push( options.value );
+ }
+ },
+
+ // sets the value in a map (map may not be built)
+ setMap: function( options ){
+ var obj = options.map;
+ var key;
+ var keys = options.keys;
+ var l = keys.length;
+
+ for(var i = 0; i < l; i++){
+ var key = keys[i];
+
+ if( is.plainObject( key ) ){
+ this.error('Tried to set map with object key');
+ }
+
+ if( i < keys.length - 1 ){
+
+ // extend the map if necessary
+ if( obj[key] == null ){
+ obj[key] = {};
+ }
+
+ obj = obj[key];
+ } else {
+ // set the value
+ obj[key] = options.value;
+ }
+ }
+ },
+
+ // gets the value in a map even if it's not built in places
+ getMap: function( options ){
+ var obj = options.map;
+ var keys = options.keys;
+ var l = keys.length;
+
+ for(var i = 0; i < l; i++){
+ var key = keys[i];
+
+ if( is.plainObject( key ) ){
+ this.error('Tried to get map with object key');
+ }
+
+ obj = obj[key];
+
+ if( obj == null ){
+ return obj;
+ }
+ }
+
+ return obj;
+ },
+
+ // deletes the entry in the map
+ deleteMap: function( options ){
+ var obj = options.map;
+ var keys = options.keys;
+ var l = keys.length;
+ var keepChildren = options.keepChildren;
+
+ for(var i = 0; i < l; i++){
+ var key = keys[i];
+
+ if( is.plainObject( key ) ){
+ this.error('Tried to delete map with object key');
+ }
+
+ var lastKey = i === options.keys.length - 1;
+ if( lastKey ){
+
+ if( keepChildren ){ // then only delete child fields not in keepChildren
+ for( var child in obj ){
+ if( !keepChildren[child] ){
+ obj[child] = undefined;
+ }
+ }
+ } else {
+ obj[key] = undefined;
+ }
+
+ } else {
+ obj = obj[key];
+ }
+ }
+ }
+};
+
+},{"../is":77}],96:[function(_dereq_,module,exports){
+'use strict';
+
+module.exports = function memoize( fn, keyFn ){
+ var self = this;
+ var cache = {};
+
+ if( !keyFn ){
+ keyFn = function(){
+ if( arguments.length === 1 ){
+ return arguments[0];
+ }
+
+ var args = [];
+
+ for( var i = 0; i < arguments.length; i++ ){
+ args.push( arguments[i] );
+ }
+
+ return args.join('$');
+ };
+ }
+
+ return function memoizedFn(){
+ var args = arguments;
+ var ret;
+ var k = keyFn.apply( self, args );
+
+ if( !(ret = cache[k]) ){
+ ret = cache[k] = fn.apply( self, args );
+ }
+
+ return ret;
+ };
+};
+
+},{}],97:[function(_dereq_,module,exports){
+'use strict';
+
+var number = "(?:[-+]?(?:(?:\\d+|\\d*\\.\\d+)(?:[Ee][+-]?\\d+)?))";
+
+var rgba = "rgb[a]?\\(("+ number +"[%]?)\\s*,\\s*("+ number +"[%]?)\\s*,\\s*("+ number +"[%]?)(?:\\s*,\\s*("+ number +"))?\\)";
+var rgbaNoBackRefs = "rgb[a]?\\((?:"+ number +"[%]?)\\s*,\\s*(?:"+ number +"[%]?)\\s*,\\s*(?:"+ number +"[%]?)(?:\\s*,\\s*(?:"+ number +"))?\\)";
+
+var hsla = "hsl[a]?\\(("+ number +")\\s*,\\s*("+ number +"[%])\\s*,\\s*("+ number +"[%])(?:\\s*,\\s*("+ number +"))?\\)";
+var hslaNoBackRefs = "hsl[a]?\\((?:"+ number +")\\s*,\\s*(?:"+ number +"[%])\\s*,\\s*(?:"+ number +"[%])(?:\\s*,\\s*(?:"+ number +"))?\\)";
+
+var hex3 = "\\#[0-9a-fA-F]{3}";
+var hex6 = "\\#[0-9a-fA-F]{6}";
+
+module.exports = {
+ regex: {
+ number: number,
+ rgba: rgba,
+ rgbaNoBackRefs: rgbaNoBackRefs,
+ hsla: hsla,
+ hslaNoBackRefs: hslaNoBackRefs,
+ hex3: hex3,
+ hex6: hex6
+ }
+};
+
+},{}],98:[function(_dereq_,module,exports){
+'use strict';
+
+var memoize = _dereq_('./memoize');
+var is = _dereq_('../is');
+
+module.exports = {
+
+ camel2dash: memoize( function( str ){
+ return str.replace(/([A-Z])/g, function( v ){
+ return '-' + v.toLowerCase();
+ });
+ } ),
+
+ dash2camel: memoize( function( str ){
+ return str.replace(/(-\w)/g, function( v ){
+ return v[1].toUpperCase();
+ });
+ } ),
+
+ capitalize: function(str){
+ if( is.emptyString(str) ){
+ return str;
+ }
+
+ return str.charAt(0).toUpperCase() + str.substring(1);
+ }
+
+};
+
+},{"../is":77,"./memoize":96}],99:[function(_dereq_,module,exports){
+'use strict';
+
+var window = _dereq_('../window');
+var is = _dereq_('../is');
+var performance = window ? window.performance : null;
+
+var util = {};
+
+var raf = !window ? null : ( window.requestAnimationFrame || window.mozRequestAnimationFrame ||
+ window.webkitRequestAnimationFrame || window.msRequestAnimationFrame );
+
+raf = raf || function( fn ){
+ if( fn ){
+ setTimeout(function(){
+ fn( pnow() );
+ }, 1000/60);
+ }
+};
+
+util.requestAnimationFrame = function(fn){
+ raf( fn );
+};
+
+var pnow = performance && performance.now ? function(){ return performance.now(); } : function(){ return Date.now(); };
+
+util.performanceNow = pnow;
+
+// ported lodash throttle function
+util.throttle = function(func, wait, options) {
+ var leading = true,
+ trailing = true;
+
+ if (options === false) {
+ leading = false;
+ } else if (is.plainObject(options)) {
+ leading = 'leading' in options ? options.leading : leading;
+ trailing = 'trailing' in options ? options.trailing : trailing;
+ }
+ options = options || {};
+ options.leading = leading;
+ options.maxWait = wait;
+ options.trailing = trailing;
+
+ return util.debounce(func, wait, options);
+};
+
+util.now = function(){
+ return Date.now();
+};
+
+util.debounce = function(func, wait, options) { // ported lodash debounce function
+ var util = this;
+ var args,
+ maxTimeoutId,
+ result,
+ stamp,
+ thisArg,
+ timeoutId,
+ trailingCall,
+ lastCalled = 0,
+ maxWait = false,
+ trailing = true;
+
+ if (!is.fn(func)) {
+ return;
+ }
+ wait = Math.max(0, wait) || 0;
+ if (options === true) {
+ var leading = true;
+ trailing = false;
+ } else if (is.plainObject(options)) {
+ leading = options.leading;
+ maxWait = 'maxWait' in options && (Math.max(wait, options.maxWait) || 0);
+ trailing = 'trailing' in options ? options.trailing : trailing;
+ }
+ var delayed = function() {
+ var remaining = wait - (util.now() - stamp);
+ if (remaining <= 0) {
+ if (maxTimeoutId) {
+ clearTimeout(maxTimeoutId);
+ }
+ var isCalled = trailingCall;
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (isCalled) {
+ lastCalled = util.now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ }
+ } else {
+ timeoutId = setTimeout(delayed, remaining);
+ }
+ };
+
+ var maxDelayed = function() {
+ if (timeoutId) {
+ clearTimeout(timeoutId);
+ }
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (trailing || (maxWait !== wait)) {
+ lastCalled = util.now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ }
+ };
+
+ return function() {
+ args = arguments;
+ stamp = util.now();
+ thisArg = this;
+ trailingCall = trailing && (timeoutId || !leading);
+
+ if (maxWait === false) {
+ var leadingCall = leading && !timeoutId;
+ } else {
+ if (!maxTimeoutId && !leading) {
+ lastCalled = stamp;
+ }
+ var remaining = maxWait - (stamp - lastCalled),
+ isCalled = remaining <= 0;
+
+ if (isCalled) {
+ if (maxTimeoutId) {
+ maxTimeoutId = clearTimeout(maxTimeoutId);
+ }
+ lastCalled = stamp;
+ result = func.apply(thisArg, args);
+ }
+ else if (!maxTimeoutId) {
+ maxTimeoutId = setTimeout(maxDelayed, remaining);
+ }
+ }
+ if (isCalled && timeoutId) {
+ timeoutId = clearTimeout(timeoutId);
+ }
+ else if (!timeoutId && wait !== maxWait) {
+ timeoutId = setTimeout(delayed, wait);
+ }
+ if (leadingCall) {
+ isCalled = true;
+ result = func.apply(thisArg, args);
+ }
+ if (isCalled && !timeoutId && !maxTimeoutId) {
+ args = thisArg = null;
+ }
+ return result;
+ };
+};
+
+module.exports = util;
+
+},{"../is":77,"../window":100}],100:[function(_dereq_,module,exports){
+module.exports = ( typeof window === 'undefined' ? null : window );
+
+},{}]},{},[76])(76)
+});
+
+
+//# sourceMappingURL=cytoscape.js.map
diff --git a/docs/htmldoc/js/cytoscape.js-panzoom.css b/docs/htmldoc/js/cytoscape.js-panzoom.css
new file mode 100644
index 0000000..46d9a36
--- /dev/null
+++ b/docs/htmldoc/js/cytoscape.js-panzoom.css
@@ -0,0 +1,203 @@
+.cy-panzoom {
+ position: fixed;
+ right: 70px;
+ top: 10px;
+ font-size: 13px;
+ color: #fff;
+ font-family: arial, helvetica, sans-serif;
+ line-height: 1;
+ color: #666;
+ font-size: 11px;
+ z-index: 99999;
+}
+
+.cy-panzoom-zoom-button {
+ cursor: pointer;
+ padding: 3px;
+ text-align: center;
+ position: absolute;
+ border-radius: 3px;
+ width: 10px;
+ height: 10px;
+ left: 16px;
+ background: #fff;
+ border: 1px solid #999;
+ margin-left: -1px;
+ margin-top: -1px;
+ z-index: 1;
+}
+
+.cy-panzoom-zoom-button:active,
+.cy-panzoom-slider-handle:active,
+.cy-panzoom-slider-handle.active {
+ background: #ddd;
+}
+
+.cy-panzoom-pan-button {
+ position: absolute;
+ z-index: 1;
+ height: 16px;
+ width: 16px;
+}
+
+.cy-panzoom-reset {
+ top: 55px;
+}
+
+.cy-panzoom-zoom-in {
+ top: 80px;
+}
+
+.cy-panzoom-zoom-out {
+ top: 197px;
+}
+
+.cy-panzoom-pan-up {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ width: 0;
+ height: 0;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-bottom: 5px solid #666;
+}
+
+.cy-panzoom-pan-down {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ width: 0;
+ height: 0;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-top: 5px solid #666;
+}
+
+.cy-panzoom-pan-left {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ width: 0;
+ height: 0;
+ border-top: 5px solid transparent;
+ border-bottom: 5px solid transparent;
+ border-right: 5px solid #666;
+}
+
+.cy-panzoom-pan-right {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ width: 0;
+ height: 0;
+ border-top: 5px solid transparent;
+ border-bottom: 5px solid transparent;
+ border-left: 5px solid #666;
+}
+
+.cy-panzoom-pan-indicator {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 8px;
+ height: 8px;
+ border-radius: 8px;
+ background: #000;
+ border-radius: 8px;
+ margin-left: -5px;
+ margin-top: -5px;
+ display: none;
+ z-index: 999;
+ opacity: 0.6;
+}
+
+.cy-panzoom-slider {
+ position: absolute;
+ top: 97px;
+ left: 17px;
+ height: 100px;
+ width: 15px;
+}
+
+.cy-panzoom-slider-background {
+ position: absolute;
+ top: 0;
+ width: 2px;
+ height: 100px;
+ left: 5px;
+ background: #fff;
+ border-left: 1px solid #999;
+ border-right: 1px solid #999;
+}
+
+.cy-panzoom-slider-handle {
+ position: absolute;
+ width: 16px;
+ height: 8px;
+ background: #fff;
+ border: 1px solid #999;
+ border-radius: 2px;
+ margin-left: -2px;
+ z-index: 999;
+ line-height: 8px;
+ cursor: default;
+}
+
+.cy-panzoom-slider-handle .icon {
+ margin: 0 4px;
+ line-height: 10px;
+}
+
+.cy-panzoom-no-zoom-tick {
+ position: absolute;
+ background: #666;
+ border: 1px solid #fff;
+ border-radius: 2px;
+ margin-left: -1px;
+ width: 8px;
+ height: 2px;
+ left: 3px;
+ z-index: 1;
+ margin-top: 3px;
+}
+
+.cy-panzoom-panner {
+ position: absolute;
+ left: 5px;
+ top: 5px;
+ height: 40px;
+ width: 40px;
+ background: #fff;
+ border: 1px solid #999;
+ border-radius: 40px;
+ margin-left: -1px;
+}
+
+.cy-panzoom-panner-handle {
+ position: absolute;
+ left: 0;
+ top: 0;
+ outline: none;
+ height: 40px;
+ width: 40px;
+ position: absolute;
+ z-index: 999;
+}
+
+.cy-panzoom-zoom-only .cy-panzoom-slider,
+.cy-panzoom-zoom-only .cy-panzoom-panner {
+ display: none;
+}
+
+.cy-panzoom-zoom-only .cy-panzoom-reset {
+ top: 20px;
+}
+
+.cy-panzoom-zoom-only .cy-panzoom-zoom-in {
+ top: 45px;
+}
+
+.cy-panzoom-zoom-only .cy-panzoom-zoom-out {
+ top: 70px;
+}
diff --git a/docs/htmldoc/js/cytoscape.min.js b/docs/htmldoc/js/cytoscape.min.js
new file mode 100644
index 0000000..a498936
--- /dev/null
+++ b/docs/htmldoc/js/cytoscape.min.js
@@ -0,0 +1,26 @@
+/*!
+ * This file is part of Cytoscape.js 2.5.1.
+ *
+ * Cytoscape.js is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * Cytoscape.js is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with
+ * Cytoscape.js. If not, see <http://www.gnu.org/licenses/>.
+ */
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.cytoscape=e()}}(function(){var define,module,exports;return function e(t,r,n){function i(o,s){if(!r[o]){if(!t[o]){var l="function"==typeof require&&require;if(!s&&l)return l(o,!0);if(a)return a(o,!0);var u=new Error("Cannot find module '"+o+"'");throw u.code="MODULE_NOT_FOUND",u}var c=r[o]={exports:{}};t[o][0].call(c.exports,function(e){var r=t[o][1][e];return i(r?r:e)},c,c.exports,e,t,r,n)}return r[o].exports}for(var a="function"==typeof require&&require,o=0;o<n.length;o++)i(n[o]);return i}({1:[function(e,t,r){"use strict";var n=e("./util"),i=e("./is"),a=e("./promise"),o=function(e,t,r){if(!(this instanceof o))return new o(e,t,r);var a=this._private=n.extend({duration:1e3},t,r);a.target=e,a.style=a.style||a.css,a.started=!1,a.playing=!1,a.hooked=!1,a.applying=!1,a.progress=0,a.completes=[],a.frames=[],a.complete&&i.fn(a.complete)&&a.completes.push(a.complete),this.length=1,this[0]=this},s=o.prototype;n.extend(s,{instanceString:function(){return"animation"},hook:function(){var e=this._private;if(!e.hooked){var t,r=e.target._private.animation;t=e.queue?r.queue:r.current,t.push(this),i.elementOrCollection(e.target)&&e.target.cy().addToAnimationPool(e.target),e.hooked=!0}return this},play:function(){var e=this._private;return 1===e.progress&&(e.progress=0),e.playing=!0,e.started=!1,e.stopped=!1,this.hook(),this},playing:function(){return this._private.playing},apply:function(){var e=this._private;return e.applying=!0,e.started=!1,e.stopped=!1,this.hook(),this},applying:function(){return this._private.applying},pause:function(){var e=this._private;return e.playing=!1,e.started=!1,this},stop:function(){var e=this._private;return e.playing=!1,e.started=!1,e.stopped=!0,this},rewind:function(){return this.progress(0)},fastforward:function(){return this.progress(1)},time:function(e){var t=this._private;return void 0===e?t.progress*t.duration:this.progress(e/t.duration)},progress:function(e){var t=this._private,r=t.playing;return void 0===e?t.progress:(r&&this.pause(),t.progress=e,t.started=!1,r&&this.play(),this)},completed:function(){return 1===this._private.progress},reverse:function(){var e=this._private,t=e.playing;t&&this.pause(),e.progress=1-e.progress,e.started=!1;var r=function(t,r){var n=e[t];e[t]=e[r],e[r]=n};r("zoom","startZoom"),r("pan","startPan"),r("position","startPosition");for(var i=0;i<e.style.length;i++){var a=e.style[i],o=a.name,s=e.startStyle[o];e.startStyle[o]=e.startStyle[n.dash2camel(o)]=a,e.style[i]=s}return t&&this.play(),this},promise:function(e){var t,r=this._private;switch(e){case"frame":t=r.frames;break;default:case"complete":case"completed":t=r.completes}return new a(function(e,r){t.push(function(){e()})})}}),s.complete=s.completed,t.exports=o},{"./is":77,"./promise":80,"./util":94}],2:[function(e,t,r){"use strict";var n=e("../../is"),i={aStar:function(e){var t=this;e=e||{};var r=function(e,t,n,i){if(e==t)return i.push(a.getElementById(t)),i;if(t in n){var o=n[t],s=v[t];return i.push(a.getElementById(t)),i.push(a.getElementById(s)),r(e,o,n,i)}return void 0},i=function(e,t){if(0===e.length)return void 0;for(var r=0,n=t[e[0]],i=1;i<e.length;i++){var a=t[e[i]];n>a&&(n=a,r=i)}return r},a=this._private.cy;if(null==e||null==e.root)return void 0;var o=n.string(e.root)?this.filter(e.root)[0]:e.root[0];if(null==e.goal)return void 0;var s=n.string(e.goal)?this.filter(e.goal)[0]:e.goal[0];if(null!=e.heuristic&&n.fn(e.heuristic))var l=e.heuristic;else var l=function(){return 0};if(null!=e.weight&&n.fn(e.weight))var u=e.weight;else var u=function(e){return 1};if(null!=e.directed)var c=e.directed;else var c=!1;var d=[],h=[o.id()],p={},v={},f={},g={};f[o.id()]=0,g[o.id()]=l(o);for(var y=this.edges().stdFilter(function(e){return!e.isLoop()}),m=this.nodes(),b=0;h.length>0;){var x=i(h,g),w=a.getElementById(h[x]);if(b++,w.id()==s.id()){var _=r(o.id(),s.id(),p,[]);return _.reverse(),{found:!0,distance:f[w.id()],path:t.spawn(_),steps:b}}d.push(w.id()),h.splice(x,1);var E=w.connectedEdges();c&&(E=E.stdFilter(function(e){return e.data("source")===w.id()})),E=E.intersect(y);for(var D=0;D<E.length;D++){var S=E[D],k=S.connectedNodes().stdFilter(function(e){return e.id()!==w.id()}).intersect(m);if(-1==d.indexOf(k.id())){var T=f[w.id()]+u.apply(S,[S]);-1!=h.indexOf(k.id())?T<f[k.id()]&&(f[k.id()]=T,g[k.id()]=T+l(k),p[k.id()]=w.id()):(f[k.id()]=T,g[k.id()]=T+l(k),h.push(k.id()),p[k.id()]=w.id(),v[k.id()]=S.id())}}}return{found:!1,distance:void 0,path:void 0,steps:b}}};t.exports=i},{"../../is":77}],3:[function(e,t,r){"use strict";var n=e("../../is"),i=e("../../util"),a={bellmanFord:function(e){var t=this;if(e=e||{},null!=e.weight&&n.fn(e.weight))var r=e.weight;else var r=function(e){return 1};if(null!=e.directed)var a=e.directed;else var a=!1;if(null==e.root)return void 0;if(n.string(e.root))var o=this.filter(e.root)[0];else var o=e.root[0];for(var s=this._private.cy,l=this.edges().stdFilter(function(e){return!e.isLoop()}),u=this.nodes(),c=u.length,d={},h=0;c>h;h++)d[u[h].id()]=h;for(var p=[],v=[],f=[],h=0;c>h;h++)u[h].id()===o.id()?p[h]=0:p[h]=1/0,v[h]=void 0;for(var g=!1,h=1;c>h;h++){g=!1;for(var y=0;y<l.length;y++){var m=d[l[y].source().id()],b=d[l[y].target().id()],x=r.apply(l[y],[l[y]]),w=p[m]+x;if(w<p[b]&&(p[b]=w,v[b]=m,f[b]=l[y],g=!0),!a){var w=p[b]+x;w<p[m]&&(p[m]=w,v[m]=b,f[m]=l[y],g=!0)}}if(!g)break}if(g)for(var y=0;y<l.length;y++){var m=d[l[y].source().id()],b=d[l[y].target().id()],x=r.apply(l[y],[l[y]]);if(p[m]+x<p[b])return i.error("Graph contains a negative weight cycle for Bellman-Ford"),{pathTo:void 0,distanceTo:void 0,hasNegativeWeightCycle:!0}}for(var _=[],h=0;c>h;h++)_.push(u[h].id());var E={distanceTo:function(e){if(n.string(e))var t=s.filter(e)[0].id();else var t=e.id();return p[d[t]]},pathTo:function(e){var r=function(e,t,r,n,i,a){for(;;){if(i.push(s.getElementById(n[r])),i.push(a[r]),t===r)return i;var o=e[r];if("undefined"==typeof o)return void 0;r=o}};if(n.string(e))var i=s.filter(e)[0].id();else var i=e.id();var a=[],l=r(v,d[o.id()],d[i],_,a,f);return null!=l&&l.reverse(),t.spawn(l)},hasNegativeWeightCycle:!1};return E}};t.exports=a},{"../../is":77,"../../util":94}],4:[function(e,t,r){"use strict";var n=e("../../is"),i={betweennessCentrality:function(e){if(e=e||{},null!=e.weight&&n.fn(e.weight))var t=e.weight,r=!0;else var r=!1;if(null!=e.directed&&n.bool(e.directed))var i=e.directed;else var i=!1;for(var a=function(e,t){e.unshift(t);for(var r=0;f[e[r]]<f[e[r+1]]&&r<e.length-1;r++){var n=e[r];e[r]=e[r+1],e[r+1]=n}},o=this._private.cy,s=this.nodes(),l={},u={},c=0;c<s.length;c++)i?l[s[c].id()]=s[c].outgoers("node"):l[s[c].id()]=s[c].openNeighborhood("node");for(var c=0;c<s.length;c++)u[s[c].id()]=0;for(var d=0;d<s.length;d++){for(var h=[],p={},v={},f={},g=[],c=0;c<s.length;c++)p[s[c].id()]=[],v[s[c].id()]=0,f[s[c].id()]=Number.POSITIVE_INFINITY;for(v[s[d].id()]=1,f[s[d].id()]=0,g.unshift(s[d].id());g.length>0;){var y=g.pop();h.push(y),r?l[y].forEach(function(e){if(o.$("#"+y).edgesTo(e).length>0)var r=o.$("#"+y).edgesTo(e)[0];else var r=e.edgesTo("#"+y)[0];var n=t.apply(r,[r]);f[e.id()]>f[y]+n&&(f[e.id()]=f[y]+n,g.indexOf(e.id())<0?a(g,e.id()):(g.splice(g.indexOf(e.id()),1),a(g,e.id())),v[e.id()]=0,p[e.id()]=[]),f[e.id()]==f[y]+n&&(v[e.id()]=v[e.id()]+v[y],p[e.id()].push(y))}):l[y].forEach(function(e){f[e.id()]==Number.POSITIVE_INFINITY&&(g.unshift(e.id()),f[e.id()]=f[y]+1),f[e.id()]==f[y]+1&&(v[e.id()]=v[e.id()]+v[y],p[e.id()].push(y))})}for(var m={},c=0;c<s.length;c++)m[s[c].id()]=0;for(;h.length>0;){var b=h.pop();p[b].forEach(function(e){m[e]=m[e]+v[e]/v[b]*(1+m[b]),b!=s[d].id()&&(u[b]=u[b]+m[b])})}}var x=0;for(var w in u)x<u[w]&&(x=u[w]);var _={betweenness:function(e){if(n.string(e))var e=o.filter(e)[0].id();else var e=e.id();return u[e]},betweennessNormalized:function(e){if(n.string(e))var e=o.filter(e)[0].id();else var e=e.id();return u[e]/x}};return _.betweennessNormalised=_.betweennessNormalized,_}};i.bc=i.betweennessCentrality,t.exports=i},{"../../is":77}],5:[function(e,t,r){"use strict";var n=e("../../is"),i=e("../../heap"),a=function(e){return e={bfs:e.bfs||!e.dfs,dfs:e.dfs||!e.bfs},function(t,r,i){var a,o,s;n.plainObject(t)&&!n.elementOrCollection(t)&&(a=t,t=a.roots||a.root,r=a.visit,i=a.directed,o=a.std,s=a.thisArg),i=2!==arguments.length||n.fn(r)?i:r,r=n.fn(r)?r:function(){};for(var l,u=this._private.cy,c=t=n.string(t)?this.filter(t):t,d=[],h=[],p={},v={},f={},g=0,y=this.nodes(),m=this.edges(),b=0;b<c.length;b++)c[b].isNode()&&(d.unshift(c[b]),e.bfs&&(f[c[b].id()]=!0,h.push(c[b])),v[c[b].id()]=0);for(;0!==d.length;){var c=e.bfs?d.shift():d.pop();if(e.dfs){if(f[c.id()])continue;f[c.id()]=!0,h.push(c)}var x,w=v[c.id()],_=p[c.id()],E=null==_?void 0:_.connectedNodes().not(c)[0];if(x=o?r.call(s,c,_,E,g++,w):r.call(c,g++,w,c,_,E),x===!0){l=c;break}if(x===!1)break;for(var D=c.connectedEdges(i?function(){return this.data("source")===c.id()}:void 0).intersect(m),b=0;b<D.length;b++){var S=D[b],k=S.connectedNodes(function(){return this.id()!==c.id()}).intersect(y);0===k.length||f[k.id()]||(k=k[0],d.push(k),e.bfs&&(f[k.id()]=!0,h.push(k)),p[k.id()]=S,v[k.id()]=v[c.id()]+1)}}for(var T=[],b=0;b<h.length;b++){var P=h[b],C=p[P.id()];C&&T.push(C),T.push(P)}return{path:u.collection(T,{unique:!0}),found:u.collection(l)}}},o={breadthFirstSearch:a({bfs:!0}),depthFirstSearch:a({dfs:!0}),kruskal:function(e){function t(e){for(var t=0;t<a.length;t++){var r=a[t];if(r.anySame(e))return{eles:r,index:t}}}var r=this.cy();e=n.fn(e)?e:function(){return 1};for(var i=r.collection(r,[]),a=[],o=this.nodes(),s=0;s<o.length;s++)a.push(o[s].collection());for(var l=this.edges(),u=l.toArray().sort(function(t,r){var n=e.call(t,t),i=e.call(r,r);return n-i}),s=0;s<u.length;s++){var c=u[s],d=c.source()[0],h=c.target()[0],p=t(d),v=t(h);p.index!==v.index&&(i=i.add(c),a[p.index]=p.eles.add(v.eles),a.splice(v.index,1))}return o.add(i)},dijkstra:function(e,t,r){var a;n.plainObject(e)&&!n.elementOrCollection(e)&&(a=e,e=a.root,t=a.weight,r=a.directed);var o=this._private.cy;t=n.fn(t)?t:function(){return 1};for(var s=n.string(e)?this.filter(e)[0]:e[0],l={},u={},c={},d=this.edges().filter(function(){return!this.isLoop()}),h=this.nodes(),p=function(e){return l[e.id()]},v=function(e,t){l[e.id()]=t,f.updateItem(e)},f=new i(function(e,t){return p(e)-p(t)}),g=0;g<h.length;g++){var y=h[g];l[y.id()]=y.same(s)?0:1/0,f.push(y)}for(var m=function(e,n){for(var i,a=(r?e.edgesTo(n):e.edgesWith(n)).intersect(d),o=1/0,s=0;s<a.length;s++){var l=a[s],u=t.apply(l,[l]);(o>u||!i)&&(o=u,i=l)}return{edge:i,dist:o}};f.size()>0;){var b=f.pop(),x=p(b),w=b.id();if(c[w]=x,x===Math.Infinite)break;for(var _=b.neighborhood().intersect(h),g=0;g<_.length;g++){var E=_[g],D=E.id(),S=m(b,E),k=x+S.dist;k<p(E)&&(v(E,k),u[D]={node:b,edge:S.edge})}}return{distanceTo:function(e){var t=n.string(e)?h.filter(e)[0]:e[0];return c[t.id()]},pathTo:function(e){var t=n.string(e)?h.filter(e)[0]:e[0],r=[],i=t;if(t.length>0)for(r.unshift(t);u[i.id()];){var a=u[i.id()];r.unshift(a.edge),r.unshift(a.node),i=a.node}return o.collection(r)}}}};o.bfs=o.breadthFirstSearch,o.dfs=o.depthFirstSearch,t.exports=o},{"../../heap":75,"../../is":77}],6:[function(e,t,r){"use strict";var n=e("../../is"),i={closenessCentralityNormalized:function(e){e=e||{};var t=this.cy(),r=e.harmonic;void 0===r&&(r=!0);for(var i={},a=0,o=this.nodes(),s=this.floydWarshall({weight:e.weight,directed:e.directed}),l=0;l<o.length;l++){for(var u=0,c=0;c<o.length;c++)if(l!=c){var d=s.distance(o[l],o[c]);u+=r?1/d:d}r||(u=1/u),u>a&&(a=u),i[o[l].id()]=u}return{closeness:function(e){if(n.string(e))var e=t.filter(e)[0].id();else var e=e.id();return i[e]/a}}},closenessCentrality:function(e){if(e=e||{},null==e.root)return void 0;if(n.string(e.root))var t=this.filter(e.root)[0];else var t=e.root[0];if(null!=e.weight&&n.fn(e.weight))var r=e.weight;else var r=function(){return 1};if(null!=e.directed&&n.bool(e.directed))var i=e.directed;else var i=!1;var a=e.harmonic;void 0===a&&(a=!0);for(var o=this.dijkstra({root:t,weight:r,directed:i}),s=0,l=this.nodes(),u=0;u<l.length;u++)if(l[u].id()!=t.id()){var c=o.distanceTo(l[u]);s+=a?1/c:c}return a?s:1/s}};i.cc=i.closenessCentrality,i.ccn=i.closenessCentralityNormalised=i.closenessCentralityNormalized,t.exports=i},{"../../is":77}],7:[function(e,t,r){"use strict";var n=e("../../is"),i=e("../../util"),a={degreeCentralityNormalized:function(e){e=e||{};var t=this.cy();if(null!=e.directed)var r=e.directed;else var r=!1;var a=this.nodes(),o=a.length;if(r){for(var s={},l={},u=0,c=0,d=0;o>d;d++){var h=a[d],p=this.degreeCentrality(i.extend({},e,{root:h}));u<p.indegree&&(u=p.indegree),c<p.outdegree&&(c=p.outdegree),s[h.id()]=p.indegree,l[h.id()]=p.outdegree}return{indegree:function(e){if(n.string(e))var e=t.filter(e)[0].id();else var e=e.id();return s[e]/u},outdegree:function(e){if(n.string(e))var e=t.filter(e)[0].id();else var e=e.id();return l[e]/c}}}for(var v={},f=0,d=0;o>d;d++){var h=a[d],p=this.degreeCentrality(i.extend({},e,{root:h}));f<p.degree&&(f=p.degree),v[h.id()]=p.degree}return{degree:function(e){if(n.string(e))var e=t.filter(e)[0].id();else var e=e.id();return v[e]/f}}},degreeCentrality:function(e){e=e||{};var t=this;if(null==e||null==e.root)return void 0;var r=n.string(e.root)?this.filter(e.root)[0]:e.root[0];if(null!=e.weight&&n.fn(e.weight))var i=e.weight;else var i=function(e){return 1};if(null!=e.directed)var a=e.directed;else var a=!1;if(null!=e.alpha&&n.number(e.alpha))var o=e.alpha;else o=0;if(a){for(var s=r.connectedEdges('edge[target = "'+r.id()+'"]').intersection(t),l=r.connectedEdges('edge[source = "'+r.id()+'"]').intersection(t),u=s.length,c=l.length,d=0,h=0,p=0;p<s.length;p++){var v=s[p];d+=i.apply(v,[v])}for(var p=0;p<l.length;p++){var v=l[p];h+=i.apply(v,[v])}return{indegree:Math.pow(u,1-o)*Math.pow(d,o),outdegree:Math.pow(c,1-o)*Math.pow(h,o)}}for(var f=r.connectedEdges().intersection(t),g=f.length,y=0,p=0;p<f.length;p++){var v=f[p];y+=i.apply(v,[v])}return{degree:Math.pow(g,1-o)*Math.pow(y,o)}}};a.dc=a.degreeCentrality,a.dcn=a.degreeCentralityNormalised=a.degreeCentralityNormalized,t.exports=a},{"../../is":77,"../../util":94}],8:[function(e,t,r){"use strict";var n=e("../../is"),i={floydWarshall:function(e){e=e||{};var t=this.cy();if(null!=e.weight&&n.fn(e.weight))var r=e.weight;else var r=function(e){return 1};if(null!=e.directed)var i=e.directed;else var i=!1;for(var a=this.edges().stdFilter(function(e){return!e.isLoop()}),o=this.nodes(),s=o.length,l={},u=0;s>u;u++)l[o[u].id()]=u;for(var c=[],u=0;s>u;u++){for(var d=new Array(s),h=0;s>h;h++)u==h?d[h]=0:d[h]=1/0;c.push(d)}var p=[],v=[],f=function(e){for(var t=0;s>t;t++){for(var r=new Array(s),n=0;s>n;n++)r[n]=void 0;e.push(r)}};f(p),f(v);for(var u=0;u<a.length;u++){var g=l[a[u].source().id()],y=l[a[u].target().id()],m=r.apply(a[u],[a[u]]);c[g][y]>m&&(c[g][y]=m,p[g][y]=y,v[g][y]=a[u])}if(!i)for(var u=0;u<a.length;u++){var g=l[a[u].target().id()],y=l[a[u].source().id()],m=r.apply(a[u],[a[u]]);c[g][y]>m&&(c[g][y]=m,p[g][y]=y,v[g][y]=a[u])}for(var b=0;s>b;b++)for(var u=0;s>u;u++)for(var h=0;s>h;h++)c[u][b]+c[b][h]<c[u][h]&&(c[u][h]=c[u][b]+c[b][h],p[u][h]=p[u][b]);for(var x=[],u=0;s>u;u++)x.push(o[u].id());var w={distance:function(e,r){if(n.string(e))var i=t.filter(e)[0].id();else var i=e.id();if(n.string(r))var a=t.filter(r)[0].id();else var a=r.id();return c[l[i]][l[a]]},path:function(e,r){var i=function(e,r,n,i,a){if(e===r)return t.getElementById(i[e]);if(void 0===n[e][r])return void 0;for(var o=[t.getElementById(i[e])],s=e;e!==r;){s=e,e=n[e][r];var l=a[s][e];o.push(l),o.push(t.getElementById(i[e]))}return o};if(n.string(e))var a=t.filter(e)[0].id();else var a=e.id();if(n.string(r))var o=t.filter(r)[0].id();else var o=r.id();var s=i(l[a],l[o],p,x,v);return t.collection(s)}};return w}};t.exports=i},{"../../is":77}],9:[function(e,t,r){"use strict";var n=e("../../util"),i={};[e("./bfs-dfs"),e("./a-star"),e("./floyd-warshall"),e("./bellman-ford"),e("./kerger-stein"),e("./page-rank"),e("./degree-centrality"),e("./closeness-centrality"),e("./betweenness-centrality")].forEach(function(e){n.extend(i,e)}),t.exports=i},{"../../util":94,"./a-star":2,"./bellman-ford":3,"./betweenness-centrality":4,"./bfs-dfs":5,"./closeness-centrality":6,"./degree-centrality":7,"./floyd-warshall":8,"./kerger-stein":10,"./page-rank":11}],10:[function(e,t,r){"use strict";var n=e("../../util"),i={kargerStein:function(e){var t=this;e=e||{};var r=function(e,t,r){for(var n=r[e],i=n[1],a=n[2],o=t[i],s=t[a],l=r.filter(function(e){return t[e[1]]===o&&t[e[2]]===s?!1:t[e[1]]===s&&t[e[2]]===o?!1:!0}),u=0;u<l.length;u++){var c=l[u];c[1]===s?(l[u]=c.slice(0),l[u][1]=o):c[2]===s&&(l[u]=c.slice(0),l[u][2]=o)}for(var u=0;u<t.length;u++)t[u]===s&&(t[u]=o);return l},i=function(e,t,n,a){if(a>=n)return t;var o=Math.floor(Math.random()*t.length),s=r(o,e,t);return i(e,s,n-1,a)},a=this._private.cy,o=this.edges().stdFilter(function(e){return!e.isLoop()}),s=this.nodes(),l=s.length,u=o.length,c=Math.ceil(Math.pow(Math.log(l)/Math.LN2,2)),d=Math.floor(l/Math.sqrt(2));if(2>l)return void n.error("At least 2 nodes are required for Karger-Stein algorithm");for(var h={},p=0;l>p;p++)h[s[p].id()]=p;for(var v=[],p=0;u>p;p++){var f=o[p];v.push([p,h[f.source().id()],h[f.target().id()]])}for(var g,y=1/0,m=[],p=0;l>p;p++)m.push(p);for(var b=0;c>=b;b++){var x=m.slice(0),w=i(x,v,l,d),_=x.slice(0),E=i(x,w,d,2),D=i(_,w,d,2);E.length<=D.length&&E.length<y?(y=E.length,g=[E,x]):D.length<=E.length&&D.length<y&&(y=D.length,g=[D,_])}for(var S=g[0].map(function(e){return o[e[0]]}),k=[],T=[],P=g[1][0],p=0;p<g[1].length;p++){var C=g[1][p];C===P?k.push(s[p]):T.push(s[p])}var N={cut:t.spawn(a,S),partition1:t.spawn(k),partition2:t.spawn(T)};return N}};t.exports=i},{"../../util":94}],11:[function(e,t,r){"use strict";var n=e("../../is"),i={pageRank:function(e){e=e||{};var t=function(e){for(var t=e.length,r=0,n=0;t>n;n++)r+=e[n];for(var n=0;t>n;n++)e[n]=e[n]/r};if(null!=e&&null!=e.dampingFactor)var r=e.dampingFactor;else var r=.8;if(null!=e&&null!=e.precision)var i=e.precision;else var i=1e-6;if(null!=e&&null!=e.iterations)var a=e.iterations;else var a=200;if(null!=e&&null!=e.weight&&n.fn(e.weight))var o=e.weight;else var o=function(e){return 1};for(var s=this._private.cy,l=this.edges().stdFilter(function(e){return!e.isLoop()}),u=this.nodes(),c=u.length,d=l.length,h={},p=0;c>p;p++)h[u[p].id()]=p;for(var v=[],f=[],g=(1-r)/c,p=0;c>p;p++){for(var y=[],m=0;c>m;m++)y.push(0);v.push(y),f.push(0)}for(var p=0;d>p;p++){var b=l[p],x=h[b.source().id()],w=h[b.target().id()],_=o.apply(b,[b]);v[w][x]+=_,f[x]+=_}for(var E=1/c+g,m=0;c>m;m++)if(0===f[m])for(var p=0;c>p;p++)v[p][m]=E;else for(var p=0;c>p;p++)v[p][m]=v[p][m]/f[m]+g;for(var D,S=[],k=[],p=0;c>p;p++)S.push(1),k.push(0);for(var T=0;a>T;T++){for(var P=k.slice(0),p=0;c>p;p++)for(var m=0;c>m;m++)P[p]+=v[p][m]*S[m];t(P),D=S,S=P;for(var C=0,p=0;c>p;p++)C+=Math.pow(D[p]-S[p],2);if(i>C)break}var N={rank:function(e){if(n.string(e))var t=s.filter(e)[0].id();else var t=e.id();return S[h[t]]}};return N}};t.exports=i},{"../../is":77}],12:[function(e,t,r){"use strict";var n=e("../define"),i={animate:n.animate(),animation:n.animation(),animated:n.animated(),clearQueue:n.clearQueue(),delay:n.delay(),delayAnimation:n.delayAnimation(),stop:n.stop()};t.exports=i},{"../define":41}],13:[function(e,t,r){"use strict";var n=e("../util"),i={classes:function(e){e=e.match(/\S+/g)||[];for(var t=this,r=[],i={},a=0;a<e.length;a++){var o=e[a];i[o]=!0}for(var s=0;s<t.length;s++){for(var l=t[s],u=l._private,c=u.classes,d=!1,a=0;a<e.length;a++){var o=e[a],h=c[o];if(!h){d=!0;break}}if(!d)for(var p in c){var h=c[p],v=i[p];if(h&&!v){d=!0;break}}d&&(u.classes=n.copy(i),r.push(l))}return r.length>0&&this.spawn(r).updateStyle().trigger("class"),t},addClass:function(e){return this.toggleClass(e,!0)},hasClass:function(e){var t=this[0];return null!=t&&t._private.classes[e]?!0:!1},toggleClass:function(e,t){for(var r=e.match(/\S+/g)||[],n=this,i=[],a=0,o=n.length;o>a;a++)for(var s=n[a],l=!1,u=0;u<r.length;u++){var c=r[u],d=s._private.classes,h=d[c],p=t||void 0===t&&!h;p?(d[c]=!0,h||l||(i.push(s),l=!0)):(d[c]=!1,h&&!l&&(i.push(s),l=!0))}return i.length>0&&this.spawn(i).updateStyle().trigger("class"),n},removeClass:function(e){return this.toggleClass(e,!1)},flashClass:function(e,t){var r=this;if(null==t)t=250;else if(0===t)return r;return r.addClass(e),setTimeout(function(){r.removeClass(e)},t),r}};t.exports=i},{"../util":94}],14:[function(e,t,r){"use strict";var n={allAre:function(e){return this.filter(e).length===this.length},is:function(e){return this.filter(e).length>0},some:function(e,t){for(var r=0;r<this.length;r++){var n=t?e.apply(t,[this[r],r,this]):e(this[r],r,this);if(n)return!0}return!1},every:function(e,t){for(var r=0;r<this.length;r++){var n=t?e.apply(t,[this[r],r,this]):e(this[r],r,this);if(!n)return!1}return!0},same:function(e){return e=this.cy().collection(e),this.length!==e.length?!1:this.intersect(e).length===this.length},anySame:function(e){return e=this.cy().collection(e),this.intersect(e).length>0},allAreNeighbors:function(e){return e=this.cy().collection(e),this.neighborhood().intersect(e).length===e.length}};n.allAreNeighbours=n.allAreNeighbors,t.exports=n},{}],15:[function(e,t,r){"use strict";var n={parent:function(e){for(var t=[],r=this._private.cy,n=0;n<this.length;n++){var i=this[n],a=r.getElementById(i._private.data.parent);a.size()>0&&t.push(a)}return this.spawn(t,{unique:!0}).filter(e)},parents:function(e){for(var t=[],r=this.parent();r.nonempty();){for(var n=0;n<r.length;n++){var i=r[n];t.push(i)}r=r.parent()}return this.spawn(t,{unique:!0}).filter(e)},commonAncestors:function(e){for(var t,r=0;r<this.length;r++){var n=this[r],i=n.parents();t=t||i,t=t.intersect(i)}return t.filter(e)},orphans:function(e){return this.stdFilter(function(e){return e.isNode()&&e.parent().empty()}).filter(e)},nonorphans:function(e){return this.stdFilter(function(e){return e.isNode()&&e.parent().nonempty()}).filter(e)},children:function(e){for(var t=[],r=0;r<this.length;r++){var n=this[r];t=t.concat(n._private.children)}return this.spawn(t,{unique:!0}).filter(e)},siblings:function(e){return this.parent().children().not(this).filter(e)},isParent:function(){var e=this[0];return e?0!==e._private.children.length:void 0},isChild:function(){var e=this[0];return e?void 0!==e._private.data.parent&&0!==e.parent().length:void 0},descendants:function(e){function t(e){for(var n=0;n<e.length;n++){var i=e[n];r.push(i),i.children().nonempty()&&t(i.children())}}var r=[];return t(this.children()),this.spawn(r,{unique:!0}).filter(e)}};n.ancestors=n.parents,t.exports=n},{}],16:[function(e,t,r){"use strict";var n,i,a=e("../define");n=i={data:a.data({field:"data",bindingEvent:"data",allowBinding:!0,allowSetting:!0,settingEvent:"data",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),removeData:a.removeData({field:"data",event:"data",triggerFnName:"trigger",triggerEvent:!0,immutableKeys:{id:!0,source:!0,target:!0,parent:!0},updateStyle:!0}),scratch:a.data({field:"scratch",bindingEvent:"scratch",allowBinding:!0,allowSetting:!0,settingEvent:"scratch",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0,updateStyle:!0}),removeScratch:a.removeData({field:"scratch",event:"scratch",triggerFnName:"trigger",triggerEvent:!0,updateStyle:!0}),rscratch:a.data({field:"rscratch",allowBinding:!1,allowSetting:!0,settingTriggersEvent:!1,allowGetting:!0}),removeRscratch:a.removeData({field:"rscratch",triggerEvent:!1}),id:function(){var e=this[0];return e?e._private.data.id:void 0}},n.attr=n.data,n.removeAttr=n.removeData,t.exports=i},{"../define":41}],17:[function(e,t,r){"use strict";function n(e){return function(t){var r=this;if(void 0===t&&(t=!0),0!==r.length&&r.isNode()&&!r.removed()){for(var n=0,i=r[0],a=i._private.edges,o=0;o<a.length;o++){var s=a[o];(t||!s.isLoop())&&(n+=e(i,s))}return n}}}function i(e,t){return function(r){for(var n,i=this.nodes(),a=0;a<i.length;a++){var o=i[a],s=o[e](r);void 0===s||void 0!==n&&!t(s,n)||(n=s)}return n}}var a=e("../util"),o={};a.extend(o,{degree:n(function(e,t){return t.source().same(t.target())?2:1}),indegree:n(function(e,t){return t.target().same(e)?1:0}),outdegree:n(function(e,t){return t.source().same(e)?1:0})}),a.extend(o,{minDegree:i("degree",function(e,t){return t>e}),maxDegree:i("degree",function(e,t){return e>t}),minIndegree:i("indegree",function(e,t){return t>e}),maxIndegree:i("indegree",function(e,t){return e>t}),minOutdegree:i("outdegree",function(e,t){return t>e}),maxOutdegree:i("outdegree",function(e,t){return e>t})}),a.extend(o,{totalDegree:function(e){for(var t=0,r=this.nodes(),n=0;n<r.length;n++)t+=r[n].degree(e);return t}}),t.exports=o},{"../util":94}],18:[function(e,t,r){"use strict";var n,i,a=e("../define"),o=e("../is"),s=e("../util");n=i={position:a.data({field:"position",bindingEvent:"position",allowBinding:!0,allowSetting:!0,settingEvent:"position",settingTriggersEvent:!0,triggerFnName:"rtrigger",allowGetting:!0,validKeys:["x","y"],onSet:function(e){var t=e.updateCompoundBounds();t.rtrigger("position")},canSet:function(e){return!e.locked()&&!e.isParent()}}),silentPosition:a.data({field:"position",bindingEvent:"position",allowBinding:!1,allowSetting:!0,settingEvent:"position",settingTriggersEvent:!1,triggerFnName:"trigger",allowGetting:!0,validKeys:["x","y"],onSet:function(e){e.updateCompoundBounds()},canSet:function(e){return!e.locked()&&!e.isParent()}}),positions:function(e,t){if(o.plainObject(e))this.position(e);else if(o.fn(e)){for(var r=e,n=0;n<this.length;n++){var i=this[n],e=r.apply(i,[n,i]);if(e&&!i.locked()&&!i.isParent()){var a=i._private.position;a.x=e.x,a.y=e.y}}var s=this.updateCompoundBounds(),l=s.length>0?this.add(s):this;t?l.trigger("position"):l.rtrigger("position")}return this},silentPositions:function(e){return this.positions(e,!0)},renderedPosition:function(e,t){var r=this[0],n=this.cy(),i=n.zoom(),a=n.pan(),s=o.plainObject(e)?e:void 0,l=void 0!==s||void 0!==t&&o.string(e);if(r&&r.isNode()){if(!l){var u=r._private.position;return s={x:u.x*i+a.x,y:u.y*i+a.y},void 0===e?s:s[e]}for(var c=0;c<this.length;c++){var r=this[c];void 0!==t?r._private.position[e]=(t-a[e])/i:void 0!==s&&(r._private.position={x:(s.x-a.x)/i,y:(s.y-a.y)/i})}this.rtrigger("position")}else if(!l)return void 0;return this},relativePosition:function(e,t){var r=this[0],n=this.cy(),i=o.plainObject(e)?e:void 0,a=void 0!==i||void 0!==t&&o.string(e),s=n.hasCompoundNodes();if(r&&r.isNode()){if(!a){var l=r._private.position,u=s?r.parent():null,c=u&&u.length>0,d=c;c&&(u=u[0]);var h=d?u._private.position:{x:0,y:0};return i={x:l.x-h.x,y:l.y-h.y},void 0===e?i:i[e]}for(var p=0;p<this.length;p++){var r=this[p],u=s?r.parent():null,c=u&&u.length>0,d=c;c&&(u=u[0]);var h=d?u._private.position:{x:0,y:0};void 0!==t?r._private.position[e]=t+h[e]:void 0!==i&&(r._private.position={x:i.x+h.x,y:i.y+h.y})}this.rtrigger("position")}else if(!a)return void 0;return this},renderedBoundingBox:function(e){var t=this.boundingBox(e),r=this.cy(),n=r.zoom(),i=r.pan(),a=t.x1*n+i.x,o=t.x2*n+i.x,s=t.y1*n+i.y,l=t.y2*n+i.y;return{x1:a,x2:o,y1:s,y2:l,w:o-a,h:l-s}},updateCompoundBounds:function(){function e(e){var t=e.children(),n=e._private.style,i="include"===n["compound-sizing-wrt-labels"].value,a=t.boundingBox({includeLabels:i,includeEdges:!0}),o={top:n["padding-top"].pfValue,bottom:n["padding-bottom"].pfValue,left:n["padding-left"].pfValue,right:n["padding-right"].pfValue},s=e._private.position,l=!1;"auto"===n.width.value&&(e._private.autoWidth=a.w,s.x=(a.x1+a.x2-o.left+o.right)/2,l=!0),"auto"===n.height.value&&(e._private.autoHeight=a.h,s.y=(a.y1+a.y2-o.top+o.bottom)/2,l=!0),l&&r.push(e)}var t=this.cy();if(!t.styleEnabled()||!t.hasCompoundNodes())return t.collection();for(var r=[],n=this.parent();n.nonempty();){for(var i=0;i<n.length;i++){var a=n[i];e(a)}n=n.parent()}return this.spawn(r)},boundingBox:function(e){var t=this,r=t._private.cy,n=r._private,i=n.styleEnabled;e=e||s.staticEmptyObject();var a=void 0===e.includeNodes?!0:e.includeNodes,o=void 0===e.includeEdges?!0:e.includeEdges,l=void 0===e.includeLabels?!0:e.includeLabels;i&&n.renderer.recalculateRenderedStyle(this);for(var u=1/0,c=-(1/0),d=1/0,h=-(1/0),p=0;p<t.length;p++){var v,f,g,y,m,b,x=t[p],w=x._private,_=w.style,E=i?w.style.display.value:"element",D="nodes"===w.group,S=!1;if("none"!==E){if(D&&a){S=!0;var k=w.position;m=k.x,b=k.y;var T=x.outerWidth(),P=T/2,C=x.outerHeight(),N=C/2;v=m-P,f=m+P,g=b-N,y=b+N,u=u>v?v:u,c=f>c?f:c,d=d>g?g:d,h=y>h?y:h}else if(x.isEdge()&&o){S=!0;var M=w.source,B=M._private,z=B.position,O=w.target,I=O._private,L=I.position,A=w.rstyle||{},T=0,R=0;if(i&&(T=_.width.pfValue,R=T/2),v=z.x,f=L.x,g=z.y,y=L.y,v>f){var V=v;v=f,f=V}if(g>y){var V=g;g=y,y=V}if(v-=R,f+=R,g-=R,y+=R,u=u>v?v:u,c=f>c?f:c,d=d>g?g:d,h=y>h?y:h,i)for(var F=A.bezierPts||A.linePts||[],j=0;j<F.length;j++){var q=F[j];v=q.x-R,f=q.x+R,g=q.y-R,y=q.y+R,u=u>v?v:u,c=f>c?f:c,d=d>g?g:d,h=y>h?y:h}if(i&&"haystack"===_["curve-style"].strValue){var X=A.haystackPts;if(v=X[0].x,g=X[0].y,f=X[1].x,y=X[1].y,v>f){var V=v;v=f,f=V}if(g>y){var V=g;g=y,y=V}u=u>v?v:u,c=f>c?f:c,d=d>g?g:d,h=y>h?y:h}}if(i){var w=x._private,_=w.style,A=w.rstyle,Y=_.label.strValue,$=_["font-size"],H=_["text-halign"],W=_["text-valign"],Z=A.labelWidth,U=A.labelHeight,G=A.labelX,K=A.labelY,J=x.isEdge(),Q="autorotate"===_["edge-text-rotation"].strValue;if(l&&Y&&$&&null!=U&&null!=Z&&null!=G&&null!=K&&H&&W){var ee,te,re,ne,ie=U,ae=Z;if(J){if(ee=G-ae/2,te=G+ae/2,re=K-ie/2,ne=K+ie/2,Q){var oe=w.rscratch.labelAngle,se=Math.cos(oe),le=Math.sin(oe),ue=function(e,t){return e-=G,t-=K,{x:e*se-t*le+G,y:e*le+t*se+K}},ce=ue(ee,re),de=ue(ee,ne),he=ue(te,re),pe=ue(te,ne);ee=Math.min(ce.x,de.x,he.x,pe.x),te=Math.max(ce.x,de.x,he.x,pe.x),re=Math.min(ce.y,de.y,he.y,pe.y),ne=Math.max(ce.y,de.y,he.y,pe.y)}}else{switch(H.value){case"left":ee=G-ae,te=G;break;case"center":ee=G-ae/2,te=G+ae/2;break;case"right":ee=G,te=G+ae}switch(W.value){case"top":re=K-ie,ne=K;break;case"center":re=K-ie/2,ne=K+ie/2;break;case"bottom":re=K,ne=K+ie}}u=u>ee?ee:u,c=te>c?te:c,d=d>re?re:d,h=ne>h?ne:h}}}}var ve=function(e){return e===1/0||e===-(1/0)?0:e};return u=ve(u),c=ve(c),d=ve(d),h=ve(h),{x1:u,x2:c,y1:d,y2:h,w:c-u,h:h-d}}};var l=function(e){e.uppercaseName=s.capitalize(e.name),e.autoName="auto"+e.uppercaseName,e.labelName="label"+e.uppercaseName,e.outerName="outer"+e.uppercaseName,e.uppercaseOuterName=s.capitalize(e.outerName),n[e.name]=function(){var t=this[0],r=t._private,n=r.cy,i=n._private.styleEnabled;if(t){if(!i)return 1;var a=r.style[e.name];switch(a.strValue){case"auto":return r[e.autoName]||0;case"label":return r.rstyle[e.labelName]||0;default:return a.pfValue}}},n["outer"+e.uppercaseName]=function(){var t=this[0],r=t._private,n=r.cy,i=n._private.styleEnabled;if(t){if(i){var a=r.style,o=t[e.name](),s=a["border-width"].pfValue,l=a[e.paddings[0]].pfValue+a[e.paddings[1]].pfValue;return o+s+l}return 1}},n["rendered"+e.uppercaseName]=function(){var t=this[0];if(t){var r=t[e.name]();return r*this.cy().zoom()}},n["rendered"+e.uppercaseOuterName]=function(){var t=this[0];if(t){var r=t[e.outerName]();return r*this.cy().zoom()}}};l({name:"width",paddings:["padding-left","padding-right"]}),l({name:"height",paddings:["padding-top","padding-bottom"]}),n.modelPosition=n.point=n.position,n.modelPositions=n.points=n.positions,n.renderedPoint=n.renderedPosition,n.relativePoint=n.relativePosition,n.boundingbox=n.boundingBox,n.renderedBoundingbox=n.renderedBoundingBox,t.exports=i},{"../define":41,"../is":77,"../util":94}],19:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a=function(e,t,r){if(!(this instanceof a))return new a(e,t,r);var o=this;if(r=void 0===r||r?!0:!1,void 0===e||void 0===t||!i.core(e))return void n.error("An element must have a core reference and parameters set");var s=t.group;
+if(null==s&&(s=null!=t.data.source&&null!=t.data.target?"edges":"nodes"),"nodes"!==s&&"edges"!==s)return void n.error("An element must be of type `nodes` or `edges`; you specified `"+s+"`");if(this.length=1,this[0]=this,this._private={cy:e,single:!0,data:t.data||{},position:t.position||{},autoWidth:void 0,autoHeight:void 0,listeners:[],group:s,style:{},rstyle:{},styleCxts:[],removed:!0,selected:t.selected?!0:!1,selectable:void 0===t.selectable?!0:t.selectable?!0:!1,locked:t.locked?!0:!1,grabbed:!1,grabbable:void 0===t.grabbable?!0:t.grabbable?!0:!1,active:!1,classes:{},animation:{current:[],queue:[]},rscratch:{},scratch:t.scratch||{},edges:[],children:[]},t.renderedPosition){var l=t.renderedPosition,u=e.pan(),c=e.zoom();this._private.position={x:(l.x-u.x)/c,y:(l.y-u.y)/c}}if(i.string(t.classes))for(var d=t.classes.split(/\s+/),h=0,p=d.length;p>h;h++){var v=d[h];v&&""!==v&&(o._private.classes[v]=!0)}(t.style||t.css)&&e.style().applyBypass(this,t.style||t.css),(void 0===r||r)&&this.restore()};t.exports=a},{"../is":77,"../util":94}],20:[function(e,t,r){"use strict";var n=e("../define"),i={on:n.on(),one:n.on({unbindSelfOnTrigger:!0}),once:n.on({unbindAllBindersOnTrigger:!0}),off:n.off(),trigger:n.trigger(),rtrigger:function(e,t){return 0!==this.length?(this.cy().notify({type:e,collection:this}),this.trigger(e,t),this):void 0}};n.eventAliasesOn(i),t.exports=i},{"../define":41}],21:[function(e,t,r){"use strict";var n=e("../is"),i=e("../selector"),a={nodes:function(e){return this.filter(function(e,t){return t.isNode()}).filter(e)},edges:function(e){return this.filter(function(e,t){return t.isEdge()}).filter(e)},filter:function(e){if(n.fn(e)){for(var t=[],r=0;r<this.length;r++){var a=this[r];e.apply(a,[r,a])&&t.push(a)}return this.spawn(t)}return n.string(e)||n.elementOrCollection(e)?i(e).filter(this):void 0===e?this:this.spawn()},not:function(e){if(e){n.string(e)&&(e=this.filter(e));for(var t=[],r=0;r<this.length;r++){var i=this[r],a=e._private.ids[i.id()];a||t.push(i)}return this.spawn(t)}return this},absoluteComplement:function(){var e=this._private.cy;return e.elements().not(this)},intersect:function(e){if(n.string(e)){var t=e;return this.filter(t)}for(var r=[],i=this,a=e,o=this.length<e.length,s=o?a._private.ids:i._private.ids,l=o?i:a,u=0;u<l.length;u++){var c=l[u]._private.data.id,d=s[c];d&&r.push(d)}return this.spawn(r)},xor:function(e){var t=this._private.cy;n.string(e)&&(e=t.$(e));var r=[],i=this,a=e,o=function(e,t){for(var n=0;n<e.length;n++){var i=e[n],a=i._private.data.id,o=t._private.ids[a];o||r.push(i)}};return o(i,a),o(a,i),this.spawn(r)},diff:function(e){var t=this._private.cy;n.string(e)&&(e=t.$(e));var r=[],i=[],a=[],o=this,s=e,l=function(e,t,r){for(var n=0;n<e.length;n++){var i=e[n],o=i._private.data.id,s=t._private.ids[o];s?a.push(i):r.push(i)}};return l(o,s,r),l(s,o,i),{left:this.spawn(r,{unique:!0}),right:this.spawn(i,{unique:!0}),both:this.spawn(a,{unique:!0})}},add:function(e){var t=this._private.cy;if(!e)return this;if(n.string(e)){var r=e;e=t.elements(r)}for(var i=[],a=0;a<this.length;a++)i.push(this[a]);for(var a=0;a<e.length;a++){var o=!this._private.ids[e[a].id()];o&&i.push(e[a])}return this.spawn(i)},merge:function(e){var t=this._private,r=t.cy;if(!e)return this;if(n.string(e)){var i=e;e=r.elements(i)}for(var a=0;a<e.length;a++){var o=e[a],s=o.id(),l=!t.ids[s];if(l){var u=this.length++;this[u]=o,t.ids[s]=o,t.indexes[s]=u}}return this},unmergeOne:function(e){e=e[0];var t=this._private,r=e.id(),n=t.indexes[r];if(null==n)return this;this[n]=void 0,t.ids[r]=void 0,t.indexes[r]=void 0;var i=n===this.length-1;if(this.length>1&&!i){var a=this.length-1,o=this[a];this[a]=void 0,this[n]=o,t.indexes[o.id()]=n}return this.length--,this},unmerge:function(e){var t=this._private.cy;if(!e)return this;if(n.string(e)){var r=e;e=t.elements(r)}for(var i=0;i<e.length;i++)this.unmergeOne(e[i]);return this},map:function(e,t){for(var r=[],n=this,i=0;i<n.length;i++){var a=n[i],o=t?e.apply(t,[a,i,n]):e(a,i,n);r.push(o)}return r},stdFilter:function(e,t){for(var r=[],n=this,i=0;i<n.length;i++){var a=n[i],o=t?e.apply(t,[a,i,n]):e(a,i,n);o&&r.push(a)}return this.spawn(r)},max:function(e,t){for(var r,n=-(1/0),i=this,a=0;a<i.length;a++){var o=i[a],s=t?e.apply(t,[o,a,i]):e(o,a,i);s>n&&(n=s,r=o)}return{value:n,ele:r}},min:function(e,t){for(var r,n=1/0,i=this,a=0;a<i.length;a++){var o=i[a],s=t?e.apply(t,[o,a,i]):e(o,a,i);n>s&&(n=s,r=o)}return{value:n,ele:r}}},o=a;o.u=o["|"]=o["+"]=o.union=o.or=o.add,o["\\"]=o["!"]=o["-"]=o.difference=o.relativeComplement=o.subtract=o.not,o.n=o["&"]=o["."]=o.and=o.intersection=o.intersect,o["^"]=o["(+)"]=o["(-)"]=o.symmetricDifference=o.symdiff=o.xor,o.fnFilter=o.filterFn=o.stdFilter,o.complement=o.abscomp=o.absoluteComplement,t.exports=a},{"../is":77,"../selector":81}],22:[function(e,t,r){"use strict";var n={isNode:function(){return"nodes"===this.group()},isEdge:function(){return"edges"===this.group()},isLoop:function(){return this.isEdge()&&this.source().id()===this.target().id()},isSimple:function(){return this.isEdge()&&this.source().id()!==this.target().id()},group:function(){var e=this[0];return e?e._private.group:void 0}};t.exports=n},{}],23:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a=e("./element"),o={prefix:"ele",id:0,generate:function(e,t,r){var n=(i.element(t)?t._private:t,null!=r?r:this.prefix+this.id);if(e.getElementById(n).empty())this.id++;else for(;!e.getElementById(n).empty();)n=this.prefix+ ++this.id;return n}},s=function(e,t,r){if(!(this instanceof s))return new s(e,t,r);if(void 0===e||!i.core(e))return void n.error("A collection must have a reference to the core");var l={},u={},c=!1;if(t){if(t.length>0&&i.plainObject(t[0])&&!i.element(t[0])){c=!0;for(var d=[],h={},p=0,v=t.length;v>p;p++){var f=t[p];null==f.data&&(f.data={});var g=f.data;if(null==g.id)g.id=o.generate(e,f);else if(0!==e.getElementById(g.id).length||h[g.id])continue;var y=new a(e,f,!1);d.push(y),h[g.id]=!0}t=d}}else t=[];this.length=0;for(var p=0,v=t.length;v>p;p++){var m=t[p];if(m){var b=m._private.data.id;(!r||r.unique&&!l[b])&&(l[b]=m,u[b]=this.length,this[this.length]=m,this.length++)}}this._private={cy:e,ids:l,indexes:u},c&&this.restore()},l=a.prototype=s.prototype;l.instanceString=function(){return"collection"},l.spawn=function(e,t,r){return i.core(e)||(r=t,t=e,e=this.cy()),new s(e,t,r)},l.cy=function(){return this._private.cy},l.element=function(){return this[0]},l.collection=function(){return i.collection(this)?this:new s(this._private.cy,[this])},l.unique=function(){return new s(this._private.cy,this,{unique:!0})},l.getElementById=function(e){var t=this._private.cy,r=this._private.ids[e];return r?r:new s(t)},l.json=function(e){var t=this.element(),r=this.cy();if(null==t&&e)return this;if(null==t)return void 0;var a=t._private;if(i.plainObject(e)){r.startBatch(),e.data&&t.data(e.data),e.position&&t.position(e.position);var o=function(r,n,i){var o=e[r];null!=o&&o!==a[r]&&(o?t[n]():t[i]())};return o("removed","remove","restore"),o("selected","select","unselect"),o("selectable","selectify","unselectify"),o("locked","lock","unlock"),o("grabbable","grabify","ungrabify"),null!=e.classes&&t.classes(e.classes),r.endBatch(),this}if(void 0===e){var s={data:n.copy(a.data),position:n.copy(a.position),group:a.group,removed:a.removed,selected:a.selected,selectable:a.selectable,locked:a.locked,grabbable:a.grabbable,classes:null},l=[];for(var u in a.classes)a.classes[u]&&l.push(u);return s.classes=l.join(" "),s}},l.jsons=function(){for(var e=[],t=0;t<this.length;t++){var r=this[t],n=r.json();e.push(n)}return e},l.clone=function(){for(var e=this.cy(),t=[],r=0;r<this.length;r++){var n=this[r],i=n.json(),o=new a(e,i,!1);t.push(o)}return new s(e,t)},l.copy=l.clone,l.restore=function(e){var t=this,r=[],a=t.cy();void 0===e&&(e=!0);for(var l=[],u=[],c=[],d=0,h=0,p=0,v=t.length;v>p;p++){var f=t[p];f.isNode()?(u.push(f),d++):(c.push(f),h++)}l=u.concat(c);for(var p=0,v=l.length;v>p;p++){var f=l[p];if(f.removed()){var g=f._private,y=g.data;if(void 0===y.id)y.id=o.generate(a,f);else if(i.number(y.id))y.id=""+y.id;else{if(i.emptyString(y.id)||!i.string(y.id)){n.error("Can not create element with invalid string ID `"+y.id+"`");continue}if(0!==a.getElementById(y.id).length){n.error("Can not create second element with ID `"+y.id+"`");continue}}var m=y.id;if(f.isNode()){var b=f,x=g.position;null==x.x&&(x.x=0),null==x.y&&(x.y=0)}if(f.isEdge()){for(var w=f,_=["source","target"],E=_.length,D=!1,S=0;E>S;S++){var k=_[S],T=y[k];i.number(T)&&(T=y[k]=""+y[k]),null==T||""===T?(n.error("Can not create edge `"+m+"` with unspecified "+k),D=!0):a.getElementById(T).empty()&&(n.error("Can not create edge `"+m+"` with nonexistant "+k+" `"+T+"`"),D=!0)}if(D)continue;var P=a.getElementById(y.source),C=a.getElementById(y.target);P._private.edges.push(w),C._private.edges.push(w),w._private.source=P,w._private.target=C}g.ids={},g.ids[m]=f,g.removed=!1,a.addToPool(f),r.push(f)}}for(var p=0;d>p;p++){var b=l[p],y=b._private.data;i.number(y.parent)&&(y.parent=""+y.parent);var N=y.parent,M=null!=N;if(M){var B=a.getElementById(N);if(B.empty())y.parent=void 0;else{for(var z=!1,O=B;!O.empty();){if(b.same(O)){z=!0,y.parent=void 0;break}O=O.parent()}z||(B[0]._private.children.push(b),b._private.parent=B[0],a._private.hasCompoundNodes=!0)}}}if(r=new s(a,r),r.length>0){var I=r.add(r.connectedNodes()).add(r.parent());I.updateStyle(e),e?r.rtrigger("add"):r.trigger("add")}return t},l.removed=function(){var e=this[0];return e&&e._private.removed},l.inside=function(){var e=this[0];return e&&!e._private.removed},l.remove=function(e){function t(e){for(var t=e._private.edges,r=0;r<t.length;r++)n(t[r])}function r(e){for(var t=e._private.children,r=0;r<t.length;r++)n(t[r])}function n(e){var n=c[e.id()];n||(c[e.id()]=!0,e.isNode()?(u.push(e),t(e),r(e)):u.unshift(e))}function i(e,t){for(var r=e._private.edges,n=0;n<r.length;n++){var i=r[n];if(t===i){r.splice(n,1);break}}}function a(e,t){t=t[0],e=e[0];for(var r=e._private.children,n=0;n<r.length;n++)if(r[n][0]===t[0]){r.splice(n,1);break}}var o=this,l=[],u=[],c={},d=o._private.cy;void 0===e&&(e=!0);for(var h=0,p=o.length;p>h;h++){var v=o[h];n(v)}for(var h=0;h<u.length;h++){var v=u[h];if(v._private.removed=!0,d.removeFromPool(v),l.push(v),v.isEdge()){var f=v.source()[0],g=v.target()[0];i(f,v),i(g,v)}else{var y=v.parent();0!==y.length&&a(y,v)}}var m=d._private.elements;d._private.hasCompoundNodes=!1;for(var h=0;h<m.length;h++){var v=m[h];if(v.isParent()){d._private.hasCompoundNodes=!0;break}}var b=new s(this.cy(),l);b.size()>0&&(e&&this.cy().notify({type:"remove",collection:b}),b.trigger("remove"));for(var x={},h=0;h<u.length;h++){var v=u[h],w="nodes"===v._private.group,_=v._private.data.parent;if(w&&void 0!==_&&!x[_]){x[_]=!0;var y=d.getElementById(_);y&&0!==y.length&&!y._private.removed&&0===y.children().length&&y.updateStyle()}}return new s(d,l)},l.move=function(e){var t=this._private.cy;if(void 0!==e.source||void 0!==e.target){var r=e.source,n=e.target,i=t.getElementById(r).length>0,a=t.getElementById(n).length>0;if(i||a){var o=this.jsons();this.remove();for(var s=0;s<o.length;s++){var l=o[s];"edges"===l.group&&(i&&(l.data.source=r),a&&(l.data.target=n))}return t.add(o)}}else if(void 0!==e.parent){var u=e.parent,c=null===u||t.getElementById(u).length>0;if(c){var o=this.jsons(),d=this.descendants(),h=d.merge(d.add(this).connectedEdges());this.remove();for(var s=0;s<this.length;s++){var l=o[s];"nodes"===l.group&&(l.data.parent=null===u?void 0:u)}}return t.add(o).merge(h.restore())}return this},[e("./algorithms"),e("./animation"),e("./class"),e("./comparators"),e("./compounds"),e("./data"),e("./degree"),e("./dimensions"),e("./events"),e("./filter"),e("./group"),e("./index"),e("./iteration"),e("./layout"),e("./style"),e("./switch-functions"),e("./traversing")].forEach(function(e){n.extend(l,e)}),t.exports=s},{"../is":77,"../util":94,"./algorithms":9,"./animation":12,"./class":13,"./comparators":14,"./compounds":15,"./data":16,"./degree":17,"./dimensions":18,"./element":19,"./events":20,"./filter":21,"./group":22,"./index":23,"./iteration":24,"./layout":25,"./style":26,"./switch-functions":27,"./traversing":28}],24:[function(e,t,r){"use strict";var n=e("../is"),i=e("./zsort"),a={each:function(e){if(n.fn(e))for(var t=0;t<this.length;t++){var r=this[t],i=e.apply(r,[t,r]);if(i===!1)break}return this},forEach:function(e,t){if(n.fn(e))for(var r=0;r<this.length;r++){var i=this[r],a=t?e.apply(t,[i,r,this]):e(i,r,this);if(a===!1)break}return this},toArray:function(){for(var e=[],t=0;t<this.length;t++)e.push(this[t]);return e},slice:function(e,t){var r=[],n=this.length;null==t&&(t=n),null==e&&(e=0),0>e&&(e=n+e),0>t&&(t=n+t);for(var i=e;i>=0&&t>i&&n>i;i++)r.push(this[i]);return this.spawn(r)},size:function(){return this.length},eq:function(e){return this[e]||this.spawn()},first:function(){return this[0]||this.spawn()},last:function(){return this[this.length-1]||this.spawn()},empty:function(){return 0===this.length},nonempty:function(){return!this.empty()},sort:function(e){if(!n.fn(e))return this;var t=this.toArray().sort(e);return this.spawn(t)},sortByZIndex:function(){return this.sort(i)},zDepth:function(){var e=this[0];if(!e)return void 0;var t=e._private,r=t.group;if("nodes"===r){var n=t.data.parent?e.parents().size():0;return e.isParent()?n:Number.MAX_VALUE}var i=t.source,a=t.target,o=i.zDepth(),s=a.zDepth();return Math.max(o,s,0)}};t.exports=a},{"../is":77,"./zsort":29}],25:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a={layoutPositions:function(e,t,r){var i=this.nodes(),a=this.cy();if(e.trigger({type:"layoutstart",layout:e}),e.animations=[],t.animate){for(var o=0;o<i.length;o++){var s=i[o],l=o===i.length-1,u=r.call(s,o,s),c=s.position();n.number(c.x)&&n.number(c.y)||s.silentPosition({x:0,y:0});var d=s.animation({position:u,duration:t.animationDuration,easing:t.animationEasing,step:l?function(){t.fit&&a.fit(t.eles,t.padding)}:void 0,complete:l?function(){null!=t.zoom&&a.zoom(t.zoom),t.pan&&a.pan(t.pan),t.fit&&a.fit(t.eles,t.padding),e.one("layoutstop",t.stop),e.trigger({type:"layoutstop",layout:e})}:void 0});e.animations.push(d),d.play()}e.one("layoutready",t.ready),e.trigger({type:"layoutready",layout:e})}else i.positions(r),t.fit&&a.fit(t.eles,t.padding),null!=t.zoom&&a.zoom(t.zoom),t.pan&&a.pan(t.pan),e.one("layoutready",t.ready),e.trigger({type:"layoutready",layout:e}),e.one("layoutstop",t.stop),e.trigger({type:"layoutstop",layout:e});return this},layout:function(e){var t=this.cy();return t.layout(i.extend({},e,{eles:this})),this},makeLayout:function(e){var t=this.cy();return t.makeLayout(i.extend({},e,{eles:this}))}};a.createLayout=a.makeLayout,t.exports=a},{"../is":77,"../util":94}],26:[function(e,t,r){"use strict";var n=e("../is"),i={updateStyle:function(e){var t=this._private.cy;if(!t.styleEnabled())return this;if(t._private.batchingStyle){var r=t._private.batchStyleEles;return r.merge(this),this}var n=t.style();e=e||void 0===e?!0:!1,n.apply(this);var i=this.updateCompoundBounds(),a=i.length>0?this.add(i):this;return e?a.rtrigger("style"):a.trigger("style"),this},updateMappers:function(e){var t=this._private.cy,r=t.style();if(e=e||void 0===e?!0:!1,!t.styleEnabled())return this;r.updateMappers(this);var n=this.updateCompoundBounds(),i=n.length>0?this.add(n):this;return e?i.rtrigger("style"):i.trigger("style"),this},renderedCss:function(e){var t=this.cy();if(!t.styleEnabled())return this;var r=this[0];if(r){var n=r.cy().style().getRenderedStyle(r);return void 0===e?n:n[e]}},css:function(e,t){var r=this.cy();if(!r.styleEnabled())return this;var i=!1,a=r.style();if(n.plainObject(e)){var o=e;a.applyBypass(this,o,i);var s=this.updateCompoundBounds(),l=s.length>0?this.add(s):this;l.rtrigger("style")}else if(n.string(e)){if(void 0===t){var u=this[0];return u?a.getStylePropertyValue(u,e):void 0}a.applyBypass(this,e,t,i);var s=this.updateCompoundBounds(),l=s.length>0?this.add(s):this;l.rtrigger("style")}else if(void 0===e){var u=this[0];return u?a.getRawStyle(u):void 0}return this},removeCss:function(e){var t=this.cy();if(!t.styleEnabled())return this;var r=!1,n=t.style(),i=this;if(void 0===e)for(var a=0;a<i.length;a++){var o=i[a];n.removeAllBypasses(o,r)}else{e=e.split(/\s+/);for(var a=0;a<i.length;a++){var o=i[a];n.removeBypasses(o,e,r)}}var s=this.updateCompoundBounds(),l=s.length>0?this.add(s):this;return l.rtrigger("style"),this},show:function(){return this.css("display","element"),this},hide:function(){return this.css("display","none"),this},visible:function(){var e=this.cy();if(!e.styleEnabled())return!0;var t=this[0],r=e.hasCompoundNodes();if(t){var n=t._private.style;if("visible"!==n.visibility.value||"element"!==n.display.value)return!1;if("nodes"===t._private.group){if(!r)return!0;var i=t._private.data.parent?t.parents():null;if(i)for(var a=0;a<i.length;a++){var o=i[a],s=o._private.style,l=s.visibility.value,u=s.display.value;if("visible"!==l||"element"!==u)return!1}return!0}var c=t._private.source,d=t._private.target;return c.visible()&&d.visible()}},hidden:function(){var e=this[0];return e?!e.visible():void 0},effectiveOpacity:function(){var e=this.cy();if(!e.styleEnabled())return 1;var t=e.hasCompoundNodes(),r=this[0];if(r){var n=r._private,i=n.style.opacity.value;if(!t)return i;var a=n.data.parent?r.parents():null;if(a)for(var o=0;o<a.length;o++){var s=a[o],l=s._private.style.opacity.value;i=l*i}return i}},transparent:function(){var e=this.cy();if(!e.styleEnabled())return!1;var t=this[0],r=t.cy().hasCompoundNodes();return t?r?0===t.effectiveOpacity():0===t._private.style.opacity.value:void 0},isFullAutoParent:function(){var e=this.cy();if(!e.styleEnabled())return!1;var t=this[0];if(t){var r="auto"===t._private.style.width.value,n="auto"===t._private.style.height.value;return t.isParent()&&r&&n}},backgrounding:function(){var e=this.cy();if(!e.styleEnabled())return!1;var t=this[0];return t._private.backgrounding?!0:!1}};i.bypass=i.style=i.css,i.renderedStyle=i.renderedCss,i.removeBypass=i.removeStyle=i.removeCss,t.exports=i},{"../is":77}],27:[function(e,t,r){"use strict";function n(e){return function(){var t=arguments,r=[];if(2===t.length){var n=t[0],i=t[1];this.bind(e.event,n,i)}else if(1===t.length){var i=t[0];this.bind(e.event,i)}else if(0===t.length){for(var a=0;a<this.length;a++){var o=this[a],s=!e.ableField||o._private[e.ableField],l=o._private[e.field]!=e.value;if(e.overrideAble){var u=e.overrideAble(o);if(void 0!==u&&(s=u,!u))return this}s&&(o._private[e.field]=e.value,l&&r.push(o))}var c=this.spawn(r);c.updateStyle(),c.trigger(e.event)}return this}}function i(e){a[e.field]=function(){var t=this[0];if(t){if(e.overrideField){var r=e.overrideField(t);if(void 0!==r)return r}return t._private[e.field]}},a[e.on]=n({event:e.on,field:e.field,ableField:e.ableField,overrideAble:e.overrideAble,value:!0}),a[e.off]=n({event:e.off,field:e.field,ableField:e.ableField,overrideAble:e.overrideAble,value:!1})}var a={};i({field:"locked",overrideField:function(e){return e.cy().autolock()?!0:void 0},on:"lock",off:"unlock"}),i({field:"grabbable",overrideField:function(e){return e.cy().autoungrabify()?!1:void 0},on:"grabify",off:"ungrabify"}),i({field:"selected",ableField:"selectable",overrideAble:function(e){return e.cy().autounselectify()?!1:void 0},on:"select",off:"unselect"}),i({field:"selectable",overrideField:function(e){return e.cy().autounselectify()?!1:void 0},on:"selectify",off:"unselectify"}),a.deselect=a.unselect,a.grabbed=function(){var e=this[0];return e?e._private.grabbed:void 0},i({field:"active",on:"activate",off:"unactivate"}),a.inactive=function(){var e=this[0];return e?!e._private.active:void 0},t.exports=a},{}],28:[function(e,t,r){"use strict";function n(e){return function(t){for(var r=[],n=0;n<this.length;n++){var i=this[n],a=i._private[e.attr];a&&r.push(a)}return this.spawn(r,{unique:!0}).filter(t)}}function i(e){return function(t){var r=[],n=this._private.cy,i=e||{};s.string(t)&&(t=n.$(t));for(var a=this._private.ids,o=t._private.ids,l=0;l<t.length;l++)for(var u=t[l]._private.edges,c=0;c<u.length;c++){var d=u[c],h=d._private.data,p=a[h.source]&&o[h.target],v=o[h.source]&&a[h.target],f=p||v;if(f){if(i.thisIs){if("source"===i.thisIs&&!p)continue;if("target"===i.thisIs&&!v)continue}r.push(d)}}return this.spawn(r,{unique:!0})}}function a(e){var t={codirected:!1};return e=o.extend({},t,e),function(t){for(var r=[],n=this.edges(),i=e,a=0;a<n.length;a++)for(var o=n[a],s=o.source()[0],l=s.id(),u=o.target()[0],c=u.id(),d=s._private.edges,h=0;h<d.length;h++){var p=d[h],v=p._private.data,f=v.target,g=v.source,y=f===c&&g===l,m=l===f&&c===g;(i.codirected&&y||!i.codirected&&(y||m))&&r.push(p)}return this.spawn(r,{unique:!0}).filter(t)}}var o=e("../util"),s=e("../is"),l={};o.extend(l,{roots:function(e){for(var t=this,r=[],n=0;n<t.length;n++){var i=t[n];if(i.isNode()){var a=i.connectedEdges(function(){return this.data("target")===i.id()&&this.data("source")!==i.id()}).length>0;a||r.push(i)}}return this.spawn(r,{unique:!0}).filter(e)},leaves:function(e){for(var t=this,r=[],n=0;n<t.length;n++){var i=t[n];if(i.isNode()){var a=i.connectedEdges(function(){return this.data("source")===i.id()&&this.data("target")!==i.id()}).length>0;a||r.push(i)}}return this.spawn(r,{unique:!0}).filter(e)},outgoers:function(e){for(var t=this,r=[],n=0;n<t.length;n++){var i=t[n],a=i.id();if(i.isNode())for(var o=i._private.edges,s=0;s<o.length;s++){var l=o[s],u=l._private.data.source,c=l._private.data.target;u===a&&c!==a&&(r.push(l),r.push(l.target()[0]))}}return this.spawn(r,{unique:!0}).filter(e)},successors:function(e){for(var t=this,r=[],n={};;){var i=t.outgoers();if(0===i.length)break;for(var a=!1,o=0;o<i.length;o++){var s=i[o],l=s.id();n[l]||(n[l]=!0,r.push(s),a=!0)}if(!a)break;t=i}return this.spawn(r,{unique:!0}).filter(e)},incomers:function(e){for(var t=this,r=[],n=0;n<t.length;n++){var i=t[n],a=i.id();if(i.isNode())for(var o=i._private.edges,s=0;s<o.length;s++){var l=o[s],u=l._private.data.source,c=l._private.data.target;c===a&&u!==a&&(r.push(l),r.push(l.source()[0]))}}return this.spawn(r,{unique:!0}).filter(e)},predecessors:function(e){for(var t=this,r=[],n={};;){var i=t.incomers();if(0===i.length)break;for(var a=!1,o=0;o<i.length;o++){var s=i[o],l=s.id();n[l]||(n[l]=!0,r.push(s),a=!0)}if(!a)break;t=i}return this.spawn(r,{unique:!0}).filter(e)}}),o.extend(l,{neighborhood:function(e){for(var t=[],r=this.nodes(),n=0;n<r.length;n++)for(var i=r[n],a=i.connectedEdges(),o=0;o<a.length;o++){var s=a[o],l=s._private.source,u=s._private.target,c=i===l?u:l;c.length>0&&t.push(c[0]),t.push(s[0])}return this.spawn(t,{unique:!0}).filter(e)},closedNeighborhood:function(e){return this.neighborhood().add(this).filter(e)},openNeighborhood:function(e){return this.neighborhood(e)}}),l.neighbourhood=l.neighborhood,l.closedNeighbourhood=l.closedNeighborhood,l.openNeighbourhood=l.openNeighborhood,o.extend(l,{source:function(e){var t,r=this[0];return r&&(t=r._private.source),t&&e?t.filter(e):t},target:function(e){var t,r=this[0];return r&&(t=r._private.target),t&&e?t.filter(e):t},sources:n({attr:"source"}),targets:n({attr:"target"})}),o.extend(l,{edgesWith:i(),edgesTo:i({thisIs:"source"})}),o.extend(l,{connectedEdges:function(e){for(var t=[],r=this,n=0;n<r.length;n++){var i=r[n];if(i.isNode())for(var a=i._private.edges,o=0;o<a.length;o++){var s=a[o];t.push(s)}}return this.spawn(t,{unique:!0}).filter(e)},connectedNodes:function(e){for(var t=[],r=this,n=0;n<r.length;n++){var i=r[n];i.isEdge()&&(t.push(i.source()[0]),t.push(i.target()[0]))}return this.spawn(t,{unique:!0}).filter(e)},parallelEdges:a(),codirectedEdges:a({codirected:!0})}),o.extend(l,{components:function(){var e=this.cy(),t=e.collection(),r=this.nodes(),n=[],i=function(e,n){t.merge(e),r.unmerge(e),n.merge(e)};do{var a=e.collection();n.push(a);var o=r[0];i(o,a),this.bfs({directed:!1,roots:o,visit:function(e,t,r,n,o){i(r,a)}})}while(r.length>0);return n.map(function(e){return e.closedNeighborhood()})}}),t.exports=l},{"../is":77,"../util":94}],29:[function(e,t,r){"use strict";var n=function(e,t){var r=e.cy(),n=e._private,i=t._private,a=n.style["z-index"].value-i.style["z-index"].value,o=0,s=0,l=r.hasCompoundNodes(),u="nodes"===n.group,c="edges"===n.group,d="nodes"===i.group,h="edges"===i.group;l&&(o=e.zDepth(),s=t.zDepth());var p=o-s,v=0===p;return v?u&&h?1:c&&d?-1:0===a?n.index-i.index:a:p};t.exports=n},{}],30:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a=e("../collection"),o=e("../collection/element"),s=e("../window"),l=(s?s.document:null,e("../extensions/renderer/null"),{add:function(e){var t,r=this;if(n.elementOrCollection(e)){var s=e;if(s._private.cy===r)t=s.restore();else{for(var l=[],u=0;u<s.length;u++){var c=s[u];l.push(c.json())}t=new a(r,l)}}else if(n.array(e)){var l=e;t=new a(r,l)}else if(n.plainObject(e)&&(n.array(e.nodes)||n.array(e.edges))){for(var d=e,l=[],h=["nodes","edges"],u=0,p=h.length;p>u;u++){var v=h[u],f=d[v];if(n.array(f))for(var g=0,y=f.length;y>g;g++){var m=i.extend({group:v},f[g]);l.push(m)}}t=new a(r,l)}else{var m=e;t=new o(r,m).collection()}return t},remove:function(e){if(n.elementOrCollection(e))e=e;else if(n.string(e)){var t=e;e=this.$(t)}return e.remove()},load:function(e,t,r){var a=this;a.notifications(!1);var o=a.elements();o.length>0&&o.remove(),null!=e&&(n.plainObject(e)||n.array(e))&&a.add(e),a.one("layoutready",function(e){a.notifications(!0),a.trigger(e),a.notify({type:"load",collection:a.elements()}),a.one("load",t),a.trigger("load")}).one("layoutstop",function(){a.one("done",r),a.trigger("done")});var s=i.extend({},a._private.options.layout);return s.eles=a.$(),a.layout(s),this}});t.exports=l},{"../collection":23,"../collection/element":19,"../extensions/renderer/null":73,"../is":77,"../util":94,"../window":100}],31:[function(e,t,r){"use strict";var n=e("../define"),i=e("../util"),a=e("../is"),o={animate:n.animate(),animation:n.animation(),animated:n.animated(),clearQueue:n.clearQueue(),delay:n.delay(),delayAnimation:n.delayAnimation(),stop:n.stop(),addToAnimationPool:function(e){var t=this;t.styleEnabled()&&t._private.aniEles.merge(e)},stopAnimationLoop:function(){this._private.animationsRunning=!1},startAnimationLoop:function(){function e(){c._private.animationsRunning&&i.requestAnimationFrame(function(r){t(r),e()})}function t(e){function t(t,i){var o=t._private,s=o.animation.current,l=o.animation.queue,u=!1;if(0===s.length){var c=l.shift();c&&s.push(c)}for(var d=function(e){for(var t=e.length-1;t>=0;t--){var r=e[t];r()}e.splice(0,e.length)},h=s.length-1;h>=0;h--){var p=s[h],v=p._private;v.stopped?(s.splice(h,1),v.hooked=!1,v.playing=!1,v.started=!1,d(v.frames)):(v.playing||v.applying)&&(v.playing&&v.applying&&(v.applying=!1),v.started||r(t,p,e),n(t,p,e,i),v.applying&&(v.applying=!1),d(v.frames),p.completed()&&(s.splice(h,1),v.hooked=!1,v.playing=!1,v.started=!1,d(v.completes)),u=!0)}return i||0!==s.length||0!==l.length||a.push(t),u}for(var i=c._private.aniEles,a=[],o=!1,s=0;s<i.length;s++){var l=i[s],u=t(l);o=o||u}var d=t(c,!0);if(o||d){var h;if(i.length>0){var p=i.updateCompoundBounds();h=p.length>0?i.add(p):i}c.notify({type:"draw",collection:h})}i.unmerge(a)}function r(e,t,r){var n=a.core(e),i=!n,o=e,s=c._private.style,l=t._private;if(i){var u=o._private.position;l.startPosition=l.startPosition||{x:u.x,y:u.y},l.startStyle=l.startStyle||s.getValueStyle(o)}if(n){var d=c._private.pan;l.startPan=l.startPan||{x:d.x,y:d.y},l.startZoom=null!=l.startZoom?l.startZoom:c._private.zoom}l.started=!0,l.startTime=r-l.progress*l.duration}function n(e,t,r,n){var i=c._private.style,s=!n,l=e._private,d=t._private,p=d.easing,v=d.startTime;if(!d.easingImpl)if(null==p)d.easingImpl=h.linear;else{var f;if(a.string(p)){var g=i.parse("transition-timing-function",p);f=g.value}else f=p;var y,m;a.string(f)?(y=f,m=[]):(y=f[1],m=f.slice(2).map(function(e){return+e})),m.length>0?("spring"===y&&m.push(d.duration),d.easingImpl=h[y].apply(null,m)):d.easingImpl=h[y]}var b,x=d.easingImpl;if(b=0===d.duration?1:(r-v)/d.duration,d.applying&&(b=d.progress),0>b?b=0:b>1&&(b=1),null==d.delay){var w=d.startPosition,_=d.position,E=l.position;_&&s&&(o(w.x,_.x)&&(E.x=u(w.x,_.x,b,x)),o(w.y,_.y)&&(E.y=u(w.y,_.y,b,x)));var D=d.startPan,S=d.pan,k=l.pan,T=null!=S&&n;T&&(o(D.x,S.x)&&(k.x=u(D.x,S.x,b,x)),o(D.y,S.y)&&(k.y=u(D.y,S.y,b,x)),e.trigger("pan"));var P=d.startZoom,C=d.zoom,N=null!=C&&n;N&&(o(P,C)&&(l.zoom=u(P,C,b,x)),e.trigger("zoom")),(T||N)&&e.trigger("viewport");var M=d.style;if(M&&s)for(var B=0;B<M.length;B++){var z=M[B],y=z.name,O=z,I=d.startStyle[y],L=u(I,O,b,x);i.overrideBypass(e,y,L)}}return a.fn(d.step)&&d.step.apply(e,[r]),d.progress=b,b}function o(e,t){return null==e||null==t?!1:a.number(e)&&a.number(t)?!0:e&&t?!0:!1}function s(e,t,r){var n=1-r,i=r*r;return 3*n*n*r*e+3*n*i*t+i*r}function l(e,t){return function(r,n,i){return r+(n-r)*s(e,t,i)}}function u(e,t,r,n){0>r?r=0:r>1&&(r=1);var i,o;if(i=null!=e.pfValue||null!=e.value?null!=e.pfValue?e.pfValue:e.value:e,o=null!=t.pfValue||null!=t.value?null!=t.pfValue?t.pfValue:t.value:t,a.number(i)&&a.number(o))return n(i,o,r);if(a.array(i)&&a.array(o)){for(var s=[],l=0;l<o.length;l++){var u=i[l],c=o[l];if(null!=u&&null!=c){var d=n(u,c,r);e.roundValue&&(d=Math.round(d)),s.push(d)}else s.push(c)}return s}return void 0}var c=this;if(c._private.animationsRunning=!0,c.styleEnabled()){e();var d=function(){function e(e){return-e.tension*e.x-e.friction*e.v}function t(t,r,n){var i={x:t.x+n.dx*r,v:t.v+n.dv*r,tension:t.tension,friction:t.friction};return{dx:i.v,dv:e(i)}}function r(r,n){var i={dx:r.v,dv:e(r)},a=t(r,.5*n,i),o=t(r,.5*n,a),s=t(r,n,o),l=1/6*(i.dx+2*(a.dx+o.dx)+s.dx),u=1/6*(i.dv+2*(a.dv+o.dv)+s.dv);return r.x=r.x+l*n,r.v=r.v+u*n,r}return function n(e,t,i){var a,o,s,l={x:-1,v:0,tension:null,friction:null},u=[0],c=0,d=1e-4,h=.016;for(e=parseFloat(e)||500,t=parseFloat(t)||20,i=i||null,l.tension=e,l.friction=t,a=null!==i,a?(c=n(e,t),o=c/i*h):o=h;;)if(s=r(s||l,o),u.push(1+s.x),c+=16,!(Math.abs(s.x)>d&&Math.abs(s.v)>d))break;return a?function(e){return u[e*(u.length-1)|0]}:c}}(),h={linear:function(e,t,r){return e+(t-e)*r},ease:l(.25,.1,.25,1),"ease-in":l(.42,0,1,1),"ease-out":l(0,0,.58,1),"ease-in-out":l(.42,0,.58,1),"ease-in-sine":l(.47,0,.745,.715),"ease-out-sine":l(.39,.575,.565,1),"ease-in-out-sine":l(.445,.05,.55,.95),"ease-in-quad":l(.55,.085,.68,.53),"ease-out-quad":l(.25,.46,.45,.94),"ease-in-out-quad":l(.455,.03,.515,.955),"ease-in-cubic":l(.55,.055,.675,.19),"ease-out-cubic":l(.215,.61,.355,1),"ease-in-out-cubic":l(.645,.045,.355,1),"ease-in-quart":l(.895,.03,.685,.22),"ease-out-quart":l(.165,.84,.44,1),"ease-in-out-quart":l(.77,0,.175,1),"ease-in-quint":l(.755,.05,.855,.06),"ease-out-quint":l(.23,1,.32,1),"ease-in-out-quint":l(.86,0,.07,1),"ease-in-expo":l(.95,.05,.795,.035),"ease-out-expo":l(.19,1,.22,1),"ease-in-out-expo":l(1,0,0,1),"ease-in-circ":l(.6,.04,.98,.335),"ease-out-circ":l(.075,.82,.165,1),"ease-in-out-circ":l(.785,.135,.15,.86),spring:function(e,t,r){var n=d(e,t,r);return function(e,t,r){return e+(t-e)*n(r)}},"cubic-bezier":function(e,t,r,n){return l(e,t,r,n)}}}}};t.exports=o},{"../define":41,"../is":77,"../util":94}],32:[function(e,t,r){"use strict";var n=e("../define"),i={on:n.on(),one:n.on({unbindSelfOnTrigger:!0}),once:n.on({unbindAllBindersOnTrigger:!0}),off:n.off(),trigger:n.trigger()};n.eventAliasesOn(i),t.exports=i},{"../define":41}],33:[function(e,t,r){"use strict";var n={png:function(e){var t=this._private.renderer;return e=e||{},t.png(e)},jpg:function(e){var t=this._private.renderer;return e=e||{},e.bg=e.bg||"#fff",t.jpg(e)}};n.jpeg=n.jpg,t.exports=n},{}],34:[function(e,t,r){"use strict";var n=e("../window"),i=e("../util"),a=e("../collection"),o=e("../is"),s=e("../promise"),l=e("../define"),u=function(e){if(!(this instanceof u))return new u(e);var t=this;e=i.extend({},e);var r=e.container;r&&!o.htmlElement(r)&&o.htmlElement(r[0])&&(r=r[0]);var l=r?r._cyreg:null;l=l||{},l&&l.cy&&(l.cy.destroy(),l={});var c=l.readies=l.readies||[];r&&(r._cyreg=l),l.cy=t;var d=void 0!==n&&void 0!==r&&!e.headless,h=e;h.layout=i.extend({name:d?"grid":"null"},h.layout),h.renderer=i.extend({
+name:d?"canvas":"null"},h.renderer);var p=function(e,t,r){return void 0!==t?t:void 0!==r?r:e},v=this._private={container:r,ready:!1,initrender:!1,options:h,elements:[],id2index:{},listeners:[],onRenders:[],aniEles:a(this),scratch:{},layout:null,renderer:null,notificationsEnabled:!0,minZoom:1e-50,maxZoom:1e50,zoomingEnabled:p(!0,h.zoomingEnabled),userZoomingEnabled:p(!0,h.userZoomingEnabled),panningEnabled:p(!0,h.panningEnabled),userPanningEnabled:p(!0,h.userPanningEnabled),boxSelectionEnabled:p(!0,h.boxSelectionEnabled),autolock:p(!1,h.autolock,h.autolockNodes),autoungrabify:p(!1,h.autoungrabify,h.autoungrabifyNodes),autounselectify:p(!1,h.autounselectify),styleEnabled:void 0===h.styleEnabled?d:h.styleEnabled,zoom:o.number(h.zoom)?h.zoom:1,pan:{x:o.plainObject(h.pan)&&o.number(h.pan.x)?h.pan.x:0,y:o.plainObject(h.pan)&&o.number(h.pan.y)?h.pan.y:0},animation:{current:[],queue:[]},hasCompoundNodes:!1,deferredExecQueue:[]},f=h.selectionType;void 0===f||"additive"!==f&&"single"!==f?v.selectionType="single":v.selectionType=f,o.number(h.minZoom)&&o.number(h.maxZoom)&&h.minZoom<h.maxZoom?(v.minZoom=h.minZoom,v.maxZoom=h.maxZoom):o.number(h.minZoom)&&void 0===h.maxZoom?v.minZoom=h.minZoom:o.number(h.maxZoom)&&void 0===h.minZoom&&(v.maxZoom=h.maxZoom);var g=function(e){for(var t=!1,r=0;r<y.length;r++){var n=y[r];if(o.promise(n)){t=!0;break}}return t?s.all(y).then(e):void e(y)};t.initRenderer(i.extend({hideEdgesOnViewport:h.hideEdgesOnViewport,hideLabelsOnViewport:h.hideLabelsOnViewport,textureOnViewport:h.textureOnViewport,wheelSensitivity:o.number(h.wheelSensitivity)&&h.wheelSensitivity>0?h.wheelSensitivity:1,motionBlur:void 0===h.motionBlur?!0:h.motionBlur,motionBlurOpacity:void 0===h.motionBlurOpacity?.05:h.motionBlurOpacity,pixelRatio:o.number(h.pixelRatio)&&h.pixelRatio>0?h.pixelRatio:"auto"===h.pixelRatio?void 0:1,desktopTapThreshold:void 0===h.desktopTapThreshold?4:h.desktopTapThreshold,touchTapThreshold:void 0===h.touchTapThreshold?8:h.touchTapThreshold},h.renderer));var y=[h.style,h.elements];g(function(e){var r=e[0],n=e[1];v.styleEnabled&&t.setStyle(r),h.initrender&&(t.on("initrender",h.initrender),t.on("initrender",function(){v.initrender=!0})),t.load(n,function(){t.startAnimationLoop(),v.ready=!0,o.fn(h.ready)&&t.on("ready",h.ready);for(var e=0;e<c.length;e++){var r=c[e];t.on("ready",r)}l&&(l.readies=[]),t.trigger("ready")},h.done)})},c=u.prototype;i.extend(c,{instanceString:function(){return"core"},isReady:function(){return this._private.ready},ready:function(e){return this.isReady()?this.trigger("ready",[],e):this.on("ready",e),this},initrender:function(){return this._private.initrender},destroy:function(){var e=this;e.stopAnimationLoop(),e.notify({type:"destroy"});var t=e.container();if(t)for(t._cyreg=null;t.childNodes.length>0;)t.removeChild(t.childNodes[0]);return e},getElementById:function(e){var t=this._private.id2index[e];return void 0!==t?this._private.elements[t]:a(this)},selectionType:function(){return this._private.selectionType},hasCompoundNodes:function(){return this._private.hasCompoundNodes},styleEnabled:function(){return this._private.styleEnabled},addToPool:function(e){for(var t=this._private.elements,r=this._private.id2index,n=0;n<e.length;n++){var i=e[n],a=i._private.data.id,o=r[a],s=void 0!==o;s||(o=t.length,t.push(i),r[a]=o,i._private.index=o)}return this},removeFromPool:function(e){for(var t=this._private.elements,r=this._private.id2index,n=0;n<e.length;n++){var i=e[n],a=i._private.data.id,o=r[a],s=void 0!==o;if(s){this._private.id2index[a]=void 0,t.splice(o,1);for(var l=o;l<t.length;l++){var u=t[l]._private.data.id;r[u]--,t[l]._private.index--}}}},container:function(){return this._private.container},options:function(){return i.copy(this._private.options)},json:function(e){var t=this,r=t._private;if(o.plainObject(e)){if(t.startBatch(),e.elements){var n={},a=function(e,r){for(var a=0;a<e.length;a++){var o=e[a],s=o.data.id,l=t.getElementById(s);n[s]=!0,0!==l.length?l.json(o):r?t.add(i.extend({group:r},o)):t.add(o)}};if(o.array(e.elements))a(e.elements);else for(var s=["nodes","edges"],l=0;l<s.length;l++){var u=s[l],c=e.elements[u];o.array(c)&&a(c,u)}t.elements().stdFilter(function(e){return!n[e.id()]}).remove()}e.style&&t.style(e.style),null!=e.zoom&&e.zoom!==r.zoom&&t.zoom(e.zoom),e.pan&&(e.pan.x!==r.pan.x||e.pan.y!==r.pan.y)&&t.pan(e.pan);for(var d=["minZoom","maxZoom","zoomingEnabled","userZoomingEnabled","panningEnabled","userPanningEnabled","boxSelectionEnabled","autolock","autoungrabify","autounselectify"],l=0;l<d.length;l++){var h=d[l];null!=e[h]&&t[h](e[h])}return t.endBatch(),this}if(void 0===e){var p={};return p.elements={},t.elements().each(function(e,t){var r=t.group();p.elements[r]||(p.elements[r]=[]),p.elements[r].push(t.json())}),this._private.styleEnabled&&(p.style=t.style().json()),p.zoomingEnabled=t._private.zoomingEnabled,p.userZoomingEnabled=t._private.userZoomingEnabled,p.zoom=t._private.zoom,p.minZoom=t._private.minZoom,p.maxZoom=t._private.maxZoom,p.panningEnabled=t._private.panningEnabled,p.userPanningEnabled=t._private.userPanningEnabled,p.pan=i.copy(t._private.pan),p.boxSelectionEnabled=t._private.boxSelectionEnabled,p.renderer=i.copy(t._private.options.renderer),p.hideEdgesOnViewport=t._private.options.hideEdgesOnViewport,p.hideLabelsOnViewport=t._private.options.hideLabelsOnViewport,p.textureOnViewport=t._private.options.textureOnViewport,p.wheelSensitivity=t._private.options.wheelSensitivity,p.motionBlur=t._private.options.motionBlur,p}},scratch:l.data({field:"scratch",bindingEvent:"scratch",allowBinding:!0,allowSetting:!0,settingEvent:"scratch",settingTriggersEvent:!0,triggerFnName:"trigger",allowGetting:!0}),removeScratch:l.removeData({field:"scratch",event:"scratch",triggerFnName:"trigger",triggerEvent:!0})}),[e("./add-remove"),e("./animation"),e("./events"),e("./export"),e("./layout"),e("./notification"),e("./renderer"),e("./search"),e("./style"),e("./viewport")].forEach(function(e){i.extend(c,e)}),t.exports=u},{"../collection":23,"../define":41,"../is":77,"../promise":80,"../util":94,"../window":100,"./add-remove":30,"./animation":31,"./events":32,"./export":33,"./layout":35,"./notification":36,"./renderer":37,"./search":38,"./style":39,"./viewport":40}],35:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a={layout:function(e){var t=this._private.prevLayout=null==e?this._private.prevLayout:this.makeLayout(e);return t.run(),this},makeLayout:function(e){var t=this;if(null==e)return void n.error("Layout options must be specified to make a layout");if(null==e.name)return void n.error("A `name` must be specified to make a layout");var r=e.name,a=t.extension("layout",r);if(null==a)return void n.error("Can not apply layout: No such layout `"+r+"` found; did you include its JS file?");var o;o=i.string(e.eles)?t.$(e.eles):null!=e.eles?e.eles:t.$();var s=new a(n.extend({},e,{cy:t,eles:o}));return s}};a.createLayout=a.makeLayout,t.exports=a},{"../is":77,"../util":94}],36:[function(e,t,r){"use strict";var n={notify:function(e){var t=this._private;if(t.batchingNotify){var r=t.batchNotifyEles,n=t.batchNotifyTypes;return e.collection&&r.merge(e.collection),void(n.ids[e.type]||n.push(e.type))}if(t.notificationsEnabled){var i=this.renderer();i.notify(e)}},notifications:function(e){var t=this._private;return void 0===e?t.notificationsEnabled:void(t.notificationsEnabled=e?!0:!1)},noNotifications:function(e){this.notifications(!1),e(),this.notifications(!0)},startBatch:function(){var e=this._private;return null==e.batchCount&&(e.batchCount=0),0===e.batchCount&&(e.batchingStyle=e.batchingNotify=!0,e.batchStyleEles=this.collection(),e.batchNotifyEles=this.collection(),e.batchNotifyTypes=[],e.batchNotifyTypes.ids={}),e.batchCount++,this},endBatch:function(){var e=this._private;return e.batchCount--,0===e.batchCount&&(e.batchingStyle=!1,e.batchStyleEles.updateStyle(),e.batchingNotify=!1,this.notify({type:e.batchNotifyTypes,collection:e.batchNotifyEles})),this},batch:function(e){return this.startBatch(),e(),this.endBatch(),this},batchData:function(e){var t=this;return this.batch(function(){for(var r in e){var n=e[r],i=t.getElementById(r);i.data(n)}})}};t.exports=n},{}],37:[function(e,t,r){"use strict";var n=e("../util"),i={renderTo:function(e,t,r,n){var i=this._private.renderer;return i.renderTo(e,t,r,n),this},renderer:function(){return this._private.renderer},forceRender:function(){return this.notify({type:"draw"}),this},resize:function(){return this.notify({type:"resize"}),this.trigger("resize"),this},initRenderer:function(e){var t=this,r=t.extension("renderer",e.name);if(null==r)return void n.error("Can not initialise: No such renderer `%s` found; did you include its JS file?",e.name);var i=n.extend({},e,{cy:t}),a=t._private.renderer=new r(i);a.init(i)},triggerOnRender:function(){for(var e=this._private.onRenders,t=0;t<e.length;t++){var r=e[t];r()}return this},onRender:function(e){return this._private.onRenders.push(e),this},offRender:function(e){var t=this._private.onRenders;if(null==e)return this._private.onRenders=[],this;for(var r=0;r<t.length;r++){var n=t[r];if(e===n){t.splice(r,1);break}}return this}};i.invalidateDimensions=i.resize,t.exports=i},{"../util":94}],38:[function(e,t,r){"use strict";var n=e("../is"),i=e("../collection"),a={collection:function(e,t){return n.string(e)?this.$(e):n.elementOrCollection(e)?e.collection():n.array(e)?i(this,e,t):i(this)},nodes:function(e){var t=this.$(function(){return this.isNode()});return e?t.filter(e):t},edges:function(e){var t=this.$(function(){return this.isEdge()});return e?t.filter(e):t},$:function(e){var t=new i(this,this._private.elements);return e?t.filter(e):t}};a.elements=a.filter=a.$,t.exports=a},{"../collection":23,"../is":77}],39:[function(e,t,r){"use strict";var n=e("../is"),i=e("../style"),a={style:function(e){if(e){var t=this.setStyle(e);t.update()}return this._private.style},setStyle:function(e){var t=this._private;return n.stylesheet(e)?t.style=e.generateStyle(this):n.array(e)?t.style=i.fromJson(this,e):n.string(e)?t.style=i.fromString(this,e):t.style=i(this),t.style}};t.exports=a},{"../is":77,"../style":86}],40:[function(e,t,r){"use strict";var n=e("../is"),i={autolock:function(e){return void 0===e?this._private.autolock:(this._private.autolock=e?!0:!1,this)},autoungrabify:function(e){return void 0===e?this._private.autoungrabify:(this._private.autoungrabify=e?!0:!1,this)},autounselectify:function(e){return void 0===e?this._private.autounselectify:(this._private.autounselectify=e?!0:!1,this)},panningEnabled:function(e){return void 0===e?this._private.panningEnabled:(this._private.panningEnabled=e?!0:!1,this)},userPanningEnabled:function(e){return void 0===e?this._private.userPanningEnabled:(this._private.userPanningEnabled=e?!0:!1,this)},zoomingEnabled:function(e){return void 0===e?this._private.zoomingEnabled:(this._private.zoomingEnabled=e?!0:!1,this)},userZoomingEnabled:function(e){return void 0===e?this._private.userZoomingEnabled:(this._private.userZoomingEnabled=e?!0:!1,this)},boxSelectionEnabled:function(e){return void 0===e?this._private.boxSelectionEnabled:(this._private.boxSelectionEnabled=e?!0:!1,this)},pan:function(){var e,t,r,i,a,o=arguments,s=this._private.pan;switch(o.length){case 0:return s;case 1:if(n.string(o[0]))return e=o[0],s[e];if(n.plainObject(o[0])){if(!this._private.panningEnabled)return this;r=o[0],i=r.x,a=r.y,n.number(i)&&(s.x=i),n.number(a)&&(s.y=a),this.trigger("pan viewport")}break;case 2:if(!this._private.panningEnabled)return this;e=o[0],t=o[1],"x"!==e&&"y"!==e||!n.number(t)||(s[e]=t),this.trigger("pan viewport")}return this.notify({type:"viewport"}),this},panBy:function(e){var t,r,i,a,o,s=arguments,l=this._private.pan;if(!this._private.panningEnabled)return this;switch(s.length){case 1:n.plainObject(s[0])&&(i=s[0],a=i.x,o=i.y,n.number(a)&&(l.x+=a),n.number(o)&&(l.y+=o),this.trigger("pan viewport"));break;case 2:t=s[0],r=s[1],"x"!==t&&"y"!==t||!n.number(r)||(l[t]+=r),this.trigger("pan viewport")}return this.notify({type:"viewport"}),this},fit:function(e,t){var r=this.getFitViewport(e,t);if(r){var n=this._private;n.zoom=r.zoom,n.pan=r.pan,this.trigger("pan zoom viewport"),this.notify({type:"viewport"})}return this},getFitViewport:function(e,t){if(n.number(e)&&void 0===t&&(t=e,e=void 0),this._private.panningEnabled&&this._private.zoomingEnabled){var r;if(n.string(e)){var i=e;e=this.$(i)}else if(n.boundingBox(e)){var a=e;r={x1:a.x1,y1:a.y1,x2:a.x2,y2:a.y2},r.w=r.x2-r.x1,r.h=r.y2-r.y1}else n.elementOrCollection(e)||(e=this.elements());r=r||e.boundingBox();var o,s=this.width(),l=this.height();if(t=n.number(t)?t:0,!isNaN(s)&&!isNaN(l)&&s>0&&l>0&&!isNaN(r.w)&&!isNaN(r.h)&&r.w>0&&r.h>0){o=Math.min((s-2*t)/r.w,(l-2*t)/r.h),o=o>this._private.maxZoom?this._private.maxZoom:o,o=o<this._private.minZoom?this._private.minZoom:o;var u={x:(s-o*(r.x1+r.x2))/2,y:(l-o*(r.y1+r.y2))/2};return{zoom:o,pan:u}}}},minZoom:function(e){return void 0===e?this._private.minZoom:(n.number(e)&&(this._private.minZoom=e),this)},maxZoom:function(e){return void 0===e?this._private.maxZoom:(n.number(e)&&(this._private.maxZoom=e),this)},zoom:function(e){var t,r;if(void 0===e)return this._private.zoom;if(n.number(e))r=e;else if(n.plainObject(e)){if(r=e.level,e.position){var i=e.position,a=this._private.pan,o=this._private.zoom;t={x:i.x*o+a.x,y:i.y*o+a.y}}else e.renderedPosition&&(t=e.renderedPosition);if(t&&!this._private.panningEnabled)return this}if(!this._private.zoomingEnabled)return this;if(!n.number(r)||t&&(!n.number(t.x)||!n.number(t.y)))return this;if(r=r>this._private.maxZoom?this._private.maxZoom:r,r=r<this._private.minZoom?this._private.minZoom:r,t){var s=this._private.pan,l=this._private.zoom,u=r,c={x:-u/l*(t.x-s.x)+t.x,y:-u/l*(t.y-s.y)+t.y};this._private.zoom=r,this._private.pan=c;var d=s.x!==c.x||s.y!==c.y;this.trigger(" zoom "+(d?" pan ":"")+" viewport ")}else this._private.zoom=r,this.trigger("zoom viewport");return this.notify({type:"viewport"}),this},viewport:function(e){var t=this._private,r=!0,i=!0,a=[],o=!1,s=!1;if(!e)return this;if(n.number(e.zoom)||(r=!1),n.plainObject(e.pan)||(i=!1),!r&&!i)return this;if(r){var l=e.zoom;l<t.minZoom||l>t.maxZoom||!t.zoomingEnabled?o=!0:(t.zoom=l,a.push("zoom"))}if(i&&(!o||!e.cancelOnFailedZoom)&&t.panningEnabled){var u=e.pan;n.number(u.x)&&(t.pan.x=u.x,s=!1),n.number(u.y)&&(t.pan.y=u.y,s=!1),s||a.push("pan")}return a.length>0&&(a.push("viewport"),this.trigger(a.join(" ")),this.notify({type:"viewport"})),this},center:function(e){var t=this.getCenterPan(e);return t&&(this._private.pan=t,this.trigger("pan viewport"),this.notify({type:"viewport"})),this},getCenterPan:function(e,t){if(this._private.panningEnabled){if(n.string(e)){var r=e;e=this.elements(r)}else n.elementOrCollection(e)||(e=this.elements());var i=e.boundingBox(),a=this.width(),o=this.height();t=void 0===t?this._private.zoom:t;var s={x:(a-t*(i.x1+i.x2))/2,y:(o-t*(i.y1+i.y2))/2};return s}},reset:function(){return this._private.panningEnabled&&this._private.zoomingEnabled?(this.viewport({pan:{x:0,y:0},zoom:1}),this):this},width:function(){var e=this._private.container;return e?e.clientWidth:1},height:function(){var e=this._private.container;return e?e.clientHeight:1},extent:function(){var e=this._private.pan,t=this._private.zoom,r=this.renderedExtent(),n={x1:(r.x1-e.x)/t,x2:(r.x2-e.x)/t,y1:(r.y1-e.y)/t,y2:(r.y2-e.y)/t};return n.w=n.x2-n.x1,n.h=n.y2-n.y1,n},renderedExtent:function(){var e=this.width(),t=this.height();return{x1:0,y1:0,x2:e,y2:t,w:e,h:t}}};i.centre=i.center,i.autolockNodes=i.autolock,i.autoungrabifyNodes=i.autoungrabify,t.exports=i},{"../is":77}],41:[function(e,t,r){"use strict";var n=e("./util"),i=e("./is"),a=e("./selector"),o=e("./promise"),s=e("./event"),l=e("./animation"),u={data:function(e){var t={field:"data",bindingEvent:"data",allowBinding:!1,allowSetting:!1,allowGetting:!1,settingEvent:"data",settingTriggersEvent:!1,triggerFnName:"trigger",immutableKeys:{},updateStyle:!1,onSet:function(e){},canSet:function(e){return!0}};return e=n.extend({},t,e),function(t,r){var n=e,a=this,o=void 0!==a.length,s=o?a:[a],l=o?a[0]:a;if(i.string(t)){if(n.allowGetting&&void 0===r){var u;return l&&(u=l._private[n.field][t]),u}if(n.allowSetting&&void 0!==r){var c=!n.immutableKeys[t];if(c){for(var d=0,h=s.length;h>d;d++)n.canSet(s[d])&&(s[d]._private[n.field][t]=r);n.updateStyle&&a.updateStyle(),n.onSet(a),n.settingTriggersEvent&&a[n.triggerFnName](n.settingEvent)}}}else if(n.allowSetting&&i.plainObject(t)){var p,v,f=t;for(p in f){v=f[p];var c=!n.immutableKeys[p];if(c)for(var d=0,h=s.length;h>d;d++)n.canSet(s[d])&&(s[d]._private[n.field][p]=v)}n.updateStyle&&a.updateStyle(),n.onSet(a),n.settingTriggersEvent&&a[n.triggerFnName](n.settingEvent)}else if(n.allowBinding&&i.fn(t)){var g=t;a.bind(n.bindingEvent,g)}else if(n.allowGetting&&void 0===t){var u;return l&&(u=l._private[n.field]),u}return a}},removeData:function(e){var t={field:"data",event:"data",triggerFnName:"trigger",triggerEvent:!1,immutableKeys:{}};return e=n.extend({},t,e),function(t){var r=e,n=this,a=void 0!==n.length,o=a?n:[n];if(i.string(t)){for(var s=t.split(/\s+/),l=s.length,u=0;l>u;u++){var c=s[u];if(!i.emptyString(c)){var d=!r.immutableKeys[c];if(d)for(var h=0,p=o.length;p>h;h++)o[h]._private[r.field][c]=void 0}}r.triggerEvent&&n[r.triggerFnName](r.event)}else if(void 0===t){for(var h=0,p=o.length;p>h;h++){var v=o[h]._private[r.field];for(var c in v){var f=!r.immutableKeys[c];f&&(v[c]=void 0)}}r.triggerEvent&&n[r.triggerFnName](r.event)}return n}},event:{regex:/(\w+)(\.\w+)?/,optionalTypeRegex:/(\w+)?(\.\w+)?/,falseCallback:function(){return!1}},on:function(e){var t={unbindSelfOnTrigger:!1,unbindAllBindersOnTrigger:!1};return e=n.extend({},t,e),function(t,r,n,o){var s=this,l=void 0!==s.length,c=l?s:[s],d=i.string(t),h=e;if(i.plainObject(r)?(o=n,n=r,r=void 0):(i.fn(r)||r===!1)&&(o=r,n=void 0,r=void 0),(i.fn(n)||n===!1)&&(o=n,n=void 0),!i.fn(o)&&o!==!1&&d)return s;if(d){var p={};p[t]=o,t=p}for(var v in t)if(o=t[v],o===!1&&(o=u.event.falseCallback),i.fn(o)){v=v.split(/\s+/);for(var f=0;f<v.length;f++){var g=v[f];if(!i.emptyString(g)){var y=g.match(u.event.regex);if(y)for(var m=y[1],b=y[2]?y[2]:void 0,x={callback:o,data:n,delegated:r?!0:!1,selector:r,selObj:new a(r),type:m,namespace:b,unbindSelfOnTrigger:h.unbindSelfOnTrigger,unbindAllBindersOnTrigger:h.unbindAllBindersOnTrigger,binders:c},w=0;w<c.length;w++){var _=c[w]._private;_.listeners=_.listeners||[],_.listeners.push(x)}}}}return s}},eventAliasesOn:function(e){var t=e;t.addListener=t.listen=t.bind=t.on,t.removeListener=t.unlisten=t.unbind=t.off,t.emit=t.trigger,t.pon=t.promiseOn=function(e,t){var r=this,n=Array.prototype.slice.call(arguments,0);return new o(function(e,t){var i=function(t){r.off.apply(r,o),e(t)},a=n.concat([i]),o=a.concat([]);r.on.apply(r,a)})}},off:function(e){var t={};return e=n.extend({},t,e),function(e,t,r){var n=this,a=void 0!==n.length,o=a?n:[n],s=i.string(e);if(0===arguments.length){for(var l=0;l<o.length;l++)o[l]._private.listeners=[];return n}if((i.fn(t)||t===!1)&&(r=t,t=void 0),s){var c={};c[e]=r,e=c}for(var d in e){r=e[d],r===!1&&(r=u.event.falseCallback),d=d.split(/\s+/);for(var h=0;h<d.length;h++){var p=d[h];if(!i.emptyString(p)){var v=p.match(u.event.optionalTypeRegex);if(v)for(var f=v[1]?v[1]:void 0,g=v[2]?v[2]:void 0,l=0;l<o.length;l++)for(var y=o[l]._private.listeners=o[l]._private.listeners||[],m=0;m<y.length;m++){var b=y[m],x=!g||g===b.namespace,w=!f||b.type===f,_=!r||r===b.callback,E=x&&w&&_;E&&(y.splice(m,1),m--)}}}}return n}},trigger:function(e){var t={};return e=n.extend({},t,e),function(t,r,n){var a=this,o=void 0!==a.length,l=o?a:[a],c=i.string(t),d=i.plainObject(t),h=i.event(t),p=this._private.cy||(i.core(this)?this:null),v=p?p.hasCompoundNodes():!1;if(c){var f=t.split(/\s+/);t=[];for(var g=0;g<f.length;g++){var y=f[g];if(!i.emptyString(y)){var m=y.match(u.event.regex),b=m[1],x=m[2]?m[2]:void 0;t.push({type:b,namespace:x})}}}else if(d){var w=t;t=[w]}r?i.array(r)||(r=[r]):r=[];for(var g=0;g<t.length;g++)for(var _=t[g],E=0;E<l.length;E++){var y,D=l[E],S=D._private.listeners=D._private.listeners||[],k=i.element(D),T=k||e.layout;if(h?(y=_,y.cyTarget=y.cyTarget||D,y.cy=y.cy||p):y=new s(_,{cyTarget:D,cy:p,namespace:_.namespace}),_.layout&&(y.layout=_.layout),e.layout&&(y.layout=D),y.cyPosition){var P=y.cyPosition,C=p.zoom(),N=p.pan();y.cyRenderedPosition={x:P.x*C+N.x,y:P.y*C+N.y}}n&&(S=[{namespace:y.namespace,type:y.type,callback:n}]);for(var M=0;M<S.length;M++){var B=S[M],z=!B.namespace||B.namespace===y.namespace,O=B.type===y.type,I=B.delegated?D!==y.cyTarget&&i.element(y.cyTarget)&&B.selObj.matches(y.cyTarget):!0,L=z&&O&&I;if(L){var A=[y];if(A=A.concat(r),B.data?y.data=B.data:y.data=void 0,(B.unbindSelfOnTrigger||B.unbindAllBindersOnTrigger)&&(S.splice(M,1),M--),B.unbindAllBindersOnTrigger)for(var R=B.binders,V=0;V<R.length;V++){var F=R[V];if(F&&F!==D)for(var j=F._private.listeners,q=0;q<j.length;q++){var X=j[q];X===B&&(j.splice(q,1),q--)}}var Y=B.delegated?y.cyTarget:D,$=B.callback.apply(Y,A);($===!1||y.isPropagationStopped())&&(T=!1,$===!1&&(y.stopPropagation(),y.preventDefault()))}}if(T){var H=v?D._private.parent:null,W=null!=H&&0!==H.length;W?(H=H[0],H.trigger(y)):p.trigger(y)}}return a}},animated:function(e){var t={};return e=n.extend({},t,e),function(){var e=this,t=void 0!==e.length,r=t?e:[e],n=this._private.cy||this;if(!n.styleEnabled())return!1;var i=r[0];return i?i._private.animation.current.length>0:void 0}},clearQueue:function(e){var t={};return e=n.extend({},t,e),function(){var e=this,t=void 0!==e.length,r=t?e:[e],n=this._private.cy||this;if(!n.styleEnabled())return this;for(var i=0;i<r.length;i++){var a=r[i];a._private.animation.queue=[]}return this}},delay:function(e){var t={};return e=n.extend({},t,e),function(e,t){var r=this._private.cy||this;return r.styleEnabled()?this.animate({delay:e,duration:e,complete:t}):this}},delayAnimation:function(e){var t={};return e=n.extend({},t,e),function(e,t){var r=this._private.cy||this;return r.styleEnabled()?this.animation({delay:e,duration:e,complete:t}):this}},animation:function(e){var t={};return e=n.extend({},t,e),function(e,t){var r=this,i=void 0!==r.length,a=i?r:[r],o=this._private.cy||this,s=!i,u=!s;if(!o.styleEnabled())return this;var c=o.style();switch(e=n.extend({},e,t),void 0===e.duration&&(e.duration=400),e.duration){case"slow":e.duration=600;break;case"fast":e.duration=200}var d=!0;if(e)for(var h in e){d=!1;break}if(d)return new l(a[0],e);if(u&&(e.style=c.getPropsList(e.style||e.css),e.css=void 0),e.renderedPosition&&u){var p=e.renderedPosition,v=o.pan(),f=o.zoom();e.position={x:(p.x-v.x)/f,y:(p.y-v.y)/f}}if(e.panBy&&s){var g=e.panBy,y=o.pan();e.pan={x:y.x+g.x,y:y.y+g.y}}var m=e.center||e.centre;if(m&&s){var b=o.getCenterPan(m.eles,e.zoom);b&&(e.pan=b)}if(e.fit&&s){var x=e.fit,w=o.getFitViewport(x.eles||x.boundingBox,x.padding);w&&(e.pan=w.pan,e.zoom=w.zoom)}return new l(a[0],e)}},animate:function(e){var t={};return e=n.extend({},t,e),function(e,t){var r=this,i=void 0!==r.length,a=i?r:[r],o=this._private.cy||this;if(!o.styleEnabled())return this;t&&(e=n.extend({},e,t));for(var s=0;s<a.length;s++){var l=a[s],u=l.animated()&&(void 0===e.queue||e.queue),c=l.animation(e,u?{queue:!0}:void 0);c.play()}return this}},stop:function(e){var t={};return e=n.extend({},t,e),function(e,t){var r=this,n=void 0!==r.length,i=n?r:[r],a=this._private.cy||this;if(!a.styleEnabled())return this;for(var o=0;o<i.length;o++){for(var s=i[o],l=s._private,u=l.animation.current,c=0;c<u.length;c++){var d=u[c],h=d._private;t&&(h.duration=0)}e&&(l.animation.queue=[]),t||(l.animation.current=[])}return a.notify({collection:this,type:"draw"}),this}}};t.exports=u},{"./animation":1,"./event":42,"./is":77,"./promise":80,"./selector":81,"./util":94}],42:[function(e,t,r){"use strict";function n(){return!1}function i(){return!0}var a=function(e,t){return this instanceof a?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented?i:n):this.type=e,t&&(this.type=void 0!==t.type?t.type:this.type,this.cy=t.cy,this.cyTarget=t.cyTarget,this.cyPosition=t.cyPosition,this.cyRenderedPosition=t.cyRenderedPosition,this.namespace=t.namespace,this.layout=t.layout,this.data=t.data,this.message=t.message),void(this.timeStamp=e&&e.timeStamp||Date.now())):new a(e,t)};a.prototype={instanceString:function(){return"event"},preventDefault:function(){this.isDefaultPrevented=i;var e=this.originalEvent;e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){this.isPropagationStopped=i;var e=this.originalEvent;e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=i,this.stopPropagation()},isDefaultPrevented:n,isPropagationStopped:n,isImmediatePropagationStopped:n},t.exports=a},{}],43:[function(e,t,r){"use strict";function n(e,t,r){var n=r;if("core"===e)c.prototype[t]=r;else if("collection"===e)u.prototype[t]=r;else if("layout"===e){for(var a=function(e){this.options=e,r.call(this,e),h.plainObject(this._private)||(this._private={}),this._private.cy=e.cy,this._private.listeners=[]},o=a.prototype=Object.create(r.prototype),d=[],v=0;v<d.length;v++){var f=d[v];o[f]=o[f]||function(){return this}}o.start&&!o.run?o.run=function(){return this.start(),this}:!o.start&&o.run&&(o.start=function(){return this.run(),this}),o.stop||(o.stop=function(){var e=this.options;if(e&&e.animate)for(var t=this.animations,r=0;r<t.length;r++)t[r].stop();return this.trigger("layoutstop"),this}),o.destroy||(o.destroy=function(){return this}),o.on=l.on({layout:!0}),o.one=l.on({layout:!0,unbindSelfOnTrigger:!0}),o.once=l.on({layout:!0,unbindAllBindersOnTrigger:!0}),o.off=l.off({layout:!0}),o.trigger=l.trigger({layout:!0}),l.eventAliasesOn(o),n=a}else if("renderer"===e&&"null"!==t&&"base"!==t){var g=i("renderer","base").prototype,y=r.prototype;for(var m in g){var b=g[m],x=null!=y[m];if(x)return void s.error("Can not register renderer `"+t+"` since it overrides `"+m+"` in its prototype");y[m]=b}g.clientFunctions.forEach(function(e){y[e]=y[e]||function(){s.error("Renderer does not implement `renderer."+e+"()` on its prototype")}})}return s.setMap({map:p,keys:[e,t],value:n})}function i(e,t){return s.getMap({map:p,keys:[e,t]})}function a(e,t,r,n,i){return s.setMap({map:v,keys:[e,t,r,n],value:i})}function o(e,t,r,n){return s.getMap({map:v,keys:[e,t,r,n]})}var s=e("./util"),l=e("./define"),u=e("./collection"),c=e("./core"),d=e("./extensions"),h=e("./is"),p={},v={},f=function(){return 2===arguments.length?i.apply(null,arguments):3===arguments.length?n.apply(null,arguments):4===arguments.length?o.apply(null,arguments):5===arguments.length?a.apply(null,arguments):void s.error("Invalid extension access syntax")};c.prototype.extension=f,d.forEach(function(e){e.extensions.forEach(function(t){n(e.type,t.name,t.impl)})}),t.exports=f},{"./collection":23,"./core":34,"./define":41,"./extensions":44,"./is":77,"./util":94}],44:[function(e,t,r){"use strict";t.exports=[{type:"layout",extensions:e("./layout")},{type:"renderer",extensions:e("./renderer")}]},{"./layout":50,"./renderer":72}],45:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},s,e)}var i=e("../../util"),a=e("../../math"),o=e("../../is"),s={fit:!0,directed:!1,padding:30,circle:!1,spacingFactor:1.75,boundingBox:void 0,avoidOverlap:!0,roots:void 0,maximalAdjustments:0,animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){var e,t=this.options,r=t,n=t.cy,i=r.eles,s=i.nodes().not(":parent"),l=i,u=a.makeBoundingBox(r.boundingBox?r.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()});if(o.elementOrCollection(r.roots))e=r.roots;else if(o.array(r.roots)){for(var c=[],d=0;d<r.roots.length;d++){var h=r.roots[d],p=n.getElementById(h);c.push(p)}e=n.collection(c)}else if(o.string(r.roots))e=n.$(r.roots);else if(r.directed)e=s.roots();else{for(var v=[],f=s;f.length>0;){var g=n.collection();i.bfs({roots:f[0],visit:function(e,t,r,n,i){g=g.add(r)},directed:!1}),f=f.not(g),v.push(g)}e=n.collection();for(var d=0;d<v.length;d++){var y=v[d],m=y.maxDegree(!1),b=y.filter(function(){return this.degree(!1)===m});e=e.add(b)}}var x=[],w={},_={},E={},D={},S={};l.bfs({roots:e,directed:r.directed,visit:function(e,t,r,n,i){var a=this[0],o=a.id();if(x[t]||(x[t]=[]),x[t].push(a),w[o]=!0,_[o]=t,E[o]=i,D[o]=n,i){var s=i.id(),l=S[s]=S[s]||[];l.push(r)}}});for(var k=[],d=0;d<s.length;d++){var p=s[d];w[p.id()]||k.push(p)}for(var T=3*k.length,P=0;0!==k.length&&T>P;){for(var C=k.shift(),N=C.neighborhood().nodes(),M=!1,d=0;d<N.length;d++){var B=_[N[d].id()];if(void 0!==B){x[B].push(C),M=!0;break}}M||k.push(C),P++}for(;0!==k.length;){var C=k.shift(),M=!1;M||(0===x.length&&x.push([]),x[0].push(C))}var z=function(){for(var e=0;e<x.length;e++)for(var t=x[e],r=0;r<t.length;r++){var n=t[r];n._private.scratch.breadthfirst={depth:e,index:r}}};z();for(var O=function(e){for(var t,r=e.connectedEdges(function(){return this.data("target")===e.id()}),n=e._private.scratch.breadthfirst,i=0,a=0;a<r.length;a++){var o=r[a],s=o.source()[0],l=s._private.scratch.breadthfirst;n.depth<=l.depth&&i<l.depth&&(i=l.depth,t=s)}return t},I=0;I<r.maximalAdjustments;I++){for(var L=x.length,A=[],d=0;L>d;d++)for(var B=x[d],R=B.length,V=0;R>V;V++){var p=B[V],F=p._private.scratch.breadthfirst,j=O(p);j&&(F.intEle=j,A.push(p))}for(var d=0;d<A.length;d++){var p=A[d],F=p._private.scratch.breadthfirst,j=F.intEle,q=j._private.scratch.breadthfirst;x[F.depth].splice(F.index,1);for(var X=q.depth+1;X>x.length-1;)x.push([]);x[X].push(p),F.depth=X,F.index=x[X].length-1}z()}var Y=0;if(r.avoidOverlap){for(var d=0;d<s.length;d++){var $=s[d],H=$.boundingBox(),W=H.w,Z=H.h;Y=Math.max(Y,W,Z)}Y*=r.spacingFactor}for(var U={},G=function(e){if(U[e.id()])return U[e.id()];for(var t=e._private.scratch.breadthfirst.depth,r=e.neighborhood().nodes().not(":parent"),n=0,i=0,a=0;a<r.length;a++){var o=r[a],s=o._private.scratch.breadthfirst,l=s.index,u=s.depth,c=x[u].length;(t>u||0===t)&&(n+=l/c,i++)}return i=Math.max(1,i),n/=i,0===i&&(n=void 0),U[e.id()]=n,n},K=function(e,t){var r=G(e),n=G(t);return r-n},J=0;3>J;J++){for(var d=0;d<x.length;d++)x[d]=x[d].sort(K);z()}for(var Q=0,d=0;d<x.length;d++)Q=Math.max(x[d].length,Q);for(var ee={x:u.x1+u.w/2,y:u.x1+u.h/2},te=function(e,t){var n=e._private.scratch.breadthfirst,i=n.depth,a=n.index,o=x[i].length,s=Math.max(u.w/(o+1),Y),l=Math.max(u.h/(x.length+1),Y),c=Math.min(u.w/2/x.length,u.h/2/x.length);if(c=Math.max(c,Y),r.circle){if(r.circle){var d=c*i+c-(x.length>0&&x[0].length<=3?c/2:0),h=2*Math.PI/x[i].length*a;return 0===i&&1===x[0].length&&(d=1),{x:ee.x+d*Math.cos(h),y:ee.y+d*Math.sin(h)}}return{x:ee.x+(a+1-(o+1)/2)*s,y:(i+1)*l}}var p={x:ee.x+(a+1-(o+1)/2)*s,y:(i+1)*l};return t?p:p},re={},d=x.length-1;d>=0;d--)for(var B=x[d],V=0;V<B.length;V++){var C=B[V];re[C.id()]=te(C,d===x.length-1)}return s.layoutPositions(this,r,function(){return re[this.id()]}),this},t.exports=n},{"../../is":77,"../../math":79,"../../util":94}],46:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},s,e)}var i=e("../../util"),a=e("../../math"),o=e("../../is"),s={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,radius:void 0,startAngle:1.5*Math.PI,sweep:void 0,clockwise:!0,sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){var e=this.options,t=e,r=e.cy,n=t.eles,i=void 0!==t.counterclockwise?!t.counterclockwise:t.clockwise,s=n.nodes().not(":parent");t.sort&&(s=s.sort(t.sort));for(var l,u=a.makeBoundingBox(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:r.width(),h:r.height()}),c={x:u.x1+u.w/2,y:u.y1+u.h/2},d=void 0===t.sweep?2*Math.PI-2*Math.PI/s.length:t.sweep,h=d/Math.max(1,s.length-1),p=0,v=0;v<s.length;v++){var f=s[v],g=f.boundingBox(),y=g.w,m=g.h;p=Math.max(p,y,m)}if(l=o.number(t.radius)?t.radius:s.length<=1?0:Math.min(u.h,u.w)/2-p,s.length>1&&t.avoidOverlap){p*=1.75;var b=Math.cos(h)-Math.cos(0),x=Math.sin(h)-Math.sin(0),w=Math.sqrt(p*p/(b*b+x*x));l=Math.max(w,l)}var _=function(e,r){var n=t.startAngle+e*h*(i?1:-1),a=l*Math.cos(n),o=l*Math.sin(n),s={
+x:c.x+a,y:c.y+o};return s};return s.layoutPositions(this,t,_),this},t.exports=n},{"../../is":77,"../../math":79,"../../util":94}],47:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},o,e)}var i=e("../../util"),a=e("../../math"),o={fit:!0,padding:30,startAngle:1.5*Math.PI,sweep:void 0,clockwise:!0,equidistant:!1,minNodeSpacing:10,boundingBox:void 0,avoidOverlap:!0,height:void 0,width:void 0,concentric:function(e){return e.degree()},levelWidth:function(e){return e.maxDegree()/4},animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){for(var e=this.options,t=e,r=void 0!==t.counterclockwise?!t.counterclockwise:t.clockwise,n=e.cy,i=t.eles,o=i.nodes().not(":parent"),s=a.makeBoundingBox(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:n.width(),h:n.height()}),l={x:s.x1+s.w/2,y:s.y1+s.h/2},u=[],c=t.startAngle,d=0,h=0;h<o.length;h++){var p,v=o[h];p=t.concentric.apply(v,[v]),u.push({value:p,node:v}),v._private.scratch.concentric=p}o.updateStyle();for(var h=0;h<o.length;h++){var v=o[h],f=v.boundingBox();d=Math.max(d,f.w,f.h)}u.sort(function(e,t){return t.value-e.value});for(var g=t.levelWidth(o),y=[[]],m=y[0],h=0;h<u.length;h++){var b=u[h];if(m.length>0){var x=Math.abs(m[0].value-b.value);x>=g&&(m=[],y.push(m))}m.push(b)}var w=d+t.minNodeSpacing;if(!t.avoidOverlap){var _=y.length>0&&y[0].length>1,E=Math.min(s.w,s.h)/2-w,D=E/(y.length+_?1:0);w=Math.min(w,D)}for(var S=0,h=0;h<y.length;h++){var k=y[h],T=void 0===t.sweep?2*Math.PI-2*Math.PI/k.length:t.sweep,P=k.dTheta=T/Math.max(1,k.length-1);if(k.length>1&&t.avoidOverlap){var C=Math.cos(P)-Math.cos(0),N=Math.sin(P)-Math.sin(0),M=Math.sqrt(w*w/(C*C+N*N));S=Math.max(M,S)}k.r=S,S+=w}if(t.equidistant){for(var B=0,S=0,h=0;h<y.length;h++){var k=y[h],z=k.r-S;B=Math.max(B,z)}S=0;for(var h=0;h<y.length;h++){var k=y[h];0===h&&(S=k.r),k.r=S,S+=B}}for(var O={},h=0;h<y.length;h++)for(var k=y[h],P=k.dTheta,S=k.r,I=0;I<k.length;I++){var b=k[I],c=t.startAngle+(r?1:-1)*P*I,L={x:l.x+S*Math.cos(c),y:l.y+S*Math.sin(c)};O[b.node.id()]=L}return o.layoutPositions(this,t,function(){var e=this.id();return O[e]}),this},t.exports=n},{"../../math":79,"../../util":94}],48:[function(e,t,r){"use strict";function n(e){this.options=a.extend({},u,e),this.options.layout=this}var i,a=e("../../util"),o=e("../../math"),s=e("../../thread"),l=e("../../is"),u={ready:function(){},stop:function(){},animate:!0,animationThreshold:250,refresh:20,fit:!0,padding:30,boundingBox:void 0,componentSpacing:100,nodeRepulsion:function(e){return 4e5},nodeOverlap:10,idealEdgeLength:function(e){return 10},edgeElasticity:function(e){return 100},nestingFactor:5,gravity:80,numIter:1e3,initialTemp:200,coolingFactor:.95,minTemp:1,useMultitasking:!0};n.prototype.run=function(){var e=this.options,t=e.cy,r=this,n=this.thread;(!n||n.stopped())&&(n=this.thread=s({disabled:!e.useMultitasking})),r.stopped=!1,r.trigger({type:"layoutstart",layout:r}),i=!0===e.debug?!0:!1;var o=c(t,r,e);i&&p(o),v(o,t);var l=Date.now(),u=!1,d=function(r){r=r||{},u||!r.force&&Date.now()-l<e.animationThreshold||(u=!0,a.requestAnimationFrame(function(){f(o,t,e),!0===e.fit&&t.fit(e.padding),u=!1}))};n.on("message",function(e){var t=e.message;o.layoutNodes=t,d()}),n.pass({layoutInfo:o,options:{animate:e.animate,refresh:e.refresh,componentSpacing:e.componentSpacing,nodeOverlap:e.nodeOverlap,nestingFactor:e.nestingFactor,gravity:e.gravity,numIter:e.numIter,initialTemp:e.initialTemp,coolingFactor:e.coolingFactor,minTemp:e.minTemp}}).run(function(e){var t,r=e.layoutInfo,n=e.options,i=!1,a=function(e,t,r){o(e,t),c(e,t),d(e,t),h(e,t),p(e,t)},o=function(e,t){for(var r=0;r<e.graphSet.length;r++)for(var n=e.graphSet[r],i=n.length,a=0;i>a;a++)for(var o=e.layoutNodes[e.idToIndex[n[a]]],l=a+1;i>l;l++){var u=e.layoutNodes[e.idToIndex[n[l]]];s(o,u,e,t)}},s=function(e,t,r,n){var i=e.cmptId,a=t.cmptId;if(i===a||r.isCompound){var o=t.positionX-e.positionX,s=t.positionY-e.positionY;if(0!==o||0!==s){var c=l(e,t,o,s);if(c>0)var d=n.nodeOverlap*c,h=Math.sqrt(o*o+s*s),p=d*o/h,v=d*s/h;else var f=u(e,o,s),g=u(t,-1*o,-1*s),y=g.x-f.x,m=g.y-f.y,b=y*y+m*m,h=Math.sqrt(b),d=(e.nodeRepulsion+t.nodeRepulsion)/b,p=d*y/h,v=d*m/h;e.isLocked||(e.offsetX-=p,e.offsetY-=v),t.isLocked||(t.offsetX+=p,t.offsetY+=v)}}},l=function(e,t,r,n){if(r>0)var i=e.maxX-t.minX;else var i=t.maxX-e.minX;if(n>0)var a=e.maxY-t.minY;else var a=t.maxY-e.minY;return i>=0&&a>=0?Math.sqrt(i*i+a*a):0},u=function(e,t,r){var n=e.positionX,i=e.positionY,a=e.height||1,o=e.width||1,s=r/t,l=a/o,u={};do{if(0===t&&r>0){u.x=n,u.y=i+a/2;break}if(0===t&&0>r){u.x=n,u.y=i+a/2;break}if(t>0&&s>=-1*l&&l>=s){u.x=n+o/2,u.y=i+o*r/2/t;break}if(0>t&&s>=-1*l&&l>=s){u.x=n-o/2,u.y=i-o*r/2/t;break}if(r>0&&(-1*l>=s||s>=l)){u.x=n+a*t/2/r,u.y=i+a/2;break}if(0>r&&(-1*l>=s||s>=l)){u.x=n-a*t/2/r,u.y=i-a/2;break}}while(!1);return u},c=function(e,t){for(var r=0;r<e.edgeSize;r++){var n=e.layoutEdges[r],i=e.idToIndex[n.sourceId],a=e.layoutNodes[i],o=e.idToIndex[n.targetId],s=e.layoutNodes[o],l=s.positionX-a.positionX,c=s.positionY-a.positionY;if(0===l&&0===c)return;var d=u(a,l,c),h=u(s,-1*l,-1*c),p=h.x-d.x,v=h.y-d.y,f=Math.sqrt(p*p+v*v),g=Math.pow(n.idealLength-f,2)/n.elasticity;if(0!==f)var y=g*p/f,m=g*v/f;else var y=0,m=0;a.isLocked||(a.offsetX+=y,a.offsetY+=m),s.isLocked||(s.offsetX-=y,s.offsetY-=m)}},d=function(e,t){for(var r=1,n=0;n<e.graphSet.length;n++){var i=e.graphSet[n],a=i.length;if(0===n)var o=e.clientHeight/2,s=e.clientWidth/2;else var l=e.layoutNodes[e.idToIndex[i[0]]],u=e.layoutNodes[e.idToIndex[l.parentId]],o=u.positionX,s=u.positionY;for(var c=0;a>c;c++){var d=e.layoutNodes[e.idToIndex[i[c]]];if(!d.isLocked){var h=o-d.positionX,p=s-d.positionY,v=Math.sqrt(h*h+p*p);if(v>r){var f=t.gravity*h/v,g=t.gravity*p/v;d.offsetX+=f,d.offsetY+=g}}}}},h=function(e,t){var r=[],n=0,i=-1;for(r.push.apply(r,e.graphSet[0]),i+=e.graphSet[0].length;i>=n;){var a=r[n++],o=e.idToIndex[a],s=e.layoutNodes[o],l=s.children;if(0<l.length&&!s.isLocked){for(var u=s.offsetX,c=s.offsetY,d=0;d<l.length;d++){var h=e.layoutNodes[e.idToIndex[l[d]]];h.offsetX+=u,h.offsetY+=c,r[++i]=l[d]}s.offsetX=0,s.offsetY=0}}},p=function(e,t){for(var r=0;r<e.nodeSize;r++){var n=e.layoutNodes[r];0<n.children.length&&(n.maxX=void 0,n.minX=void 0,n.maxY=void 0,n.minY=void 0)}for(var r=0;r<e.nodeSize;r++){var n=e.layoutNodes[r];if(!(0<n.children.length||n.isLocked)){var i=v(n.offsetX,n.offsetY,e.temperature);n.positionX+=i.x,n.positionY+=i.y,n.offsetX=0,n.offsetY=0,n.minX=n.positionX-n.width,n.maxX=n.positionX+n.width,n.minY=n.positionY-n.height,n.maxY=n.positionY+n.height,f(n,e)}}for(var r=0;r<e.nodeSize;r++){var n=e.layoutNodes[r];0<n.children.length&&!n.isLocked&&(n.positionX=(n.maxX+n.minX)/2,n.positionY=(n.maxY+n.minY)/2,n.width=n.maxX-n.minX,n.height=n.maxY-n.minY)}},v=function(e,t,r){var n=Math.sqrt(e*e+t*t);if(n>r)var i={x:r*e/n,y:r*t/n};else var i={x:e,y:t};return i},f=function(e,t){var r=e.parentId;if(null!=r){var n=t.layoutNodes[t.idToIndex[r]],i=!1;return(null==n.maxX||e.maxX+n.padRight>n.maxX)&&(n.maxX=e.maxX+n.padRight,i=!0),(null==n.minX||e.minX-n.padLeft<n.minX)&&(n.minX=e.minX-n.padLeft,i=!0),(null==n.maxY||e.maxY+n.padBottom>n.maxY)&&(n.maxY=e.maxY+n.padBottom,i=!0),(null==n.minY||e.minY-n.padTop<n.minY)&&(n.minY=e.minY-n.padTop,i=!0),i?f(n,t):void 0}},g=function(e,t){for(var n=r.layoutNodes,i=[],a=0;a<n.length;a++){var o=n[a],s=o.cmptId,l=i[s]=i[s]||[];l.push(o)}for(var u=0,a=0;a<i.length;a++){var c=i[a];c.x1=1/0,c.x2=-(1/0),c.y1=1/0,c.y2=-(1/0);for(var d=0;d<c.length;d++){var h=c[d];c.x1=Math.min(c.x1,h.positionX-h.width/2),c.x2=Math.max(c.x2,h.positionX+h.width/2),c.y1=Math.min(c.y1,h.positionY-h.height/2),c.y2=Math.max(c.y2,h.positionY+h.height/2)}c.w=c.x2-c.x1,c.h=c.y2-c.y1,u+=c.w*c.h}i.sort(function(e,t){return t.w*t.h-e.w*e.h});for(var p=0,v=0,f=0,g=0,y=Math.sqrt(u)*r.clientWidth/r.clientHeight,a=0;a<i.length;a++){for(var c=i[a],d=0;d<c.length;d++){var h=c[d];h.isLocked||(h.positionX+=p,h.positionY+=v)}p+=c.w+t.componentSpacing,f+=c.w+t.componentSpacing,g=Math.max(g,c.h),f>y&&(v+=g+t.componentSpacing,p=0,f=0,g=0)}},y=function(e){return i?!1:(a(r,n,e),r.temperature=r.temperature*n.coolingFactor,r.temperature<n.minTemp?!1:!0)},m=0;do{for(var b=0;b<n.refresh&&m<n.numIter;){var t=y(m);if(!t)break;b++,m++}n.animate&&broadcast(r.layoutNodes)}while(t&&m+1<n.numIter);return g(r,n),r}).then(function(e){o.layoutNodes=e.layoutNodes,n.stop(),h()});var h=function(){d({force:!0}),r.one("layoutstop",e.stop),r.trigger({type:"layoutstop",layout:r})};return this},n.prototype.stop=function(){return this.stopped=!0,this.thread&&this.thread.stop(),this.trigger("layoutstop"),this},n.prototype.destroy=function(){return this.thread&&this.thread.stop(),this};var c=function(e,t,r){for(var n=r.eles.edges(),i=r.eles.nodes(),a={isCompound:e.hasCompoundNodes(),layoutNodes:[],idToIndex:{},nodeSize:i.size(),graphSet:[],indexToGraph:[],layoutEdges:[],edgeSize:n.size(),temperature:r.initialTemp,clientWidth:e.width(),clientHeight:e.width(),boundingBox:o.makeBoundingBox(r.boundingBox?r.boundingBox:{x1:0,y1:0,w:e.width(),h:e.height()})},s=r.eles.components(),u={},c=0;c<s.length;c++)for(var h=s[c],p=0;p<h.length;p++){var v=h[p];u[v.id()]=c}for(var c=0;c<a.nodeSize;c++){var f=i[c],g=f.boundingBox(),y={};y.isLocked=f.locked(),y.id=f.data("id"),y.parentId=f.data("parent"),y.cmptId=u[f.id()],y.children=[],y.positionX=f.position("x"),y.positionY=f.position("y"),y.offsetX=0,y.offsetY=0,y.height=g.w,y.width=g.h,y.maxX=y.positionX+y.width/2,y.minX=y.positionX-y.width/2,y.maxY=y.positionY+y.height/2,y.minY=y.positionY-y.height/2,y.padLeft=parseFloat(f.style("padding-left")),y.padRight=parseFloat(f.style("padding-right")),y.padTop=parseFloat(f.style("padding-top")),y.padBottom=parseFloat(f.style("padding-bottom")),y.nodeRepulsion=l.fn(r.nodeRepulsion)?r.nodeRepulsion.call(f,f):r.nodeRepulsion,a.layoutNodes.push(y),a.idToIndex[y.id]=c}for(var m=[],b=0,x=-1,w=[],c=0;c<a.nodeSize;c++){var f=a.layoutNodes[c],_=f.parentId;null!=_?a.layoutNodes[a.idToIndex[_]].children.push(f.id):(m[++x]=f.id,w.push(f.id))}for(a.graphSet.push(w);x>=b;){var E=m[b++],D=a.idToIndex[E],v=a.layoutNodes[D],S=v.children;if(S.length>0){a.graphSet.push(S);for(var c=0;c<S.length;c++)m[++x]=S[c]}}for(var c=0;c<a.graphSet.length;c++)for(var k=a.graphSet[c],p=0;p<k.length;p++){var T=a.idToIndex[k[p]];a.indexToGraph[T]=c}for(var c=0;c<a.edgeSize;c++){var P=n[c],C={};C.id=P.data("id"),C.sourceId=P.data("source"),C.targetId=P.data("target");var N=l.fn(r.idealEdgeLength)?r.idealEdgeLength.call(P,P):r.idealEdgeLength,M=l.fn(r.edgeElasticity)?r.edgeElasticity.call(P,P):r.edgeElasticity,B=a.idToIndex[C.sourceId],z=a.idToIndex[C.targetId],O=a.indexToGraph[B],I=a.indexToGraph[z];if(O!=I){for(var L=d(C.sourceId,C.targetId,a),A=a.graphSet[L],R=0,y=a.layoutNodes[B];-1===A.indexOf(y.id);)y=a.layoutNodes[a.idToIndex[y.parentId]],R++;for(y=a.layoutNodes[z];-1===A.indexOf(y.id);)y=a.layoutNodes[a.idToIndex[y.parentId]],R++;N*=R*r.nestingFactor}C.idealLength=N,C.elasticity=M,a.layoutEdges.push(C)}return a},d=function(e,t,r){var n=h(e,t,0,r);return 2>n.count?0:n.graph},h=function(e,t,r,n){var i=n.graphSet[r];if(-1<i.indexOf(e)&&-1<i.indexOf(t))return{count:2,graph:r};for(var a=0,o=0;o<i.length;o++){var s=i[o],l=n.idToIndex[s],u=n.layoutNodes[l].children;if(0!==u.length){var c=n.indexToGraph[n.idToIndex[u[0]]],d=h(e,t,c,n);if(0!==d.count){if(1!==d.count)return d;if(a++,2===a)break}}}return{count:a,graph:r}},p=function(e){if(i){console.debug("layoutNodes:");for(var t=0;t<e.nodeSize;t++){var r=e.layoutNodes[t],n="\nindex: "+t+"\nId: "+r.id+"\nChildren: "+r.children.toString()+"\nparentId: "+r.parentId+"\npositionX: "+r.positionX+"\npositionY: "+r.positionY+"\nOffsetX: "+r.offsetX+"\nOffsetY: "+r.offsetY+"\npadLeft: "+r.padLeft+"\npadRight: "+r.padRight+"\npadTop: "+r.padTop+"\npadBottom: "+r.padBottom;console.debug(n)}console.debug("idToIndex");for(var t in e.idToIndex)console.debug("Id: "+t+"\nIndex: "+e.idToIndex[t]);console.debug("Graph Set");for(var a=e.graphSet,t=0;t<a.length;t++)console.debug("Set : "+t+": "+a[t].toString());for(var n="IndexToGraph",t=0;t<e.indexToGraph.length;t++)n+="\nIndex : "+t+" Graph: "+e.indexToGraph[t];console.debug(n),n="Layout Edges";for(var t=0;t<e.layoutEdges.length;t++){var o=e.layoutEdges[t];n+="\nEdge Index: "+t+" ID: "+o.id+" SouceID: "+o.sourceId+" TargetId: "+o.targetId+" Ideal Length: "+o.idealLength}console.debug(n),n="nodeSize: "+e.nodeSize,n+="\nedgeSize: "+e.edgeSize,n+="\ntemperature: "+e.temperature,console.debug(n)}},v=function(e,t){for(var r=e.clientWidth,n=e.clientHeight,i=0;i<e.nodeSize;i++){var a=e.layoutNodes[i];0!==a.children.length||a.isLocked||(a.positionX=Math.random()*r,a.positionY=Math.random()*n)}},f=function(e,t,r){var n=r.layout,i=r.eles.nodes(),a=e.boundingBox,o={x1:1/0,x2:-(1/0),y1:1/0,y2:-(1/0)};r.boundingBox&&(i.forEach(function(t){var r=e.layoutNodes[e.idToIndex[t.data("id")]];o.x1=Math.min(o.x1,r.positionX),o.x2=Math.max(o.x2,r.positionX),o.y1=Math.min(o.y1,r.positionY),o.y2=Math.max(o.y2,r.positionY)}),o.w=o.x2-o.x1,o.h=o.y2-o.y1),i.positions(function(t,n){var i=e.layoutNodes[e.idToIndex[n.data("id")]];if(r.boundingBox){var s=(i.positionX-o.x1)/o.w,l=(i.positionY-o.y1)/o.h;return{x:a.x1+s*a.w,y:a.y1+l*a.h}}return{x:i.positionX,y:i.positionY}}),!0!==e.ready&&(e.ready=!0,n.one("layoutready",r.ready),n.trigger({type:"layoutready",layout:this}))};t.exports=n},{"../../is":77,"../../math":79,"../../thread":92,"../../util":94}],49:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},o,e)}var i=e("../../util"),a=e("../../math"),o={fit:!0,padding:30,boundingBox:void 0,avoidOverlap:!0,avoidOverlapPadding:10,condense:!1,rows:void 0,cols:void 0,position:function(e){},sort:void 0,animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){var e=this.options,t=e,r=e.cy,n=t.eles,i=n.nodes().not(":parent");t.sort&&(i=i.sort(t.sort));var o=a.makeBoundingBox(t.boundingBox?t.boundingBox:{x1:0,y1:0,w:r.width(),h:r.height()});if(0===o.h||0===o.w)i.layoutPositions(this,t,function(){return{x:o.x1,y:o.y1}});else{var s=i.size(),l=Math.sqrt(s*o.h/o.w),u=Math.round(l),c=Math.round(o.w/o.h*l),d=function(e){if(null==e)return Math.min(u,c);var t=Math.min(u,c);t==u?u=e:c=e},h=function(e){if(null==e)return Math.max(u,c);var t=Math.max(u,c);t==u?u=e:c=e},p=t.rows,v=null!=t.cols?t.cols:t.columns;if(null!=p&&null!=v)u=p,c=v;else if(null!=p&&null==v)u=p,c=Math.ceil(s/u);else if(null==p&&null!=v)c=v,u=Math.ceil(s/c);else if(c*u>s){var f=d(),g=h();(f-1)*g>=s?d(f-1):(g-1)*f>=s&&h(g-1)}else for(;s>c*u;){var f=d(),g=h();(g+1)*f>=s?h(g+1):d(f+1)}var y=o.w/c,m=o.h/u;if(t.condense&&(y=0,m=0),t.avoidOverlap)for(var b=0;b<i.length;b++){var x=i[b],w=x._private.position;(null==w.x||null==w.y)&&(w.x=0,w.y=0);var _=x.boundingBox(),E=t.avoidOverlapPadding,D=_.w+E,S=_.h+E;y=Math.max(y,D),m=Math.max(m,S)}for(var k={},T=function(e,t){return k["c-"+e+"-"+t]?!0:!1},P=function(e,t){k["c-"+e+"-"+t]=!0},C=0,N=0,M=function(){N++,N>=c&&(N=0,C++)},B={},b=0;b<i.length;b++){var x=i[b],z=t.position(x);if(z&&(void 0!==z.row||void 0!==z.col)){var w={row:z.row,col:z.col};if(void 0===w.col)for(w.col=0;T(w.row,w.col);)w.col++;else if(void 0===w.row)for(w.row=0;T(w.row,w.col);)w.row++;B[x.id()]=w,P(w.row,w.col)}}var O=function(e,t){var r,n;if(t.locked()||t.isFullAutoParent())return!1;var i=B[t.id()];if(i)r=i.col*y+y/2+o.x1,n=i.row*m+m/2+o.y1;else{for(;T(C,N);)M();r=N*y+y/2+o.x1,n=C*m+m/2+o.y1,P(C,N),M()}return{x:r,y:n}};i.layoutPositions(this,t,O)}return this},t.exports=n},{"../../math":79,"../../util":94}],50:[function(e,t,r){"use strict";t.exports=[{name:"breadthfirst",impl:e("./breadthfirst")},{name:"circle",impl:e("./circle")},{name:"concentric",impl:e("./concentric")},{name:"cose",impl:e("./cose")},{name:"grid",impl:e("./grid")},{name:"null",impl:e("./null")},{name:"preset",impl:e("./preset")},{name:"random",impl:e("./random")}]},{"./breadthfirst":45,"./circle":46,"./concentric":47,"./cose":48,"./grid":49,"./null":51,"./preset":52,"./random":53}],51:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},a,e)}var i=e("../../util"),a={ready:function(){},stop:function(){}};n.prototype.run=function(){var e=this.options,t=e.eles,r=this;e.cy;return r.trigger("layoutstart"),t.nodes().positions(function(){return{x:0,y:0}}),r.one("layoutready",e.ready),r.trigger("layoutready"),r.one("layoutstop",e.stop),r.trigger("layoutstop"),this},n.prototype.stop=function(){return this},t.exports=n},{"../../util":94}],52:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},o,e)}var i=e("../../util"),a=e("../../is"),o={positions:void 0,zoom:void 0,pan:void 0,fit:!0,padding:30,animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){function e(e){if(null==t.positions)return null;if(i)return t.positions.apply(e,[e]);var r=t.positions[e._private.data.id];return null==r?null:r}var t=this.options,r=t.eles,n=r.nodes(),i=a.fn(t.positions);return n.layoutPositions(this,t,function(t,r){var n=e(r);return r.locked()||null==n?!1:n}),this},t.exports=n},{"../../is":77,"../../util":94}],53:[function(e,t,r){"use strict";function n(e){this.options=i.extend({},o,e)}var i=e("../../util"),a=e("../../math"),o={fit:!0,padding:30,boundingBox:void 0,animate:!1,animationDuration:500,animationEasing:void 0,ready:void 0,stop:void 0};n.prototype.run=function(){var e=this.options,t=e.cy,r=e.eles,n=r.nodes().not(":parent"),i=a.makeBoundingBox(e.boundingBox?e.boundingBox:{x1:0,y1:0,w:t.width(),h:t.height()}),o=function(e,t){return{x:i.x1+Math.round(Math.random()*i.w),y:i.y1+Math.round(Math.random()*i.h)}};return n.layoutPositions(this,e,o),this},t.exports=n},{"../../math":79,"../../util":94}],54:[function(e,t,r){"use strict";var n=e("../../../math"),i=e("../../../is"),a=e("../../../util"),o={};o.arrowShapeHeight=.3,o.registerArrowShapes=function(){var e=this.arrowShapes={},t=this,r=function(e,t,r,n,i,a){var o=i.x-r/2-a,s=i.x+r/2+a,l=i.y-r/2-a,u=i.y+r/2+a,c=e>=o&&s>=e&&t>=l&&u>=t;return c},o=function(e,t,r,n,i){var a=e*Math.cos(n)-t*Math.sin(n),o=e*Math.sin(n)+t*Math.cos(n),s=a*r,l=o*r,u=s+i.x,c=l+i.y;return{x:u,y:c}},s=function(e,t,r,n){for(var i=[],a=0;a<e.length;a+=2){var s=e[a],l=e[a+1];i.push(o(s,l,t,r,n))}return i},l=function(e){for(var t=[],r=0;r<e.length;r++){var n=e[r];t.push(n.x,n.y)}return t},u=function(o,u){i.string(u)&&(u=e[u]),e[o]=a.extend({name:o,points:[-.15,-.3,.15,-.3,.15,.3,-.15,.3],collide:function(e,t,r,i,a,o){var u=l(s(this.points,r+2*o,i,a)),c=n.pointInsidePolygonPoints(e,t,u);return c},roughCollide:r,draw:function(e,r,n,i){var a=s(this.points,r,n,i);t.arrowShapeImpl("polygon")(e,a)},spacing:function(e){return 0},gap:function(e){return 2*e._private.style.width.pfValue}},u)};u("none",{collide:a.falsify,roughCollide:a.falsify,draw:a.noop,spacing:a.zeroify,gap:a.zeroify}),u("triangle",{points:[-.15,-.3,0,0,.15,-.3]}),u("arrow","triangle"),u("triangle-backcurve",{points:e.triangle.points,controlPoint:[0,-.15],roughCollide:r,draw:function(e,r,n,i){var a=s(this.points,r,n,i),l=this.controlPoint,u=o(l[0],l[1],r,n,i);t.arrowShapeImpl(this.name)(e,a,u)},gap:function(e){return e._private.style.width.pfValue}}),u("triangle-tee",{points:[-.15,-.3,0,0,.15,-.3,-.15,-.3],pointsTee:[-.15,-.4,-.15,-.5,.15,-.5,.15,-.4],collide:function(e,t,r,i,a,o){var u=l(s(this.points,r+2*o,i,a)),c=l(s(this.pointsTee,r+2*o,i,a)),d=n.pointInsidePolygonPoints(e,t,u)||n.pointInsidePolygonPoints(e,t,c);return d},draw:function(e,r,n,i){var a=s(this.points,r,n,i),o=s(this.pointsTee,r,n,i);t.arrowShapeImpl(this.name)(e,a,o)}}),u("vee",{points:[-.15,-.3,0,0,.15,-.3,0,-.15],gap:function(e){return e._private.style.width.pfValue}}),u("half-triangle-overshot",{points:[0,-.25,-.5,-.25,.5,.25],leavePathOpen:!0,matchEdgeWidth:!0}),u("circle",{radius:.15,collide:function(e,t,r,n,i,a){var o=i,s=Math.pow(o.x-e,2)+Math.pow(o.y-t,2)<=Math.pow((r+2*a)*this.radius,2);return s},draw:function(e,r,n,i){t.arrowShapeImpl(this.name)(e,i.x,i.y,this.radius*r)},spacing:function(e){return t.getArrowWidth(e._private.style.width.pfValue)*this.radius}}),u("inhibitor",{points:[-.25,0,-.25,-.1,.25,-.1,.25,0],spacing:function(e){return 1},gap:function(e){return 1}}),u("tee","inhibitor"),u("square",{points:[-.15,0,.15,0,.15,-.3,-.15,-.3]}),u("diamond",{points:[-.15,-.15,0,-.3,.15,-.15,0,0],gap:function(e){return e._private.style.width.pfValue}})},t.exports=o},{"../../../is":77,"../../../math":79,"../../../util":94}],55:[function(e,t,r){"use strict";var n={},i=function(e){e.eleEache=null},a=function(e){return e.eleEache||(e.eleEache={nodes:e.cy.nodes(),edges:e.cy.edges()}),e.eleEache};n.getCachedElements=function(){return a(this)},n.getCachedNodes=function(){return a(this).nodes},n.getCachedEdges=function(){return a(this).edges},n.updateElementsCache=function(){var e=this;return i(e),a(e)},t.exports=n},{}],56:[function(e,t,r){"use strict";function n(e,t){var r=function(e,t,r,n){return i.qbezierAt(e,t,r,n)},n=e._private,a=n.rstyle.bezierPts;a.push({x:r(t[0],t[2],t[4],.05),y:r(t[1],t[3],t[5],.05)}),a.push({x:r(t[0],t[2],t[4],.25),y:r(t[1],t[3],t[5],.25)}),a.push({x:r(t[0],t[2],t[4],.4),y:r(t[1],t[3],t[5],.4)}),a.push({x:r(t[0],t[2],t[4],.5),y:r(t[1],t[3],t[5],.5)}),a.push({x:r(t[0],t[2],t[4],.6),y:r(t[1],t[3],t[5],.6)}),a.push({x:r(t[0],t[2],t[4],.75),y:r(t[1],t[3],t[5],.75)}),a.push({x:r(t[0],t[2],t[4],.95),y:r(t[1],t[3],t[5],.95)})}var i=e("../../../math"),a=e("../../../is"),o=e("../../../collection/zsort"),s={};s.projectIntoViewport=function(e,t){var r=this.findContainerClientCoords(),n=r[0],i=r[1],a=e-n,o=t-i;return a-=this.cy.pan().x,o-=this.cy.pan().y,a/=this.cy.zoom(),o/=this.cy.zoom(),[a,o]},s.findContainerClientCoords=function(){var e=this.container,t=this.containerBB=this.containerBB||e.getBoundingClientRect();return[t.left,t.top,t.right-t.left,t.bottom-t.top]},s.invalidateContainerClientCoordsCache=function(){this.containerBB=null},s.findNearestElement=function(e,t,r,n){function a(n){var i=n._private;if("no"!==i.style.events.strValue){var a=n.outerWidth()+2*f,o=n.outerHeight()+2*f,s=a/2,c=o/2,h=i.position;if(h.x-s<=e&&e<=h.x+s&&h.y-c<=t&&t<=h.y+c){var p=!r||n.visible()&&!n.transparent();if(r&&!p)return;var v=u.nodeShapes[l.getNodeShape(n)];v.checkPoint(e,t,0,a,o,h.x,h.y)&&d.push(n)}}}function o(n){var o=n._private;if("no"!==o.style.events.strValue){var s,c,h=o.rscratch,f=o.style,g=f.width.pfValue/2+v,y=g*g,m=2*g,b=o.source,x=o.target,w=!1,_=function(){if(void 0!==c)return c;if(!r)return c=!0,!0;var e=n.visible()&&!n.transparent();return e?(c=!0,!0):(c=!1,!1)};if("segments"===h.edgeType||"straight"===h.edgeType||"haystack"===h.edgeType)for(var E=h.allpts,D=0;D+3<E.length;D+=2)(w=i.inLineVicinity(e,t,E[D],E[D+1],E[D+2],E[D+3],m))&&_()&&y>(s=i.sqDistanceToFiniteLine(e,t,E[D],E[D+1],E[D+2],E[D+3]))&&d.push(n);else if("bezier"===h.edgeType||"multibezier"===h.edgeType||"self"===h.edgeType||"compound"===h.edgeType)for(var E=h.allpts,D=0;D+5<h.allpts.length;D+=4)(w=i.inBezierVicinity(e,t,E[D],E[D+1],E[D+2],E[D+3],E[D+4],E[D+5],m))&&_()&&y>(s=i.sqDistanceToQuadraticBezier(e,t,E[D],E[D+1],E[D+2],E[D+3],E[D+4],E[D+5]))&&d.push(n);if(w&&_()&&0===d.length||d[d.length-1]!==n)for(var b=b||o.source,x=x||o.target,S=f.width.pfValue,k=l.getArrowWidth(S),T=[{name:"source",x:h.arrowStartX,y:h.arrowStartY,angle:h.srcArrowAngle},{name:"target",x:h.arrowEndX,y:h.arrowEndY,angle:h.tgtArrowAngle},{name:"mid-source",x:h.midX,y:h.midY,angle:h.midsrcArrowAngle},{name:"mid-target",x:h.midX,y:h.midY,angle:h.midtgtArrowAngle}],D=0;D<T.length;D++){var P=T[D],C=u.arrowShapes[f[P.name+"-arrow-shape"].value];if(C.roughCollide(e,t,k,P.angle,{x:P.x,y:P.y},v)&&C.collide(e,t,k,P.angle,{x:P.x,y:P.y},v)){d.push(n);break}}p&&d.length>0&&d[d.length-1]===n&&(a(b),a(x))}}function s(r){var n=r._private,a=g;if("no"!==n.style["text-events"].strValue)if("edges"===n.group&&"autorotate"===n.style["edge-text-rotation"].strValue){var o=n.rstyle,s=o.labelWidth+2*a,l=o.labelHeight+2*a,u=o.labelX,c=o.labelY,h=n.rscratch.labelAngle,p=Math.cos(h),v=Math.sin(h),f=function(e,t){return e-=u,t-=c,{x:e*p-t*v+u,y:e*v+t*p+c}},y=u-s/2,m=u+s/2,b=c-l/2,x=c+l/2,w=f(y,b),_=f(y,x),E=f(m,b),D=f(m,x),S=[w.x,w.y,E.x,E.y,D.x,D.y,_.x,_.y];i.pointInsidePolygonPoints(e,t,S)&&d.push(r)}else{var k=r.boundingBox({includeLabels:!0,includeNodes:!1,includeEdges:!1});k.x1-=a,k.y1-=a,k.x2+=a,k.y2+=a,k.w=k.x2-k.x1,k.h=k.y2-k.y1,i.inBoundingBox(k,e,t)&&d.push(r)}}for(var l=this,u=this,c=u.getCachedZSortedEles(),d=[],h=u.cy.zoom(),p=u.cy.hasCompoundNodes(),v=(n?24:8)/h,f=(n?8:2)/h,g=(n?8:2)/h,y=c.length-1;y>=0;y--){var m=c[y],b=m._private;if(d.length>0)break;"nodes"===b.group?a(m):o(m),s(m)}return d.length>0?d[d.length-1]:null},s.getAllInBox=function(e,t,r,n){var a=this.getCachedNodes(),o=this.getCachedEdges(),s=[],l=Math.min(e,r),u=Math.max(e,r),c=Math.min(t,n),d=Math.max(t,n);e=l,r=u,t=c,n=d;for(var h=i.makeBoundingBox({x1:e,y1:t,x2:r,y2:n}),p=0;p<a.length;p++){var v=a[p],f=v.boundingBox({includeNodes:!0,includeEdges:!1,includeLabels:!1});i.boundingBoxesIntersect(h,f)&&s.push(a[p])}for(var g=0;g<o.length;g++){var y=o[g],m=y._private,b=m.rscratch;if((null==b.startX||null==b.startY||i.inBoundingBox(h,b.startX,b.startY))&&(null==b.endX||null==b.endY||i.inBoundingBox(h,b.endX,b.endY)))if("bezier"===b.edgeType||"multibezier"===b.edgeType||"self"===b.edgeType||"compound"===b.edgeType||"segments"===b.edgeType||"haystack"===b.edgeType){for(var x=m.rstyle.bezierPts||m.rstyle.linePts||m.rstyle.haystackPts,w=!0,p=0;p<x.length;p++)if(!i.pointInBoundingBox(h,x[p])){w=!1;break}w&&s.push(y)}else("haystack"===b.edgeType||"straight"===b.edgeType)&&s.push(y)}return s},s.getNodeShape=function(e){var t=this,r=e._private.style,n=r.shape.value;if(e.isParent())return"rectangle"===n||"roundrectangle"===n?n:"rectangle";if("polygon"===n){var i=r["shape-polygon-points"].value;return t.nodeShapes.makePolygon(i).name}return n},s.updateCachedZSortedEles=function(){this.getCachedZSortedEles(!0)},s.getCachedZSortedEles=function(e){var t=this.lastZOrderCachedNodes,r=this.lastZOrderCachedEdges,n=this.getCachedNodes(),i=this.getCachedEdges(),a=[];if(!e&&t&&r&&t===n&&r===i)a=this.cachedZSortedEles;else{for(var s=0;s<n.length;s++){var l=n[s];(l.animated()||l.visible()&&!l.transparent())&&a.push(l)}for(var s=0;s<i.length;s++){var u=i[s];(u.animated()||u.visible()&&!u.transparent())&&a.push(u)}a.sort(o),this.cachedZSortedEles=a}return this.lastZOrderCachedNodes=n,this.lastZOrderCachedEdges=i,a},s.projectLines=function(e){var t=e._private,r=t.rscratch,i=r.edgeType;if("multibezier"===i||"bezier"===i||"self"===i||"compound"===i)for(var a=(t.rstyle.bezierPts=[],0);a+5<r.allpts.length;a+=4)n(e,r.allpts.slice(a,a+6));else if("segments"===i)for(var o=t.rstyle.linePts=[],a=0;a+1<r.allpts.length;a+=2)o.push({x:r.allpts[a],y:r.allpts[a+1]});else if("haystack"===i){var s=r.haystackPts;t.rstyle.haystackPts=[{x:s[0],y:s[1]},{x:s[2],y:s[3]}]}},s.projectBezier=s.projectLines,s.recalculateNodeLabelProjection=function(e){var t=e._private.style.label.strValue;if(t&&!t.match(/^\s+$/)){var r,n,i=e.outerWidth(),a=e.outerHeight(),o=e._private.position,s=e._private.style["text-halign"].strValue,l=e._private.style["text-valign"].strValue,u=e._private.rscratch,c=e._private.rstyle;switch(s){case"left":r=o.x-i/2;break;case"right":r=o.x+i/2;break;default:r=o.x}switch(l){case"top":n=o.y-a/2;break;case"bottom":n=o.y+a/2;break;default:n=o.y}u.labelX=r,u.labelY=n,c.labelX=r,c.labelY=n,this.applyLabelDimensions(e)}},s.recalculateEdgeLabelProjection=function(e){var t=e._private.style.label.strValue;if(t&&!t.match(/^\s+$/)){var r,n,i=e._private,a=i.rscratch,o=i.rstyle;r=a.midX,n=a.midY,a.labelX=r,a.labelY=n,o.labelX=r,o.labelY=n,this.applyLabelDimensions(e)}},s.applyLabelDimensions=function(e){var t=e._private.rscratch,r=e._private.rstyle,n=this.getLabelText(e),i=this.calculateLabelDimensions(e,n);r.labelWidth=i.width,t.labelWidth=i.width,r.labelHeight=i.height,t.labelHeight=i.height},s.getLabelText=function(e){var t=e._private.style,r=e._private.style.label.strValue,n=t["text-transform"].value,i=e._private.rscratch;if("none"==n||("uppercase"==n?r=r.toUpperCase():"lowercase"==n&&(r=r.toLowerCase())),"wrap"===t["text-wrap"].value){if(i.labelWrapKey===i.labelKey)return i.labelWrapCachedText;for(var a=r.split("\n"),o=t["text-max-width"].pfValue,s=[],l=0;l<a.length;l++){var u=a[l],c=this.calculateLabelDimensions(e,u,"line="+u),d=c.width;if(d>o){for(var h=u.split(/\s+/),p="",v=0;v<h.length;v++){var f=h[v],g=0===p.length?f:p+" "+f,y=this.calculateLabelDimensions(e,g,"testLine="+g),m=y.width;o>=m?p+=f+" ":(s.push(p),p=f+" ")}p.match(/^\s+$/)||s.push(p)}else s.push(u)}i.labelWrapCachedLines=s,i.labelWrapCachedText=r=s.join("\n"),i.labelWrapKey=i.labelKey}return r},s.calculateLabelDimensions=function(e,t,r){var n=this,i=e._private.style,a=i["font-style"].strValue,o=i["font-size"].pfValue+"px",s=i["font-family"].strValue,l=i["font-weight"].strValue,u=e._private.labelKey;r&&(u+="$@$"+r);var c=n.labelDimCache||(n.labelDimCache={});if(c[u])return c[u];var d=this.labelCalcDiv;d||(d=this.labelCalcDiv=document.createElement("div"),document.body.appendChild(d));var h=d.style;return h.fontFamily=s,h.fontStyle=a,h.fontSize=o,h.fontWeight=l,h.position="absolute",h.left="-9999px",h.top="-9999px",h.zIndex="-1",h.visibility="hidden",h.pointerEvents="none",h.padding="0",h.lineHeight="1","wrap"===i["text-wrap"].value?h.whiteSpace="pre":h.whiteSpace="normal",d.textContent=t,c[u]={width:d.clientWidth,height:d.clientHeight},c[u]},s.recalculateRenderedStyle=function(e){for(var t=[],r=[],n={},i=0;i<e.length;i++){var a=e[i],o=a._private,s=o.style,l=o.rscratch,u=o.rstyle,c=o.data.id,d=null!=l.boundingBoxKey&&o.boundingBoxKey===l.boundingBoxKey,h=null!=l.labelKey&&o.labelKey===l.labelKey,p=d&&h;if("nodes"===o.group){var v=o.position,f=null!=u.nodeX&&null!=u.nodeY&&v.x===u.nodeX&&v.y===u.nodeY,g=null!=u.nodeW&&u.nodeW===s.width.pfValue,y=null!=u.nodeH&&u.nodeH===s.height.pfValue;f&&p&&g&&y||r.push(a),u.nodeX=v.x,u.nodeY=v.y,u.nodeW=s.width.pfValue,u.nodeH=s.height.pfValue}else{var m=o.source._private.position,b=o.target._private.position,x=null!=u.srcX&&null!=u.srcY&&m.x===u.srcX&&m.y===u.srcY,w=null!=u.tgtX&&null!=u.tgtY&&b.x===u.tgtX&&b.y===u.tgtY,_=x&&w;if(!_||!p)if("bezier"===l.edgeType||"straight"===l.edgeType||"self"===l.edgeType||"compound"===l.edgeType){if(!n[c]){t.push(a),n[c]=!0;for(var E=a.parallelEdges(),i=0;i<E.length;i++){var D=E[i],S=D._private.data.id;n[S]||(t.push(D),n[S]=!0)}}}else t.push(a);u.srcX=m.x,u.srcY=m.y,u.tgtX=b.x,u.tgtY=b.y}l.boundingBoxKey=o.boundingBoxKey,l.labelKey=o.labelKey}this.recalculateEdgeProjections(t),this.recalculateLabelProjections(r,t)},s.recalculateLabelProjections=function(e,t){for(var r=0;r<e.length;r++)this.recalculateNodeLabelProjection(e[r]);for(var r=0;r<t.length;r++)this.recalculateEdgeLabelProjection(t[r])},s.recalculateEdgeProjections=function(e){this.findEdgeControlPoints(e)},s.findEdgeControlPoints=function(e){if(e&&0!==e.length){for(var t,r=this,n=r.cy,o=n.hasCompoundNodes(),s={},l=[],u=[],c=[],d=0;d<e.length;d++){var h=e[d],p=h._private,v=p.data,f=p.style,g=f["curve-style"].value,y="unbundled-bezier"===g||"segments"===g;if("none"!==f.display.value)if("autorotate"===f["edge-text-rotation"].strValue&&c.push(h),"haystack"!==g){var m=v.source,b=v.target;t=m>b?b+"$-$"+m:m+"$-$"+b,y&&(t="unbundled$-$"+v.id),null==s[t]&&(s[t]=[],l.push(t)),s[t].push(h),y&&(s[t].hasUnbundled=!0)}else u.push(h)}for(var x,w,_,E,D,S,k,T,P,C,N,M,B,z,O=0;O<l.length;O++){t=l[O];var I=s[t];if(I.sort(function(e,t){return e._private.index-t._private.index}),x=I[0]._private.source,w=I[0]._private.target,_=x._private,E=w._private,_.data.id>E.data.id){var L=x;x=w,w=L}if(D=_.position,S=E.position,k=x.outerWidth(),T=x.outerHeight(),P=w.outerWidth(),C=w.outerHeight(),N=r.nodeShapes[this.getNodeShape(x)],M=r.nodeShapes[this.getNodeShape(w)],z=!1,I.length>1&&x!==w||I.hasUnbundled){var A=N.intersectLine(D.x,D.y,k,T,S.x,S.y,0),R=M.intersectLine(S.x,S.y,P,C,D.x,D.y,0),V={x1:A[0],x2:R[0],y1:A[1],y2:R[1]},F=R[1]-A[1],j=R[0]-A[0],q=Math.sqrt(j*j+F*F),X={
+x:j,y:F},Y={x:X.x/q,y:X.y/q};B={x:-Y.y,y:Y.x},(M.checkPoint(A[0],A[1],0,P,C,S.x,S.y)||N.checkPoint(R[0],R[1],0,k,T,D.x,D.y))&&(B={},z=!0)}for(var h,$,H,d=0;d<I.length;d++){h=I[d],$=h._private,H=$.rscratch;var W=H.lastEdgeIndex,Z=d,U=H.lastNumEdges,G=I.length,K=$.style,f=K,g=K["curve-style"].value,J=K["control-point-distances"],Q=K["control-point-weights"],ee=J&&Q?Math.min(J.value.length,Q.value.length):1,te=K["control-point-step-size"].pfValue,re=void 0!==J?J.pfValue[0]:void 0,ne=Q.value[0],y="unbundled-bezier"===g||"segments"===g,ie=$.source!==x;ie&&y&&(re*=-1);var ae=H.lastSrcCtlPtX,oe=D.x,se=H.lastSrcCtlPtY,le=D.y,ue=H.lastSrcCtlPtW,ce=x.outerWidth(),de=H.lastSrcCtlPtH,he=x.outerHeight(),pe=H.lastTgtCtlPtX,ve=S.x,fe=H.lastTgtCtlPtY,ge=S.y,ye=H.lastTgtCtlPtW,me=w.outerWidth(),be=H.lastTgtCtlPtH,xe=w.outerHeight(),we=H.lastW,_e=K["control-point-step-size"].pfValue;if(z?H.badBezier=!0:H.badBezier=!1,ae!==oe||se!==le||ue!==ce||de!==he||pe!==ve||fe!==ge||ye!==me||be!==xe||we!==_e||!(W===Z&&U===G||y)){if(H.lastSrcCtlPtX=oe,H.lastSrcCtlPtY=le,H.lastSrcCtlPtW=ce,H.lastSrcCtlPtH=he,H.lastTgtCtlPtX=ve,H.lastTgtCtlPtY=ge,H.lastTgtCtlPtW=me,H.lastTgtCtlPtH=xe,H.lastEdgeIndex=Z,H.lastNumEdges=G,H.lastWidth=_e,x===w){H.edgeType="self";var Ee=d,De=te;y&&(Ee=0,De=re),H.ctrlpts=[D.x,D.y-(1+Math.pow(T,1.12)/100)*De*(Ee/3+1),D.x-(1+Math.pow(k,1.12)/100)*De*(Ee/3+1),D.y]}else if(o&&(x.isParent()||x.isChild()||w.isParent()||w.isChild())&&(x.parents().anySame(w)||w.parents().anySame(x))){H.edgeType="compound",H.badBezier=!1;var Ee=d,De=te;y&&(Ee=0,De=re);var Se=50,ke={x:D.x-k/2,y:D.y-T/2},Te={x:S.x-P/2,y:S.y-C/2},Pe={x:Math.min(ke.x,Te.x),y:Math.min(ke.y,Te.y)},Ce=.5,Ne=Math.max(Ce,Math.log(.01*k)),Me=Math.max(Ce,Math.log(.01*P));H.ctrlpts=[Pe.x,Pe.y-(1+Math.pow(Se,1.12)/100)*De*(Ee/3+1)*Ne,Pe.x-(1+Math.pow(Se,1.12)/100)*De*(Ee/3+1)*Me,Pe.y]}else if("segments"===g){H.edgeType="segments",H.segpts=[];for(var Be=K["segment-weights"].pfValue,ze=K["segment-distances"].pfValue,Oe=Math.min(Be.length,ze.length),Ie=0;Oe>Ie;Ie++){var Le=Be[Ie],Ae=ze[Ie],Re=1-Le,Ve=Le,Fe={x:V.x1*Re+V.x2*Ve,y:V.y1*Re+V.y2*Ve};H.segpts.push(Fe.x+B.x*Ae,Fe.y+B.y*Ae)}}else if(I.length%2!==1||d!==Math.floor(I.length/2)||y){var je=y;H.edgeType=je?"multibezier":"bezier",H.ctrlpts=[];for(var qe=0;ee>qe;qe++){var Xe,Ye=(.5-I.length/2+d)*te,$e=i.signum(Ye);je&&(re=J?J.pfValue[qe]:te,ne=Q.value[qe]),Xe=y?re:void 0!==re?$e*re:void 0;var He=void 0!==Xe?Xe:Ye,Re=!ie||y?1-ne:ne,Ve=!ie||y?ne:1-ne,Fe={x:V.x1*Re+V.x2*Ve,y:V.y1*Re+V.y2*Ve};H.ctrlpts.push(Fe.x+B.x*He,Fe.y+B.y*He)}}else H.edgeType="straight";this.findEndpoints(h);var We=!a.number(H.startX)||!a.number(H.startY),Ze=!a.number(H.arrowStartX)||!a.number(H.arrowStartY),Ue=!a.number(H.endX)||!a.number(H.endY),Ge=!a.number(H.arrowEndX)||!a.number(H.arrowEndY),Ke=3,Je=this.getArrowWidth(K.width.pfValue)*this.arrowShapeHeight,Qe=Ke*Je;if("bezier"===H.edgeType){var et=i.distance({x:H.ctrlpts[0],y:H.ctrlpts[1]},{x:H.startX,y:H.startY}),tt=Qe>et,rt=i.distance({x:H.ctrlpts[0],y:H.ctrlpts[1]},{x:H.endX,y:H.endY}),nt=Qe>rt,it=!1;if(We||Ze||tt){it=!0;var at={x:H.ctrlpts[0]-D.x,y:H.ctrlpts[1]-D.y},ot=Math.sqrt(at.x*at.x+at.y*at.y),st={x:at.x/ot,y:at.y/ot},lt=Math.max(k,T),ut={x:H.ctrlpts[0]+2*st.x*lt,y:H.ctrlpts[1]+2*st.y*lt},ct=N.intersectLine(D.x,D.y,k,T,ut.x,ut.y,0);tt?(H.ctrlpts[0]=H.ctrlpts[0]+st.x*(Qe-et),H.ctrlpts[1]=H.ctrlpts[1]+st.y*(Qe-et)):(H.ctrlpts[0]=ct[0]+st.x*Qe,H.ctrlpts[1]=ct[1]+st.y*Qe)}if(Ue||Ge||nt){it=!0;var at={x:H.ctrlpts[0]-S.x,y:H.ctrlpts[1]-S.y},ot=Math.sqrt(at.x*at.x+at.y*at.y),st={x:at.x/ot,y:at.y/ot},lt=Math.max(k,T),ut={x:H.ctrlpts[0]+2*st.x*lt,y:H.ctrlpts[1]+2*st.y*lt},dt=M.intersectLine(S.x,S.y,P,C,ut.x,ut.y,0);nt?(H.ctrlpts[0]=H.ctrlpts[0]+st.x*(Qe-rt),H.ctrlpts[1]=H.ctrlpts[1]+st.y*(Qe-rt)):(H.ctrlpts[0]=dt[0]+st.x*Qe,H.ctrlpts[1]=dt[1]+st.y*Qe)}it&&this.findEndpoints(h)}if("multibezier"===H.edgeType||"bezier"===H.edgeType||"self"===H.edgeType||"compound"===H.edgeType){H.allpts=[],H.allpts.push(H.startX,H.startY);for(var qe=0;qe+1<H.ctrlpts.length;qe+=2)H.allpts.push(H.ctrlpts[qe],H.ctrlpts[qe+1]),qe+3<H.ctrlpts.length&&H.allpts.push((H.ctrlpts[qe]+H.ctrlpts[qe+2])/2,(H.ctrlpts[qe+1]+H.ctrlpts[qe+3])/2);H.allpts.push(H.endX,H.endY);var ht,pt;"bezier"===H.edgeType?(H.midX=i.qbezierAt(H.arrowStartX,H.ctrlpts[0],H.arrowEndX,.5),H.midY=i.qbezierAt(H.arrowStartY,H.ctrlpts[1],H.arrowEndY,.5)):H.ctrlpts.length/2%2===0?(ht=H.allpts.length/2-1,H.midX=H.allpts[ht],H.midY=H.allpts[ht+1]):(ht=H.allpts.length/2-3,pt=.5,H.midX=i.qbezierAt(H.allpts[ht],H.allpts[ht+2],H.allpts[ht+4],pt),H.midY=i.qbezierAt(H.allpts[ht+1],H.allpts[ht+3],H.allpts[ht+5],pt))}else if("straight"===H.edgeType)H.allpts=[H.startX,H.startY,H.endX,H.endY],H.midX=(H.arrowStartX+H.arrowEndX)/2,H.midY=(H.arrowStartY+H.arrowEndY)/2;else if("segments"===H.edgeType)if(H.allpts=[],H.allpts.push(H.startX,H.startY),H.allpts.push.apply(H.allpts,H.segpts),H.allpts.push(H.endX,H.endY),H.segpts.length%4===0){var vt=H.segpts.length/2,ft=vt-2;H.midX=(H.segpts[ft]+H.segpts[vt])/2,H.midY=(H.segpts[ft+1]+H.segpts[vt+1])/2}else{var ft=H.segpts.length/2-1;H.midX=H.segpts[ft],H.midY=H.segpts[ft+1]}this.projectLines(h),this.calculateArrowAngles(h),this.recalculateEdgeLabelProjection(h)}}}for(var d=0;d<u.length;d++){var h=u[d],p=h._private,f=p.style,gt=p.rscratch,H=gt;if(!gt.haystack){var yt=2*Math.random()*Math.PI;gt.source={x:Math.cos(yt),y:Math.sin(yt)};var yt=2*Math.random()*Math.PI;gt.target={x:Math.cos(yt),y:Math.sin(yt)}}var x=p.source,w=p.target,D=x._private.position,S=w._private.position,k=x.width(),P=w.width(),T=x.height(),C=w.height(),lt=f["haystack-radius"].value,mt=lt/2;H.haystackPts=H.allpts=[H.source.x*k*mt+D.x,H.source.y*T*mt+D.y,H.target.x*P*mt+S.x,H.target.y*C*mt+S.y],H.midX=(H.allpts[0]+H.allpts[2])/2,H.midY=(H.allpts[1]+H.allpts[3])/2,gt.edgeType="haystack",gt.haystack=!0,this.projectLines(h),this.calculateArrowAngles(h),this.recalculateEdgeLabelProjection(h)}for(var d=0;d<c.length;d++){var h=c[d],H=h._private.rscratch;H.labelAngle=Math.atan(H.midDispY/H.midDispX)}return s}};var l=function(e,t){return Math.atan2(t,e)-Math.PI/2};s.calculateArrowAngles=function(e){var t,r,n,a,o,s,u=e._private.rscratch,c="haystack"===u.edgeType,d="multibezier"===u.edgeType,h="segments"===u.edgeType,p="compound"===u.edgeType,v="self"===u.edgeType,f=e.source().position(),g=e.target().position();c?(n=u.haystackPts[0],a=u.haystackPts[1],o=u.haystackPts[2],s=u.haystackPts[3]):(n=u.arrowStartX,a=u.arrowStartY,o=u.arrowEndX,s=u.arrowEndY),t=f.x-n,r=f.y-a,u.srcArrowAngle=l(t,r);var y=u.midX,m=u.midY;if(c&&(y=(n+o)/2,m=(a+s)/2),t=o-n,r=s-a,v)t=-1,r=1;else if(h){var b=u.allpts;if(b.length/2%2===0){var x=b.length/2,w=x-2;t=b[x]-b[w],r=b[x+1]-b[w+1]}else{var x=b.length/2-1,w=x-2,_=x+2;t=b[x]-b[w],r=b[x+1]-b[w+1]}}else if(d||p){var E,D,S,k,b=u.allpts,T=u.ctrlpts;if(T.length/2%2===0){var P=b.length/2-1,C=P+2,N=C+2;E=i.qbezierAt(b[P],b[C],b[N],0),D=i.qbezierAt(b[P+1],b[C+1],b[N+1],0),S=i.qbezierAt(b[P],b[C],b[N],1e-4),k=i.qbezierAt(b[P+1],b[C+1],b[N+1],1e-4)}else{var C=b.length/2-1,P=C-2,N=C+2;E=i.qbezierAt(b[P],b[C],b[N],.4999),D=i.qbezierAt(b[P+1],b[C+1],b[N+1],.4999),S=i.qbezierAt(b[P],b[C],b[N],.5),k=i.qbezierAt(b[P+1],b[C+1],b[N+1],.5)}t=S-E,r=k-D}if(u.midtgtArrowAngle=l(t,r),u.midDispX=t,u.midDispY=r,t*=-1,r*=-1,h){var b=u.allpts;if(b.length/2%2===0);else{var x=b.length/2-1,_=x+2;t=-(b[_]-b[x]),r=-(b[_+1]-b[x+1])}}u.midsrcArrowAngle=l(t,r),t=g.x-o,r=g.y-s,u.tgtArrowAngle=l(t,r)},s.findEndpoints=function(e){var t,r,n,o=this,s=e.source()[0],l=e.target()[0],u=s._private,c=l._private,d=u.position,h=c.position,p=e._private.style["target-arrow-shape"].value,v=e._private.style["source-arrow-shape"].value,f=e._private.rscratch,g=f.edgeType,y="bezier"===g||"multibezier"===g||"self"===g||"compound"===g,m="bezier"!==g,b="straight"===g||"segments"===g,x="segments"===g;if(y){var w=[f.ctrlpts[0],f.ctrlpts[1]],_=m?[f.ctrlpts[f.ctrlpts.length-2],f.ctrlpts[f.ctrlpts.length-1]]:w;r=_,n=w}else if(b){var E=x?f.segpts.slice(0,2):[h.x,h.y],D=x?f.segpts.slice(f.segpts.length-2):[d.x,d.y];r=D,n=E}t=o.nodeShapes[this.getNodeShape(l)].intersectLine(h.x,h.y,l.outerWidth(),l.outerHeight(),r[0],r[1],0);var S=i.shortenIntersection(t,r,o.arrowShapes[p].spacing(e)),k=i.shortenIntersection(t,r,o.arrowShapes[p].gap(e));f.endX=k[0],f.endY=k[1],f.arrowEndX=S[0],f.arrowEndY=S[1],t=o.nodeShapes[this.getNodeShape(s)].intersectLine(d.x,d.y,s.outerWidth(),s.outerHeight(),n[0],n[1],0);var T=i.shortenIntersection(t,n,o.arrowShapes[v].spacing(e)),P=i.shortenIntersection(t,n,o.arrowShapes[v].gap(e));f.startX=P[0],f.startY=P[1],f.arrowStartX=T[0],f.arrowStartY=T[1],b&&(a.number(f.startX)&&a.number(f.startY)&&a.number(f.endX)&&a.number(f.endY)?f.badLine=!1:f.badLine=!0)},s.getArrowWidth=s.getArrowHeight=function(e){var t=this.arrowWidthCache=this.arrowWidthCache||{},r=t[e];return r?r:(r=Math.max(Math.pow(13.37*e,.9),29),t[e]=r,r)},t.exports=s},{"../../../collection/zsort":29,"../../../is":77,"../../../math":79}],57:[function(e,t,r){"use strict";var n={};n.getCachedImage=function(e,t){var r=this,n=r.imageCache=r.imageCache||{};if(n[e]&&n[e].image)return n[e].image;var i=n[e]=n[e]||{},a=i.image=new Image;return a.addEventListener("load",t),a.src=e,a},t.exports=n},{}],58:[function(e,t,r){"use strict";var n=e("../../../is"),i=e("../../../util"),a=function(){},o=a,s=o.prototype;s.clientFunctions=["redrawHint","render","renderTo","matchCanvasSize","nodeShapeImpl","arrowShapeImpl"],s.init=function(e){var t=this;t.options=e,t.cy=e.cy,t.container=e.cy.container(),t.selection=[void 0,void 0,void 0,void 0,0],t.hoverData={down:null,last:null,downTime:null,triggerMode:null,dragging:!1,initialPan:[null,null],capture:!1},t.dragData={possibleDragElements:[]},t.touchData={start:null,capture:!1,startPosition:[null,null,null,null,null,null],singleTouchStartTime:null,singleTouchMoved:!0,now:[null,null,null,null,null,null],earlier:[null,null,null,null,null,null]},t.redraws=0,t.showFps=e.showFps,t.hideEdgesOnViewport=e.hideEdgesOnViewport,t.hideLabelsOnViewport=e.hideLabelsOnViewport,t.textureOnViewport=e.textureOnViewport,t.wheelSensitivity=e.wheelSensitivity,t.motionBlurEnabled=e.motionBlur,t.forcedPixelRatio=e.pixelRatio,t.motionBlur=!0,t.motionBlurOpacity=e.motionBlurOpacity,t.motionBlurTransparency=1-t.motionBlurOpacity,t.motionBlurPxRatio=1,t.mbPxRBlurry=1,t.minMbLowQualFrames=4,t.fullQualityMb=!1,t.clearedForMotionBlur=[],t.desktopTapThreshold=e.desktopTapThreshold,t.desktopTapThreshold2=e.desktopTapThreshold*e.desktopTapThreshold,t.touchTapThreshold=e.touchTapThreshold,t.touchTapThreshold2=e.touchTapThreshold*e.touchTapThreshold,t.tapholdDuration=500,t.bindings=[],t.registerNodeShapes(),t.registerArrowShapes(),t.load()},s.notify=function(e){var t,r=this;t=n.array(e.type)?e.type:[e.type];for(var i=0;i<t.length;i++){var a=t[i];switch(a){case"destroy":return void r.destroy();case"add":case"remove":case"load":r.updateElementsCache();break;case"viewport":r.redrawHint("select",!0);break;case"style":r.updateCachedZSortedEles()}("load"===a||"resize"===a)&&(r.invalidateContainerClientCoordsCache(),r.matchCanvasSize(r.container))}r.redrawHint("eles",!0),r.redrawHint("drag",!0),this.startRenderLoop(),this.redraw()},s.destroy=function(){this.destroyed=!0,this.cy.stopAnimationLoop();for(var e=0;e<this.bindings.length;e++){var t=this.bindings[e],r=t;r.target.removeEventListener(r.event,r.handler,r.useCapture)}if(this.removeObserver&&this.removeObserver.disconnect(),this.labelCalcDiv)try{document.body.removeChild(this.labelCalcDiv)}catch(n){}},[e("./arrow-shapes"),e("./cached-eles"),e("./coord-ele-math"),e("./images"),e("./load-listeners"),e("./node-shapes"),e("./redraw")].forEach(function(e){i.extend(s,e)}),t.exports=o},{"../../../is":77,"../../../util":94,"./arrow-shapes":54,"./cached-eles":55,"./coord-ele-math":56,"./images":57,"./load-listeners":59,"./node-shapes":60,"./redraw":61}],59:[function(e,t,r){"use strict";var n=e("../../../is"),i=e("../../../util"),a=e("../../../event"),o=e("../../../collection"),s={};s.registerBinding=function(e,t,r,n){this.bindings.push({target:e,event:t,handler:r,useCapture:n}),e.addEventListener(t,r,n)},s.nodeIsDraggable=function(e){return 0!==e._private.style.opacity.value&&"visible"==e._private.style.visibility.value&&"element"==e._private.style.display.value&&!e.locked()&&e.grabbable()?!0:!1},s.load=function(){var e=this,t=function(t,r,n,o){null==t&&(t=e.cy);for(var s=0;s<r.length;s++){var l=r[s],u=a(n,i.extend({type:l},o));t.trigger(u)}},r=function(e){return e.shiftKey||e.metaKey||e.ctrlKey},s=function(t){var r;if(t.addToList&&e.cy.hasCompoundNodes()){if(!t.addToList.hasId){t.addToList.hasId={};for(var n=0;n<t.addToList.length;n++){var i=t.addToList[n];t.addToList.hasId[i.id()]=!0}}r=t.addToList.hasId}return r||{}},l=function(e,t){if(e._private.cy.hasCompoundNodes()&&(null!=t.inDragLayer||null!=t.addToList))for(var r=s(t),n=e.descendants(),i=0;i<n.size();i++){var a=n[i],o=a._private;t.inDragLayer&&(o.rscratch.inDragLayer=!0),t.addToList&&!r[a.id()]&&(t.addToList.push(a),r[a.id()]=!0,o.grabbed=!0);for(var l=o.edges,u=0;t.inDragLayer&&u<l.length;u++)l[u]._private.rscratch.inDragLayer=!0}},u=function(e,t){var r=e._private,n=s(t);t.inDragLayer&&(r.rscratch.inDragLayer=!0),t.addToList&&!n[e.id()]&&(t.addToList.push(e),n[e.id()]=!0,r.grabbed=!0);for(var i=r.edges,a=0;t.inDragLayer&&a<i.length;a++)i[a]._private.rscratch.inDragLayer=!0;l(e,t),d(e,{inDragLayer:t.inDragLayer})},c=function(e){if(e)for(var t=0;t<e.length;t++){var r=e[t]._private;if("nodes"===r.group){r.rscratch.inDragLayer=!1,r.grabbed=!1;for(var n=r.edges,i=0;i<n.length;i++)n[i]._private.rscratch.inDragLayer=!1;d(e[t],{inDragLayer:!1})}else"edges"===r.group&&(r.rscratch.inDragLayer=!1)}},d=function(e,t){if(null!=t.inDragLayer||null!=t.addToList){var r=e;if(e._private.cy.hasCompoundNodes()){for(;r.parent().nonempty();)r=r.parent()[0];if(r!=e){for(var n=r.descendants().merge(r).unmerge(e).unmerge(e.descendants()),i=n.connectedEdges(),a=s(t),o=0;o<n.size();o++)void 0!==t.inDragLayer&&(n[o]._private.rscratch.inDragLayer=t.inDragLayer),t.addToList&&!a[n[o].id()]&&(t.addToList.push(n[o]),a[n[o].id()]=!0,n[o]._private.grabbed=!0);for(var l=0;void 0!==t.inDragLayer&&l<i.length;l++)i[l]._private.rscratch.inDragLayer=t.inDragLayer}}}};"undefined"!=typeof MutationObserver?(e.removeObserver=new MutationObserver(function(t){for(var r=0;r<t.length;r++){var n=t[r],i=n.removedNodes;if(i)for(var a=0;a<i.length;a++){var o=i[a];if(o===e.container){e.destroy();break}}}}),e.container.parentNode&&e.removeObserver.observe(e.container.parentNode,{childList:!0})):e.registerBinding(e.container,"DOMNodeRemoved",function(t){e.destroy()}),e.registerBinding(window,"resize",i.debounce(function(t){e.invalidateContainerClientCoordsCache(),e.matchCanvasSize(e.container),e.redrawHint("eles",!0),e.redraw()},100));for(var h=function(t){e.registerBinding(t,"scroll",function(t){e.invalidateContainerClientCoordsCache()})},p=e.cy.container();h(p),p.parentNode;)p=p.parentNode;e.registerBinding(e.container,"contextmenu",function(e){e.preventDefault()});var v=function(){return 0!==e.selection[4]};e.registerBinding(e.container,"mousedown",function(r){r.preventDefault(),e.hoverData.capture=!0,e.hoverData.which=r.which;var n=e.cy,i=e.projectIntoViewport(r.clientX,r.clientY),o=e.selection,s=e.findNearestElement(i[0],i[1],!0,!1),l=e.dragData.possibleDragElements;e.hoverData.mdownPos=i;var c=function(){e.hoverData.tapholdCancelled=!1,clearTimeout(e.hoverData.tapholdTimeout),e.hoverData.tapholdTimeout=setTimeout(function(){if(!e.hoverData.tapholdCancelled){var t=e.hoverData.down;t?t.trigger(a(r,{type:"taphold",cyPosition:{x:i[0],y:i[1]}})):n.trigger(a(r,{type:"taphold",cyPosition:{x:i[0],y:i[1]}}))}},e.tapholdDuration)};if(3==r.which){e.hoverData.cxtStarted=!0;var d=a(r,{type:"cxttapstart",cyPosition:{x:i[0],y:i[1]}});s?(s.activate(),s.trigger(d),e.hoverData.down=s):n.trigger(d),e.hoverData.downTime=(new Date).getTime(),e.hoverData.cxtDragged=!1}else if(1==r.which){if(s&&s.activate(),null!=s&&e.nodeIsDraggable(s)){var h=a(r,{type:"grab",cyPosition:{x:i[0],y:i[1]}});if(s.isNode()&&!s.selected())l=e.dragData.possibleDragElements=[],u(s,{addToList:l}),s.trigger(h);else if(s.isNode()&&s.selected()){l=e.dragData.possibleDragElements=[];for(var p=n.$(function(){return this.isNode()&&this.selected()}),v=0;v<p.length;v++)e.nodeIsDraggable(p[v])&&u(p[v],{addToList:l});s.trigger(h)}e.redrawHint("eles",!0),e.redrawHint("drag",!0)}e.hoverData.down=s,e.hoverData.downTime=(new Date).getTime(),t(s,["mousedown","tapstart","vmousedown"],r,{cyPosition:{x:i[0],y:i[1]}}),null==s?(o[4]=1,e.data.bgActivePosistion={x:i[0],y:i[1]},e.redrawHint("select",!0),e.redraw()):s.isEdge()&&(o[4]=1),c()}o[0]=o[2]=i[0],o[1]=o[3]=i[1]},!1),e.registerBinding(window,"mousemove",function(i){var s=!1,l=e.hoverData.capture;if(!l){var c=e.findContainerClientCoords();if(!(i.clientX>c[0]&&i.clientX<c[0]+e.canvasWidth&&i.clientY>c[1]&&i.clientY<c[1]+e.canvasHeight))return;for(var d=e.container,h=i.target,p=h.parentNode,v=!1;p;){if(p===d){v=!0;break}p=p.parentNode}if(!v)return}var f=e.cy,g=f.zoom(),y=e.projectIntoViewport(i.clientX,i.clientY),m=e.selection,b=null;e.hoverData.draggingEles||(b=e.findNearestElement(y[0],y[1],!0,!1));var x=e.hoverData.last,w=e.hoverData.down,_=[y[0]-m[2],y[1]-m[3]],E=e.dragData.possibleDragElements,D=m[2]-m[0],S=D*D,k=m[3]-m[1],T=k*k,P=S+T,C=P*g*g,N=r(i);e.hoverData.tapholdCancelled=!0;var M=function(){var t=e.hoverData.dragDelta=e.hoverData.dragDelta||[];0===t.length?(t.push(_[0]),t.push(_[1])):(t[0]+=_[0],t[1]+=_[1])};if(s=!0,t(b,["mousemove","vmousemove","tapdrag"],i,{cyPosition:{x:y[0],y:y[1]}}),3===e.hoverData.which){var B=a(i,{type:"cxtdrag",cyPosition:{x:y[0],y:y[1]}});w?w.trigger(B):f.trigger(B),e.hoverData.cxtDragged=!0,e.hoverData.cxtOver&&b===e.hoverData.cxtOver||(e.hoverData.cxtOver&&e.hoverData.cxtOver.trigger(a(i,{type:"cxtdragout",cyPosition:{x:y[0],y:y[1]}})),e.hoverData.cxtOver=b,b&&b.trigger(a(i,{type:"cxtdragover",cyPosition:{x:y[0],y:y[1]}})))}else if(e.hoverData.dragging){if(s=!0,f.panningEnabled()&&f.userPanningEnabled()){var z;if(e.hoverData.justStartedPan){var O=e.hoverData.mdownPos;z={x:(y[0]-O[0])*g,y:(y[1]-O[1])*g},e.hoverData.justStartedPan=!1}else z={x:_[0]*g,y:_[1]*g};f.panBy(z),e.hoverData.dragged=!0}y=e.projectIntoViewport(i.clientX,i.clientY)}else if(1!=m[4]||null!=w&&!w.isEdge()){if(w&&w.isEdge()&&w.active()&&w.unactivate(),b!=x&&(x&&t(x,["mouseout","tapdragout"],i,{cyPosition:{x:y[0],y:y[1]}}),b&&t(b,["mouseover","tapdragover"],i,{cyPosition:{x:y[0],y:y[1]}}),e.hoverData.last=b),w&&w.isNode()&&e.nodeIsDraggable(w))if(C>=e.desktopTapThreshold2){var I=!e.dragData.didDrag;I&&e.redrawHint("eles",!0),e.dragData.didDrag=!0;for(var L=[],A=0;A<E.length;A++){var R=E[A];if(e.hoverData.draggingEles||u(R,{inDragLayer:!0}),R.isNode()&&e.nodeIsDraggable(R)&&R.grabbed()){var V=R._private.position;if(L.push(R),n.number(_[0])&&n.number(_[1])){var F=!R.isParent();if(F&&(V.x+=_[0],V.y+=_[1]),I){var j=e.hoverData.dragDelta;F&&n.number(j[0])&&n.number(j[1])&&(V.x+=j[0],V.y+=j[1])}}}}e.hoverData.draggingEles=!0;var q=o(f,L);q.updateCompoundBounds(),q.trigger("position drag"),e.redrawHint("drag",!0),e.redraw()}else M();s=!0}else e.hoverData.dragging||!f.boxSelectionEnabled()||!N&&f.panningEnabled()&&f.userPanningEnabled()?!e.hoverData.selecting&&f.panningEnabled()&&f.userPanningEnabled()&&(e.hoverData.dragging=!0,e.hoverData.justStartedPan=!0,m[4]=0,e.data.bgActivePosistion={x:y[0],y:y[1]},e.redrawHint("select",!0),e.redraw()):(e.data.bgActivePosistion=void 0,e.hoverData.selecting=!0,e.redrawHint("select",!0),e.redraw()),w&&w.isEdge()&&w.active()&&w.unactivate();return m[2]=y[0],m[3]=y[1],s?(i.stopPropagation&&i.stopPropagation(),i.preventDefault&&i.preventDefault(),!1):void 0},!1),e.registerBinding(window,"mouseup",function(n){var i=e.hoverData.capture;if(i){e.hoverData.capture=!1;var s=e.cy,l=e.projectIntoViewport(n.clientX,n.clientY),u=e.selection,d=e.findNearestElement(l[0],l[1],!0,!1),h=e.dragData.possibleDragElements,p=e.hoverData.down,v=r(n);if(e.data.bgActivePosistion&&(e.redrawHint("select",!0),e.redraw()),e.hoverData.tapholdCancelled=!0,e.data.bgActivePosistion=void 0,p&&p.unactivate(),3===e.hoverData.which){var f=a(n,{type:"cxttapend",cyPosition:{x:l[0],y:l[1]}});if(p?p.trigger(f):s.trigger(f),!e.hoverData.cxtDragged){var g=a(n,{type:"cxttap",cyPosition:{x:l[0],y:l[1]}});p?p.trigger(g):s.trigger(g)}e.hoverData.cxtDragged=!1,e.hoverData.which=null}else if(1===e.hoverData.which){if(null!=p||e.dragData.didDrag||e.hoverData.selecting||e.hoverData.dragged||r(n)||(s.$(function(){return this.selected()}).unselect(),h.length>0&&e.redrawHint("eles",!0),e.dragData.possibleDragElements=h=[]),t(d,["mouseup","tapend","vmouseup"],n,{cyPosition:{x:l[0],y:l[1]}}),e.dragData.didDrag||e.hoverData.dragged||t(d,["click","tap","vclick"],n,{cyPosition:{x:l[0],y:l[1]}}),d!=p||e.dragData.didDrag||e.hoverData.selecting||null!=d&&d._private.selectable&&(e.hoverData.dragging||("additive"===s.selectionType()||v?d.selected()?d.unselect():d.select():v||(s.$(":selected").unmerge(d).unselect(),d.select())),e.redrawHint("eles",!0)),e.hoverData.selecting){var y=[],m=e.getAllInBox(u[0],u[1],u[2],u[3]);e.redrawHint("select",!0),m.length>0&&e.redrawHint("eles",!0);for(var b=0;b<m.length;b++)m[b]._private.selectable&&y.push(m[b]);var x=o(s,y);"additive"===s.selectionType()?x.select():(v||s.$(":selected").unmerge(x).unselect(),x.select()),e.redraw()}e.hoverData.dragging&&(e.hoverData.dragging=!1,e.redrawHint("select",!0),e.redrawHint("eles",!0),e.redraw()),u[4]||(e.redrawHint("drag",!0),e.redrawHint("eles",!0),c(h),p&&p.trigger("free"))}u[4]=0,e.hoverData.down=null,e.hoverData.cxtStarted=!1,e.hoverData.draggingEles=!1,e.hoverData.selecting=!1,e.dragData.didDrag=!1,e.hoverData.dragged=!1,e.hoverData.dragDelta=[]}},!1);var f=function(t){if(!e.scrollingPage){var r=e.cy,n=e.projectIntoViewport(t.clientX,t.clientY),i=[n[0]*r.zoom()+r.pan().x,n[1]*r.zoom()+r.pan().y];if(e.hoverData.draggingEles||e.hoverData.dragging||e.hoverData.cxtStarted||v())return void t.preventDefault();if(r.panningEnabled()&&r.userPanningEnabled()&&r.zoomingEnabled()&&r.userZoomingEnabled()){t.preventDefault(),e.data.wheelZooming=!0,clearTimeout(e.data.wheelTimeout),e.data.wheelTimeout=setTimeout(function(){e.data.wheelZooming=!1,e.redrawHint("eles",!0),e.redraw()},150);var a=t.deltaY/-250||t.wheelDeltaY/1e3||t.wheelDelta/1e3;a*=e.wheelSensitivity;var o=1===t.deltaMode;o&&(a*=33),r.zoom({level:r.zoom()*Math.pow(10,a),renderedPosition:{x:i[0],y:i[1]}})}}};e.registerBinding(e.container,"wheel",f,!0),e.registerBinding(window,"scroll",function(t){e.scrollingPage=!0,clearTimeout(e.scrollingPageTimeout),e.scrollingPageTimeout=setTimeout(function(){e.scrollingPage=!1},250)},!0),e.registerBinding(e.container,"mouseout",function(t){var r=e.projectIntoViewport(t.clientX,t.clientY);e.cy.trigger(a(t,{type:"mouseout",cyPosition:{x:r[0],y:r[1]}}))},!1),e.registerBinding(e.container,"mouseover",function(t){var r=e.projectIntoViewport(t.clientX,t.clientY);e.cy.trigger(a(t,{type:"mouseover",cyPosition:{x:r[0],y:r[1]}}))},!1);var g,y,m,b,x,w,_,E,D,S,k,T,P,C,N=function(e,t,r,n){return Math.sqrt((r-e)*(r-e)+(n-t)*(n-t))},M=function(e,t,r,n){return(r-e)*(r-e)+(n-t)*(n-t)};e.registerBinding(e.container,"touchstart",C=function(r){e.touchData.capture=!0,e.data.bgActivePosistion=void 0;var n=e.cy,i=e.getCachedNodes(),o=e.getCachedEdges(),s=e.touchData.now,l=e.touchData.earlier;if(r.touches[0]){var c=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);s[0]=c[0],s[1]=c[1]}if(r.touches[1]){var c=e.projectIntoViewport(r.touches[1].clientX,r.touches[1].clientY);s[2]=c[0],s[3]=c[1]}if(r.touches[2]){var c=e.projectIntoViewport(r.touches[2].clientX,r.touches[2].clientY);s[4]=c[0],s[5]=c[1]}if(r.touches[1]){var d=function(e){for(var t=0;t<e.length;t++)e[t]._private.grabbed=!1,e[t]._private.rscratch.inDragLayer=!1,e[t].active()&&e[t].unactivate()};d(i),d(o);var h=e.findContainerClientCoords();D=h[0],S=h[1],k=h[2],T=h[3],g=r.touches[0].clientX-D,y=r.touches[0].clientY-S,m=r.touches[1].clientX-D,b=r.touches[1].clientY-S,P=g>=0&&k>=g&&m>=0&&k>=m&&y>=0&&T>=y&&b>=0&&T>=b;var p=n.pan(),v=n.zoom();x=N(g,y,m,b),w=M(g,y,m,b),_=[(g+m)/2,(y+b)/2],E=[(_[0]-p.x)/v,(_[1]-p.y)/v];var f=200,C=f*f;if(C>w&&!r.touches[2]){var B=e.findNearestElement(s[0],s[1],!0,!0),z=e.findNearestElement(s[2],s[3],!0,!0);return B&&B.isNode()?(B.activate().trigger(a(r,{type:"cxttapstart",cyPosition:{x:s[0],y:s[1]}})),e.touchData.start=B):z&&z.isNode()?(z.activate().trigger(a(r,{type:"cxttapstart",cyPosition:{x:s[0],y:s[1]}})),e.touchData.start=z):(n.trigger(a(r,{type:"cxttapstart",cyPosition:{x:s[0],y:s[1]}})),e.touchData.start=null),e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxt=!0,e.touchData.cxtDragged=!1,e.data.bgActivePosistion=void 0,void e.redraw()}}if(r.touches[2]);else if(r.touches[1]);else if(r.touches[0]){var O=e.findNearestElement(s[0],s[1],!0,!0);if(null!=O&&(O.activate(),e.touchData.start=O,O.isNode()&&e.nodeIsDraggable(O))){var I=e.dragData.touchDragEles=[];if(e.redrawHint("eles",!0),e.redrawHint("drag",!0),O.selected())for(var L=n.$(function(){return this.isNode()&&this.selected()}),A=0;A<L.length;A++){var R=L[A];e.nodeIsDraggable(R)&&u(R,{addToList:I})}else u(O,{addToList:I});O.trigger(a(r,{type:"grab",cyPosition:{x:s[0],y:s[1]}}))}t(O,["touchstart","tapstart","vmousedown"],r,{cyPosition:{x:s[0],y:s[1]}}),null==O&&(e.data.bgActivePosistion={x:c[0],y:c[1]},e.redrawHint("select",!0),e.redraw());for(var V=0;V<s.length;V++)l[V]=s[V],e.touchData.startPosition[V]=s[V];e.touchData.singleTouchMoved=!1,e.touchData.singleTouchStartTime=+new Date,clearTimeout(e.touchData.tapholdTimeout),e.touchData.tapholdTimeout=setTimeout(function(){e.touchData.singleTouchMoved!==!1||e.pinching||(t(e.touchData.start,["taphold"],r,{cyPosition:{x:s[0],y:s[1]}}),e.touchData.start||n.$(":selected").unselect())},e.tapholdDuration)}},!1);var B;e.registerBinding(window,"touchmove",B=function(r){var i=e.selection,s=e.touchData.capture,l=e.cy,c=e.touchData.now,d=e.touchData.earlier,h=l.zoom();if(r.touches[0]){var p=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);c[0]=p[0],c[1]=p[1]}if(r.touches[1]){var p=e.projectIntoViewport(r.touches[1].clientX,r.touches[1].clientY);c[2]=p[0],c[3]=p[1]}if(r.touches[2]){var p=e.projectIntoViewport(r.touches[2].clientX,r.touches[2].clientY);c[4]=p[0],c[5]=p[1]}for(var v=[],f=0;f<c.length;f++)v[f]=c[f]-d[f];var _=e.touchData.startPosition,k=c[0]-_[0],T=k*k,C=c[1]-_[1],B=C*C,z=T+B,O=z*h*h;if(s&&e.touchData.cxt){r.preventDefault();var I=r.touches[0].clientX-D,L=r.touches[0].clientY-S,A=r.touches[1].clientX-D,R=r.touches[1].clientY-S,V=M(I,L,A,R),F=V/w,j=150,q=j*j,X=1.5,Y=X*X;if(F>=Y||V>=q){e.touchData.cxt=!1,e.touchData.start&&(e.touchData.start.unactivate(),e.touchData.start=null),e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);var $=a(r,{type:"cxttapend",cyPosition:{x:c[0],y:c[1]}});e.touchData.start?e.touchData.start.trigger($):l.trigger($)}}if(s&&e.touchData.cxt){var $=a(r,{type:"cxtdrag",cyPosition:{x:c[0],y:c[1]}});e.data.bgActivePosistion=void 0,e.redrawHint("select",!0),e.touchData.start?e.touchData.start.trigger($):l.trigger($),e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxtDragged=!0;var H=e.findNearestElement(c[0],c[1],!0,!0);e.touchData.cxtOver&&H===e.touchData.cxtOver||(e.touchData.cxtOver&&e.touchData.cxtOver.trigger(a(r,{type:"cxtdragout",cyPosition:{x:c[0],y:c[1]}})),e.touchData.cxtOver=H,H&&H.trigger(a(r,{type:"cxtdragover",cyPosition:{x:c[0],y:c[1]}})))}else if(s&&r.touches[2]&&l.boxSelectionEnabled())r.preventDefault(),e.data.bgActivePosistion=void 0,this.lastThreeTouch=+new Date,e.touchData.selecting=!0,e.redrawHint("select",!0),i&&0!==i.length&&void 0!==i[0]?(i[2]=(c[0]+c[2]+c[4])/3,i[3]=(c[1]+c[3]+c[5])/3):(i[0]=(c[0]+c[2]+c[4])/3,i[1]=(c[1]+c[3]+c[5])/3,i[2]=(c[0]+c[2]+c[4])/3+1,i[3]=(c[1]+c[3]+c[5])/3+1),i[4]=1,e.touchData.selecting=!0,e.redraw();else if(s&&r.touches[1]&&l.zoomingEnabled()&&l.panningEnabled()&&l.userZoomingEnabled()&&l.userPanningEnabled()){r.preventDefault(),e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);var W=e.dragData.touchDragEles;if(W){e.redrawHint("drag",!0);for(var Z=0;Z<W.length;Z++)W[Z]._private.grabbed=!1,W[Z]._private.rscratch.inDragLayer=!1}var I=r.touches[0].clientX-D,L=r.touches[0].clientY-S,A=r.touches[1].clientX-D,R=r.touches[1].clientY-S,U=N(I,L,A,R),G=U/x;if(1!=G&&P){var K=I-g,J=L-y,Q=A-m,ee=R-b,te=(K+Q)/2,re=(J+ee)/2,ne=l.zoom(),ie=ne*G,ae=l.pan(),oe=E[0]*ne+ae.x,se=E[1]*ne+ae.y,le={x:-ie/ne*(oe-ae.x-te)+oe,y:-ie/ne*(se-ae.y-re)+se};if(e.touchData.start){var W=e.dragData.touchDragEles;if(W)for(var Z=0;Z<W.length;Z++){var ue=W[Z]._private;ue.grabbed=!1,ue.rscratch.inDragLayer=!1}var ce=e.touchData.start._private;ce.active=!1,ce.grabbed=!1,ce.rscratch.inDragLayer=!1,e.redrawHint("drag",!0),e.touchData.start.trigger("free").trigger("unactivate")}l.viewport({zoom:ie,pan:le,cancelOnFailedZoom:!0}),x=U,g=I,y=L,m=A,b=R,e.pinching=!0}if(r.touches[0]){var p=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);c[0]=p[0],c[1]=p[1]}if(r.touches[1]){var p=e.projectIntoViewport(r.touches[1].clientX,r.touches[1].clientY);c[2]=p[0],c[3]=p[1]}if(r.touches[2]){var p=e.projectIntoViewport(r.touches[2].clientX,r.touches[2].clientY);c[4]=p[0],c[5]=p[1]}}else if(r.touches[0]){var de=e.touchData.start,he=e.touchData.last,H=H||e.findNearestElement(c[0],c[1],!0,!0);if(null!=de&&r.preventDefault(),null!=de&&"nodes"==de._private.group&&e.nodeIsDraggable(de))if(O>=e.touchTapThreshold2){for(var W=e.dragData.touchDragEles,pe=!e.dragData.didDrag,ve=0;ve<W.length;ve++){var fe=W[ve];if(pe&&u(fe,{inDragLayer:!0}),e.nodeIsDraggable(fe)&&fe.isNode()&&fe.grabbed()){e.dragData.didDrag=!0;var ge=fe._private.position,ye=!fe.isParent();if(ye&&n.number(v[0])&&n.number(v[1])&&(ge.x+=v[0],ge.y+=v[1]),pe){e.redrawHint("eles",!0);var me=e.touchData.dragDelta;ye&&n.number(me[0])&&n.number(me[1])&&(ge.x+=me[0],ge.y+=me[1])}}}var be=o(l,W);be.updateCompoundBounds(),be.trigger("position drag"),e.hoverData.draggingEles=!0,e.redrawHint("drag",!0),e.touchData.startPosition[0]==d[0]&&e.touchData.startPosition[1]==d[1]&&e.redrawHint("eles",!0),e.redraw()}else{var me=e.touchData.dragDelta=e.touchData.dragDelta||[];0===me.length?(me.push(v[0]),me.push(v[1])):(me[0]+=v[0],me[1]+=v[1])}t(de||H,["touchmove","tapdrag","vmousemove"],r,{cyPosition:{x:c[0],y:c[1]}}),H!=he&&(he&&he.trigger(a(r,{type:"tapdragout",cyPosition:{x:c[0],y:c[1]}})),H&&H.trigger(a(r,{type:"tapdragover",cyPosition:{x:c[0],y:c[1]}}))),e.touchData.last=H;for(var Z=0;Z<c.length;Z++)c[Z]&&e.touchData.startPosition[Z]&&O>e.touchTapThreshold2&&(e.touchData.singleTouchMoved=!0);if(s&&(null==de||de.isEdge())&&l.panningEnabled()&&l.userPanningEnabled()){r.preventDefault(),e.swipePanning?l.panBy({x:v[0]*h,y:v[1]*h}):O>=e.touchTapThreshold2&&(e.swipePanning=!0,l.panBy({x:k*h,y:C*h}),de&&(de.unactivate(),e.data.bgActivePosistion||(e.data.bgActivePosistion={x:c[0],y:c[1]}),e.redrawHint("select",!0),e.touchData.start=null));var p=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);c[0]=p[0],c[1]=p[1]}}for(var f=0;f<c.length;f++)d[f]=c[f]},!1);var z;e.registerBinding(window,"touchcancel",z=function(t){var r=e.touchData.start;e.touchData.capture=!1,r&&r.unactivate()});var O;if(e.registerBinding(window,"touchend",O=function(r){var n=e.touchData.start,i=e.touchData.capture;if(i){e.touchData.capture=!1,r.preventDefault();var s=e.selection;e.swipePanning=!1,e.hoverData.draggingEles=!1;var l=e.cy,u=l.zoom(),d=e.touchData.now,h=e.touchData.earlier;if(r.touches[0]){var p=e.projectIntoViewport(r.touches[0].clientX,r.touches[0].clientY);d[0]=p[0],d[1]=p[1]}if(r.touches[1]){var p=e.projectIntoViewport(r.touches[1].clientX,r.touches[1].clientY);d[2]=p[0],d[3]=p[1]}if(r.touches[2]){var p=e.projectIntoViewport(r.touches[2].clientX,r.touches[2].clientY);d[4]=p[0],d[5]=p[1]}n&&n.unactivate();var v;if(e.touchData.cxt){if(v=a(r,{
+type:"cxttapend",cyPosition:{x:d[0],y:d[1]}}),n?n.trigger(v):l.trigger(v),!e.touchData.cxtDragged){var f=a(r,{type:"cxttap",cyPosition:{x:d[0],y:d[1]}});n?n.trigger(f):l.trigger(f)}return e.touchData.start&&(e.touchData.start._private.grabbed=!1),e.touchData.cxt=!1,e.touchData.start=null,void e.redraw()}if(!r.touches[2]&&l.boxSelectionEnabled()&&e.touchData.selecting){e.touchData.selecting=!1;var g=[],y=e.getAllInBox(s[0],s[1],s[2],s[3]);s[0]=void 0,s[1]=void 0,s[2]=void 0,s[3]=void 0,s[4]=0,e.redrawHint("select",!0);for(var m=0;m<y.length;m++)y[m]._private.selectable&&g.push(y[m]);var b=o(l,g);b.select(),b.length>0?e.redrawHint("eles",!0):e.redraw()}var x=!1;if(null!=n&&(n._private.active=!1,x=!0,n.unactivate()),r.touches[2])e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);else if(r.touches[1]);else if(r.touches[0]);else if(!r.touches[0]){e.data.bgActivePosistion=void 0,e.redrawHint("select",!0);var w=e.dragData.touchDragEles;if(null!=n){var _=n._private.grabbed;c(w),e.redrawHint("drag",!0),e.redrawHint("eles",!0),_&&n.trigger("free"),t(n,["touchend","tapend","vmouseup"],r,{cyPosition:{x:d[0],y:d[1]}}),n.unactivate(),e.touchData.start=null}else{var E=e.findNearestElement(d[0],d[1],!0,!0);t(E,["touchend","tapend","vmouseup"],r,{cyPosition:{x:d[0],y:d[1]}})}var D=e.touchData.startPosition[0]-d[0],S=D*D,k=e.touchData.startPosition[1]-d[1],T=k*k,P=S+T,C=P*u*u;null!=n&&!e.dragData.didDrag&&n._private.selectable&&C<e.touchTapThreshold2&&!e.pinching&&("single"===l.selectionType()?(l.$(":selected").unmerge(n).unselect(),n.select()):n.selected()?n.unselect():n.select(),x=!0,e.redrawHint("eles",!0)),e.touchData.singleTouchMoved||t(n,["tap","vclick"],r,{cyPosition:{x:d[0],y:d[1]}}),e.touchData.singleTouchMoved=!0}for(var N=0;N<d.length;N++)h[N]=d[N];e.dragData.didDrag=!1,0===r.touches.length&&(e.touchData.dragDelta=[]),x&&n&&n.updateStyle(!1),r.touches.length<2&&(e.pinching=!1,e.redrawHint("eles",!0),e.redraw())}},!1),"undefined"==typeof TouchEvent){var I=[],L=function(e){return{clientX:e.clientX,clientY:e.clientY,force:1,identifier:e.pointerId,pageX:e.pageX,pageY:e.pageY,radiusX:e.width/2,radiusY:e.height/2,screenX:e.screenX,screenY:e.screenY,target:e.target}},A=function(e){return{event:e,touch:L(e)}},R=function(e){I.push(A(e))},V=function(e){for(var t=0;t<I.length;t++){var r=I[t];if(r.event.pointerId===e.pointerId)return void I.splice(t,1)}},F=function(e){var t=I.filter(function(t){return t.event.pointerId===e.pointerId})[0];t.event=e,t.touch=L(e)},j=function(e){e.touches=I.map(function(e){return e.touch})};e.registerBinding(e.container,"pointerdown",function(e){"mouse"!==e.pointerType&&(e.preventDefault(),R(e),j(e),C(e))}),e.registerBinding(e.container,"pointerup",function(e){"mouse"!==e.pointerType&&(V(e),j(e),O(e))}),e.registerBinding(e.container,"pointercancel",function(e){"mouse"!==e.pointerType&&(V(e),j(e),z(e))}),e.registerBinding(e.container,"pointermove",function(e){"mouse"!==e.pointerType&&(e.preventDefault(),F(e),j(e),B(e))})}},t.exports=s},{"../../../collection":23,"../../../event":42,"../../../is":77,"../../../util":94}],60:[function(e,t,r){"use strict";var n=e("../../../math"),i={};i.registerNodeShapes=function(){function e(e,i){return t[e]={name:e,points:i,draw:function(e,t,n,i,a){r.nodeShapeImpl("polygon")(e,t,n,i,a,this.points)},intersectLine:function(e,t,r,i,a,o,s){return n.polygonIntersectLine(a,o,this.points,e,t,r/2,i/2,s)},checkPoint:function(r,i,a,o,s,l,u){return n.pointInsidePolygon(r,i,t[e].points,l,u,o,s,[0,-1],a)}}}var t=this.nodeShapes={},r=this;t.ellipse={name:"ellipse",draw:function(e,t,n,i,a){r.nodeShapeImpl(this.name)(e,t,n,i,a)},intersectLine:function(e,t,r,i,a,o,s){return n.intersectLineEllipse(a,o,e,t,r/2+s,i/2+s)},checkPoint:function(e,t,r,n,i,a,o){return e-=a,t-=o,e/=n/2+r,t/=i/2+r,1>=e*e+t*t}},e("triangle",n.generateUnitNgonPointsFitToSquare(3,0)),e("square",n.generateUnitNgonPointsFitToSquare(4,0)),t.rectangle=t.square,t.roundrectangle={name:"roundrectangle",points:n.generateUnitNgonPointsFitToSquare(4,0),draw:function(e,t,n,i,a){r.nodeShapeImpl(this.name)(e,t,n,i,a)},intersectLine:function(e,t,r,i,a,o,s){return n.roundRectangleIntersectLine(a,o,e,t,r,i,s)},checkPoint:function(e,t,r,i,a,o,s){var l=n.getRoundRectangleRadius(i,a);if(n.pointInsidePolygon(e,t,this.points,o,s,i,a-2*l,[0,-1],r))return!0;if(n.pointInsidePolygon(e,t,this.points,o,s,i-2*l,a,[0,-1],r))return!0;var u=function(e,t,r,n,i,a,o){return e-=r,t-=n,e/=i/2+o,t/=a/2+o,1>=e*e+t*t};return u(e,t,o-i/2+l,s-a/2+l,2*l,2*l,r)?!0:u(e,t,o+i/2-l,s-a/2+l,2*l,2*l,r)?!0:u(e,t,o+i/2-l,s+a/2-l,2*l,2*l,r)?!0:u(e,t,o-i/2+l,s+a/2-l,2*l,2*l,r)?!0:!1}},e("diamond",[0,1,1,0,0,-1,-1,0]),e("pentagon",n.generateUnitNgonPointsFitToSquare(5,0)),e("hexagon",n.generateUnitNgonPointsFitToSquare(6,0)),e("heptagon",n.generateUnitNgonPointsFitToSquare(7,0)),e("octagon",n.generateUnitNgonPointsFitToSquare(8,0));var i=new Array(20),a=n.generateUnitNgonPoints(5,0),o=n.generateUnitNgonPoints(5,Math.PI/5),s=.5*(3-Math.sqrt(5));s*=1.57;for(var l=0;l<o.length/2;l++)o[2*l]*=s,o[2*l+1]*=s;for(var l=0;5>l;l++)i[4*l]=a[2*l],i[4*l+1]=a[2*l+1],i[4*l+2]=o[2*l],i[4*l+3]=o[2*l+1];i=n.fitPolygonToSquare(i),e("star",i),e("vee",[-1,-1,0,-.333,1,-1,0,1]),e("rhomboid",[-1,-1,.333,-1,1,1,-.333,1]),t.makePolygon=function(r){var n,i=r.join("$"),a="polygon-"+i;return(n=t[a])?n:e(a,r)}},t.exports=i},{"../../../math":79}],61:[function(e,t,r){"use strict";var n=e("../../../util"),i={};i.timeToRender=function(){return this.redrawTotalTime/this.redrawCount};var a=1e3/60,o=1e3;i.redraw=function(e){e=e||n.staticEmptyObject();var t=this,r=e.forcedContext;void 0===t.averageRedrawTime&&(t.averageRedrawTime=0),void 0===t.lastRedrawTime&&(t.lastRedrawTime=0);var i=t.lastRedrawTime;i=a>i?a:i,i=o>i?i:o,void 0===t.lastDrawTime&&(t.lastDrawTime=0);var s=Date.now(),l=s-t.lastDrawTime,u=l>=i;return r||u&&!t.currentlyDrawing?(t.requestedFrame=!0,t.currentlyDrawing=!0,void(t.renderOptions=e)):void(t.skipFrame=!0)},i.startRenderLoop=function(){var e=this,t=function(){if(!e.destroyed){if(e.requestedFrame&&!e.skipFrame){var r=n.performanceNow();e.render(e.renderOptions);var i=e.lastRedrawTime=n.performanceNow();void 0===e.averageRedrawTime&&(e.averageRedrawTime=i-r),void 0===e.redrawCount&&(e.redrawCount=0),e.redrawCount++,void 0===e.redrawTotalTime&&(e.redrawTotalTime=0);var a=i-r;e.redrawTotalTime+=a,e.lastRedrawTime=a,e.averageRedrawTime=e.averageRedrawTime/2+a/2,e.requestedFrame=!1}e.skipFrame=!1,n.requestAnimationFrame(t)}};n.requestAnimationFrame(t)},t.exports=i},{"../../../util":94}],62:[function(e,t,r){"use strict";var n,i={};i.arrowShapeImpl=function(e){return(n||(n={polygon:function(e,t){for(var r=0;r<t.length;r++){var n=t[r];e.lineTo(n.x,n.y)}},"triangle-backcurve":function(e,t,r){for(var n,i=0;i<t.length;i++){var a=t[i];0===i&&(n=a),e.lineTo(a.x,a.y)}e.quadraticCurveTo(r.x,r.y,n.x,n.y)},"triangle-tee":function(e,t,r){for(var n=t,i=0;i<n.length;i++){var a=n[i];e.lineTo(a.x,a.y)}var o=r,s=r[0];e.moveTo(s.x,s.y);for(var i=0;i<o.length;i++){var a=o[i];e.lineTo(a.x,a.y)}},circle:function(e,t,r,n){e.arc(t,r,n,0,2*Math.PI,!1)}}))[e]},t.exports=i},{}],63:[function(e,t,r){"use strict";var n={};n.drawEdge=function(e,t,r){var n=t._private.rscratch,i=this.usePaths();if(!(n.badBezier||n.badLine||isNaN(n.allpts[0]))){var a=t._private.style;if(!(a.width.pfValue<=0)){var o=a["overlay-padding"].pfValue,s=a["overlay-opacity"].value,l=a["overlay-color"].value;if(r){if(0===s)return;this.strokeStyle(e,l[0],l[1],l[2],s),e.lineCap="round","self"!=n.edgeType||i||(e.lineCap="butt")}else{var u=a["line-color"].value;this.strokeStyle(e,u[0],u[1],u[2],a.opacity.value),e.lineCap="butt"}var c=a.width.pfValue+(r?2*o:0),d=r?"solid":a["line-style"].value;e.lineWidth=c;var h=a["shadow-blur"].pfValue,p=a["shadow-opacity"].value,v=a["shadow-color"].value,f=a["shadow-offset-x"].pfValue,g=a["shadow-offset-y"].pfValue;this.shadowStyle(e,v,r?0:p,h,f,g),this.drawEdgePath(t,e,n.allpts,d,c),this.drawArrowheads(e,t,r),this.shadowStyle(e,"transparent",0)}}},n.drawEdgePath=function(e,t,r,n,i){var a,o=e._private.rscratch,s=t,l=!1,u=this.usePaths();if(u){var c=r.join("$"),d=o.pathCacheKey&&o.pathCacheKey===c;d?(a=t=o.pathCache,l=!0):(a=t=new Path2D,o.pathCacheKey=c,o.pathCache=a)}if(s.setLineDash)switch(n){case"dotted":s.setLineDash([1,1]);break;case"dashed":s.setLineDash([6,3]);break;case"solid":s.setLineDash([])}if(!l)switch(t.beginPath&&t.beginPath(),t.moveTo(r[0],r[1]),o.edgeType){case"bezier":case"self":case"compound":case"multibezier":if(!o.badBezier)for(var h=2;h+3<r.length;h+=4)t.quadraticCurveTo(r[h],r[h+1],r[h+2],r[h+3]);break;case"straight":case"segments":case"haystack":if(!o.badLine)for(var h=2;h+1<r.length;h+=2)t.lineTo(r[h],r[h+1])}t=s,u?t.stroke(a):t.stroke(),t.setLineDash&&t.setLineDash([])},n.drawArrowheads=function(e,t,r){if(!r){var n=t._private.rscratch,i="haystack"===n.edgeType;i||this.drawArrowhead(e,t,"source",n.arrowStartX,n.arrowStartY,n.srcArrowAngle),this.drawArrowhead(e,t,"mid-target",n.midX,n.midY,n.midtgtArrowAngle),this.drawArrowhead(e,t,"mid-source",n.midX,n.midY,n.midsrcArrowAngle),i||this.drawArrowhead(e,t,"target",n.arrowEndX,n.arrowEndY,n.tgtArrowAngle)}},n.drawArrowhead=function(e,t,r,n,i,a){if(!(isNaN(n)||null==n||isNaN(i)||null==i||isNaN(a)||null==a)){var o=this,s=t._private.style,l=s[r+"-arrow-shape"].value;if("none"!==l){var u=e.globalCompositeOperation,c="hollow"===s[r+"-arrow-fill"].value?"both":"filled",d=s[r+"-arrow-fill"].value;"half-triangle-overshot"===l&&(d="hollow",c="hollow"),(1!==s.opacity.value||"hollow"===d)&&(e.globalCompositeOperation="destination-out",o.fillStyle(e,255,255,255,1),o.strokeStyle(e,255,255,255,1),o.drawArrowShape(t,r,e,c,s.width.pfValue,s[r+"-arrow-shape"].value,n,i,a),e.globalCompositeOperation=u);var h=s[r+"-arrow-color"].value;o.fillStyle(e,h[0],h[1],h[2],s.opacity.value),o.strokeStyle(e,h[0],h[1],h[2],s.opacity.value),o.drawArrowShape(t,r,e,d,s.width.pfValue,s[r+"-arrow-shape"].value,n,i,a)}}},n.drawArrowShape=function(e,t,r,n,i,a,o,s,l){var u,c=this,d=this.usePaths(),h=e._private.rscratch,p=!1,v=r,f={x:o,y:s},g=this.getArrowWidth(i),y=c.arrowShapes[a];if(d){var m=g+"$"+a+"$"+l+"$"+o+"$"+s;h.arrowPathCacheKey=h.arrowPathCacheKey||{},h.arrowPathCache=h.arrowPathCache||{};var b=h.arrowPathCacheKey[t]===m;b?(u=r=h.arrowPathCache[t],p=!0):(u=r=new Path2D,h.arrowPathCacheKey[t]=m,h.arrowPathCache[t]=u)}r.beginPath&&r.beginPath(),p||y.draw(r,g,l,f),!y.leavePathOpen&&r.closePath&&r.closePath(),r=v,("filled"===n||"both"===n)&&(d?r.fill(u):r.fill()),("hollow"===n||"both"===n)&&(r.lineWidth=y.matchEdgeWidth?i:1,r.lineJoin="miter",d?r.stroke(u):r.stroke())},t.exports=n},{}],64:[function(e,t,r){"use strict";var n={};n.safeDrawImage=function(e,t,r,n,i,a,o,s,l,u){var c=this;try{e.drawImage(t,r,n,i,a,o,s,l,u)}catch(d){c.data.canvasNeedsRedraw[c.NODE]=!0,c.data.canvasNeedsRedraw[c.DRAG]=!0,c.drawingImage=!0,c.redraw()}},n.drawInscribedImage=function(e,t,r){var n=this,i=r._private.position.x,a=r._private.position.y,o=r._private.style,s=o["background-fit"].value,l=o["background-position-x"],u=o["background-position-y"],c=o["background-repeat"].value,d=r.width(),h=r.height(),p=r._private.rscratch,v=o["background-clip"].value,f="node"===v,g=o["background-image-opacity"].value,y=t.width||t.cachedW,m=t.height||t.cachedH;(null==y||null==m)&&(document.body.appendChild(t),y=t.cachedW=t.width||t.offsetWidth,m=t.cachedH=t.height||t.offsetHeight,document.body.removeChild(t));var b=y,x=m,w=o["background-width"];"auto"!==w.value&&(b="%"===w.units?w.value/100*d:w.pfValue);var _=o["background-height"];if("auto"!==_.value&&(x="%"===_.units?_.value/100*h:_.pfValue),0!==b&&0!==x){if("contain"===s){var E=Math.min(d/b,h/x);b*=E,x*=E}else if("cover"===s){var E=Math.max(d/b,h/x);b*=E,x*=E}var D=i-d/2;D+="%"===l.units?(d-b)*l.value/100:l.pfValue;var S=a-h/2;S+="%"===u.units?(h-x)*u.value/100:u.pfValue,p.pathCache&&(D-=i,S-=a,i=0,a=0);var k=e.globalAlpha;if(e.globalAlpha=g,"no-repeat"===c)f&&(e.save(),p.pathCache?e.clip(p.pathCache):(n.nodeShapes[n.getNodeShape(r)].draw(e,i,a,d,h),e.clip())),n.safeDrawImage(e,t,0,0,y,m,D,S,b,x),f&&e.restore();else{var T=e.createPattern(t,c);e.fillStyle=T,n.nodeShapes[n.getNodeShape(r)].draw(e,i,a,d,h),e.translate(D,S),e.fill(),e.translate(-D,-S)}e.globalAlpha=k}},t.exports=n},{}],65:[function(e,t,r){"use strict";function n(e,t,r,n,i,a){var a=a||5;e.beginPath(),e.moveTo(t+a,r),e.lineTo(t+n-a,r),e.quadraticCurveTo(t+n,r,t+n,r+a),e.lineTo(t+n,r+i-a),e.quadraticCurveTo(t+n,r+i,t+n-a,r+i),e.lineTo(t+a,r+i),e.quadraticCurveTo(t,r+i,t,r+i-a),e.lineTo(t,r+a),e.quadraticCurveTo(t,r,t+a,r),e.closePath(),e.fill()}var i=e("../../../is"),a={};a.drawEdgeText=function(e,t){var r=t._private.style.label.strValue;if(r&&!r.match(/^\s+$/)&&(!this.hideEdgesOnViewport||!(this.dragData.didDrag||this.pinching||this.hoverData.dragging||this.data.wheel||this.swipePanning))){var n=t._private.style["font-size"].pfValue*t.cy().zoom(),a=t._private.style["min-zoomed-font-size"].pfValue;if(!(a>n)){e.textAlign="center",e.textBaseline="middle";var o=t._private.rscratch;if(i.number(o.labelX)&&i.number(o.labelY)){var s,l=t._private.style,u="autorotate"===l["edge-text-rotation"].strValue;u?(s=o.labelAngle,e.translate(o.labelX,o.labelY),e.rotate(s),this.drawText(e,t,0,0),e.rotate(-s),e.translate(-o.labelX,-o.labelY)):this.drawText(e,t,o.labelX,o.labelY)}}}},a.drawNodeText=function(e,t){var r=t._private.style.label.strValue;if(r&&!r.match(/^\s+$/)){var n=t._private.style["font-size"].pfValue*t.cy().zoom(),a=t._private.style["min-zoomed-font-size"].pfValue;if(!(a>n)){var o=t._private.style["text-halign"].strValue,s=t._private.style["text-valign"].strValue,l=t._private.rscratch;if(i.number(l.labelX)&&i.number(l.labelY)){switch(o){case"left":e.textAlign="right";break;case"right":e.textAlign="left";break;default:e.textAlign="center"}switch(s){case"top":e.textBaseline="bottom";break;case"bottom":e.textBaseline="top";break;default:e.textBaseline="middle"}this.drawText(e,t,l.labelX,l.labelY)}}}},a.getFontCache=function(e){var t;this.fontCaches=this.fontCaches||[];for(var r=0;r<this.fontCaches.length;r++)if(t=this.fontCaches[r],t.context===e)return t;return t={context:e},this.fontCaches.push(t),t},a.setupTextStyle=function(e,t){var r=t.effectiveOpacity(),n=t._private.style,i=n["font-style"].strValue,a=n["font-size"].pfValue+"px",o=n["font-family"].strValue,s=n["font-weight"].strValue,l=n["text-opacity"].value*n.opacity.value*r,u=n["text-outline-opacity"].value*l,c=n.color.value,d=n["text-outline-color"].value,h=n["text-shadow-blur"].pfValue,p=n["text-shadow-opacity"].value,v=n["text-shadow-color"].value,f=n["text-shadow-offset-x"].pfValue,g=n["text-shadow-offset-y"].pfValue,y=t._private.fontKey,m=this.getFontCache(e);m.key!==y&&(e.font=i+" "+s+" "+a+" "+o,m.key=y);var b=this.getLabelText(t);return e.lineJoin="round",this.fillStyle(e,c[0],c[1],c[2],l),this.strokeStyle(e,d[0],d[1],d[2],u),this.shadowStyle(e,v,p,h,f,g),b},a.drawText=function(e,t,r,i){var a=t._private,o=a.style,s=a.rstyle,l=a.rscratch,u=t.effectiveOpacity();if(0!==u&&0!==o["text-opacity"].value){var c=this.setupTextStyle(e,t),d=o["text-halign"].value,h=o["text-valign"].value;if(t.isEdge()&&(d="center",h="center"),t.isNode()){var p=o["padding-left"].pfValue,v=o["padding-right"].pfValue,f=o["padding-top"].pfValue,g=o["padding-bottom"].pfValue;r+=p/2,r-=v/2,i+=f/2,i-=g/2}if(null!=c&&!isNaN(r)&&!isNaN(i)){var y=o["text-background-opacity"].value,m=o["text-border-opacity"].value,b=o["text-border-width"].pfValue;if(y>0||b>0&&m>0){var x=4+b/2;t.isNode()&&("top"===h?i-=x:"bottom"===h&&(i+=x),"left"===d?r-=x:"right"===d&&(r+=x));var w=s.labelWidth,_=s.labelHeight,E=r;d&&("center"==d?E-=w/2:"left"==d&&(E-=w));var D=i;if(t.isNode()?"top"==h?D-=_:"center"==h&&(D-=_/2):D-=_/2,"autorotate"===o["edge-text-rotation"].strValue?(i=0,w+=4,E=r-w/2,D=i-_/2):(E-=x,D-=x,_+=2*x,w+=2*x),y>0){var S=e.fillStyle,k=o["text-background-color"].value;e.fillStyle="rgba("+k[0]+","+k[1]+","+k[2]+","+y*u+")";var T=o["text-background-shape"].strValue;"roundrectangle"==T?n(e,E,D,w,_,2):e.fillRect(E,D,w,_),e.fillStyle=S}if(b>0&&m>0){var P=e.strokeStyle,C=e.lineWidth,N=o["text-border-color"].value,M=o["text-border-style"].value;if(e.strokeStyle="rgba("+N[0]+","+N[1]+","+N[2]+","+m*u+")",e.lineWidth=b,e.setLineDash)switch(M){case"dotted":e.setLineDash([1,1]);break;case"dashed":e.setLineDash([4,2]);break;case"double":e.lineWidth=b/4,e.setLineDash([]);break;case"solid":e.setLineDash([])}if(e.strokeRect(E,D,w,_),"double"===M){var B=b/2;e.strokeRect(E+B,D+B,w-2*B,_-2*B)}e.setLineDash&&e.setLineDash([]),e.lineWidth=C,e.strokeStyle=P}}var z=2*o["text-outline-width"].pfValue;if(z>0&&(e.lineWidth=z),"wrap"===o["text-wrap"].value){var O=l.labelWrapCachedLines,I=s.labelHeight/O.length;switch(h){case"top":i-=(O.length-1)*I;break;case"bottom":break;default:case"center":i-=(O.length-1)*I/2}for(var L=0;L<O.length;L++)z>0&&e.strokeText(O[L],r,i),e.fillText(O[L],r,i),i+=I}else z>0&&e.strokeText(c,r,i),e.fillText(c,r,i);this.shadowStyle(e,"transparent",0)}}},t.exports=a},{"../../../is":77}],66:[function(e,t,r){"use strict";var n=e("../../../is"),i={};i.drawNode=function(e,t,r){var i,a,o=this,s=t._private.style,l=t._private.rscratch,u=t._private,c=u.position;if(n.number(c.x)&&n.number(c.y)){var d,h=this.usePaths(),p=e,v=!1,f=s["overlay-padding"].pfValue,g=s["overlay-opacity"].value,y=s["overlay-color"].value;if(!r||0!==g){var m=t.effectiveOpacity();if(0!==m)if(i=t.width()+s["padding-left"].pfValue+s["padding-right"].pfValue,a=t.height()+s["padding-top"].pfValue+s["padding-bottom"].pfValue,e.lineWidth=s["border-width"].pfValue,void 0!==r&&r)g>0&&(this.fillStyle(e,y[0],y[1],y[2],g),o.nodeShapes.roundrectangle.draw(e,t._private.position.x,t._private.position.y,i+2*f,a+2*f),e.fill());else{var b,x=s["background-image"].value[2]||s["background-image"].value[1];if(void 0!==x){b=this.getCachedImage(x,function(){o.data.canvasNeedsRedraw[o.NODE]=!0,o.data.canvasNeedsRedraw[o.DRAG]=!0,o.drawingImage=!0,o.redraw()});var w=u.backgrounding;u.backgrounding=!b.complete,w!==u.backgrounding&&t.updateStyle(!1)}var _=s["background-color"].value,E=s["border-color"].value,D=s["border-style"].value;this.fillStyle(e,_[0],_[1],_[2],s["background-opacity"].value*m),this.strokeStyle(e,E[0],E[1],E[2],s["border-opacity"].value*m);var S=s["shadow-blur"].pfValue,k=s["shadow-opacity"].value,T=s["shadow-color"].value,P=s["shadow-offset-x"].pfValue,C=s["shadow-offset-y"].pfValue;if(this.shadowStyle(e,T,k,S,P,C),e.lineJoin="miter",e.setLineDash)switch(D){case"dotted":e.setLineDash([1,1]);break;case"dashed":e.setLineDash([4,2]);break;case"solid":case"double":e.setLineDash([])}var N=s.shape.strValue;if(h){var M=N+"$"+i+"$"+a;e.translate(c.x,c.y),l.pathCacheKey===M?(d=e=l.pathCache,v=!0):(d=e=new Path2D,l.pathCacheKey=M,l.pathCache=d)}if(!v){var B=c;h&&(B={x:0,y:0}),o.nodeShapes[this.getNodeShape(t)].draw(e,B.x,B.y,i,a)}e=p,h?e.fill(d):e.fill(),this.shadowStyle(e,"transparent",0),void 0!==x&&b.complete&&this.drawInscribedImage(e,b,t);var z=s["background-blacken"].value,O=s["border-width"].pfValue;if(this.hasPie(t)&&(this.drawPie(e,t,m),(0!==z||0!==O)&&(h||o.nodeShapes[this.getNodeShape(t)].draw(e,c.x,c.y,i,a))),z>0?(this.fillStyle(e,0,0,0,z),h?e.fill(d):e.fill()):0>z&&(this.fillStyle(e,255,255,255,-z),h?e.fill(d):e.fill()),O>0&&(h?e.stroke(d):e.stroke(),"double"===D)){e.lineWidth=s["border-width"].pfValue/3;var I=e.globalCompositeOperation;e.globalCompositeOperation="destination-out",h?e.stroke(d):e.stroke(),e.globalCompositeOperation=I}h&&e.translate(-c.x,-c.y),e.setLineDash&&e.setLineDash([])}}}},i.hasPie=function(e){return e=e[0],e._private.hasPie},i.drawPie=function(e,t,r){t=t[0];var n=t._private,i=t.cy().style(),a=n.style,o=a["pie-size"],s=t.width(),l=t.height(),u=n.position.x,c=n.position.y,d=Math.min(s,l)/2,h=0,p=this.usePaths();p&&(u=0,c=0),"%"===o.units?d=d*o.value/100:void 0!==o.pfValue&&(d=o.pfValue/2);for(var v=1;v<=i.pieBackgroundN;v++){var f=a["pie-"+v+"-background-size"].value,g=a["pie-"+v+"-background-color"].value,y=a["pie-"+v+"-background-opacity"].value*r,m=f/100;m+h>1&&(m=1-h);var b=1.5*Math.PI+2*Math.PI*h,x=2*Math.PI*m,w=b+x;0===f||h>=1||h+m>1||(e.beginPath(),e.moveTo(u,c),e.arc(u,c,d,b,w),e.closePath(),this.fillStyle(e,g[0],g[1],g[2],y),e.fill(),h+=m)}},t.exports=i},{"../../../is":77}],67:[function(e,t,r){"use strict";var n={},i=e("../../../util"),a=e("../../../math"),o=100;n.getPixelRatio=function(){var e=this.data.contexts[0];if(null!=this.forcedPixelRatio)return this.forcedPixelRatio;var t=e.backingStorePixelRatio||e.webkitBackingStorePixelRatio||e.mozBackingStorePixelRatio||e.msBackingStorePixelRatio||e.oBackingStorePixelRatio||e.backingStorePixelRatio||1;return(window.devicePixelRatio||1)/t},n.paintCache=function(e){for(var t,r=this.paintCaches=this.paintCaches||[],n=!0,i=0;i<r.length;i++)if(t=r[i],t.context===e){n=!1;break}return n&&(t={context:e},r.push(t)),t},n.fillStyle=function(e,t,r,n,i){e.fillStyle="rgba("+t+","+r+","+n+","+i+")"},n.strokeStyle=function(e,t,r,n,i){e.strokeStyle="rgba("+t+","+r+","+n+","+i+")"},n.shadowStyle=function(e,t,r,n,i,a){var o=this.cy.zoom(),s=this.paintCache(e);(0!==s.shadowOpacity||0!==r)&&(s.shadowOpacity=r,r>0?(e.shadowBlur=n*o,e.shadowColor="rgba("+t[0]+","+t[1]+","+t[2]+","+r+")",e.shadowOffsetX=i*o,e.shadowOffsetY=a*o):(e.shadowBlur=0,e.shadowColor="transparent"))},n.matchCanvasSize=function(e){var t=this,r=t.data,n=e.clientWidth,i=e.clientHeight,a=t.getPixelRatio(),o=t.motionBlurPxRatio;(e===t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_NODE]||e===t.data.bufferCanvases[t.MOTIONBLUR_BUFFER_DRAG])&&(a=o);var s,l=n*a,u=i*a;if(l!==t.canvasWidth||u!==t.canvasHeight){t.fontCaches=null;var c=r.canvasContainer;c.style.width=n+"px",c.style.height=i+"px";for(var d=0;d<t.CANVAS_LAYERS;d++)s=r.canvases[d],(s.width!==l||s.height!==u)&&(s.width=l,s.height=u,s.style.width=n+"px",s.style.height=i+"px");for(var d=0;d<t.BUFFER_COUNT;d++)s=r.bufferCanvases[d],(s.width!==l||s.height!==u)&&(s.width=l,s.height=u,s.style.width=n+"px",s.style.height=i+"px");t.textureMult=1,1>=a&&(s=r.bufferCanvases[t.TEXTURE_BUFFER],t.textureMult=2,s.width=l*t.textureMult,s.height=u*t.textureMult),t.canvasWidth=l,t.canvasHeight=u}},n.renderTo=function(e,t,r,n){this.render({forcedContext:e,forcedZoom:t,forcedPan:r,drawAllLayers:!0,forcedPxRatio:n})},n.render=function(e){function t(e,t,r,n,i){var a=e.globalCompositeOperation;e.globalCompositeOperation="destination-out",h.fillStyle(e,255,255,255,h.motionBlurTransparency),e.fillRect(t,r,n,i),e.globalCompositeOperation=a}function r(e,r){var n,i,a,o;h.clearingMotionBlur||e!==f.bufferContexts[h.MOTIONBLUR_BUFFER_NODE]&&e!==f.bufferContexts[h.MOTIONBLUR_BUFFER_DRAG]?(n=C,i=T,a=h.canvasWidth,o=h.canvasHeight):(n={x:P.x*b,y:P.y*b},i=k*b,a=h.canvasWidth*b,o=h.canvasHeight*b),e.setTransform(1,0,0,1,0,0),"motionBlur"===r?t(e,0,0,a,o):s||void 0!==r&&!r||e.clearRect(0,0,a,o),l||(e.translate(n.x,n.y),e.scale(i,i)),d&&e.translate(d.x,d.y),c&&e.scale(c,c)}function n(e,t){for(var r=e.eles,n=0;n<r.length;n++){var i=r[n];i.isNode()?(h.drawNode(t,i),q||h.drawNodeText(t,i),h.drawNode(t,i,!0)):j||(h.drawEdge(t,i),q||h.drawEdgeText(t,i),h.drawEdge(t,i,!0))}}e=e||i.staticEmptyObject();var s=e.forcedContext,l=e.drawAllLayers,u=e.drawOnlyNodeLayer,c=e.forcedZoom,d=e.forcedPan,h=this,p=void 0===e.forcedPxRatio?this.getPixelRatio():e.forcedPxRatio,v=h.cy,f=h.data,g=f.canvasNeedsRedraw,y=h.textureOnViewport&&!s&&(h.pinching||h.hoverData.dragging||h.swipePanning||h.data.wheelZooming),m=void 0!==e.motionBlur?e.motionBlur:h.motionBlur,b=h.motionBlurPxRatio,x=v.hasCompoundNodes(),w=h.hoverData.draggingEles,_=h.hoverData.selecting||h.touchData.selecting?!0:!1;m=m&&!s&&h.motionBlurEnabled&&!_;var E=m;!s&&h.motionBlurTimeout&&clearTimeout(h.motionBlurTimeout),m&&(null==h.mbFrames&&(h.mbFrames=0),h.drawingImage||h.mbFrames++,h.mbFrames<3&&(E=!1),h.mbFrames>h.minMbLowQualFrames&&(h.motionBlurPxRatio=h.mbPxRBlurry)),h.clearingMotionBlur&&(h.motionBlurPxRatio=1),h.textureDrawLastFrame&&!y&&(g[h.NODE]=!0,g[h.SELECT_BOX]=!0);var D=h.getCachedEdges(),S=v.style()._private.coreStyle,k=v.zoom(),T=void 0!==c?c:k,P=v.pan(),C={x:P.x,y:P.y},N={zoom:k,pan:{x:P.x,y:P.y}},M=h.prevViewport,B=void 0===M||N.zoom!==M.zoom||N.pan.x!==M.pan.x||N.pan.y!==M.pan.y;B||w&&!x||(h.motionBlurPxRatio=1),d&&(C=d),T*=p,C.x*=p,C.y*=p;var z={drag:{nodes:[],edges:[],eles:[]},nondrag:{nodes:[],edges:[],eles:[]}};if(y||(h.textureDrawLastFrame=!1),y){h.textureDrawLastFrame=!0;var O;if(!h.textureCache){h.textureCache={},O=h.textureCache.bb=v.elements().boundingBox(),h.textureCache.texture=h.data.bufferCanvases[h.TEXTURE_BUFFER];var I=h.data.bufferContexts[h.TEXTURE_BUFFER];I.setTransform(1,0,0,1,0,0),I.clearRect(0,0,h.canvasWidth*h.textureMult,h.canvasHeight*h.textureMult),h.render({forcedContext:I,drawOnlyNodeLayer:!0,forcedPxRatio:p*h.textureMult});var N=h.textureCache.viewport={zoom:v.zoom(),pan:v.pan(),width:h.canvasWidth,height:h.canvasHeight};N.mpan={x:(0-N.pan.x)/N.zoom,y:(0-N.pan.y)/N.zoom}}g[h.DRAG]=!1,g[h.NODE]=!1;var L=f.contexts[h.NODE],A=h.textureCache.texture,N=h.textureCache.viewport;O=h.textureCache.bb,L.setTransform(1,0,0,1,0,0),m?t(L,0,0,N.width,N.height):L.clearRect(0,0,N.width,N.height);var R=S["outside-texture-bg-color"].value,V=S["outside-texture-bg-opacity"].value;h.fillStyle(L,R[0],R[1],R[2],V),L.fillRect(0,0,N.width,N.height);var k=v.zoom();r(L,!1),L.clearRect(N.mpan.x,N.mpan.y,N.width/N.zoom/p,N.height/N.zoom/p),L.drawImage(A,N.mpan.x,N.mpan.y,N.width/N.zoom/p,N.height/N.zoom/p)}else h.textureOnViewport&&!s&&(h.textureCache=null);var F=h.pinching||h.hoverData.dragging||h.swipePanning||h.data.wheelZooming||h.hoverData.draggingEles,j=h.hideEdgesOnViewport&&F,q=h.hideLabelsOnViewport&&F;if(g[h.DRAG]||g[h.NODE]||l||u){j||h.findEdgeControlPoints(D);for(var X=h.getCachedZSortedEles(),Y=v.extent(),$=0;$<X.length;$++){var H,W=X[$],O=s?null:W.boundingBox(),Z=s?!0:a.boundingBoxesIntersect(Y,O);Z&&(H=W._private.rscratch.inDragLayer?z.drag:z.nondrag,H.eles.push(W))}}var U=[];if(U[h.NODE]=!g[h.NODE]&&m&&!h.clearedForMotionBlur[h.NODE]||h.clearingMotionBlur,U[h.NODE]&&(h.clearedForMotionBlur[h.NODE]=!0),U[h.DRAG]=!g[h.DRAG]&&m&&!h.clearedForMotionBlur[h.DRAG]||h.clearingMotionBlur,U[h.DRAG]&&(h.clearedForMotionBlur[h.DRAG]=!0),g[h.NODE]||l||u||U[h.NODE]){var G=m&&!U[h.NODE]&&1!==b,L=s||(G?h.data.bufferContexts[h.MOTIONBLUR_BUFFER_NODE]:f.contexts[h.NODE]),K=m&&!G?"motionBlur":void 0;r(L,K),n(z.nondrag,L),l||m||(g[h.NODE]=!1)}if(!u&&(g[h.DRAG]||l||U[h.DRAG])){var G=m&&!U[h.DRAG]&&1!==b,L=s||(G?h.data.bufferContexts[h.MOTIONBLUR_BUFFER_DRAG]:f.contexts[h.DRAG]);r(L,m&&!G?"motionBlur":void 0),n(z.drag,L),l||m||(g[h.DRAG]=!1)}if(h.showFps||!u&&g[h.SELECT_BOX]&&!l){var L=s||f.contexts[h.SELECT_BOX];if(r(L),1==h.selection[4]&&(h.hoverData.selecting||h.touchData.selecting)){var k=h.cy.zoom(),J=S["selection-box-border-width"].value/k;L.lineWidth=J,L.fillStyle="rgba("+S["selection-box-color"].value[0]+","+S["selection-box-color"].value[1]+","+S["selection-box-color"].value[2]+","+S["selection-box-opacity"].value+")",L.fillRect(h.selection[0],h.selection[1],h.selection[2]-h.selection[0],h.selection[3]-h.selection[1]),J>0&&(L.strokeStyle="rgba("+S["selection-box-border-color"].value[0]+","+S["selection-box-border-color"].value[1]+","+S["selection-box-border-color"].value[2]+","+S["selection-box-opacity"].value+")",L.strokeRect(h.selection[0],h.selection[1],h.selection[2]-h.selection[0],h.selection[3]-h.selection[1]))}if(f.bgActivePosistion&&!h.hoverData.selecting){var k=h.cy.zoom(),Q=f.bgActivePosistion;L.fillStyle="rgba("+S["active-bg-color"].value[0]+","+S["active-bg-color"].value[1]+","+S["active-bg-color"].value[2]+","+S["active-bg-opacity"].value+")",L.beginPath(),L.arc(Q.x,Q.y,S["active-bg-size"].pfValue/k,0,2*Math.PI),L.fill()}var ee=h.lastRedrawTime;if(h.showFps&&ee){ee=Math.round(ee);var te=Math.round(1e3/ee);L.setTransform(1,0,0,1,0,0),L.fillStyle="rgba(255, 0, 0, 0.75)",L.strokeStyle="rgba(255, 0, 0, 0.75)",L.lineWidth=1,L.fillText("1 frame = "+ee+" ms = "+te+" fps",0,20);var re=60;L.strokeRect(0,30,250,20),L.fillRect(0,30,250*Math.min(te/re,1),20)}l||(g[h.SELECT_BOX]=!1)}if(m&&1!==b){var ne=f.contexts[h.NODE],ie=h.data.bufferCanvases[h.MOTIONBLUR_BUFFER_NODE],ae=f.contexts[h.DRAG],oe=h.data.bufferCanvases[h.MOTIONBLUR_BUFFER_DRAG],se=function(e,r,n){e.setTransform(1,0,0,1,0,0),n||!E?e.clearRect(0,0,h.canvasWidth,h.canvasHeight):t(e,0,0,h.canvasWidth,h.canvasHeight);var i=b;e.drawImage(r,0,0,h.canvasWidth*i,h.canvasHeight*i,0,0,h.canvasWidth,h.canvasHeight)};(g[h.NODE]||U[h.NODE])&&(se(ne,ie,U[h.NODE]),g[h.NODE]=!1),(g[h.DRAG]||U[h.DRAG])&&(se(ae,oe,U[h.DRAG]),g[h.DRAG]=!1)}h.currentlyDrawing=!1,h.prevViewport=N,h.clearingMotionBlur&&(h.clearingMotionBlur=!1,h.motionBlurCleared=!0,h.motionBlur=!0),m&&(h.motionBlurTimeout=setTimeout(function(){h.motionBlurTimeout=null,h.clearedForMotionBlur[h.NODE]=!1,h.clearedForMotionBlur[h.DRAG]=!1,h.motionBlur=!1,h.clearingMotionBlur=!y,h.mbFrames=0,g[h.NODE]=!0,g[h.DRAG]=!0,h.redraw()},o)),h.drawingImage=!1,s||h.initrender||(h.initrender=!0,v.trigger("initrender")),s||v.triggerOnRender()},t.exports=n},{"../../../math":79,"../../../util":94}],68:[function(e,t,r){"use strict";var n=e("../../../math"),i={};i.drawPolygonPath=function(e,t,r,n,i,a){var o=n/2,s=i/2;e.beginPath&&e.beginPath(),e.moveTo(t+o*a[0],r+s*a[1]);for(var l=1;l<a.length/2;l++)e.lineTo(t+o*a[2*l],r+s*a[2*l+1]);e.closePath()},i.drawRoundRectanglePath=function(e,t,r,i,a,o){var s=i/2,l=a/2,u=n.getRoundRectangleRadius(i,a);e.beginPath&&e.beginPath(),e.moveTo(t,r-l),e.arcTo(t+s,r-l,t+s,r,u),e.arcTo(t+s,r+l,t,r+l,u),e.arcTo(t-s,r+l,t-s,r,u),e.arcTo(t-s,r-l,t,r-l,u),e.lineTo(t,r-l),e.closePath()};for(var a=Math.sin(0),o=Math.cos(0),s={},l={},u=Math.PI/40,c=0*Math.PI;c<2*Math.PI;c+=u)s[c]=Math.sin(c),l[c]=Math.cos(c);i.drawEllipsePath=function(e,t,r,n,i){if(e.beginPath&&e.beginPath(),e.ellipse)e.ellipse(t,r,n/2,i/2,0,0,2*Math.PI);else for(var c,d,h=n/2,p=i/2,v=0*Math.PI;v<2*Math.PI;v+=u)c=t-h*s[v]*a+h*l[v]*o,d=r+p*l[v]*a+p*s[v]*o,0===v?e.moveTo(c,d):e.lineTo(c,d);e.closePath()},t.exports=i},{"../../../math":79}],69:[function(e,t,r){"use strict";var n=e("../../../is"),i={};i.createBuffer=function(e,t){var r=document.createElement("canvas");return r.width=e,r.height=t,[r,r.getContext("2d")]},i.bufferCanvasImage=function(e){var t=this.cy,r=t.elements().boundingBox(),i=e.full?Math.ceil(r.w):this.container.clientWidth,a=e.full?Math.ceil(r.h):this.container.clientHeight,o=1;if(void 0!==e.scale)i*=e.scale,a*=e.scale,o=e.scale;else if(n.number(e.maxWidth)||n.number(e.maxHeight)){var s=1/0,l=1/0;n.number(e.maxWidth)&&(s=o*e.maxWidth/i),n.number(e.maxHeight)&&(l=o*e.maxHeight/a),o=Math.min(s,l),i*=o,a*=o}var u=document.createElement("canvas");u.width=i,u.height=a,u.style.width=i+"px",u.style.height=a+"px";var c=u.getContext("2d");if(i>0&&a>0)if(c.clearRect(0,0,i,a),e.bg&&(c.fillStyle=e.bg,c.rect(0,0,i,a),c.fill()),c.globalCompositeOperation="source-over",e.full)this.render({forcedContext:c,drawAllLayers:!0,forcedZoom:o,forcedPan:{x:-r.x1*o,y:-r.y1*o},forcedPxRatio:1});else{var d=t.pan(),h={x:d.x*o,y:d.y*o},p=t.zoom()*o;this.render({forcedContext:c,drawAllLayers:!0,forcedZoom:p,forcedPan:h,forcedPxRatio:1})}return u},i.png=function(e){return this.bufferCanvasImage(e).toDataURL("image/png")},i.jpg=function(e){return this.bufferCanvasImage(e).toDataURL("image/jpeg")},t.exports=i},{"../../../is":77}],70:[function(e,t,r){"use strict";function n(e){var t=this;t.data={canvases:new Array(s.CANVAS_LAYERS),contexts:new Array(s.CANVAS_LAYERS),canvasNeedsRedraw:new Array(s.CANVAS_LAYERS),bufferCanvases:new Array(s.BUFFER_COUNT),bufferContexts:new Array(s.CANVAS_LAYERS)},t.data.canvasContainer=document.createElement("div");var r=t.data.canvasContainer.style;t.data.canvasContainer.setAttribute("style","-webkit-tap-highlight-color: rgba(0,0,0,0);"),r.position="relative",r.zIndex="0",r.overflow="hidden";var n=e.cy.container();n.appendChild(t.data.canvasContainer),n.setAttribute("style",(n.getAttribute("style")||"")+"-webkit-tap-highlight-color: rgba(0,0,0,0);");
+for(var i=0;i<s.CANVAS_LAYERS;i++){var o=t.data.canvases[i]=document.createElement("canvas");t.data.contexts[i]=o.getContext("2d"),o.setAttribute("style","-webkit-user-select: none; -moz-user-select: -moz-none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0); outline-style: none;"+(a.ms()?" -ms-touch-action: none; touch-action: none; ":"")),o.style.position="absolute",o.setAttribute("data-id","layer"+i),o.style.zIndex=String(s.CANVAS_LAYERS-i),t.data.canvasContainer.appendChild(o),t.data.canvasNeedsRedraw[i]=!1}t.data.topCanvas=t.data.canvases[0],t.data.canvases[s.NODE].setAttribute("data-id","layer"+s.NODE+"-node"),t.data.canvases[s.SELECT_BOX].setAttribute("data-id","layer"+s.SELECT_BOX+"-selectbox"),t.data.canvases[s.DRAG].setAttribute("data-id","layer"+s.DRAG+"-drag");for(var i=0;i<s.BUFFER_COUNT;i++)t.data.bufferCanvases[i]=document.createElement("canvas"),t.data.bufferContexts[i]=t.data.bufferCanvases[i].getContext("2d"),t.data.bufferCanvases[i].style.position="absolute",t.data.bufferCanvases[i].setAttribute("data-id","buffer"+i),t.data.bufferCanvases[i].style.zIndex=String(-i-1),t.data.bufferCanvases[i].style.visibility="hidden";t.pathsEnabled=!0}var i=e("../../../util"),a=e("../../../is"),o=n,s=n.prototype;s.CANVAS_LAYERS=3,s.SELECT_BOX=0,s.DRAG=1,s.NODE=2,s.BUFFER_COUNT=3,s.TEXTURE_BUFFER=0,s.MOTIONBLUR_BUFFER_NODE=1,s.MOTIONBLUR_BUFFER_DRAG=2,s.redrawHint=function(e,t){var r=this;switch(e){case"eles":r.data.canvasNeedsRedraw[s.NODE]=t;break;case"drag":r.data.canvasNeedsRedraw[s.DRAG]=t;break;case"select":r.data.canvasNeedsRedraw[s.SELECT_BOX]=t}};var l="undefined"!=typeof Path2D;s.path2dEnabled=function(e){return void 0===e?this.pathsEnabled:void(this.pathsEnabled=e?!0:!1)},s.usePaths=function(){return l&&this.pathsEnabled},[e("./arrow-shapes"),e("./drawing-edges"),e("./drawing-images"),e("./drawing-label-text"),e("./drawing-nodes"),e("./drawing-redraw"),e("./drawing-shapes"),e("./export-image"),e("./node-shapes")].forEach(function(e){i.extend(s,e)}),t.exports=o},{"../../../is":77,"../../../util":94,"./arrow-shapes":62,"./drawing-edges":63,"./drawing-images":64,"./drawing-label-text":65,"./drawing-nodes":66,"./drawing-redraw":67,"./drawing-shapes":68,"./export-image":69,"./node-shapes":71}],71:[function(e,t,r){"use strict";var n,i={};i.nodeShapeImpl=function(e){var t=this;return(n||(n={ellipse:function(e,r,n,i,a){t.drawEllipsePath(e,r,n,i,a)},polygon:function(e,r,n,i,a,o){t.drawPolygonPath(e,r,n,i,a,o)},roundrectangle:function(e,r,n,i,a){t.drawRoundRectanglePath(e,r,n,i,a,10)}}))[e]},t.exports=i},{}],72:[function(e,t,r){"use strict";t.exports=[{name:"null",impl:e("./null")},{name:"base",impl:e("./base")},{name:"canvas",impl:e("./canvas")}]},{"./base":58,"./canvas":70,"./null":73}],73:[function(e,t,r){"use strict";function n(e){this.options=e,this.notifications=0}var i=function(){};n.prototype={recalculateRenderedStyle:i,notify:function(){this.notifications++},init:i},t.exports=n},{}],74:[function(e,t,r){"use strict";var n=e("./is"),i=e("./util"),a=e("./thread"),o=e("./promise"),s=e("./define"),l=function(t){if(!(this instanceof l))return new l(t);this._private={pass:[]};var r=4;if(n.number(t),"undefined"!=typeof navigator&&null!=navigator.hardwareConcurrency)t=navigator.hardwareConcurrency;else try{t=e("os").cpus().length}catch(i){t=r}for(var o=0;t>o;o++)this[o]=new a;this.length=t},u=l.prototype;i.extend(u,{instanceString:function(){return"fabric"},require:function(e,t){for(var r=0;r<this.length;r++){var n=this[r];n.require(e,t)}return this},random:function(){var e=Math.round((this.length-1)*Math.random()),t=this[e];return t},run:function(e){var t=this._private.pass.shift();return this.random().pass(t).run(e)},message:function(e){return this.random().message(e)},broadcast:function(e){for(var t=0;t<this.length;t++){var r=this[t];r.message(e)}return this},stop:function(){for(var e=0;e<this.length;e++){var t=this[e];t.stop()}return this},pass:function(e){var t=this._private.pass;if(!n.array(e))throw"Only arrays may be used with fabric.pass()";return t.push(e),this},spreadSize:function(){var e=Math.ceil(this._private.pass[0].length/this.length);return e=Math.max(1,e)},spread:function(e){for(var t=this,r=t._private,n=t.spreadSize(),i=r.pass.shift().concat([]),a=[],s=0;s<this.length;s++){var l=this[s],u=i.splice(0,n),c=l.pass(u).run(e);a.push(c);var d=0===i.length;if(d)break}return o.all(a).then(function(e){for(var t=[],r=0,n=0;n<e.length;n++)for(var i=e[n],a=0;a<i.length;a++){var o=i[a];t[r++]=o}return t})},map:function(e){var t=this;return t.require(e,"_$_$_fabmap"),t.spread(function(e){var t=[],r=resolve;resolve=function(e){t.push(e)};for(var n=0;n<e.length;n++){var i=t.length,a=_$_$_fabmap(e[n]),o=i===t.length;o&&t.push(a)}return resolve=r,t})},filter:function(e){var t=this._private,r=t.pass[0];return this.map(e).then(function(e){for(var t=[],n=0;n<r.length;n++){var i=r[n],a=e[n];a&&t.push(i)}return t})},sort:function(e){var t=this,r=this._private.pass[0].length,n=this.spreadSize();return e=e||function(e,t){return t>e?-1:e>t?1:0},t.require(e,"_$_$_cmp"),t.spread(function(e){var t=e.sort(_$_$_cmp);resolve(t)}).then(function(t){for(var i=function(n,i,a){i=Math.min(i,r),a=Math.min(a,r);for(var o=n,s=i,l=[],u=o;a>u;u++){var c=t[n],d=t[i];s>n&&(i>=a||e(c,d)<=0)?(l.push(c),n++):(l.push(d),i++)}for(var u=0;u<l.length;u++){var h=o+u;t[h]=l[u]}},a=n;r>a;a*=2)for(var o=0;r>o;o+=2*a)i(o,o+a,o+2*a);return t})}});var c=function(e){return e=e||{},function(t,r){var n=this._private.pass.shift();return this.random().pass(n)[e.threadFn](t,r)}};i.extend(u,{randomMap:c({threadFn:"map"}),reduce:c({threadFn:"reduce"}),reduceRight:c({threadFn:"reduceRight"})});var d=u;d.promise=d.run,d.terminate=d.halt=d.stop,d.include=d.require,i.extend(u,{on:s.on(),one:s.on({unbindSelfOnTrigger:!0}),off:s.off(),trigger:s.trigger()}),s.eventAliasesOn(u),t.exports=l},{"./define":41,"./is":77,"./promise":80,"./thread":92,"./util":94,os:void 0}],75:[function(e,t,r){"use strict";(function(){var e,n,i,a,o,s,l,u,c,d,h,p,v,f,g;i=Math.floor,d=Math.min,n=function(e,t){return t>e?-1:e>t?1:0},c=function(e,t,r,a,o){var s;if(null==r&&(r=0),null==o&&(o=n),0>r)throw new Error("lo must be non-negative");for(null==a&&(a=e.length);a>r;)s=i((r+a)/2),o(t,e[s])<0?a=s:r=s+1;return[].splice.apply(e,[r,r-r].concat(t)),t},s=function(e,t,r){return null==r&&(r=n),e.push(t),f(e,0,e.length-1,r)},o=function(e,t){var r,i;return null==t&&(t=n),r=e.pop(),e.length?(i=e[0],e[0]=r,g(e,0,t)):i=r,i},u=function(e,t,r){var i;return null==r&&(r=n),i=e[0],e[0]=t,g(e,0,r),i},l=function(e,t,r){var i;return null==r&&(r=n),e.length&&r(e[0],t)<0&&(i=[e[0],t],t=i[0],e[0]=i[1],g(e,0,r)),t},a=function(e,t){var r,a,o,s,l,u;for(null==t&&(t=n),s=function(){u=[];for(var t=0,r=i(e.length/2);r>=0?r>t:t>r;r>=0?t++:t--)u.push(t);return u}.apply(this).reverse(),l=[],a=0,o=s.length;o>a;a++)r=s[a],l.push(g(e,r,t));return l},v=function(e,t,r){var i;return null==r&&(r=n),i=e.indexOf(t),-1!==i?(f(e,0,i,r),g(e,i,r)):void 0},h=function(e,t,r){var i,o,s,u,c;if(null==r&&(r=n),o=e.slice(0,t),!o.length)return o;for(a(o,r),c=e.slice(t),s=0,u=c.length;u>s;s++)i=c[s],l(o,i,r);return o.sort(r).reverse()},p=function(e,t,r){var i,s,l,u,h,p,v,f,g,y;if(null==r&&(r=n),10*t<=e.length){if(u=e.slice(0,t).sort(r),!u.length)return u;for(l=u[u.length-1],f=e.slice(t),h=0,v=f.length;v>h;h++)i=f[h],r(i,l)<0&&(c(u,i,0,null,r),u.pop(),l=u[u.length-1]);return u}for(a(e,r),y=[],s=p=0,g=d(t,e.length);g>=0?g>p:p>g;s=g>=0?++p:--p)y.push(o(e,r));return y},f=function(e,t,r,i){var a,o,s;for(null==i&&(i=n),a=e[r];r>t&&(s=r-1>>1,o=e[s],i(a,o)<0);)e[r]=o,r=s;return e[r]=a},g=function(e,t,r){var i,a,o,s,l;for(null==r&&(r=n),a=e.length,l=t,o=e[t],i=2*t+1;a>i;)s=i+1,a>s&&!(r(e[i],e[s])<0)&&(i=s),e[t]=e[i],t=i,i=2*t+1;return e[t]=o,f(e,l,t,r)},e=function(){function e(e){this.cmp=null!=e?e:n,this.nodes=[]}return e.push=s,e.pop=o,e.replace=u,e.pushpop=l,e.heapify=a,e.updateItem=v,e.nlargest=h,e.nsmallest=p,e.prototype.push=function(e){return s(this.nodes,e,this.cmp)},e.prototype.pop=function(){return o(this.nodes,this.cmp)},e.prototype.peek=function(){return this.nodes[0]},e.prototype.contains=function(e){return-1!==this.nodes.indexOf(e)},e.prototype.replace=function(e){return u(this.nodes,e,this.cmp)},e.prototype.pushpop=function(e){return l(this.nodes,e,this.cmp)},e.prototype.heapify=function(){return a(this.nodes,this.cmp)},e.prototype.updateItem=function(e){return v(this.nodes,e,this.cmp)},e.prototype.clear=function(){return this.nodes=[]},e.prototype.empty=function(){return 0===this.nodes.length},e.prototype.size=function(){return this.nodes.length},e.prototype.clone=function(){var t;return t=new e,t.nodes=this.nodes.slice(0),t},e.prototype.toArray=function(){return this.nodes.slice(0)},e.prototype.insert=e.prototype.push,e.prototype.top=e.prototype.peek,e.prototype.front=e.prototype.peek,e.prototype.has=e.prototype.contains,e.prototype.copy=e.prototype.clone,e}(),function(e,n){return"function"==typeof define&&define.amd?define([],n):"object"==typeof r?t.exports=n():e.Heap=n()}(this,function(){return e})}).call(this)},{}],76:[function(e,t,r){"use strict";var n=e("./window"),i=e("./is"),a=e("./core"),o=e("./extension"),s=e("./jquery-plugin"),l=e("./stylesheet"),u=e("./thread"),c=e("./fabric"),d=function(e){return void 0===e&&(e={}),i.plainObject(e)?new a(e):i.string(e)?o.apply(o,arguments):void 0};d.version="2.5.1",n&&n.jQuery&&s(n.jQuery,d),d.registerJquery=function(e){s(e,d)},d.stylesheet=d.Stylesheet=l,d.thread=d.Thread=u,d.fabric=d.Fabric=c,t.exports=d},{"./core":34,"./extension":43,"./fabric":74,"./is":77,"./jquery-plugin":78,"./stylesheet":91,"./thread":92,"./window":100}],77:[function(e,t,r){"use strict";var n=e("./window"),i=n?n.navigator:null,a="string",o=typeof{},s="function",l=typeof HTMLElement,u=function(e){return e&&e.instanceString&&c.fn(e.instanceString)?e.instanceString():null},c={defined:function(e){return null!=e},string:function(e){return null!=e&&typeof e==a},fn:function(e){return null!=e&&typeof e===s},array:function(e){return Array.isArray?Array.isArray(e):null!=e&&e instanceof Array},plainObject:function(e){return null!=e&&typeof e===o&&!c.array(e)&&e.constructor===Object},object:function(e){return null!=e&&typeof e===o},number:function(e){return null!=e&&"number"==typeof e&&!isNaN(e)},integer:function(e){return c.number(e)&&Math.floor(e)===e},bool:function(e){return null!=e&&typeof e==typeof!0},htmlElement:function(e){return"undefined"===l?void 0:null!=e&&e instanceof HTMLElement},elementOrCollection:function(e){return c.element(e)||c.collection(e)},element:function(e){return"collection"===u(e)&&e._private.single},collection:function(e){return"collection"===u(e)&&!e._private.single},core:function(e){return"core"===u(e)},style:function(e){return"style"===u(e)},stylesheet:function(e){return"stylesheet"===u(e)},event:function(e){return"event"===u(e)},thread:function(e){return"thread"===u(e)},fabric:function(e){return"fabric"===u(e)},emptyString:function(e){return e?c.string(e)&&(""===e||e.match(/^\s+$/))?!0:!1:!0},nonemptyString:function(e){return e&&c.string(e)&&""!==e&&!e.match(/^\s+$/)?!0:!1},domElement:function(e){return"undefined"==typeof HTMLElement?!1:e instanceof HTMLElement},boundingBox:function(e){return c.plainObject(e)&&c.number(e.x1)&&c.number(e.x2)&&c.number(e.y1)&&c.number(e.y2)},promise:function(e){return c.object(e)&&c.fn(e.then)},touch:function(){return n&&("ontouchstart"in n||n.DocumentTouch&&document instanceof DocumentTouch)},gecko:function(){return"undefined"!=typeof InstallTrigger||"MozAppearance"in document.documentElement.style},webkit:function(){return"undefined"!=typeof webkitURL||"WebkitAppearance"in document.documentElement.style},chromium:function(){return"undefined"!=typeof chrome},khtml:function(){return i&&i.vendor.match(/kde/i)},khtmlEtc:function(){return c.khtml()||c.webkit()||c.chromium()},ms:function(){return i&&i.userAgent.match(/msie|trident|edge/i)},windows:function(){return i&&i.appVersion.match(/Win/i)},mac:function(){return i&&i.appVersion.match(/Mac/i)},linux:function(){return i&&i.appVersion.match(/Linux/i)},unix:function(){return i&&i.appVersion.match(/X11/i)}};t.exports=c},{"./window":100}],78:[function(e,t,r){"use strict";var n=e("./is"),i=function(e){var t=e[0]._cyreg=e[0]._cyreg||{};return t},a=function(e,t){e&&(e.fn.cytoscape||(e.fn.cytoscape=function(r){var a=e(this);if("get"===r)return i(a).cy;if(n.fn(r)){var o=r,s=i(a).cy;if(s&&s.isReady())s.trigger("ready",[],o);else{var l=i(a),u=l.readies=l.readies||[];u.push(o)}}else if(n.plainObject(r))return a.each(function(){var n=e.extend({},r,{container:e(this)[0]});t(n)})},e.cytoscape=t,null==e.fn.cy&&null==e.cy&&(e.fn.cy=e.fn.cytoscape,e.cy=e.cytoscape)))};t.exports=a},{"./is":77}],79:[function(e,t,r){"use strict";var n={};n.signum=function(e){return e>0?1:0>e?-1:0},n.distance=function(e,t){return Math.sqrt(n.sqDistance(e,t))},n.sqDistance=function(e,t){var r=t.x-e.x,n=t.y-e.y;return r*r+n*n},n.qbezierAt=function(e,t,r,n){return(1-n)*(1-n)*e+2*(1-n)*n*t+n*n*r},n.qbezierPtAt=function(e,t,r,i){return{x:n.qbezierAt(e.x,t.x,r.x,i),y:n.qbezierAt(e.y,t.y,r.y,i)}},n.makeBoundingBox=function(e){if(null!=e.x1&&null!=e.y1){if(null!=e.x2&&null!=e.y2&&e.x2>=e.x1&&e.y2>=e.y1)return{x1:e.x1,y1:e.y1,x2:e.x2,y2:e.y2,w:e.x2-e.x1,h:e.y2-e.y1};if(null!=e.w&&null!=e.h&&e.w>=0&&e.h>=0)return{x1:e.x1,y1:e.y1,x2:e.x1+e.w,y2:e.y1+e.h,w:e.w,h:e.h}}},n.boundingBoxesIntersect=function(e,t){return e.x1>t.x2?!1:t.x1>e.x2?!1:e.x2<t.x1?!1:t.x2<e.x1?!1:e.y2<t.y1?!1:t.y2<e.y1?!1:e.y1>t.y2?!1:t.y1>e.y2?!1:!0},n.inBoundingBox=function(e,t,r){return e.x1<=t&&t<=e.x2&&e.y1<=r&&r<=e.y2},n.pointInBoundingBox=function(e,t){return this.inBoundingBox(e,t.x,t.y)},n.roundRectangleIntersectLine=function(e,t,r,n,i,a,o){var s,l=this.getRoundRectangleRadius(i,a),u=i/2,c=a/2,d=r-u+l-o,h=n-c-o,p=r+u-l+o,v=h;if(s=this.finiteLinesIntersect(e,t,r,n,d,h,p,v,!1),s.length>0)return s;var f=r+u+o,g=n-c+l-o,y=f,m=n+c-l+o;if(s=this.finiteLinesIntersect(e,t,r,n,f,g,y,m,!1),s.length>0)return s;var b=r-u+l-o,x=n+c+o,w=r+u-l+o,_=x;if(s=this.finiteLinesIntersect(e,t,r,n,b,x,w,_,!1),s.length>0)return s;var E=r-u-o,D=n-c+l-o,S=E,k=n+c-l+o;if(s=this.finiteLinesIntersect(e,t,r,n,E,D,S,k,!1),s.length>0)return s;var T,P=r-u+l,C=n-c+l;if(T=this.intersectLineCircle(e,t,r,n,P,C,l+o),T.length>0&&T[0]<=P&&T[1]<=C)return[T[0],T[1]];var N=r+u-l,M=n-c+l;if(T=this.intersectLineCircle(e,t,r,n,N,M,l+o),T.length>0&&T[0]>=N&&T[1]<=M)return[T[0],T[1]];var B=r+u-l,z=n+c-l;if(T=this.intersectLineCircle(e,t,r,n,B,z,l+o),T.length>0&&T[0]>=B&&T[1]>=z)return[T[0],T[1]];var O=r-u+l,I=n+c-l;return T=this.intersectLineCircle(e,t,r,n,O,I,l+o),T.length>0&&T[0]<=O&&T[1]>=I?[T[0],T[1]]:[]},n.inLineVicinity=function(e,t,r,n,i,a,o){var s=o,l=Math.min(r,i),u=Math.max(r,i),c=Math.min(n,a),d=Math.max(n,a);return e>=l-s&&u+s>=e&&t>=c-s&&d+s>=t},n.inBezierVicinity=function(e,t,r,n,i,a,o,s,l){var u={x1:Math.min(r,o,i)-l,x2:Math.max(r,o,i)+l,y1:Math.min(n,s,a)-l,y2:Math.max(n,s,a)+l};return e<u.x1||e>u.x2||t<u.y1||t>u.y2?!1:!0},n.solveCubic=function(e,t,r,n,i){t/=e,r/=e,n/=e;var a,o,s,l,u,c,d,h;return o=(3*r-t*t)/9,s=-(27*n)+t*(9*r-2*(t*t)),s/=54,a=o*o*o+s*s,i[1]=0,d=t/3,a>0?(u=s+Math.sqrt(a),u=0>u?-Math.pow(-u,1/3):Math.pow(u,1/3),c=s-Math.sqrt(a),c=0>c?-Math.pow(-c,1/3):Math.pow(c,1/3),i[0]=-d+u+c,d+=(u+c)/2,i[4]=i[2]=-d,d=Math.sqrt(3)*(-c+u)/2,i[3]=d,void(i[5]=-d)):(i[5]=i[3]=0,0===a?(h=0>s?-Math.pow(-s,1/3):Math.pow(s,1/3),i[0]=-d+2*h,void(i[4]=i[2]=-(h+d))):(o=-o,l=o*o*o,l=Math.acos(s/Math.sqrt(l)),h=2*Math.sqrt(o),i[0]=-d+h*Math.cos(l/3),i[2]=-d+h*Math.cos((l+2*Math.PI)/3),void(i[4]=-d+h*Math.cos((l+4*Math.PI)/3))))},n.sqDistanceToQuadraticBezier=function(e,t,r,n,i,a,o,s){var l=1*r*r-4*r*i+2*r*o+4*i*i-4*i*o+o*o+n*n-4*n*a+2*n*s+4*a*a-4*a*s+s*s,u=9*r*i-3*r*r-3*r*o-6*i*i+3*i*o+9*n*a-3*n*n-3*n*s-6*a*a+3*a*s,c=3*r*r-6*r*i+r*o-r*e+2*i*i+2*i*e-o*e+3*n*n-6*n*a+n*s-n*t+2*a*a+2*a*t-s*t,d=1*r*i-r*r+r*e-i*e+n*a-n*n+n*t-a*t,h=[];this.solveCubic(l,u,c,d,h);for(var p=1e-7,v=[],f=0;6>f;f+=2)Math.abs(h[f+1])<p&&h[f]>=0&&h[f]<=1&&v.push(h[f]);v.push(1),v.push(0);for(var g,y,m,b,x=-1,w=0;w<v.length;w++)y=Math.pow(1-v[w],2)*r+2*(1-v[w])*v[w]*i+v[w]*v[w]*o,m=Math.pow(1-v[w],2)*n+2*(1-v[w])*v[w]*a+v[w]*v[w]*s,b=Math.pow(y-e,2)+Math.pow(m-t,2),x>=0?x>b&&(x=b,g=v[w]):(x=b,g=v[w]);return x},n.sqDistanceToFiniteLine=function(e,t,r,n,i,a){var o=[e-r,t-n],s=[i-r,a-n],l=s[0]*s[0]+s[1]*s[1],u=o[0]*o[0]+o[1]*o[1],c=o[0]*s[0]+o[1]*s[1],d=c*c/l;return 0>c?u:d>l?(e-i)*(e-i)+(t-a)*(t-a):u-d},n.pointInsidePolygonPoints=function(e,t,r){for(var n,i,a,o,s,l=0,u=0,c=0;c<r.length/2;c++)if(n=r[2*c],i=r[2*c+1],c+1<r.length/2?(a=r[2*(c+1)],o=r[2*(c+1)+1]):(a=r[2*(c+1-r.length/2)],o=r[2*(c+1-r.length/2)+1]),n==e&&a==e);else{if(!(n>=e&&e>=a||e>=n&&a>=e))continue;s=(e-n)/(a-n)*(o-i)+i,s>t&&l++,t>s&&u++}return l%2===0?!1:!0},n.pointInsidePolygon=function(e,t,r,i,a,o,s,l,u){var c,d=new Array(r.length);null!=l[0]?(c=Math.atan(l[1]/l[0]),l[0]<0?c+=Math.PI/2:c=-c-Math.PI/2):c=l;for(var h=Math.cos(-c),p=Math.sin(-c),v=0;v<d.length/2;v++)d[2*v]=o/2*(r[2*v]*h-r[2*v+1]*p),d[2*v+1]=s/2*(r[2*v+1]*h+r[2*v]*p),d[2*v]+=i,d[2*v+1]+=a;var f;if(u>0){var g=this.expandPolygon(d,-u);f=this.joinLines(g)}else f=d;return n.pointInsidePolygonPoints(e,t,f)},n.joinLines=function(e){for(var t,r,n,i,a,o,s,l,u=new Array(e.length/2),c=0;c<e.length/4;c++){t=e[4*c],r=e[4*c+1],n=e[4*c+2],i=e[4*c+3],c<e.length/4-1?(a=e[4*(c+1)],o=e[4*(c+1)+1],s=e[4*(c+1)+2],l=e[4*(c+1)+3]):(a=e[0],o=e[1],s=e[2],l=e[3]);var d=this.finiteLinesIntersect(t,r,n,i,a,o,s,l,!0);u[2*c]=d[0],u[2*c+1]=d[1]}return u},n.expandPolygon=function(e,t){for(var r,n,i,a,o=new Array(2*e.length),s=0;s<e.length/2;s++){r=e[2*s],n=e[2*s+1],s<e.length/2-1?(i=e[2*(s+1)],a=e[2*(s+1)+1]):(i=e[0],a=e[1]);var l=a-n,u=-(i-r),c=Math.sqrt(l*l+u*u),d=l/c,h=u/c;o[4*s]=r+d*t,o[4*s+1]=n+h*t,o[4*s+2]=i+d*t,o[4*s+3]=a+h*t}return o},n.intersectLineEllipse=function(e,t,r,n,i,a){var o=r-e,s=n-t;o/=i,s/=a;var l=Math.sqrt(o*o+s*s),u=l-1;if(0>u)return[];var c=u/l;return[(r-e)*c+e,(n-t)*c+t]},n.intersectLineCircle=function(e,t,r,n,i,a,o){var s=[r-e,n-t],l=[i,a],u=[e-i,t-a],c=s[0]*s[0]+s[1]*s[1],d=2*(u[0]*s[0]+u[1]*s[1]),l=u[0]*u[0]+u[1]*u[1]-o*o,h=d*d-4*c*l;if(0>h)return[];var p=(-d+Math.sqrt(h))/(2*c),v=(-d-Math.sqrt(h))/(2*c),f=Math.min(p,v),g=Math.max(p,v),y=[];if(f>=0&&1>=f&&y.push(f),g>=0&&1>=g&&y.push(g),0===y.length)return[];var m=y[0]*s[0]+e,b=y[0]*s[1]+t;if(y.length>1){if(y[0]==y[1])return[m,b];var x=y[1]*s[0]+e,w=y[1]*s[1]+t;return[m,b,x,w]}return[m,b]},n.findCircleNearPoint=function(e,t,r,n,i){var a=n-e,o=i-t,s=Math.sqrt(a*a+o*o),l=a/s,u=o/s;return[e+l*r,t+u*r]},n.findMaxSqDistanceToOrigin=function(e){for(var t,r=1e-6,n=0;n<e.length/2;n++)t=e[2*n]*e[2*n]+e[2*n+1]*e[2*n+1],t>r&&(r=t);return r},n.finiteLinesIntersect=function(e,t,r,n,i,a,o,s,l){var u=(o-i)*(t-a)-(s-a)*(e-i),c=(r-e)*(t-a)-(n-t)*(e-i),d=(s-a)*(r-e)-(o-i)*(n-t);if(0!==d){var h=u/d,p=c/d;return h>=0&&1>=h&&p>=0&&1>=p?[e+h*(r-e),t+h*(n-t)]:l?[e+h*(r-e),t+h*(n-t)]:[]}return 0===u||0===c?[e,r,o].sort()[1]===o?[o,s]:[e,r,i].sort()[1]===i?[i,a]:[i,o,r].sort()[1]===r?[r,n]:[]:[]},n.polygonIntersectLine=function(e,t,r,i,a,o,s,l){for(var u,c=[],d=new Array(r.length),h=0;h<d.length/2;h++)d[2*h]=r[2*h]*o+i,d[2*h+1]=r[2*h+1]*s+a;var p;if(l>0){var v=n.expandPolygon(d,-l);p=n.joinLines(v)}else p=d;for(var f,g,y,m,h=0;h<p.length/2;h++)f=p[2*h],g=p[2*h+1],h<p.length/2-1?(y=p[2*(h+1)],m=p[2*(h+1)+1]):(y=p[0],m=p[1]),u=this.finiteLinesIntersect(e,t,i,a,f,g,y,m),0!==u.length&&c.push(u[0],u[1]);return c},n.shortenIntersection=function(e,t,r){var n=[e[0]-t[0],e[1]-t[1]],i=Math.sqrt(n[0]*n[0]+n[1]*n[1]),a=(i-r)/i;return 0>a&&(a=1e-5),[t[0]+a*n[0],t[1]+a*n[1]]},n.generateUnitNgonPointsFitToSquare=function(e,t){var r=n.generateUnitNgonPoints(e,t);return r=n.fitPolygonToSquare(r)},n.fitPolygonToSquare=function(e){for(var t,r,n=e.length/2,i=1/0,a=1/0,o=-(1/0),s=-(1/0),l=0;n>l;l++)t=e[2*l],r=e[2*l+1],i=Math.min(i,t),o=Math.max(o,t),a=Math.min(a,r),s=Math.max(s,r);for(var u=2/(o-i),c=2/(s-a),l=0;n>l;l++)t=e[2*l]=e[2*l]*u,r=e[2*l+1]=e[2*l+1]*c,i=Math.min(i,t),o=Math.max(o,t),a=Math.min(a,r),s=Math.max(s,r);if(-1>a)for(var l=0;n>l;l++)r=e[2*l+1]=e[2*l+1]+(-1-a);return e},n.generateUnitNgonPoints=function(e,t){var r=1/e*2*Math.PI,n=e%2===0?Math.PI/2+r/2:Math.PI/2;n+=t;for(var i,a,o,s=new Array(2*e),l=0;e>l;l++)i=l*r+n,a=s[2*l]=Math.cos(i),o=s[2*l+1]=Math.sin(-i);return s},n.getRoundRectangleRadius=function(e,t){return Math.min(e/4,t/4,8)},t.exports=n},{}],80:[function(e,t,r){"use strict";var n=0,i=1,a=2,o=function(e){return this instanceof o?(this.id="Thenable/1.0.7",this.state=n,this.fulfillValue=void 0,this.rejectReason=void 0,this.onFulfilled=[],this.onRejected=[],this.proxy={then:this.then.bind(this)},void("function"==typeof e&&e.call(this,this.fulfill.bind(this),this.reject.bind(this)))):new o(e)};o.prototype={fulfill:function(e){return s(this,i,"fulfillValue",e)},reject:function(e){return s(this,a,"rejectReason",e)},then:function(e,t){var r=this,n=new o;return r.onFulfilled.push(c(e,n,"fulfill")),r.onRejected.push(c(t,n,"reject")),l(r),n.proxy}};var s=function(e,t,r,i){return e.state===n&&(e.state=t,e[r]=i,l(e)),e},l=function(e){e.state===i?u(e,"onFulfilled",e.fulfillValue):e.state===a&&u(e,"onRejected",e.rejectReason)},u=function(e,t,r){if(0!==e[t].length){var n=e[t];e[t]=[];var i=function(){for(var e=0;e<n.length;e++)n[e](r)};"function"==typeof setImmediate?setImmediate(i):setTimeout(i,0)}},c=function(e,t,r){return function(n){if("function"!=typeof e)t[r].call(t,n);else{var i;try{i=e(n)}catch(a){return void t.reject(a)}d(t,i)}}},d=function(e,t){if(e===t||e.proxy===t)return void e.reject(new TypeError("cannot resolve promise with itself"));var r;if("object"==typeof t&&null!==t||"function"==typeof t)try{r=t.then}catch(n){return void e.reject(n)}if("function"!=typeof r)e.fulfill(t);else{var i=!1;try{r.call(t,function(r){i||(i=!0,r===t?e.reject(new TypeError("circular thenable chain")):d(e,r))},function(t){i||(i=!0,e.reject(t))})}catch(n){i||e.reject(n)}}},h="undefined"==typeof h?o:h;h.all=h.all||function(e){return new h(function(t,r){for(var n=new Array(e.length),i=0,a=function(r,a){n[r]=a,i++,i===e.length&&t(n)},o=0;o<e.length;o++)!function(t){var n=e[t],i=null!=n.then;if(i)n.then(function(e){a(t,e)},function(e){r(e)});else{var o=n;a(t,o)}}(o)})},t.exports=h},{}],81:[function(e,t,r){"use strict";var n=e("./is"),i=e("./util"),a=function(e,t){if(!(this instanceof a))return new a(e,t);void 0===t&&void 0!==e&&(t=e,e=void 0);var r=this;if(r._private={selectorText:null,invalid:!0},!t||n.string(t)&&t.match(/^\s*$/))null==e?r.length=0:(r[0]=l(),r[0].group=e,r.length=1);else if(n.elementOrCollection(t)){var o=t.collection();r[0]=l(),r[0].collection=o,r.length=1}else if(n.fn(t))r[0]=l(),r[0].filter=t,r.length=1;else{if(!n.string(t))return void i.error("A selector must be created from a string; found "+t);var s=null,l=function(){return{classes:[],colonSelectors:[],data:[],group:null,ids:[],meta:[],collection:null,filter:null,parent:null,ancestor:null,subject:null,child:null,descendant:null}},u={metaChar:"[\\!\\\"\\#\\$\\%\\&\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\]\\^\\`\\{\\|\\}\\~]",comparatorOp:"=|\\!=|>|>=|<|<=|\\$=|\\^=|\\*=",boolOp:"\\?|\\!|\\^",string:'"(?:\\\\"|[^"])+"|'+"'(?:\\\\'|[^'])+'",number:i.regex.number,meta:"degree|indegree|outdegree",separator:"\\s*,\\s*",descendant:"\\s+",child:"\\s+>\\s+",subject:"\\$"};u.variable="(?:[\\w-]|(?:\\\\"+u.metaChar+"))+",u.value=u.string+"|"+u.number,u.className=u.variable,u.id=u.variable;for(var c=function(e){return e.replace(new RegExp("\\\\("+u.metaChar+")","g"),function(e,t,r,n){return t})},d=u.comparatorOp.split("|"),h=0;h<d.length;h++){var p=d[h];u.comparatorOp+="|@"+p}for(var d=u.comparatorOp.split("|"),h=0;h<d.length;h++){var p=d[h];p.indexOf("!")>=0||"="!==p&&(u.comparatorOp+="|\\!"+p)}var v=[{name:"group",query:!0,regex:"(node|edge|\\*)",populate:function(e){this.group="*"==e?e:e+"s"}},{name:"state",query:!0,regex:"(:selected|:unselected|:locked|:unlocked|:visible|:hidden|:transparent|:grabbed|:free|:removed|:inside|:grabbable|:ungrabbable|:animated|:unanimated|:selectable|:unselectable|:orphan|:nonorphan|:parent|:child|:loop|:simple|:active|:inactive|:touch|:backgrounding|:nonbackgrounding)",populate:function(e){this.colonSelectors.push(e)}},{name:"id",query:!0,regex:"\\#("+u.id+")",populate:function(e){this.ids.push(c(e))}},{name:"className",query:!0,regex:"\\.("+u.className+")",populate:function(e){this.classes.push(c(e))}},{name:"dataExists",query:!0,regex:"\\[\\s*("+u.variable+")\\s*\\]",populate:function(e){this.data.push({field:c(e)})}},{name:"dataCompare",query:!0,regex:"\\[\\s*("+u.variable+")\\s*("+u.comparatorOp+")\\s*("+u.value+")\\s*\\]",populate:function(e,t,r){var n=null!=new RegExp("^"+u.string+"$").exec(r);r=n?r.substring(1,r.length-1):parseFloat(r),this.data.push({field:c(e),operator:t,value:r})}},{name:"dataBool",query:!0,regex:"\\[\\s*("+u.boolOp+")\\s*("+u.variable+")\\s*\\]",populate:function(e,t){this.data.push({field:c(t),operator:e})}},{name:"metaCompare",query:!0,regex:"\\[\\[\\s*("+u.meta+")\\s*("+u.comparatorOp+")\\s*("+u.number+")\\s*\\]\\]",populate:function(e,t,r){this.meta.push({field:c(e),operator:t,value:parseFloat(r)})}},{name:"nextQuery",separator:!0,regex:u.separator,populate:function(){r[++h]=l(),s=null}},{name:"child",separator:!0,regex:u.child,populate:function(){var e=l();e.parent=this,e.subject=s,r[h]=e}},{name:"descendant",separator:!0,regex:u.descendant,populate:function(){var e=l();e.ancestor=this,e.subject=s,r[h]=e}},{name:"subject",modifier:!0,regex:u.subject,populate:function(){return null!=s&&this.subject!=this?(i.error("Redefinition of subject in selector `"+t+"`"),!1):(s=this,void(this.subject=this))}}];r._private.selectorText=t;var f=t,h=0,g=function(e){for(var t,r,i,a=0;a<v.length;a++){var o=v[a],s=o.name;if(!n.fn(e)||e(s,o)){var l=f.match(new RegExp("^"+o.regex));if(null!=l){r=l,t=o,i=s;var u=l[0];f=f.substring(u.length);break}}}return{expr:t,match:r,name:i}},y=function(){var e=f.match(/^\s+/);if(e){var t=e[0];f=f.substring(t.length)}};for(r[0]=l(),y();;){var m=g();if(null==m.expr)return void i.error("The selector `"+t+"`is invalid");for(var b=[],x=1;x<m.match.length;x++)b.push(m.match[x]);var w=m.expr.populate.apply(r[h],b);if(w===!1)return;if(f.match(/^\s*$/))break}r.length=h+1;for(var x=0;x<r.length;x++){var _=r[x];if(null!=_.subject){for(;_.subject!=_;)if(null!=_.parent){var E=_.parent,D=_;D.parent=null,E.child=D,_=E}else{if(null==_.ancestor){i.error("When adjusting references for the selector `"+_+"`, neither parent nor ancestor was found");break}var S=_.ancestor,k=_;k.ancestor=null,S.descendant=k,_=S}r[x]=_.subject}}if(null!=e)for(var x=0;x<r.length;x++){if(null!=r[x].group&&r[x].group!=e)return void i.error("Group `"+r[x].group+"` conflicts with implicit group `"+e+"` in selector `"+t+"`");r[x].group=e}}r._private.invalid=!1},o=a.prototype;o.size=function(){return this.length},o.eq=function(e){return this[e]};var s=function(e,t){if(null!=e.group&&"*"!=e.group&&e.group!=t._private.group)return!1;for(var r=t.cy(),i=!0,a=0;a<e.colonSelectors.length;a++){var o=e.colonSelectors[a];switch(o){case":selected":i=t.selected();break;case":unselected":i=!t.selected();break;case":selectable":i=t.selectable();break;case":unselectable":i=!t.selectable();break;case":locked":i=t.locked();break;case":unlocked":i=!t.locked();break;case":visible":i=t.visible();break;case":hidden":i=!t.visible();break;case":transparent":i=t.transparent();break;case":grabbed":i=t.grabbed();break;case":free":i=!t.grabbed();break;case":removed":i=t.removed();break;case":inside":i=!t.removed();break;case":grabbable":i=t.grabbable();break;case":ungrabbable":i=!t.grabbable();break;case":animated":i=t.animated();break;case":unanimated":i=!t.animated();break;case":parent":i=t.isNode()&&t.children().nonempty();break;case":child":case":nonorphan":i=t.isNode()&&t.parent().nonempty();break;case":orphan":i=t.isNode()&&t.parent().empty();break;case":loop":i=t.isEdge()&&t.data("source")===t.data("target");break;case":simple":i=t.isEdge()&&t.data("source")!==t.data("target");break;case":active":i=t.active();break;case":inactive":i=!t.active();break;case":touch":i=n.touch();break;case":backgrounding":i=t.backgrounding();break;case":nonbackgrounding":i=!t.backgrounding()}if(!i)break}if(!i)return!1;for(var l=!0,a=0;a<e.ids.length;a++){var u=e.ids[a],c=t._private.data.id;if(l=l&&u==c,!l)break}if(!l)return!1;for(var d=!0,a=0;a<e.classes.length;a++){var h=e.classes[a];if(d=d&&t.hasClass(h),!d)break}if(!d)return!1;var p=function(t){for(var r=!0,i=0;i<e[t.name].length;i++){var a,o=e[t.name][i],s=o.operator,l=o.value,u=o.field;if(null!=s&&null!=l){var c=t.fieldValue(u),d=n.string(c)||n.number(c)?""+c:"",h=""+l,p=!1;s.indexOf("@")>=0&&(d=d.toLowerCase(),h=h.toLowerCase(),s=s.replace("@",""),p=!0);var v=!1,f=!1;switch(s.indexOf("!")>=0&&(s=s.replace("!",""),v=!0),p&&(l=h.toLowerCase(),c=d.toLowerCase()),s){case"*=":a=d.search(h)>=0;break;case"$=":a=null!=new RegExp(h+"$").exec(d);break;case"^=":a=null!=new RegExp("^"+h).exec(d);break;case"=":a=c===l;break;case"!=":a=c!==l;break;case">":a=v?l>=c:c>l,f=!0;break;case">=":a=v?l>c:c>=l,f=!0;break;case"<":a=v?c>=l:l>c,f=!0;break;case"<=":a=v?c>l:l>=c,f=!0;break;default:a=!1}}else if(null!=s)switch(s){case"?":a=t.fieldTruthy(u);break;case"!":a=!t.fieldTruthy(u);break;case"^":a=t.fieldUndefined(u)}else a=!t.fieldUndefined(u);if(v&&!f&&(a=!a,f=!0),!a){r=!1;break}}return r},v=p({name:"data",fieldValue:function(e){return t._private.data[e]},fieldRef:function(e){return"element._private.data."+e},fieldUndefined:function(e){return void 0===t._private.data[e]},fieldTruthy:function(e){return t._private.data[e]?!0:!1}});if(!v)return!1;var f=p({name:"meta",fieldValue:function(e){return t[e]()},fieldRef:function(e){return"element."+e+"()"},fieldUndefined:function(e){return null==t[e]()},fieldTruthy:function(e){return t[e]()?!0:!1}});if(!f)return!1;if(null!=e.collection){var g=null!=e.collection._private.ids[t.id()];if(!g)return!1}if(null!=e.filter&&0===t.collection().filter(e.filter).size())return!1;var y=function(e,t){if(null!=e){var n=!1;if(!r.hasCompoundNodes())return!1;t=t();for(var i=0;i<t.length;i++)if(s(e,t[i])){n=!0;break}return n}return!0};return y(e.parent,function(){return t.parent()})&&y(e.ancestor,function(){return t.parents()})&&y(e.child,function(){return t.children()})&&y(e.descendant,function(){return t.descendants()})?!0:!1};o.filter=function(e){var t=this,r=e.cy();if(t._private.invalid)return r.collection();var n=function(e,r){for(var n=0;n<t.length;n++){var i=t[n];if(s(i,r))return!0}return!1};null==t._private.selectorText&&(n=function(){return!0});var i=e.filter(n);return i},o.matches=function(e){var t=this;if(t._private.invalid)return!1;for(var r=0;r<t.length;r++){var n=t[r];if(s(n,e))return!0}return!1},o.toString=o.selector=function(){for(var e="",t=function(e,t){return n.string(e)?t?'"'+e+'"':e:""},r=function(e){var n="";e.subject===e&&(n+="$");var a=t(e.group);n+=a.substring(0,a.length-1);for(var o=0;o<e.data.length;o++){var s=e.data[o];n+=s.value?"["+s.field+t(s.operator)+t(s.value,!0)+"]":"["+t(s.operator)+s.field+"]"}for(var o=0;o<e.meta.length;o++){var l=e.meta[o];n+="[["+l.field+t(l.operator)+t(l.value,!0)+"]]"}for(var o=0;o<e.colonSelectors.length;o++){var u=e.colonSelectors[i];n+=u}for(var o=0;o<e.ids.length;o++){var u="#"+e.ids[i];n+=u}for(var o=0;o<e.classes.length;o++){var u="."+e.classes[o];n+=u}return null!=e.parent&&(n=r(e.parent)+" > "+n),null!=e.ancestor&&(n=r(e.ancestor)+" "+n),null!=e.child&&(n+=" > "+r(e.child)),null!=e.descendant&&(n+=" "+r(e.descendant)),n},i=0;i<this.length;i++){var a=this[i];e+=r(a),this.length>1&&i<this.length-1&&(e+=", ")}return e},t.exports=a},{"./is":77,"./util":94}],82:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a={};a.apply=function(e){var t=this;t._private.newStyle&&(this._private.contextStyles={},this._private.propDiffs={});for(var r=0;r<e.length;r++){var n=e[r],i=t.getContextMeta(n),a=t.getContextStyle(i),o=t.applyContextStyle(i,a,n);
+t.updateTransitions(n,o.diffProps),t.updateStyleHints(n)}t._private.newStyle=!1},a.getPropertiesDiff=function(e,t){var r=this,n=r._private.propDiffs=r._private.propDiffs||{},i=e+"-"+t,a=n[i];if(a)return a;for(var o=[],s={},l=0;l<r.length;l++){var u=r[l],c="t"===e[l],d="t"===t[l],h=c!==d,p=u.mappedProperties.length>0;if(h||p){var v;h&&p?v=u.properties:h?v=u.properties:p&&(v=u.mappedProperties);for(var f=0;f<v.length;f++){for(var g=v[f],y=g.name,m=!1,b=l+1;b<r.length;b++){var x=r[b],w="t"===t[b];if(w&&(m=null!=x.properties[g.name]))break}s[y]||m||(s[y]=!0,o.push(y))}}}return n[i]=o,o},a.getContextMeta=function(e){var t,r=this,n="",i=e._private.styleCxtKey||"";r._private.newStyle&&(i="");for(var a=0;a<r.length;a++){var o=r[a],s=o.selector&&o.selector.matches(e);n+=s?"t":"f"}return t=r.getPropertiesDiff(i,n),e._private.styleCxtKey=n,{key:n,diffPropNames:t}},a.getContextStyle=function(e){var t=e.key,r=this,n=this._private.contextStyles=this._private.contextStyles||{};if(n[t])return n[t];for(var i={_private:{key:t}},a=0;a<r.length;a++){var o=r[a],s="t"===t[a];if(s)for(var l=0;l<o.properties.length;l++){var u=o.properties[l],c=i[u.name]=u;c.context=o}}return n[t]=i,i},a.applyContextStyle=function(e,t,r){for(var n=this,i=e.diffPropNames,a={},o=0;o<i.length;o++){var s=i[o],l=t[s],u=r._private.style[s];if(l&&u!==l){var c=a[s]={prev:u};n.applyParsedProperty(r,l),c.next=r._private.style[s],c.next&&c.next.bypass&&(c.next=c.next.bypassed)}}return{diffProps:a}},a.updateStyleHints=function(e){var t=e._private,r=this,n=t.style;if(!e.removed()){var i=!1;if("nodes"===t.group&&r._private.hasPie)for(var a=1;a<=r.pieBackgroundN;a++){var o=t.style["pie-"+a+"-background-size"].value;if(o>0){i=!0;break}}t.hasPie=i;var s=n["text-transform"].strValue,l=n.label.strValue,u=n["font-style"].strValue,o=n["font-size"].pfValue+"px",c=n["font-family"].strValue,d=n["font-weight"].strValue,h=n["text-valign"].strValue,p=n["text-valign"].strValue,v=n["text-outline-width"].pfValue,f=n["text-wrap"].strValue,g=n["text-max-width"].pfValue;t.labelKey=u+"$"+o+"$"+c+"$"+d+"$"+l+"$"+s+"$"+h+"$"+p+"$"+v+"$"+f+"$"+g,t.fontKey=u+"$"+d+"$"+o+"$"+c;var y=n.width.pfValue,m=n.height.pfValue,b=n["border-width"].pfValue;if(t.boundingBoxKey=y+"$"+m+"$"+b,"edges"===e._private.group){var x=n["control-point-step-size"].pfValue,w=n["control-point-distances"]?n["control-point-distances"].pfValue.join("_"):void 0,_=n["control-point-weights"].value.join("_"),E=n["curve-style"].strValue;t.boundingBoxKey+="$"+x+"$"+w+"$"+_+"$"+E}t.styleKey=Date.now()}},a.applyParsedProperty=function(e,t){var r,a,o=this,s=t,l=e._private.style,u=o.types,c=o.properties[s.name].type,d=s.bypass,h=l[s.name],p=h&&h.bypass,v=e._private;if(("height"===t.name||"width"===t.name)&&e.isNode()){if("auto"===t.value&&!e.isParent())return!1;"auto"!==t.value&&e.isParent()&&(s=t=this.parse(t.name,"auto",d))}if(d&&s.deleteBypass){var f=l[s.name];return f?f.bypass&&f.bypassed?(l[s.name]=f.bypassed,!0):!1:!0}var g=function(){n.error("Do not assign mappings to elements without corresponding data (e.g. ele `"+e.id()+"` for property `"+s.name+"` with data field `"+s.field+"`); try a `["+s.field+"]` selector to limit scope to elements with `"+s.field+"` defined")};switch(s.mapped){case u.mapData:case u.mapLayoutData:case u.mapScratch:var r,y=s.mapped===u.mapLayoutData,m=s.mapped===u.mapScratch,b=s.field.split(".");r=m||y?v.scratch:v.data;for(var x=0;x<b.length&&r;x++){var w=b[x];r=r[w]}var _;if(_=i.number(r)?(r-s.fieldMin)/(s.fieldMax-s.fieldMin):0,0>_?_=0:_>1&&(_=1),c.color){var E=s.valueMin[0],D=s.valueMax[0],S=s.valueMin[1],k=s.valueMax[1],T=s.valueMin[2],P=s.valueMax[2],C=null==s.valueMin[3]?1:s.valueMin[3],N=null==s.valueMax[3]?1:s.valueMax[3],M=[Math.round(E+(D-E)*_),Math.round(S+(k-S)*_),Math.round(T+(P-T)*_),Math.round(C+(N-C)*_)];a={bypass:s.bypass,name:s.name,value:M,strValue:"rgb("+M[0]+", "+M[1]+", "+M[2]+")"}}else{if(!c.number)return!1;var B=s.valueMin+(s.valueMax-s.valueMin)*_;a=this.parse(s.name,B,s.bypass,!0)}a||(a=this.parse(s.name,h.strValue,s.bypass,!0)),a||g(),a.mapping=s,s=a;break;case u.data:case u.layoutData:case u.scratch:var r,y=s.mapped===u.layoutData,m=s.mapped===u.scratch,b=s.field.split(".");if(r=m||y?v.scratch:v.data)for(var x=0;x<b.length;x++){var w=b[x];r=r[w]}if(a=this.parse(s.name,r,s.bypass,!0),!a){var z=h?h.strValue:"";a=this.parse(s.name,z,s.bypass,!0)}a||g(),a.mapping=s,s=a;break;case u.fn:var O=s.value,I=O(e);a=this.parse(s.name,I,s.bypass,!0),a.mapping=s,s=a;break;case void 0:break;default:return!1}return d?(p?s.bypassed=h.bypassed:s.bypassed=h,l[s.name]=s):p?h.bypassed=s:l[s.name]=s,!0},a.update=function(){var e=this._private.cy,t=e.elements();t.updateStyle()},a.updateMappers=function(e){for(var t=this,r=0;r<e.length;r++){for(var n=e[r],i=n._private.style,a=0;a<t.properties.length;a++){var o=t.properties[a],s=i[o.name];if(s&&s.mapping){var l=s.mapping;this.applyParsedProperty(n,l)}}this.updateStyleHints(n)}},a.updateTransitions=function(e,t,r){var n=this,a=e._private,o=a.style,s=o["transition-property"].value,l=o["transition-duration"].pfValue,u=o["transition-delay"].pfValue,c={};if(s.length>0&&l>0){for(var d=!1,h=0;h<s.length;h++){var p=s[h],v=o[p],f=t[p];if(f){var g,y=f.prev,m=y,b=null!=f.next?f.next:v,x=!1,w=1e-6;m&&(i.number(m.pfValue)&&i.number(b.pfValue)?(x=b.pfValue-m.pfValue,g=m.pfValue+w*x):i.number(m.value)&&i.number(b.value)?(x=b.value-m.value,g=m.value+w*x):i.array(m.value)&&i.array(b.value)&&(x=m.value[0]!==b.value[0]||m.value[1]!==b.value[1]||m.value[2]!==b.value[2],g=m.strValue),x&&(c[p]=b.strValue,this.applyBypass(e,p,g),d=!0))}}if(!d)return;a.transitioning=!0,e.stop(),u>0&&e.delay(u),e.animate({css:c},{duration:l,easing:o["transition-timing-function"].value,queue:!1,complete:function(){r||n.removeBypasses(e,s),a.transitioning=!1}})}else a.transitioning&&(e.stop(),this.removeBypasses(e,s),a.transitioning=!1)},t.exports=a},{"../is":77,"../util":94}],83:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a={};a.applyBypass=function(e,t,r,a){var o=this,s=[],l=!0;if("*"===t||"**"===t){if(void 0!==r)for(var u=0;u<o.properties.length;u++){var c=o.properties[u],t=c.name,d=this.parse(t,r,!0);d&&s.push(d)}}else if(n.string(t)){var d=this.parse(t,r,!0);d&&s.push(d)}else{if(!n.plainObject(t))return!1;var h=t;a=r;for(var u=0;u<o.properties.length;u++){var c=o.properties[u],t=c.name,r=h[t];if(void 0===r&&(r=h[i.dash2camel(t)]),void 0!==r){var d=this.parse(t,r,!0);d&&s.push(d)}}}if(0===s.length)return!1;for(var p=!1,u=0;u<e.length;u++){for(var v,f=e[u],g=f._private.style,y={},m=0;m<s.length;m++){var c=s[m];if(a){var b=g[c.name];v=y[c.name]={prev:b}}p=this.applyParsedProperty(f,c)||p,a&&(v.next=g[c.name])}p&&this.updateStyleHints(f),a&&this.updateTransitions(f,y,l)}return p},a.overrideBypass=function(e,t,r){t=i.camel2dash(t);for(var n=0;n<e.length;n++){var a=e[n],o=a._private.style[t],s=this.properties[t].type,l=s.color,u=s.mutiple;o.bypass?(o.value=r,null!=o.pfValue&&(o.pfValue=r),l?o.strValue="rgb("+r.join(",")+")":u?o.strValue=r.join(" "):o.strValue=""+r):this.applyBypass(a,t,r)}},a.removeAllBypasses=function(e,t){return this.removeBypasses(e,this.propertyNames,t)},a.removeBypasses=function(e,t,r){for(var n=!0,i=0;i<e.length;i++){for(var a=e[i],o={},s=a._private.style,l=0;l<t.length;l++){var u=t[l],c=this.properties[u],d="",h=this.parse(u,d,!0),p=s[c.name],v=o[c.name]={prev:p};this.applyParsedProperty(a,h),v.next=s[c.name]}this.updateStyleHints(a),r&&this.updateTransitions(a,o,n)}},t.exports=a},{"../is":77,"../util":94}],84:[function(e,t,r){"use strict";var n=e("../window"),i={};i.getEmSizeInPixels=function(){var e=this.containerCss("font-size");return null!=e?parseFloat(e):1},i.containerCss=function(e){var t=this._private.cy,r=t.container();return n&&r&&n.getComputedStyle?n.getComputedStyle(r).getPropertyValue(e):void 0},t.exports=i},{"../window":100}],85:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a={};a.getRenderedStyle=function(e){return this.getRawStyle(e,!0)},a.getRawStyle=function(e,t){var r=this,e=e[0];if(e){for(var i={},a=0;a<r.properties.length;a++){var o=r.properties[a],s=r.getStylePropertyValue(e,o.name,t);s&&(i[o.name]=s,i[n.dash2camel(o.name)]=s)}return i}},a.getStylePropertyValue=function(e,t,r){var n=this,e=e[0];if(e){var i=e._private.style,a=n.properties[t],o=a.type,s=i[a.name],l=e.cy().zoom();if(s){var u=s.units?o.implicitUnits||"px":null,c=u?[].concat(s.pfValue).map(function(e){return e*(r?l:1)+u}).join(" "):s.strValue;return c}}},a.getValueStyle=function(e){var t,r=this,a={},o=i.element(e);if(t=o?e._private.style:e)for(var s=0;s<r.properties.length;s++){var l=r.properties[s],u=t[l.name]||t[n.dash2camel(l.name)];void 0!==u&&(u=i.plainObject(u)?this.parse(l.name,u.strValue):this.parse(l.name,u)),u&&(a[l.name]=u,a[n.dash2camel(l.name)]=u)}return a},a.getPropsList=function(e){var t=this,r=[],i=e,a=t.properties;if(i)for(var o in i){var s=i[o],l=a[o]||a[n.camel2dash(o)],u=this.parse(l.name,s);r.push(u)}return r},t.exports=a},{"../is":77,"../util":94}],86:[function(e,t,r){"use strict";var n=e("../is"),i=e("../util"),a=e("../selector"),o=function(e){return this instanceof o?n.core(e)?(this._private={cy:e,coreStyle:{},newStyle:!0},this.length=0,void this.addDefaultStylesheet()):void i.error("A style must have a core reference"):new o(e)},s=o.prototype;s.instanceString=function(){return"style"},s.clear=function(){for(var e=0;e<this.length;e++)this[e]=void 0;return this.length=0,this._private.newStyle=!0,this},s.resetToDefault=function(){return this.clear(),this.addDefaultStylesheet(),this},s.core=function(){return this._private.coreStyle},s.selector=function(e){var t="core"===e?null:new a(e),r=this.length++;return this[r]={selector:t,properties:[],mappedProperties:[],index:r},this},s.css=function(){var e=this,t=arguments;switch(t.length){case 1:for(var r=t[0],n=0;n<e.properties.length;n++){var a=e.properties[n],o=r[a.name];void 0===o&&(o=r[i.dash2camel(a.name)]),void 0!==o&&this.cssRule(a.name,o)}break;case 2:this.cssRule(t[0],t[1])}return this},s.style=s.css,s.cssRule=function(e,t){var r=this.parse(e,t);if(r){var n=this.length-1;this[n].properties.push(r),this[n].properties[r.name]=r,r.name.match(/pie-(\d+)-background-size/)&&r.value&&(this._private.hasPie=!0),r.mapped&&this[n].mappedProperties.push(r);var i=!this[n].selector;i&&(this._private.coreStyle[r.name]=r)}return this},o.fromJson=function(e,t){var r=new o(e);return r.fromJson(t),r},o.fromString=function(e,t){return new o(e).fromString(t)},[e("./apply"),e("./bypass"),e("./container"),e("./get-for-ele"),e("./json"),e("./string-sheet"),e("./properties"),e("./parse")].forEach(function(e){i.extend(s,e)}),o.types=s.types,o.properties=s.properties,t.exports=o},{"../is":77,"../selector":81,"../util":94,"./apply":82,"./bypass":83,"./container":84,"./get-for-ele":85,"./json":87,"./parse":88,"./properties":89,"./string-sheet":90}],87:[function(e,t,r){"use strict";var n={};n.applyFromJson=function(e){for(var t=this,r=0;r<e.length;r++){var n=e[r],i=n.selector,a=n.style||n.css;t.selector(i);for(var o in a){var s=a[o];t.css(o,s)}}return t},n.fromJson=function(e){var t=this;return t.resetToDefault(),t.applyFromJson(e),t},n.json=function(){for(var e=[],t=this.defaultLength;t<this.length;t++){for(var r=this[t],n=r.selector,i=r.properties,a={},o=0;o<i.length;o++){var s=i[o];a[s.name]=s.strValue}e.push({selector:n?n.toString():"core",style:a})}return e},t.exports=n},{}],88:[function(e,t,r){"use strict";var n=e("../util"),i=e("../is"),a={};a.parse=function(e,t,r,i){var a,s=[e,t,r,i].join("$"),l=this.propCache=this.propCache||{},u=o.bind(this);return(a=l[s])||(a=l[s]=u(e,t,r,i)),a=n.copy(a),a&&(a.value=n.copy(a.value)),a};var o=function(e,t,r,a){var o=this;e=n.camel2dash(e);var s=o.properties[e],l=t,u=o.types;if(!s)return null;if(void 0===t||null===t)return null;s.alias&&(s=s.pointsTo,e=s.name);var c=i.string(t);c&&(t=t.trim());var d=s.type;if(!d)return null;if(r&&(""===t||null===t))return{name:e,value:t,bypass:!0,deleteBypass:!0};if(i.fn(t))return{name:e,value:t,strValue:"fn",mapped:u.fn,bypass:r};var h,p,v,f,g,y;if(!c||a);else{if((h=new RegExp(u.data.regex).exec(t))||(v=new RegExp(u.layoutData.regex).exec(t))||(g=new RegExp(u.scratch.regex).exec(t))){if(r)return!1;var m;return m=h?u.data:v?u.layoutData:u.scratch,h=h||v||g,{name:e,value:h,strValue:""+t,mapped:m,field:h[1],bypass:r}}if((p=new RegExp(u.mapData.regex).exec(t))||(f=new RegExp(u.mapLayoutData.regex).exec(t))||(y=new RegExp(u.mapScratch.regex).exec(t))){if(r)return!1;if(d.multiple)return!1;var m;if(m=p?u.mapData:f?u.mapLayoutData:u.mapScratch,p=p||f||y,!d.color&&!d.number)return!1;var b=this.parse(e,p[4]);if(!b||b.mapped)return!1;var x=this.parse(e,p[5]);if(!x||x.mapped)return!1;if(b.value===x.value)return!1;if(d.color){var w=b.value,_=x.value,E=!(w[0]!==_[0]||w[1]!==_[1]||w[2]!==_[2]||w[3]!==_[3]&&(null!=w[3]&&1!==w[3]||null!=_[3]&&1!==_[3]));if(E)return!1}return{name:e,value:p,strValue:""+t,mapped:m,field:p[1],fieldMin:parseFloat(p[2]),fieldMax:parseFloat(p[3]),valueMin:b.value,valueMax:x.value,bypass:r}}}if(d.multiple&&!a){var D;if(D=c?t.split(/\s+/):i.array(t)?t:[t],d.evenMultiple&&D.length%2!==0)return null;var S=D.map(function(t){var n=o.parse(e,t,r,!0);return null!=n.pfValue?n.pfValue:n.value});return{name:e,value:S,pfValue:S,strValue:S.join(" "),bypass:r,units:d.number&&!d.unitless?d.implicitUnits||"px":void 0}}var k=function(){for(var n=0;n<d.enums.length;n++){var i=d.enums[n];if(i===t)return{name:e,value:t,strValue:""+t,bypass:r}}return null};if(d.number){var T,P="px";if(d.units&&(T=d.units),d.implicitUnits&&(P=d.implicitUnits),!d.unitless)if(c){var C="px|em"+(d.allowPercent?"|\\%":"");T&&(C=T);var N=t.match("^("+n.regex.number+")("+C+")?$");N&&(t=N[1],T=N[2]||P)}else(!T||d.implicitUnits)&&(T=P);if(t=parseFloat(t),isNaN(t)&&void 0===d.enums)return null;if(isNaN(t)&&void 0!==d.enums)return t=l,k();if(d.integer&&!i.integer(t))return null;if(void 0!==d.min&&t<d.min||void 0!==d.max&&t>d.max)return null;var M={name:e,value:t,strValue:""+t+(T?T:""),units:T,bypass:r};return d.unitless||"px"!==T&&"em"!==T?M.pfValue=t:M.pfValue="px"!==T&&T?this.getEmSizeInPixels()*t:t,("ms"===T||"s"===T)&&(M.pfValue="ms"===T?t:1e3*t),("deg"===T||"rad"===T)&&(M.pfValue="rad"===T?t:t*Math.PI/180),M}if(d.propList){var B=[],z=""+t;if("none"===z);else{for(var O=z.split(","),I=0;I<O.length;I++){var L=O[I].trim();o.properties[L]&&B.push(L)}if(0===B.length)return null}return{name:e,value:B,strValue:0===B.length?"none":B.join(", "),bypass:r}}if(d.color){var A=n.color2tuple(t);return A?{name:e,value:A,strValue:""+t,bypass:r,roundValue:!0}:null}if(d.regex||d.regexes){if(d.enums){var R=k();if(R)return R}for(var V=d.regexes?d.regexes:[d.regex],I=0;I<V.length;I++){var F=new RegExp(V[I]),j=F.exec(t);if(j)return{name:e,value:j,strValue:""+t,bypass:r}}return null}return d.string?{name:e,value:t,strValue:""+t,bypass:r}:d.enums?k():null};t.exports=a},{"../is":77,"../util":94}],89:[function(e,t,r){"use strict";var n=e("../util"),i={};!function(){var e=n.regex.number,t=n.regex.rgbaNoBackRefs,r=n.regex.hslaNoBackRefs,a=n.regex.hex3,o=n.regex.hex6,s=function(e){return"^"+e+"\\s*\\(\\s*([\\w\\.]+)\\s*\\)$"},l=function(n){var i=e+"|\\w+|"+t+"|"+r+"|"+a+"|"+o;return"^"+n+"\\s*\\(([\\w\\.]+)\\s*\\,\\s*("+e+")\\s*\\,\\s*("+e+")\\s*,\\s*("+i+")\\s*\\,\\s*("+i+")\\)$"};i.types={time:{number:!0,min:0,units:"s|ms",implicitUnits:"ms"},percent:{number:!0,min:0,max:100,units:"%",implicitUnits:"%"},zeroOneNumber:{number:!0,min:0,max:1,unitless:!0},nOneOneNumber:{number:!0,min:-1,max:1,unitless:!0},nonNegativeInt:{number:!0,min:0,integer:!0,unitless:!0},position:{enums:["parent","origin"]},nodeSize:{number:!0,min:0,enums:["auto","label"]},number:{number:!0,unitless:!0},numbers:{number:!0,unitless:!0,multiple:!0},size:{number:!0,min:0},bidirectionalSize:{number:!0},bidirectionalSizes:{number:!0,multiple:!0},bgSize:{number:!0,min:0,allowPercent:!0},bgWH:{number:!0,min:0,allowPercent:!0,enums:["auto"]},bgPos:{number:!0,allowPercent:!0},bgRepeat:{enums:["repeat","repeat-x","repeat-y","no-repeat"]},bgFit:{enums:["none","contain","cover"]},bgClip:{enums:["none","node"]},color:{color:!0},bool:{enums:["yes","no"]},lineStyle:{enums:["solid","dotted","dashed"]},borderStyle:{enums:["solid","dotted","dashed","double"]},curveStyle:{enums:["bezier","unbundled-bezier","haystack","segments"]},fontFamily:{regex:'^([\\w- \\"]+(?:\\s*,\\s*[\\w- \\"]+)*)$'},fontVariant:{enums:["small-caps","normal"]},fontStyle:{enums:["italic","normal","oblique"]},fontWeight:{enums:["normal","bold","bolder","lighter","100","200","300","400","500","600","800","900",100,200,300,400,500,600,700,800,900]},textDecoration:{enums:["none","underline","overline","line-through"]},textTransform:{enums:["none","uppercase","lowercase"]},textWrap:{enums:["none","wrap"]},textBackgroundShape:{enums:["rectangle","roundrectangle"]},nodeShape:{enums:["rectangle","roundrectangle","ellipse","triangle","square","pentagon","hexagon","heptagon","octagon","star","diamond","vee","rhomboid","polygon"]},compoundIncludeLabels:{enums:["include","exclude"]},arrowShape:{enums:["tee","triangle","triangle-tee","triangle-backcurve","half-triangle-overshot","vee","square","circle","diamond","none"]},arrowFill:{enums:["filled","hollow"]},display:{enums:["element","none"]},visibility:{enums:["hidden","visible"]},valign:{enums:["top","center","bottom"]},halign:{enums:["left","center","right"]},text:{string:!0},data:{mapping:!0,regex:s("data")},layoutData:{mapping:!0,regex:s("layoutData")},scratch:{mapping:!0,regex:s("scratch")},mapData:{mapping:!0,regex:l("mapData")},mapLayoutData:{mapping:!0,regex:l("mapLayoutData")},mapScratch:{mapping:!0,regex:l("mapScratch")},fn:{mapping:!0,fn:!0},url:{regex:"^url\\s*\\(\\s*([^\\s]+)\\s*\\s*\\)|none|(.+)$"},propList:{propList:!0},angle:{number:!0,units:"deg|rad",implicitUnits:"rad"},textRotation:{enums:["none","autorotate"]},polygonPointList:{number:!0,multiple:!0,evenMultiple:!0,min:-1,max:1,unitless:!0},easing:{regexes:["^(spring)\\s*\\(\\s*("+e+")\\s*,\\s*("+e+")\\s*\\)$","^(cubic-bezier)\\s*\\(\\s*("+e+")\\s*,\\s*("+e+")\\s*,\\s*("+e+")\\s*,\\s*("+e+")\\s*\\)$"],enums:["linear","ease","ease-in","ease-out","ease-in-out","ease-in-sine","ease-out-sine","ease-in-out-sine","ease-in-quad","ease-out-quad","ease-in-out-quad","ease-in-cubic","ease-out-cubic","ease-in-out-cubic","ease-in-quart","ease-out-quart","ease-in-out-quart","ease-in-quint","ease-out-quint","ease-in-out-quint","ease-in-expo","ease-out-expo","ease-in-out-expo","ease-in-circ","ease-out-circ","ease-in-out-circ"]}};var u=i.types,c=i.properties=[{name:"text-valign",type:u.valign},{name:"text-halign",type:u.halign},{name:"color",type:u.color},{name:"label",type:u.text},{name:"text-outline-color",type:u.color},{name:"text-outline-width",type:u.size},{name:"text-outline-opacity",type:u.zeroOneNumber},{name:"text-opacity",type:u.zeroOneNumber},{name:"text-background-color",type:u.color},{name:"text-background-opacity",type:u.zeroOneNumber},{name:"text-border-opacity",type:u.zeroOneNumber},{name:"text-border-color",type:u.color},{name:"text-border-width",type:u.size},{name:"text-border-style",type:u.borderStyle},{name:"text-background-shape",type:u.textBackgroundShape},{name:"text-transform",type:u.textTransform},{name:"text-wrap",type:u.textWrap},{name:"text-max-width",type:u.size},{name:"text-events",type:u.bool},{name:"font-family",type:u.fontFamily},{name:"font-style",type:u.fontStyle},{name:"font-weight",type:u.fontWeight},{name:"font-size",type:u.size},{name:"min-zoomed-font-size",type:u.size},{name:"edge-text-rotation",type:u.textRotation},{name:"events",type:u.bool},{name:"display",type:u.display},{name:"visibility",type:u.visibility},{name:"opacity",type:u.zeroOneNumber},{name:"z-index",type:u.nonNegativeInt},{name:"overlay-padding",type:u.size},{name:"overlay-color",type:u.color},{name:"overlay-opacity",type:u.zeroOneNumber},{name:"shadow-blur",type:u.size},{name:"shadow-color",type:u.color},{name:"shadow-opacity",type:u.zeroOneNumber},{name:"shadow-offset-x",type:u.bidirectionalSize},{name:"shadow-offset-y",type:u.bidirectionalSize},{name:"text-shadow-blur",type:u.size},{name:"text-shadow-color",type:u.color},{name:"text-shadow-opacity",type:u.zeroOneNumber},{name:"text-shadow-offset-x",type:u.bidirectionalSize},{name:"text-shadow-offset-y",type:u.bidirectionalSize},{name:"transition-property",type:u.propList},{name:"transition-duration",type:u.time},{name:"transition-delay",type:u.time},{name:"transition-timing-function",type:u.easing},{name:"height",type:u.nodeSize},{name:"width",type:u.nodeSize},{name:"shape",type:u.nodeShape},{name:"shape-polygon-points",type:u.polygonPointList},{name:"background-color",type:u.color},{name:"background-opacity",type:u.zeroOneNumber},{name:"background-blacken",type:u.nOneOneNumber},{name:"padding-left",type:u.size},{name:"padding-right",type:u.size},{name:"padding-top",type:u.size},{name:"padding-bottom",type:u.size},{name:"border-color",type:u.color},{name:"border-opacity",type:u.zeroOneNumber},{name:"border-width",type:u.size},{name:"border-style",type:u.borderStyle},{name:"background-image",type:u.url},{name:"background-image-opacity",type:u.zeroOneNumber},{name:"background-position-x",type:u.bgPos},{name:"background-position-y",type:u.bgPos},{name:"background-repeat",type:u.bgRepeat},{name:"background-fit",type:u.bgFit},{name:"background-clip",type:u.bgClip},{name:"background-width",type:u.bgWH},{name:"background-height",type:u.bgWH},{name:"position",type:u.position},{name:"compound-sizing-wrt-labels",type:u.compoundIncludeLabels},{name:"line-style",type:u.lineStyle},{name:"line-color",type:u.color},{name:"curve-style",type:u.curveStyle},{name:"haystack-radius",type:u.zeroOneNumber},{name:"control-point-step-size",type:u.size},{name:"control-point-distances",type:u.bidirectionalSizes},{name:"control-point-weights",type:u.numbers},{name:"segment-distances",type:u.bidirectionalSizes},{name:"segment-weights",type:u.numbers},{name:"selection-box-color",type:u.color},{name:"selection-box-opacity",type:u.zeroOneNumber},{name:"selection-box-border-color",type:u.color},{name:"selection-box-border-width",type:u.size},{name:"active-bg-color",type:u.color},{name:"active-bg-opacity",type:u.zeroOneNumber},{name:"active-bg-size",type:u.size},{name:"outside-texture-bg-color",type:u.color},{name:"outside-texture-bg-opacity",type:u.zeroOneNumber}],d=i.aliases=[{name:"content",pointsTo:"label"},{name:"control-point-distance",pointsTo:"control-point-distances"},{name:"control-point-weight",pointsTo:"control-point-weights"}];i.pieBackgroundN=16,c.push({name:"pie-size",type:u.bgSize});for(var h=1;h<=i.pieBackgroundN;h++)c.push({name:"pie-"+h+"-background-color",type:u.color}),c.push({name:"pie-"+h+"-background-size",type:u.percent}),c.push({name:"pie-"+h+"-background-opacity",type:u.zeroOneNumber});var p=i.arrowPrefixes=["source","mid-source","target","mid-target"];[{name:"arrow-shape",type:u.arrowShape},{name:"arrow-color",type:u.color},{name:"arrow-fill",type:u.arrowFill}].forEach(function(e){p.forEach(function(t){var r=t+"-"+e.name,n=e.type;c.push({name:r,type:n})})},{}),i.propertyNames=c.map(function(e){return e.name});for(var h=0;h<c.length;h++){var v=c[h];c[v.name]=v}for(var h=0;h<d.length;h++){var f=d[h],g=c[f.pointsTo],y={name:f.name,alias:!0,pointsTo:g};c.push(y),c[f.name]=y}}(),i.addDefaultStylesheet=function(){this.selector("node, edge").css(n.extend({events:"yes","text-events":"no","text-valign":"top","text-halign":"center",color:"#000","text-outline-color":"#000","text-outline-width":0,"text-outline-opacity":1,"text-opacity":1,"text-decoration":"none","text-transform":"none","text-wrap":"none","text-max-width":9999,"text-background-color":"#000","text-background-opacity":0,"text-border-opacity":0,"text-border-width":0,"text-border-style":"solid","text-border-color":"#000","text-background-shape":"rectangle","font-family":"Helvetica Neue, Helvetica, sans-serif","font-style":"normal","font-weight":"normal","font-size":16,"min-zoomed-font-size":0,"edge-text-rotation":"none",visibility:"visible",display:"element",opacity:1,"z-index":0,label:"","overlay-opacity":0,"overlay-color":"#000","overlay-padding":10,"shadow-opacity":0,"shadow-color":"#000","shadow-blur":10,"shadow-offset-x":0,"shadow-offset-y":0,"text-shadow-opacity":0,"text-shadow-color":"#000","text-shadow-blur":5,"text-shadow-offset-x":0,"text-shadow-offset-y":0,"transition-property":"none","transition-duration":0,"transition-delay":0,"transition-timing-function":"linear","background-blacken":0,"background-color":"#888","background-opacity":1,"background-image":"none","background-image-opacity":1,"background-position-x":"50%","background-position-y":"50%","background-repeat":"no-repeat","background-fit":"none","background-clip":"node","background-width":"auto","background-height":"auto","border-color":"#000","border-opacity":1,"border-width":0,"border-style":"solid",height:30,width:30,shape:"ellipse","shape-polygon-points":"-1, -1, 1, -1, 1, 1, -1, 1","padding-top":0,"padding-bottom":0,"padding-left":0,"padding-right":0,position:"origin","compound-sizing-wrt-labels":"include"},{"pie-size":"100%"},[{name:"pie-{{i}}-background-color",value:"black"},{name:"pie-{{i}}-background-size",value:"0%"},{name:"pie-{{i}}-background-opacity",value:1}].reduce(function(e,t){for(var r=1;r<=i.pieBackgroundN;r++){var n=t.name.replace("{{i}}",r),a=t.value;e[n]=a}return e},{}),{"line-style":"solid","line-color":"#ddd","control-point-step-size":40,"control-point-weights":.5,"segment-weights":.25,"segment-distances":20,"curve-style":"bezier","haystack-radius":.8},[{name:"arrow-shape",value:"none"},{name:"arrow-color",value:"#ddd"},{name:"arrow-fill",value:"filled"}].reduce(function(e,t){return i.arrowPrefixes.forEach(function(r){var n=r+"-"+t.name,i=t.value;e[n]=i}),e},{}))).selector("$node > node").css({width:"auto",height:"auto",shape:"rectangle","padding-top":10,"padding-right":10,"padding-left":10,"padding-bottom":10}).selector("edge").css({width:1}).selector(":active").css({"overlay-color":"black","overlay-padding":10,"overlay-opacity":.25}).selector("core").css({"selection-box-color":"#ddd","selection-box-opacity":.65,"selection-box-border-color":"#aaa","selection-box-border-width":1,"active-bg-color":"black","active-bg-opacity":.15,"active-bg-size":30,"outside-texture-bg-color":"#000","outside-texture-bg-opacity":.125}),this.defaultLength=this.length},t.exports=i},{"../util":94}],90:[function(e,t,r){"use strict";var n=e("../util"),i=e("../selector"),a={};a.applyFromString=function(e){function t(){c=c.length>a.length?c.substr(a.length):""}function r(){o=o.length>s.length?o.substr(s.length):""}var a,o,s,l=this,u=this,c=""+e;for(c=c.replace(/[\/][*](\s|.)+?[*][\/]/g,"");;){var d=c.match(/^\s*$/);if(d)break;var h=c.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);if(!h){n.error("Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: "+c);break}a=h[0];var p=h[1];if("core"!==p){var v=new i(p);if(v._private.invalid){n.error("Skipping parsing of block: Invalid selector found in string stylesheet: "+p),t();continue}}var f=h[2],g=!1;o=f;for(var y=[];;){var d=o.match(/^\s*$/);if(d)break;var m=o.match(/^\s*(.+?)\s*:\s*(.+?)\s*;/);if(!m){n.error("Skipping parsing of block: Invalid formatting of style property and value definitions found in:"+f),g=!0;break}s=m[0];var b=m[1],x=m[2],w=l.properties[b];if(w){var _=u.parse(b,x);_?(y.push({name:b,val:x}),r()):(n.error("Skipping property: Invalid property definition in: "+s),r())}else n.error("Skipping property: Invalid property name in: "+s),r()}if(g){t();break}u.selector(p);for(var E=0;E<y.length;E++){var w=y[E];u.css(w.name,w.val)}t()}return u},a.fromString=function(e){var t=this;return t.resetToDefault(),t.applyFromString(e),t},t.exports=a},{"../selector":81,"../util":94}],91:[function(e,t,r){"use strict";var n=e("./is"),i=e("./util"),a=e("./style"),o=function(){return this instanceof o?void(this.length=0):new o},s=o.prototype;s.instanceString=function(){return"stylesheet"},s.selector=function(e){var t=this.length++;return this[t]={selector:e,properties:[]},this},s.css=function(e,t){var r=this.length-1;if(n.string(e))this[r].properties.push({name:e,value:t});else if(n.plainObject(e))for(var o=e,s=0;s<a.properties.length;s++){var l=a.properties[s],u=o[l.name];if(void 0===u&&(u=o[i.dash2camel(l.name)]),void 0!==u){var e=l.name,t=u;this[r].properties.push({name:e,value:t})}}return this},s.style=s.css,s.generateStyle=function(e){for(var t=new a(e),r=0;r<this.length;r++){var n=this[r],i=n.selector,o=n.properties;t.selector(i);for(var s=0;s<o.length;s++){var l=o[s];t.css(l.name,l.value)}}return t},t.exports=o},{"./is":77,"./style":86,"./util":94}],92:[function(_dereq_,module,exports){"use strict";var window=_dereq_("./window"),util=_dereq_("./util"),Promise=_dereq_("./promise"),Event=_dereq_("./event"),define=_dereq_("./define"),is=_dereq_("./is"),Thread=function(e){if(!(this instanceof Thread))return new Thread(e);var t=this._private={requires:[],files:[],queue:null,pass:[],disabled:!1};is.plainObject(e)&&null!=e.disabled&&(t.disabled=!!e.disabled)},thdfn=Thread.prototype,stringifyFieldVal=function(e){var t=is.fn(e)?e.toString():'JSON.parse("'+JSON.stringify(e)+'")';return t},fnAsRequire=function(e){var t,r;is.object(e)&&e.fn?(t=fnAs(e.fn,e.name),r=e.name,e=e.fn):is.fn(e)?(t=e.toString(),r=e.name):is.string(e)?t=e:is.object(e)&&(t=e.proto?"":e.name+" = {};",r=e.name,e=e.obj),t+="\n";var n=function(e,r){if(e.prototype){var n=!1;for(var i in e.prototype){n=!0;break}n&&(t+=fnAsRequire({name:r,obj:e,proto:!0},e))}};if(e.prototype&&null!=r)for(var i in e.prototype){var a="",o=e.prototype[i],s=stringifyFieldVal(o),l=r+".prototype."+i;a+=l+" = "+s+";\n",a&&(t+=a),n(o,l)}if(!is.string(e))for(var i in e){var u="";if(e.hasOwnProperty(i)){var o=e[i],s=stringifyFieldVal(o),l=r+'["'+i+'"]';u+=l+" = "+s+";\n"}u&&(t+=u),n(o,l)}return t},isPathStr=function(e){return is.string(e)&&e.match(/\.js$/)};util.extend(thdfn,{instanceString:function(){return"thread"},require:function(e,t){var r=this._private.requires;if(isPathStr(e))return this._private.files.push(e),this;if(t)e=is.fn(e)?{name:t,fn:e}:{name:t,obj:e};else if(is.fn(e)){if(!e.name)throw'The function name could not be automatically determined. Use thread.require( someFunction, "someFunction" )';e={name:e.name,fn:e}}return r.push(e),this},pass:function(e){return this._private.pass.push(e),this},run:function(fn,pass){var self=this,_p=this._private;if(pass=pass||_p.pass.shift(),_p.stopped)throw"Attempted to run a stopped thread! Start a new thread or do not stop the existing thread and reuse it.";if(_p.running)return _p.queue=_p.queue.then(function(){return self.run(fn,pass)});var useWW=null!=window&&!_p.disabled,useNode=!window&&"undefined"!=typeof module&&!_p.disabled;self.trigger("run");var runP=new Promise(function(resolve,reject){_p.running=!0;var threadTechAlreadyExists=_p.ran,fnImplStr=is.string(fn)?fn:fn.toString(),fnStr="\n"+_p.requires.map(function(e){return fnAsRequire(e)}).concat(_p.files.map(function(e){if(useWW){var t=function(e){return e.match(/^\.\//)||e.match(/^\.\./)?window.location.origin+window.location.pathname+e:e.match(/^\//)?window.location.origin+"/"+e:e};return'importScripts("'+t(e)+'");'}if(useNode)return'eval( require("fs").readFileSync("'+e+'", { encoding: "utf8" }) );';throw"External file `"+e+"` can not be required without any threading technology."})).concat(["( function(){","var ret = ("+fnImplStr+")("+JSON.stringify(pass)+");","if( ret !== undefined ){ resolve(ret); }","} )()\n"]).join("\n");if(_p.requires=[],_p.files=[],useWW){var fnBlob,fnUrl;if(!threadTechAlreadyExists){var fnPre=fnStr+"";fnStr=["function _ref_(o){ return eval(o); };","function broadcast(m){ return message(m); };","function message(m){ postMessage(m); };","function listen(fn){",' self.addEventListener("message", function(m){ ',' if( typeof m === "object" && (m.data.$$eval || m.data === "$$start") ){'," } else { "," fn( m.data );"," }"," });","};",'self.addEventListener("message", function(m){ if( m.data.$$eval ){ eval( m.data.$$eval ); } });',"function resolve(v){ postMessage({ $$resolve: v }); };","function reject(v){ postMessage({ $$reject: v }); };"].join("\n"),
+fnStr+=fnPre,fnBlob=new Blob([fnStr],{type:"application/javascript"}),fnUrl=window.URL.createObjectURL(fnBlob)}var ww=_p.webworker=_p.webworker||new Worker(fnUrl);threadTechAlreadyExists&&ww.postMessage({$$eval:fnStr});var cb;ww.addEventListener("message",cb=function(e){var t=is.object(e)&&is.object(e.data);t&&"$$resolve"in e.data?(ww.removeEventListener("message",cb),resolve(e.data.$$resolve)):t&&"$$reject"in e.data?(ww.removeEventListener("message",cb),reject(e.data.$$reject)):self.trigger(new Event(e,{type:"message",message:e.data}))},!1),threadTechAlreadyExists||ww.postMessage("$$start")}else if(useNode){_p.child||(_p.child=_dereq_("child_process").fork(_dereq_("path").join(__dirname,"thread-node-fork")));var child=_p.child,cb;child.on("message",cb=function(e){is.object(e)&&"$$resolve"in e?(child.removeListener("message",cb),resolve(e.$$resolve)):is.object(e)&&"$$reject"in e?(child.removeListener("message",cb),reject(e.$$reject)):self.trigger(new Event({},{type:"message",message:e}))}),child.send({$$eval:fnStr})}else{var promiseResolve=resolve,promiseReject=reject,timer=_p.timer=_p.timer||{listeners:[],exec:function(){fnStr=["function _ref_(o){ return eval(o); };","function broadcast(m){ return message(m); };",'function message(m){ self.trigger( new Event({}, { type: "message", message: m }) ); };',"function listen(fn){ timer.listeners.push( fn ); };","function resolve(v){ promiseResolve(v); };","function reject(v){ promiseReject(v); };"].join("\n")+fnStr,eval(fnStr)},message:function(e){for(var t=timer.listeners,r=0;r<t.length;r++){var n=t[r];n(e)}}};timer.exec()}}).then(function(e){return _p.running=!1,_p.ran=!0,self.trigger("ran"),e});return null==_p.queue&&(_p.queue=runP),runP},message:function(e){var t=this._private;return t.webworker&&t.webworker.postMessage(e),t.child&&t.child.send(e),t.timer&&t.timer.message(e),this},stop:function(){var e=this._private;return e.webworker&&e.webworker.terminate(),e.child&&e.child.kill(),e.timer,e.stopped=!0,this.trigger("stop")},stopped:function(){return this._private.stopped}});var fnAs=function(e,t){var r=e.toString();return r=r.replace(/function\s*?\S*?\s*?\(/,"function "+t+"(")},defineFnal=function(e){return e=e||{},function(t,r){var n=fnAs(t,"_$_$_"+e.name);return this.require(n),this.run(["function( data ){"," var origResolve = resolve;"," var res = [];"," "," resolve = function( val ){"," res.push( val );"," };"," "," var ret = data."+e.name+"( _$_$_"+e.name+(arguments.length>1?", "+JSON.stringify(r):"")+" );"," "," resolve = origResolve;"," resolve( res.length > 0 ? res : ret );","}"].join("\n"))}};util.extend(thdfn,{reduce:defineFnal({name:"reduce"}),reduceRight:defineFnal({name:"reduceRight"}),map:defineFnal({name:"map"})});var fn=thdfn;fn.promise=fn.run,fn.terminate=fn.halt=fn.stop,fn.include=fn.require,util.extend(thdfn,{on:define.on(),one:define.on({unbindSelfOnTrigger:!0}),off:define.off(),trigger:define.trigger()}),define.eventAliasesOn(thdfn),module.exports=Thread},{"./define":41,"./event":42,"./is":77,"./promise":80,"./util":94,"./window":100,child_process:void 0,path:void 0}],93:[function(e,t,r){"use strict";var n=e("../is");t.exports={hex2tuple:function(e){if((4===e.length||7===e.length)&&"#"===e[0]){var t,r,n,i=4===e.length,a=16;return i?(t=parseInt(e[1]+e[1],a),r=parseInt(e[2]+e[2],a),n=parseInt(e[3]+e[3],a)):(t=parseInt(e[1]+e[2],a),r=parseInt(e[3]+e[4],a),n=parseInt(e[5]+e[6],a)),[t,r,n]}},hsl2tuple:function(e){function t(e,t,r){return 0>r&&(r+=1),r>1&&(r-=1),1/6>r?e+6*(t-e)*r:.5>r?t:2/3>r?e+(t-e)*(2/3-r)*6:e}var r,n,i,a,o,s,l,u,c=new RegExp("^"+this.regex.hsla+"$").exec(e);if(c){if(n=parseInt(c[1]),0>n?n=(360- -1*n%360)%360:n>360&&(n%=360),n/=360,i=parseFloat(c[2]),0>i||i>100)return;if(i/=100,a=parseFloat(c[3]),0>a||a>100)return;if(a/=100,o=c[4],void 0!==o&&(o=parseFloat(o),0>o||o>1))return;if(0===i)s=l=u=Math.round(255*a);else{var d=.5>a?a*(1+i):a+i-a*i,h=2*a-d;s=Math.round(255*t(h,d,n+1/3)),l=Math.round(255*t(h,d,n)),u=Math.round(255*t(h,d,n-1/3))}r=[s,l,u,o]}return r},rgb2tuple:function(e){var t,r=new RegExp("^"+this.regex.rgba+"$").exec(e);if(r){t=[];for(var n=[],i=1;3>=i;i++){var a=r[i];if("%"===a[a.length-1]&&(n[i]=!0),a=parseFloat(a),n[i]&&(a=a/100*255),0>a||a>255)return;t.push(Math.floor(a))}var o=n[1]||n[2]||n[3],s=n[1]&&n[2]&&n[3];if(o&&!s)return;var l=r[4];if(void 0!==l){if(l=parseFloat(l),0>l||l>1)return;t.push(l)}}return t},colorname2tuple:function(e){return this.colors[e.toLowerCase()]},color2tuple:function(e){return(n.array(e)?e:null)||this.colorname2tuple(e)||this.hex2tuple(e)||this.rgb2tuple(e)||this.hsl2tuple(e)},colors:{transparent:[0,0,0,0],aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],grey:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}}},{"../is":77}],94:[function(e,t,r){"use strict";var n=e("../is"),i=e("../math"),a={falsify:function(){return!1},zeroify:function(){return 0},noop:function(){},error:function(e){console.error?(console.error.apply(console,arguments),console.trace&&console.trace()):(console.log.apply(console,arguments),console.trace&&console.trace())},clone:function(e){return this.extend({},e)},copy:function(e){return null==e?e:n.array(e)?e.slice():n.plainObject(e)?this.clone(e):e}};a.makeBoundingBox=i.makeBoundingBox.bind(i),a._staticEmptyObject={},a.staticEmptyObject=function(){return a._staticEmptyObject},a.extend=null!=Object.assign?Object.assign:function(e){for(var t=arguments,r=1;r<t.length;r++){var n=t[r];for(var i in n)e[i]=n[i]}return e},[e("./colors"),e("./maps"),{memoize:e("./memoize")},e("./regex"),e("./strings"),e("./timing")].forEach(function(e){a.extend(a,e)}),t.exports=a},{"../is":77,"../math":79,"./colors":93,"./maps":95,"./memoize":96,"./regex":97,"./strings":98,"./timing":99}],95:[function(e,t,r){"use strict";var n=e("../is");t.exports={mapEmpty:function(e){var t=!0;if(null!=e)for(var r in e){t=!1;break}return t},pushMap:function(e){var t=this.getMap(e);null==t?this.setMap(this.extend({},e,{value:[e.value]})):t.push(e.value)},setMap:function(e){for(var t,r=e.map,i=e.keys,a=i.length,o=0;a>o;o++){var t=i[o];n.plainObject(t)&&this.error("Tried to set map with object key"),o<i.length-1?(null==r[t]&&(r[t]={}),r=r[t]):r[t]=e.value}},getMap:function(e){for(var t=e.map,r=e.keys,i=r.length,a=0;i>a;a++){var o=r[a];if(n.plainObject(o)&&this.error("Tried to get map with object key"),t=t[o],null==t)return t}return t},deleteMap:function(e){for(var t=e.map,r=e.keys,i=r.length,a=e.keepChildren,o=0;i>o;o++){var s=r[o];n.plainObject(s)&&this.error("Tried to delete map with object key");var l=o===e.keys.length-1;if(l)if(a)for(var u in t)a[u]||(t[u]=void 0);else t[s]=void 0;else t=t[s]}}}},{"../is":77}],96:[function(e,t,r){"use strict";t.exports=function(e,t){var r=this,n={};return t||(t=function(){if(1===arguments.length)return arguments[0];for(var e=[],t=0;t<arguments.length;t++)e.push(arguments[t]);return e.join("$")}),function(){var i,a=arguments,o=t.apply(r,a);return(i=n[o])||(i=n[o]=e.apply(r,a)),i}}},{}],97:[function(e,t,r){"use strict";var n="(?:[-+]?(?:(?:\\d+|\\d*\\.\\d+)(?:[Ee][+-]?\\d+)?))",i="rgb[a]?\\(("+n+"[%]?)\\s*,\\s*("+n+"[%]?)\\s*,\\s*("+n+"[%]?)(?:\\s*,\\s*("+n+"))?\\)",a="rgb[a]?\\((?:"+n+"[%]?)\\s*,\\s*(?:"+n+"[%]?)\\s*,\\s*(?:"+n+"[%]?)(?:\\s*,\\s*(?:"+n+"))?\\)",o="hsl[a]?\\(("+n+")\\s*,\\s*("+n+"[%])\\s*,\\s*("+n+"[%])(?:\\s*,\\s*("+n+"))?\\)",s="hsl[a]?\\((?:"+n+")\\s*,\\s*(?:"+n+"[%])\\s*,\\s*(?:"+n+"[%])(?:\\s*,\\s*(?:"+n+"))?\\)",l="\\#[0-9a-fA-F]{3}",u="\\#[0-9a-fA-F]{6}";t.exports={regex:{number:n,rgba:i,rgbaNoBackRefs:a,hsla:o,hslaNoBackRefs:s,hex3:l,hex6:u}}},{}],98:[function(e,t,r){"use strict";var n=e("./memoize"),i=e("../is");t.exports={camel2dash:n(function(e){return e.replace(/([A-Z])/g,function(e){return"-"+e.toLowerCase()})}),dash2camel:n(function(e){return e.replace(/(-\w)/g,function(e){return e[1].toUpperCase()})}),capitalize:function(e){return i.emptyString(e)?e:e.charAt(0).toUpperCase()+e.substring(1)}}},{"../is":77,"./memoize":96}],99:[function(e,t,r){"use strict";var n=e("../window"),i=e("../is"),a=n?n.performance:null,o={},s=n?n.requestAnimationFrame||n.mozRequestAnimationFrame||n.webkitRequestAnimationFrame||n.msRequestAnimationFrame:null;s=s||function(e){e&&setTimeout(function(){e(l())},1e3/60)},o.requestAnimationFrame=function(e){s(e)};var l=a&&a.now?function(){return a.now()}:function(){return Date.now()};o.performanceNow=l,o.throttle=function(e,t,r){var n=!0,a=!0;return r===!1?n=!1:i.plainObject(r)&&(n="leading"in r?r.leading:n,a="trailing"in r?r.trailing:a),r=r||{},r.leading=n,r.maxWait=t,r.trailing=a,o.debounce(e,t,r)},o.now=function(){return Date.now()},o.debounce=function(e,t,r){var n,a,o,s,l,u,c,d=this,h=0,p=!1,v=!0;if(i.fn(e)){if(t=Math.max(0,t)||0,r===!0){var f=!0;v=!1}else i.plainObject(r)&&(f=r.leading,p="maxWait"in r&&(Math.max(t,r.maxWait)||0),v="trailing"in r?r.trailing:v);var g=function(){var r=t-(d.now()-s);if(0>=r){a&&clearTimeout(a);var i=c;a=u=c=void 0,i&&(h=d.now(),o=e.apply(l,n),u||a||(n=l=null))}else u=setTimeout(g,r)},y=function(){u&&clearTimeout(u),a=u=c=void 0,(v||p!==t)&&(h=d.now(),o=e.apply(l,n),u||a||(n=l=null))};return function(){if(n=arguments,s=d.now(),l=this,c=v&&(u||!f),p===!1)var r=f&&!u;else{a||f||(h=s);var i=p-(s-h),m=0>=i;m?(a&&(a=clearTimeout(a)),h=s,o=e.apply(l,n)):a||(a=setTimeout(y,i))}return m&&u?u=clearTimeout(u):u||t===p||(u=setTimeout(g,t)),r&&(m=!0,o=e.apply(l,n)),!m||u||a||(n=l=null),o}}},t.exports=o},{"../is":77,"../window":100}],100:[function(e,t,r){t.exports="undefined"==typeof window?null:window},{}]},{},[76])(76)});
+//# sourceMappingURL=cytoscape.min.js.map
diff --git a/docs/htmldoc/js/dagre.js b/docs/htmldoc/js/dagre.js
new file mode 100644
index 0000000..830997b
--- /dev/null
+++ b/docs/htmldoc/js/dagre.js
@@ -0,0 +1,16396 @@
+!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){
+/*
+Copyright (c) 2012-2014 Chris Pettitt
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+
+module.exports = {
+ graphlib: require("./lib/graphlib"),
+
+ layout: require("./lib/layout"),
+ debug: require("./lib/debug"),
+ util: {
+ time: require("./lib/util").time,
+ notime: require("./lib/util").notime
+ },
+ version: require("./lib/version")
+};
+
+},{"./lib/debug":6,"./lib/graphlib":7,"./lib/layout":9,"./lib/util":29,"./lib/version":30}],2:[function(require,module,exports){
+"use strict";
+
+var _ = require("./lodash"),
+ greedyFAS = require("./greedy-fas");
+
+module.exports = {
+ run: run,
+ undo: undo
+};
+
+function run(g) {
+ var fas = (g.graph().acyclicer === "greedy"
+ ? greedyFAS(g, weightFn(g))
+ : dfsFAS(g));
+ _.each(fas, function(e) {
+ var label = g.edge(e);
+ g.removeEdge(e);
+ label.forwardName = e.name;
+ label.reversed = true;
+ g.setEdge(e.w, e.v, label, _.uniqueId("rev"));
+ });
+
+ function weightFn(g) {
+ return function(e) {
+ return g.edge(e).weight;
+ };
+ }
+}
+
+function dfsFAS(g) {
+ var fas = [],
+ stack = {},
+ visited = {};
+
+ function dfs(v) {
+ if (_.has(visited, v)) {
+ return;
+ }
+ visited[v] = true;
+ stack[v] = true;
+ _.each(g.outEdges(v), function(e) {
+ if (_.has(stack, e.w)) {
+ fas.push(e);
+ } else {
+ dfs(e.w);
+ }
+ });
+ delete stack[v];
+ }
+
+ _.each(g.nodes(), dfs);
+ return fas;
+}
+
+function undo(g) {
+ _.each(g.edges(), function(e) {
+ var label = g.edge(e);
+ if (label.reversed) {
+ g.removeEdge(e);
+
+ var forwardName = label.forwardName;
+ delete label.reversed;
+ delete label.forwardName;
+ g.setEdge(e.w, e.v, label, forwardName);
+ }
+ });
+}
+
+},{"./greedy-fas":8,"./lodash":10}],3:[function(require,module,exports){
+var _ = require("./lodash"),
+ util = require("./util");
+
+module.exports = addBorderSegments;
+
+function addBorderSegments(g) {
+ function dfs(v) {
+ var children = g.children(v),
+ node = g.node(v);
+ if (children.length) {
+ _.each(children, dfs);
+ }
+
+ if (_.has(node, "minRank")) {
+ node.borderLeft = [];
+ node.borderRight = [];
+ for (var rank = node.minRank, maxRank = node.maxRank + 1;
+ rank < maxRank;
+ ++rank) {
+ addBorderNode(g, "borderLeft", "_bl", v, node, rank);
+ addBorderNode(g, "borderRight", "_br", v, node, rank);
+ }
+ }
+ }
+
+ _.each(g.children(), dfs);
+}
+
+function addBorderNode(g, prop, prefix, sg, sgNode, rank) {
+ var label = { width: 0, height: 0, rank: rank, borderType: prop },
+ prev = sgNode[prop][rank - 1],
+ curr = util.addDummyNode(g, "border", label, prefix);
+ sgNode[prop][rank] = curr;
+ g.setParent(curr, sg);
+ if (prev) {
+ g.setEdge(prev, curr, { weight: 1 });
+ }
+}
+
+},{"./lodash":10,"./util":29}],4:[function(require,module,exports){
+"use strict";
+
+var _ = require("./lodash");
+
+module.exports = {
+ adjust: adjust,
+ undo: undo
+};
+
+function adjust(g) {
+ var rankDir = g.graph().rankdir.toLowerCase();
+ if (rankDir === "lr" || rankDir === "rl") {
+ swapWidthHeight(g);
+ }
+}
+
+function undo(g) {
+ var rankDir = g.graph().rankdir.toLowerCase();
+ if (rankDir === "bt" || rankDir === "rl") {
+ reverseY(g);
+ }
+
+ if (rankDir === "lr" || rankDir === "rl") {
+ swapXY(g);
+ swapWidthHeight(g);
+ }
+}
+
+function swapWidthHeight(g) {
+ _.each(g.nodes(), function(v) { swapWidthHeightOne(g.node(v)); });
+ _.each(g.edges(), function(e) { swapWidthHeightOne(g.edge(e)); });
+}
+
+function swapWidthHeightOne(attrs) {
+ var w = attrs.width;
+ attrs.width = attrs.height;
+ attrs.height = w;
+}
+
+function reverseY(g) {
+ _.each(g.nodes(), function(v) { reverseYOne(g.node(v)); });
+
+ _.each(g.edges(), function(e) {
+ var edge = g.edge(e);
+ _.each(edge.points, reverseYOne);
+ if (_.has(edge, "y")) {
+ reverseYOne(edge);
+ }
+ });
+}
+
+function reverseYOne(attrs) {
+ attrs.y = -attrs.y;
+}
+
+function swapXY(g) {
+ _.each(g.nodes(), function(v) { swapXYOne(g.node(v)); });
+
+ _.each(g.edges(), function(e) {
+ var edge = g.edge(e);
+ _.each(edge.points, swapXYOne);
+ if (_.has(edge, "x")) {
+ swapXYOne(edge);
+ }
+ });
+}
+
+function swapXYOne(attrs) {
+ var x = attrs.x;
+ attrs.x = attrs.y;
+ attrs.y = x;
+}
+
+},{"./lodash":10}],5:[function(require,module,exports){
+/*
+ * Simple doubly linked list implementation derived from Cormen, et al.,
+ * "Introduction to Algorithms".
+ */
+
+module.exports = List;
+
+function List() {
+ var sentinel = {};
+ sentinel._next = sentinel._prev = sentinel;
+ this._sentinel = sentinel;
+}
+
+List.prototype.dequeue = function() {
+ var sentinel = this._sentinel,
+ entry = sentinel._prev;
+ if (entry !== sentinel) {
+ unlink(entry);
+ return entry;
+ }
+};
+
+List.prototype.enqueue = function(entry) {
+ var sentinel = this._sentinel;
+ if (entry._prev && entry._next) {
+ unlink(entry);
+ }
+ entry._next = sentinel._next;
+ sentinel._next._prev = entry;
+ sentinel._next = entry;
+ entry._prev = sentinel;
+};
+
+List.prototype.toString = function() {
+ var strs = [],
+ sentinel = this._sentinel,
+ curr = sentinel._prev;
+ while (curr !== sentinel) {
+ strs.push(JSON.stringify(curr, filterOutLinks));
+ curr = curr._prev;
+ }
+ return "[" + strs.join(", ") + "]";
+};
+
+function unlink(entry) {
+ entry._prev._next = entry._next;
+ entry._next._prev = entry._prev;
+ delete entry._next;
+ delete entry._prev;
+}
+
+function filterOutLinks(k, v) {
+ if (k !== "_next" && k !== "_prev") {
+ return v;
+ }
+}
+
+},{}],6:[function(require,module,exports){
+var _ = require("./lodash"),
+ util = require("./util"),
+ Graph = require("./graphlib").Graph;
+
+module.exports = {
+ debugOrdering: debugOrdering
+};
+
+/* istanbul ignore next */
+function debugOrdering(g) {
+ var layerMatrix = util.buildLayerMatrix(g);
+
+ var h = new Graph({ compound: true, multigraph: true }).setGraph({});
+
+ _.each(g.nodes(), function(v) {
+ h.setNode(v, { label: v });
+ h.setParent(v, "layer" + g.node(v).rank);
+ });
+
+ _.each(g.edges(), function(e) {
+ h.setEdge(e.v, e.w, {}, e.name);
+ });
+
+ _.each(layerMatrix, function(layer, i) {
+ var layerV = "layer" + i;
+ h.setNode(layerV, { rank: "same" });
+ _.reduce(layer, function(u, v) {
+ h.setEdge(u, v, { style: "invis" });
+ return v;
+ });
+ });
+
+ return h;
+}
+
+},{"./graphlib":7,"./lodash":10,"./util":29}],7:[function(require,module,exports){
+/* global window */
+
+var graphlib;
+
+if (typeof require === "function") {
+ try {
+ graphlib = require("graphlib");
+ } catch (e) {}
+}
+
+if (!graphlib) {
+ graphlib = window.graphlib;
+}
+
+module.exports = graphlib;
+
+},{"graphlib":31}],8:[function(require,module,exports){
+var _ = require("./lodash"),
+ Graph = require("./graphlib").Graph,
+ List = require("./data/list");
+
+/*
+ * A greedy heuristic for finding a feedback arc set for a graph. A feedback
+ * arc set is a set of edges that can be removed to make a graph acyclic.
+ * The algorithm comes from: P. Eades, X. Lin, and W. F. Smyth, "A fast and
+ * effective heuristic for the feedback arc set problem." This implementation
+ * adjusts that from the paper to allow for weighted edges.
+ */
+module.exports = greedyFAS;
+
+var DEFAULT_WEIGHT_FN = _.constant(1);
+
+function greedyFAS(g, weightFn) {
+ if (g.nodeCount() <= 1) {
+ return [];
+ }
+ var state = buildState(g, weightFn || DEFAULT_WEIGHT_FN);
+ var results = doGreedyFAS(state.graph, state.buckets, state.zeroIdx);
+
+ // Expand multi-edges
+ return _.flatten(_.map(results, function(e) {
+ return g.outEdges(e.v, e.w);
+ }), true);
+}
+
+function doGreedyFAS(g, buckets, zeroIdx) {
+ var results = [],
+ sources = buckets[buckets.length - 1],
+ sinks = buckets[0];
+
+ var entry;
+ while (g.nodeCount()) {
+ while ((entry = sinks.dequeue())) { removeNode(g, buckets, zeroIdx, entry); }
+ while ((entry = sources.dequeue())) { removeNode(g, buckets, zeroIdx, entry); }
+ if (g.nodeCount()) {
+ for (var i = buckets.length - 2; i > 0; --i) {
+ entry = buckets[i].dequeue();
+ if (entry) {
+ results = results.concat(removeNode(g, buckets, zeroIdx, entry, true));
+ break;
+ }
+ }
+ }
+ }
+
+ return results;
+}
+
+function removeNode(g, buckets, zeroIdx, entry, collectPredecessors) {
+ var results = collectPredecessors ? [] : undefined;
+
+ _.each(g.inEdges(entry.v), function(edge) {
+ var weight = g.edge(edge),
+ uEntry = g.node(edge.v);
+
+ if (collectPredecessors) {
+ results.push({ v: edge.v, w: edge.w });
+ }
+
+ uEntry.out -= weight;
+ assignBucket(buckets, zeroIdx, uEntry);
+ });
+
+ _.each(g.outEdges(entry.v), function(edge) {
+ var weight = g.edge(edge),
+ w = edge.w,
+ wEntry = g.node(w);
+ wEntry["in"] -= weight;
+ assignBucket(buckets, zeroIdx, wEntry);
+ });
+
+ g.removeNode(entry.v);
+
+ return results;
+}
+
+function buildState(g, weightFn) {
+ var fasGraph = new Graph(),
+ maxIn = 0,
+ maxOut = 0;
+
+ _.each(g.nodes(), function(v) {
+ fasGraph.setNode(v, { v: v, "in": 0, out: 0 });
+ });
+
+ // Aggregate weights on nodes, but also sum the weights across multi-edges
+ // into a single edge for the fasGraph.
+ _.each(g.edges(), function(e) {
+ var prevWeight = fasGraph.edge(e.v, e.w) || 0,
+ weight = weightFn(e),
+ edgeWeight = prevWeight + weight;
+ fasGraph.setEdge(e.v, e.w, edgeWeight);
+ maxOut = Math.max(maxOut, fasGraph.node(e.v).out += weight);
+ maxIn = Math.max(maxIn, fasGraph.node(e.w)["in"] += weight);
+ });
+
+ var buckets = _.range(maxOut + maxIn + 3).map(function() { return new List(); });
+ var zeroIdx = maxIn + 1;
+
+ _.each(fasGraph.nodes(), function(v) {
+ assignBucket(buckets, zeroIdx, fasGraph.node(v));
+ });
+
+ return { graph: fasGraph, buckets: buckets, zeroIdx: zeroIdx };
+}
+
+function assignBucket(buckets, zeroIdx, entry) {
+ if (!entry.out) {
+ buckets[0].enqueue(entry);
+ } else if (!entry["in"]) {
+ buckets[buckets.length - 1].enqueue(entry);
+ } else {
+ buckets[entry.out - entry["in"] + zeroIdx].enqueue(entry);
+ }
+}
+
+},{"./data/list":5,"./graphlib":7,"./lodash":10}],9:[function(require,module,exports){
+"use strict";
+
+var _ = require("./lodash"),
+ acyclic = require("./acyclic"),
+ normalize = require("./normalize"),
+ rank = require("./rank"),
+ normalizeRanks = require("./util").normalizeRanks,
+ parentDummyChains = require("./parent-dummy-chains"),
+ removeEmptyRanks = require("./util").removeEmptyRanks,
+ nestingGraph = require("./nesting-graph"),
+ addBorderSegments = require("./add-border-segments"),
+ coordinateSystem = require("./coordinate-system"),
+ order = require("./order"),
+ position = require("./position"),
+ util = require("./util"),
+ Graph = require("./graphlib").Graph;
+
+module.exports = layout;
+
+function layout(g, opts) {
+ var time = opts && opts.debugTiming ? util.time : util.notime;
+ time("layout", function() {
+ var layoutGraph = time(" buildLayoutGraph",
+ function() { return buildLayoutGraph(g); });
+ time(" runLayout", function() { runLayout(layoutGraph, time); });
+ time(" updateInputGraph", function() { updateInputGraph(g, layoutGraph); });
+ });
+}
+
+function runLayout(g, time) {
+ time(" makeSpaceForEdgeLabels", function() { makeSpaceForEdgeLabels(g); });
+ time(" removeSelfEdges", function() { removeSelfEdges(g); });
+ time(" acyclic", function() { acyclic.run(g); });
+ time(" nestingGraph.run", function() { nestingGraph.run(g); });
+ time(" rank", function() { rank(util.asNonCompoundGraph(g)); });
+ time(" injectEdgeLabelProxies", function() { injectEdgeLabelProxies(g); });
+ time(" removeEmptyRanks", function() { removeEmptyRanks(g); });
+ time(" nestingGraph.cleanup", function() { nestingGraph.cleanup(g); });
+ time(" normalizeRanks", function() { normalizeRanks(g); });
+ time(" assignRankMinMax", function() { assignRankMinMax(g); });
+ time(" removeEdgeLabelProxies", function() { removeEdgeLabelProxies(g); });
+ time(" normalize.run", function() { normalize.run(g); });
+ time(" parentDummyChains", function() { parentDummyChains(g); });
+ time(" addBorderSegments", function() { addBorderSegments(g); });
+ time(" order", function() { order(g); });
+ time(" insertSelfEdges", function() { insertSelfEdges(g); });
+ time(" adjustCoordinateSystem", function() { coordinateSystem.adjust(g); });
+ time(" position", function() { position(g); });
+ time(" positionSelfEdges", function() { positionSelfEdges(g); });
+ time(" removeBorderNodes", function() { removeBorderNodes(g); });
+ time(" normalize.undo", function() { normalize.undo(g); });
+ time(" fixupEdgeLabelCoords", function() { fixupEdgeLabelCoords(g); });
+ time(" undoCoordinateSystem", function() { coordinateSystem.undo(g); });
+ time(" translateGraph", function() { translateGraph(g); });
+ time(" assignNodeIntersects", function() { assignNodeIntersects(g); });
+ time(" reversePoints", function() { reversePointsForReversedEdges(g); });
+ time(" acyclic.undo", function() { acyclic.undo(g); });
+}
+
+/*
+ * Copies final layout information from the layout graph back to the input
+ * graph. This process only copies whitelisted attributes from the layout graph
+ * to the input graph, so it serves as a good place to determine what
+ * attributes can influence layout.
+ */
+function updateInputGraph(inputGraph, layoutGraph) {
+ _.each(inputGraph.nodes(), function(v) {
+ var inputLabel = inputGraph.node(v),
+ layoutLabel = layoutGraph.node(v);
+
+ if (inputLabel) {
+ inputLabel.x = layoutLabel.x;
+ inputLabel.y = layoutLabel.y;
+
+ if (layoutGraph.children(v).length) {
+ inputLabel.width = layoutLabel.width;
+ inputLabel.height = layoutLabel.height;
+ }
+ }
+ });
+
+ _.each(inputGraph.edges(), function(e) {
+ var inputLabel = inputGraph.edge(e),
+ layoutLabel = layoutGraph.edge(e);
+
+ inputLabel.points = layoutLabel.points;
+ if (_.has(layoutLabel, "x")) {
+ inputLabel.x = layoutLabel.x;
+ inputLabel.y = layoutLabel.y;
+ }
+ });
+
+ inputGraph.graph().width = layoutGraph.graph().width;
+ inputGraph.graph().height = layoutGraph.graph().height;
+}
+
+var graphNumAttrs = ["nodesep", "edgesep", "ranksep", "marginx", "marginy"],
+ graphDefaults = { ranksep: 50, edgesep: 20, nodesep: 50, rankdir: "tb" },
+ graphAttrs = ["acyclicer", "ranker", "rankdir", "align"],
+ nodeNumAttrs = ["width", "height"],
+ nodeDefaults = { width: 0, height: 0 },
+ edgeNumAttrs = ["minlen", "weight", "width", "height", "labeloffset"],
+ edgeDefaults = {
+ minlen: 1, weight: 1, width: 0, height: 0,
+ labeloffset: 10, labelpos: "r"
+ },
+ edgeAttrs = ["labelpos"];
+
+/*
+ * Constructs a new graph from the input graph, which can be used for layout.
+ * This process copies only whitelisted attributes from the input graph to the
+ * layout graph. Thus this function serves as a good place to determine what
+ * attributes can influence layout.
+ */
+function buildLayoutGraph(inputGraph) {
+ var g = new Graph({ multigraph: true, compound: true }),
+ graph = canonicalize(inputGraph.graph());
+
+ g.setGraph(_.merge({},
+ graphDefaults,
+ selectNumberAttrs(graph, graphNumAttrs),
+ _.pick(graph, graphAttrs)));
+
+ _.each(inputGraph.nodes(), function(v) {
+ var node = canonicalize(inputGraph.node(v));
+ g.setNode(v, _.defaults(selectNumberAttrs(node, nodeNumAttrs), nodeDefaults));
+ g.setParent(v, inputGraph.parent(v));
+ });
+
+ _.each(inputGraph.edges(), function(e) {
+ var edge = canonicalize(inputGraph.edge(e));
+ g.setEdge(e, _.merge({},
+ edgeDefaults,
+ selectNumberAttrs(edge, edgeNumAttrs),
+ _.pick(edge, edgeAttrs)));
+ });
+
+ return g;
+}
+
+/*
+ * This idea comes from the Gansner paper: to account for edge labels in our
+ * layout we split each rank in half by doubling minlen and halving ranksep.
+ * Then we can place labels at these mid-points between nodes.
+ *
+ * We also add some minimal padding to the width to push the label for the edge
+ * away from the edge itself a bit.
+ */
+function makeSpaceForEdgeLabels(g) {
+ var graph = g.graph();
+ graph.ranksep /= 2;
+ _.each(g.edges(), function(e) {
+ var edge = g.edge(e);
+ edge.minlen *= 2;
+ if (edge.labelpos.toLowerCase() !== "c") {
+ if (graph.rankdir === "TB" || graph.rankdir === "BT") {
+ edge.width += edge.labeloffset;
+ } else {
+ edge.height += edge.labeloffset;
+ }
+ }
+ });
+}
+
+/*
+ * Creates temporary dummy nodes that capture the rank in which each edge's
+ * label is going to, if it has one of non-zero width and height. We do this
+ * so that we can safely remove empty ranks while preserving balance for the
+ * label's position.
+ */
+function injectEdgeLabelProxies(g) {
+ _.each(g.edges(), function(e) {
+ var edge = g.edge(e);
+ if (edge.width && edge.height) {
+ var v = g.node(e.v),
+ w = g.node(e.w),
+ label = { rank: (w.rank - v.rank) / 2 + v.rank, e: e };
+ util.addDummyNode(g, "edge-proxy", label, "_ep");
+ }
+ });
+}
+
+function assignRankMinMax(g) {
+ var maxRank = 0;
+ _.each(g.nodes(), function(v) {
+ var node = g.node(v);
+ if (node.borderTop) {
+ node.minRank = g.node(node.borderTop).rank;
+ node.maxRank = g.node(node.borderBottom).rank;
+ maxRank = _.max(maxRank, node.maxRank);
+ }
+ });
+ g.graph().maxRank = maxRank;
+}
+
+function removeEdgeLabelProxies(g) {
+ _.each(g.nodes(), function(v) {
+ var node = g.node(v);
+ if (node.dummy === "edge-proxy") {
+ g.edge(node.e).labelRank = node.rank;
+ g.removeNode(v);
+ }
+ });
+}
+
+function translateGraph(g) {
+ var minX = Number.POSITIVE_INFINITY,
+ maxX = 0,
+ minY = Number.POSITIVE_INFINITY,
+ maxY = 0,
+ graphLabel = g.graph(),
+ marginX = graphLabel.marginx || 0,
+ marginY = graphLabel.marginy || 0;
+
+ function getExtremes(attrs) {
+ var x = attrs.x,
+ y = attrs.y,
+ w = attrs.width,
+ h = attrs.height;
+ minX = Math.min(minX, x - w / 2);
+ maxX = Math.max(maxX, x + w / 2);
+ minY = Math.min(minY, y - h / 2);
+ maxY = Math.max(maxY, y + h / 2);
+ }
+
+ _.each(g.nodes(), function(v) { getExtremes(g.node(v)); });
+ _.each(g.edges(), function(e) {
+ var edge = g.edge(e);
+ if (_.has(edge, "x")) {
+ getExtremes(edge);
+ }
+ });
+
+ minX -= marginX;
+ minY -= marginY;
+
+ _.each(g.nodes(), function(v) {
+ var node = g.node(v);
+ node.x -= minX;
+ node.y -= minY;
+ });
+
+ _.each(g.edges(), function(e) {
+ var edge = g.edge(e);
+ _.each(edge.points, function(p) {
+ p.x -= minX;
+ p.y -= minY;
+ });
+ if (_.has(edge, "x")) { edge.x -= minX; }
+ if (_.has(edge, "y")) { edge.y -= minY; }
+ });
+
+ graphLabel.width = maxX - minX + marginX;
+ graphLabel.height = maxY - minY + marginY;
+}
+
+function assignNodeIntersects(g) {
+ _.each(g.edges(), function(e) {
+ var edge = g.edge(e),
+ nodeV = g.node(e.v),
+ nodeW = g.node(e.w),
+ p1, p2;
+ if (!edge.points) {
+ edge.points = [];
+ p1 = nodeW;
+ p2 = nodeV;
+ } else {
+ p1 = edge.points[0];
+ p2 = edge.points[edge.points.length - 1];
+ }
+ edge.points.unshift(util.intersectRect(nodeV, p1));
+ edge.points.push(util.intersectRect(nodeW, p2));
+ });
+}
+
+function fixupEdgeLabelCoords(g) {
+ _.each(g.edges(), function(e) {
+ var edge = g.edge(e);
+ if (_.has(edge, "x")) {
+ if (edge.labelpos === "l" || edge.labelpos === "r") {
+ edge.width -= edge.labeloffset;
+ }
+ switch (edge.labelpos) {
+ case "l": edge.x -= edge.width / 2 + edge.labeloffset; break;
+ case "r": edge.x += edge.width / 2 + edge.labeloffset; break;
+ }
+ }
+ });
+}
+
+function reversePointsForReversedEdges(g) {
+ _.each(g.edges(), function(e) {
+ var edge = g.edge(e);
+ if (edge.reversed) {
+ edge.points.reverse();
+ }
+ });
+}
+
+function removeBorderNodes(g) {
+ _.each(g.nodes(), function(v) {
+ if (g.children(v).length) {
+ var node = g.node(v),
+ t = g.node(node.borderTop),
+ b = g.node(node.borderBottom),
+ l = g.node(_.last(node.borderLeft)),
+ r = g.node(_.last(node.borderRight));
+
+ node.width = Math.abs(r.x - l.x);
+ node.height = Math.abs(b.y - t.y);
+ node.x = l.x + node.width / 2;
+ node.y = t.y + node.height / 2;
+ }
+ });
+
+ _.each(g.nodes(), function(v) {
+ if (g.node(v).dummy === "border") {
+ g.removeNode(v);
+ }
+ });
+}
+
+function removeSelfEdges(g) {
+ _.each(g.edges(), function(e) {
+ if (e.v === e.w) {
+ var node = g.node(e.v);
+ if (!node.selfEdges) {
+ node.selfEdges = [];
+ }
+ node.selfEdges.push({ e: e, label: g.edge(e) });
+ g.removeEdge(e);
+ }
+ });
+}
+
+function insertSelfEdges(g) {
+ var layers = util.buildLayerMatrix(g);
+ _.each(layers, function(layer) {
+ var orderShift = 0;
+ _.each(layer, function(v, i) {
+ var node = g.node(v);
+ node.order = i + orderShift;
+ _.each(node.selfEdges, function(selfEdge) {
+ util.addDummyNode(g, "selfedge", {
+ width: selfEdge.label.width,
+ height: selfEdge.label.height,
+ rank: node.rank,
+ order: i + (++orderShift),
+ e: selfEdge.e,
+ label: selfEdge.label
+ }, "_se");
+ });
+ delete node.selfEdges;
+ });
+ });
+}
+
+function positionSelfEdges(g) {
+ _.each(g.nodes(), function(v) {
+ var node = g.node(v);
+ if (node.dummy === "selfedge") {
+ var selfNode = g.node(node.e.v),
+ x = selfNode.x + selfNode.width / 2,
+ y = selfNode.y,
+ dx = node.x - x,
+ dy = selfNode.height / 2;
+ g.setEdge(node.e, node.label);
+ g.removeNode(v);
+ node.label.points = [
+ { x: x + 2 * dx / 3, y: y - dy },
+ { x: x + 5 * dx / 6, y: y - dy },
+ { x: x + dx , y: y },
+ { x: x + 5 * dx / 6, y: y + dy },
+ { x: x + 2 * dx / 3, y: y + dy },
+ ];
+ node.label.x = node.x;
+ node.label.y = node.y;
+ }
+ });
+}
+
+function selectNumberAttrs(obj, attrs) {
+ return _.mapValues(_.pick(obj, attrs), Number);
+}
+
+function canonicalize(attrs) {
+ var newAttrs = {};
+ _.each(attrs, function(v, k) {
+ newAttrs[k.toLowerCase()] = v;
+ });
+ return newAttrs;
+}
+
+},{"./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){
+/* global window */
+
+var lodash;
+
+if (typeof require === "function") {
+ try {
+ lodash = require("lodash");
+ } catch (e) {}
+}
+
+if (!lodash) {
+ lodash = window._;
+}
+
+module.exports = lodash;
+
+},{"lodash":51}],11:[function(require,module,exports){
+var _ = require("./lodash"),
+ util = require("./util");
+
+module.exports = {
+ run: run,
+ cleanup: cleanup
+};
+
+/*
+ * A nesting graph creates dummy nodes for the tops and bottoms of subgraphs,
+ * adds appropriate edges to ensure that all cluster nodes are placed between
+ * these boundries, and ensures that the graph is connected.
+ *
+ * In addition we ensure, through the use of the minlen property, that nodes
+ * and subgraph border nodes to not end up on the same rank.
+ *
+ * Preconditions:
+ *
+ * 1. Input graph is a DAG
+ * 2. Nodes in the input graph has a minlen attribute
+ *
+ * Postconditions:
+ *
+ * 1. Input graph is connected.
+ * 2. Dummy nodes are added for the tops and bottoms of subgraphs.
+ * 3. The minlen attribute for nodes is adjusted to ensure nodes do not
+ * get placed on the same rank as subgraph border nodes.
+ *
+ * The nesting graph idea comes from Sander, "Layout of Compound Directed
+ * Graphs."
+ */
+function run(g) {
+ var root = util.addDummyNode(g, "root", {}, "_root"),
+ depths = treeDepths(g),
+ height = _.max(depths) - 1,
+ nodeSep = 2 * height + 1;
+
+ g.graph().nestingRoot = root;
+
+ // Multiply minlen by nodeSep to align nodes on non-border ranks.
+ _.each(g.edges(), function(e) { g.edge(e).minlen *= nodeSep; });
+
+ // Calculate a weight that is sufficient to keep subgraphs vertically compact
+ var weight = sumWeights(g) + 1;
+
+ // Create border nodes and link them up
+ _.each(g.children(), function(child) {
+ dfs(g, root, nodeSep, weight, height, depths, child);
+ });
+
+ // Save the multiplier for node layers for later removal of empty border
+ // layers.
+ g.graph().nodeRankFactor = nodeSep;
+}
+
+function dfs(g, root, nodeSep, weight, height, depths, v) {
+ var children = g.children(v);
+ if (!children.length) {
+ if (v !== root) {
+ g.setEdge(root, v, { weight: 0, minlen: nodeSep });
+ }
+ return;
+ }
+
+ var top = util.addBorderNode(g, "_bt"),
+ bottom = util.addBorderNode(g, "_bb"),
+ label = g.node(v);
+
+ g.setParent(top, v);
+ label.borderTop = top;
+ g.setParent(bottom, v);
+ label.borderBottom = bottom;
+
+ _.each(children, function(child) {
+ dfs(g, root, nodeSep, weight, height, depths, child);
+
+ var childNode = g.node(child),
+ childTop = childNode.borderTop ? childNode.borderTop : child,
+ childBottom = childNode.borderBottom ? childNode.borderBottom : child,
+ thisWeight = childNode.borderTop ? weight : 2 * weight,
+ minlen = childTop !== childBottom ? 1 : height - depths[v] + 1;
+
+ g.setEdge(top, childTop, {
+ weight: thisWeight,
+ minlen: minlen,
+ nestingEdge: true
+ });
+
+ g.setEdge(childBottom, bottom, {
+ weight: thisWeight,
+ minlen: minlen,
+ nestingEdge: true
+ });
+ });
+
+ if (!g.parent(v)) {
+ g.setEdge(root, top, { weight: 0, minlen: height + depths[v] });
+ }
+}
+
+function treeDepths(g) {
+ var depths = {};
+ function dfs(v, depth) {
+ var children = g.children(v);
+ if (children && children.length) {
+ _.each(children, function(child) {
+ dfs(child, depth + 1);
+ });
+ }
+ depths[v] = depth;
+ }
+ _.each(g.children(), function(v) { dfs(v, 1); });
+ return depths;
+}
+
+function sumWeights(g) {
+ return _.reduce(g.edges(), function(acc, e) {
+ return acc + g.edge(e).weight;
+ }, 0);
+}
+
+function cleanup(g) {
+ var graphLabel = g.graph();
+ g.removeNode(graphLabel.nestingRoot);
+ delete graphLabel.nestingRoot;
+ _.each(g.edges(), function(e) {
+ var edge = g.edge(e);
+ if (edge.nestingEdge) {
+ g.removeEdge(e);
+ }
+ });
+}
+
+},{"./lodash":10,"./util":29}],12:[function(require,module,exports){
+"use strict";
+
+var _ = require("./lodash"),
+ util = require("./util");
+
+module.exports = {
+ run: run,
+ undo: undo
+};
+
+/*
+ * Breaks any long edges in the graph into short segments that span 1 layer
+ * each. This operation is undoable with the denormalize function.
+ *
+ * Pre-conditions:
+ *
+ * 1. The input graph is a DAG.
+ * 2. Each node in the graph has a "rank" property.
+ *
+ * Post-condition:
+ *
+ * 1. All edges in the graph have a length of 1.
+ * 2. Dummy nodes are added where edges have been split into segments.
+ * 3. The graph is augmented with a "dummyChains" attribute which contains
+ * the first dummy in each chain of dummy nodes produced.
+ */
+function run(g) {
+ g.graph().dummyChains = [];
+ _.each(g.edges(), function(edge) { normalizeEdge(g, edge); });
+}
+
+function normalizeEdge(g, e) {
+ var v = e.v,
+ vRank = g.node(v).rank,
+ w = e.w,
+ wRank = g.node(w).rank,
+ name = e.name,
+ edgeLabel = g.edge(e),
+ labelRank = edgeLabel.labelRank;
+
+ if (wRank === vRank + 1) return;
+
+ g.removeEdge(e);
+
+ var dummy, attrs, i;
+ for (i = 0, ++vRank; vRank < wRank; ++i, ++vRank) {
+ edgeLabel.points = [];
+ attrs = {
+ width: 0, height: 0,
+ edgeLabel: edgeLabel, edgeObj: e,
+ rank: vRank
+ };
+ dummy = util.addDummyNode(g, "edge", attrs, "_d");
+ if (vRank === labelRank) {
+ attrs.width = edgeLabel.width;
+ attrs.height = edgeLabel.height;
+ attrs.dummy = "edge-label";
+ attrs.labelpos = edgeLabel.labelpos;
+ }
+ g.setEdge(v, dummy, { weight: edgeLabel.weight }, name);
+ if (i === 0) {
+ g.graph().dummyChains.push(dummy);
+ }
+ v = dummy;
+ }
+
+ g.setEdge(v, w, { weight: edgeLabel.weight }, name);
+}
+
+function undo(g) {
+ _.each(g.graph().dummyChains, function(v) {
+ var node = g.node(v),
+ origLabel = node.edgeLabel,
+ w;
+ g.setEdge(node.edgeObj, origLabel);
+ while (node.dummy) {
+ w = g.successors(v)[0];
+ g.removeNode(v);
+ origLabel.points.push({ x: node.x, y: node.y });
+ if (node.dummy === "edge-label") {
+ origLabel.x = node.x;
+ origLabel.y = node.y;
+ origLabel.width = node.width;
+ origLabel.height = node.height;
+ }
+ v = w;
+ node = g.node(v);
+ }
+ });
+}
+
+},{"./lodash":10,"./util":29}],13:[function(require,module,exports){
+var _ = require("../lodash");
+
+module.exports = addSubgraphConstraints;
+
+function addSubgraphConstraints(g, cg, vs) {
+ var prev = {},
+ rootPrev;
+
+ _.each(vs, function(v) {
+ var child = g.parent(v),
+ parent,
+ prevChild;
+ while (child) {
+ parent = g.parent(child);
+ if (parent) {
+ prevChild = prev[parent];
+ prev[parent] = child;
+ } else {
+ prevChild = rootPrev;
+ rootPrev = child;
+ }
+ if (prevChild && prevChild !== child) {
+ cg.setEdge(prevChild, child);
+ return;
+ }
+ child = parent;
+ }
+ });
+
+ /*
+ function dfs(v) {
+ var children = v ? g.children(v) : g.children();
+ if (children.length) {
+ var min = Number.POSITIVE_INFINITY,
+ subgraphs = [];
+ _.each(children, function(child) {
+ var childMin = dfs(child);
+ if (g.children(child).length) {
+ subgraphs.push({ v: child, order: childMin });
+ }
+ min = Math.min(min, childMin);
+ });
+ _.reduce(_.sortBy(subgraphs, "order"), function(prev, curr) {
+ cg.setEdge(prev.v, curr.v);
+ return curr;
+ });
+ return min;
+ }
+ return g.node(v).order;
+ }
+ dfs(undefined);
+ */
+}
+
+},{"../lodash":10}],14:[function(require,module,exports){
+var _ = require("../lodash");
+
+module.exports = barycenter;
+
+function barycenter(g, movable) {
+ return _.map(movable, function(v) {
+ var inV = g.inEdges(v);
+ if (!inV.length) {
+ return { v: v };
+ } else {
+ var result = _.reduce(inV, function(acc, e) {
+ var edge = g.edge(e),
+ nodeU = g.node(e.v);
+ return {
+ sum: acc.sum + (edge.weight * nodeU.order),
+ weight: acc.weight + edge.weight
+ };
+ }, { sum: 0, weight: 0 });
+
+ return {
+ v: v,
+ barycenter: result.sum / result.weight,
+ weight: result.weight
+ };
+ }
+ });
+}
+
+
+},{"../lodash":10}],15:[function(require,module,exports){
+var _ = require("../lodash"),
+ Graph = require("../graphlib").Graph;
+
+module.exports = buildLayerGraph;
+
+/*
+ * Constructs a graph that can be used to sort a layer of nodes. The graph will
+ * contain all base and subgraph nodes from the request layer in their original
+ * hierarchy and any edges that are incident on these nodes and are of the type
+ * requested by the "relationship" parameter.
+ *
+ * Nodes from the requested rank that do not have parents are assigned a root
+ * node in the output graph, which is set in the root graph attribute. This
+ * makes it easy to walk the hierarchy of movable nodes during ordering.
+ *
+ * Pre-conditions:
+ *
+ * 1. Input graph is a DAG
+ * 2. Base nodes in the input graph have a rank attribute
+ * 3. Subgraph nodes in the input graph has minRank and maxRank attributes
+ * 4. Edges have an assigned weight
+ *
+ * Post-conditions:
+ *
+ * 1. Output graph has all nodes in the movable rank with preserved
+ * hierarchy.
+ * 2. Root nodes in the movable layer are made children of the node
+ * indicated by the root attribute of the graph.
+ * 3. Non-movable nodes incident on movable nodes, selected by the
+ * relationship parameter, are included in the graph (without hierarchy).
+ * 4. Edges incident on movable nodes, selected by the relationship
+ * parameter, are added to the output graph.
+ * 5. The weights for copied edges are aggregated as need, since the output
+ * graph is not a multi-graph.
+ */
+function buildLayerGraph(g, rank, relationship) {
+ var root = createRootNode(g),
+ result = new Graph({ compound: true }).setGraph({ root: root })
+ .setDefaultNodeLabel(function(v) { return g.node(v); });
+
+ _.each(g.nodes(), function(v) {
+ var node = g.node(v),
+ parent = g.parent(v);
+
+ if (node.rank === rank || node.minRank <= rank && rank <= node.maxRank) {
+ result.setNode(v);
+ result.setParent(v, parent || root);
+
+ // This assumes we have only short edges!
+ _.each(g[relationship](v), function(e) {
+ var u = e.v === v ? e.w : e.v,
+ edge = result.edge(u, v),
+ weight = !_.isUndefined(edge) ? edge.weight : 0;
+ result.setEdge(u, v, { weight: g.edge(e).weight + weight });
+ });
+
+ if (_.has(node, "minRank")) {
+ result.setNode(v, {
+ borderLeft: node.borderLeft[rank],
+ borderRight: node.borderRight[rank]
+ });
+ }
+ }
+ });
+
+ return result;
+}
+
+function createRootNode(g) {
+ var v;
+ while (g.hasNode((v = _.uniqueId("_root"))));
+ return v;
+}
+
+},{"../graphlib":7,"../lodash":10}],16:[function(require,module,exports){
+"use strict";
+
+var _ = require("../lodash");
+
+module.exports = crossCount;
+
+/*
+ * A function that takes a layering (an array of layers, each with an array of
+ * ordererd nodes) and a graph and returns a weighted crossing count.
+ *
+ * Pre-conditions:
+ *
+ * 1. Input graph must be simple (not a multigraph), directed, and include
+ * only simple edges.
+ * 2. Edges in the input graph must have assigned weights.
+ *
+ * Post-conditions:
+ *
+ * 1. The graph and layering matrix are left unchanged.
+ *
+ * This algorithm is derived from Barth, et al., "Bilayer Cross Counting."
+ */
+function crossCount(g, layering) {
+ var cc = 0;
+ for (var i = 1; i < layering.length; ++i) {
+ cc += twoLayerCrossCount(g, layering[i-1], layering[i]);
+ }
+ return cc;
+}
+
+function twoLayerCrossCount(g, northLayer, southLayer) {
+ // Sort all of the edges between the north and south layers by their position
+ // in the north layer and then the south. Map these edges to the position of
+ // their head in the south layer.
+ var southPos = _.zipObject(southLayer,
+ _.map(southLayer, function (v, i) { return i; }));
+ var southEntries = _.flatten(_.map(northLayer, function(v) {
+ return _.chain(g.outEdges(v))
+ .map(function(e) {
+ return { pos: southPos[e.w], weight: g.edge(e).weight };
+ })
+ .sortBy("pos")
+ .value();
+ }), true);
+
+ // Build the accumulator tree
+ var firstIndex = 1;
+ while (firstIndex < southLayer.length) firstIndex <<= 1;
+ var treeSize = 2 * firstIndex - 1;
+ firstIndex -= 1;
+ var tree = _.map(new Array(treeSize), function() { return 0; });
+
+ // Calculate the weighted crossings
+ var cc = 0;
+ _.each(southEntries.forEach(function(entry) {
+ var index = entry.pos + firstIndex;
+ tree[index] += entry.weight;
+ var weightSum = 0;
+ while (index > 0) {
+ if (index % 2) {
+ weightSum += tree[index + 1];
+ }
+ index = (index - 1) >> 1;
+ tree[index] += entry.weight;
+ }
+ cc += entry.weight * weightSum;
+ }));
+
+ return cc;
+}
+
+},{"../lodash":10}],17:[function(require,module,exports){
+"use strict";
+
+var _ = require("../lodash"),
+ initOrder = require("./init-order"),
+ crossCount = require("./cross-count"),
+ sortSubgraph = require("./sort-subgraph"),
+ buildLayerGraph = require("./build-layer-graph"),
+ addSubgraphConstraints = require("./add-subgraph-constraints"),
+ Graph = require("../graphlib").Graph,
+ util = require("../util");
+
+module.exports = order;
+
+/*
+ * Applies heuristics to minimize edge crossings in the graph and sets the best
+ * order solution as an order attribute on each node.
+ *
+ * Pre-conditions:
+ *
+ * 1. Graph must be DAG
+ * 2. Graph nodes must be objects with a "rank" attribute
+ * 3. Graph edges must have the "weight" attribute
+ *
+ * Post-conditions:
+ *
+ * 1. Graph nodes will have an "order" attribute based on the results of the
+ * algorithm.
+ */
+function order(g) {
+ var maxRank = util.maxRank(g),
+ downLayerGraphs = buildLayerGraphs(g, _.range(1, maxRank + 1), "inEdges"),
+ upLayerGraphs = buildLayerGraphs(g, _.range(maxRank - 1, -1, -1), "outEdges");
+
+ var layering = initOrder(g);
+ assignOrder(g, layering);
+
+ var bestCC = Number.POSITIVE_INFINITY,
+ best;
+
+ for (var i = 0, lastBest = 0; lastBest < 4; ++i, ++lastBest) {
+ sweepLayerGraphs(i % 2 ? downLayerGraphs : upLayerGraphs, i % 4 >= 2);
+
+ layering = util.buildLayerMatrix(g);
+ var cc = crossCount(g, layering);
+ if (cc < bestCC) {
+ lastBest = 0;
+ best = _.cloneDeep(layering);
+ bestCC = cc;
+ }
+ }
+
+ assignOrder(g, best);
+}
+
+function buildLayerGraphs(g, ranks, relationship) {
+ return _.map(ranks, function(rank) {
+ return buildLayerGraph(g, rank, relationship);
+ });
+}
+
+function sweepLayerGraphs(layerGraphs, biasRight) {
+ var cg = new Graph();
+ _.each(layerGraphs, function(lg) {
+ var root = lg.graph().root;
+ var sorted = sortSubgraph(lg, root, cg, biasRight);
+ _.each(sorted.vs, function(v, i) {
+ lg.node(v).order = i;
+ });
+ addSubgraphConstraints(lg, cg, sorted.vs);
+ });
+}
+
+function assignOrder(g, layering) {
+ _.each(layering, function(layer) {
+ _.each(layer, function(v, i) {
+ g.node(v).order = i;
+ });
+ });
+}
+
+},{"../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){
+"use strict";
+
+var _ = require("../lodash");
+
+module.exports = initOrder;
+
+/*
+ * Assigns an initial order value for each node by performing a DFS search
+ * starting from nodes in the first rank. Nodes are assigned an order in their
+ * rank as they are first visited.
+ *
+ * This approach comes from Gansner, et al., "A Technique for Drawing Directed
+ * Graphs."
+ *
+ * Returns a layering matrix with an array per layer and each layer sorted by
+ * the order of its nodes.
+ */
+function initOrder(g) {
+ var visited = {},
+ simpleNodes = _.filter(g.nodes(), function(v) {
+ return !g.children(v).length;
+ }),
+ maxRank = _.max(_.map(simpleNodes, function(v) { return g.node(v).rank; })),
+ layers = _.map(_.range(maxRank + 1), function() { return []; });
+
+ function dfs(v) {
+ if (_.has(visited, v)) return;
+ visited[v] = true;
+ var node = g.node(v);
+ layers[node.rank].push(v);
+ _.each(g.successors(v), dfs);
+ }
+
+ var orderedVs = _.sortBy(simpleNodes, function(v) { return g.node(v).rank; });
+ _.each(orderedVs, dfs);
+
+ return layers;
+}
+
+},{"../lodash":10}],19:[function(require,module,exports){
+"use strict";
+
+var _ = require("../lodash");
+
+module.exports = resolveConflicts;
+
+/*
+ * Given a list of entries of the form {v, barycenter, weight} and a
+ * constraint graph this function will resolve any conflicts between the
+ * constraint graph and the barycenters for the entries. If the barycenters for
+ * an entry would violate a constraint in the constraint graph then we coalesce
+ * the nodes in the conflict into a new node that respects the contraint and
+ * aggregates barycenter and weight information.
+ *
+ * This implementation is based on the description in Forster, "A Fast and
+ * Simple Hueristic for Constrained Two-Level Crossing Reduction," thought it
+ * differs in some specific details.
+ *
+ * Pre-conditions:
+ *
+ * 1. Each entry has the form {v, barycenter, weight}, or if the node has
+ * no barycenter, then {v}.
+ *
+ * Returns:
+ *
+ * A new list of entries of the form {vs, i, barycenter, weight}. The list
+ * `vs` may either be a singleton or it may be an aggregation of nodes
+ * ordered such that they do not violate constraints from the constraint
+ * graph. The property `i` is the lowest original index of any of the
+ * elements in `vs`.
+ */
+function resolveConflicts(entries, cg) {
+ var mappedEntries = {};
+ _.each(entries, function(entry, i) {
+ var tmp = mappedEntries[entry.v] = {
+ indegree: 0,
+ "in": [],
+ out: [],
+ vs: [entry.v],
+ i: i
+ };
+ if (!_.isUndefined(entry.barycenter)) {
+ tmp.barycenter = entry.barycenter;
+ tmp.weight = entry.weight;
+ }
+ });
+
+ _.each(cg.edges(), function(e) {
+ var entryV = mappedEntries[e.v],
+ entryW = mappedEntries[e.w];
+ if (!_.isUndefined(entryV) && !_.isUndefined(entryW)) {
+ entryW.indegree++;
+ entryV.out.push(mappedEntries[e.w]);
+ }
+ });
+
+ var sourceSet = _.filter(mappedEntries, function(entry) {
+ return !entry.indegree;
+ });
+
+ return doResolveConflicts(sourceSet);
+}
+
+function doResolveConflicts(sourceSet) {
+ var entries = [];
+
+ function handleIn(vEntry) {
+ return function(uEntry) {
+ if (uEntry.merged) {
+ return;
+ }
+ if (_.isUndefined(uEntry.barycenter) ||
+ _.isUndefined(vEntry.barycenter) ||
+ uEntry.barycenter >= vEntry.barycenter) {
+ mergeEntries(vEntry, uEntry);
+ }
+ };
+ }
+
+ function handleOut(vEntry) {
+ return function(wEntry) {
+ wEntry["in"].push(vEntry);
+ if (--wEntry.indegree === 0) {
+ sourceSet.push(wEntry);
+ }
+ };
+ }
+
+ while (sourceSet.length) {
+ var entry = sourceSet.pop();
+ entries.push(entry);
+ _.each(entry["in"].reverse(), handleIn(entry));
+ _.each(entry.out, handleOut(entry));
+ }
+
+ return _.chain(entries)
+ .filter(function(entry) { return !entry.merged; })
+ .map(function(entry) {
+ return _.pick(entry, ["vs", "i", "barycenter", "weight"]);
+ })
+ .value();
+}
+
+function mergeEntries(target, source) {
+ var sum = 0,
+ weight = 0;
+
+ if (target.weight) {
+ sum += target.barycenter * target.weight;
+ weight += target.weight;
+ }
+
+ if (source.weight) {
+ sum += source.barycenter * source.weight;
+ weight += source.weight;
+ }
+
+ target.vs = source.vs.concat(target.vs);
+ target.barycenter = sum / weight;
+ target.weight = weight;
+ target.i = Math.min(source.i, target.i);
+ source.merged = true;
+}
+
+},{"../lodash":10}],20:[function(require,module,exports){
+var _ = require("../lodash"),
+ barycenter = require("./barycenter"),
+ resolveConflicts = require("./resolve-conflicts"),
+ sort = require("./sort");
+
+module.exports = sortSubgraph;
+
+function sortSubgraph(g, v, cg, biasRight) {
+ var movable = g.children(v),
+ node = g.node(v),
+ bl = node ? node.borderLeft : undefined,
+ br = node ? node.borderRight: undefined,
+ subgraphs = {};
+
+ if (bl) {
+ movable = _.filter(movable, function(w) {
+ return w !== bl && w !== br;
+ });
+ }
+
+ var barycenters = barycenter(g, movable);
+ _.each(barycenters, function(entry) {
+ if (g.children(entry.v).length) {
+ var subgraphResult = sortSubgraph(g, entry.v, cg, biasRight);
+ subgraphs[entry.v] = subgraphResult;
+ if (_.has(subgraphResult, "barycenter")) {
+ mergeBarycenters(entry, subgraphResult);
+ }
+ }
+ });
+
+ var entries = resolveConflicts(barycenters, cg);
+ expandSubgraphs(entries, subgraphs);
+
+ var result = sort(entries, biasRight);
+
+ if (bl) {
+ result.vs = _.flatten([bl, result.vs, br], true);
+ if (g.predecessors(bl).length) {
+ var blPred = g.node(g.predecessors(bl)[0]),
+ brPred = g.node(g.predecessors(br)[0]);
+ if (!_.has(result, "barycenter")) {
+ result.barycenter = 0;
+ result.weight = 0;
+ }
+ result.barycenter = (result.barycenter * result.weight +
+ blPred.order + brPred.order) / (result.weight + 2);
+ result.weight += 2;
+ }
+ }
+
+ return result;
+}
+
+function expandSubgraphs(entries, subgraphs) {
+ _.each(entries, function(entry) {
+ entry.vs = _.flatten(entry.vs.map(function(v) {
+ if (subgraphs[v]) {
+ return subgraphs[v].vs;
+ }
+ return v;
+ }), true);
+ });
+}
+
+function mergeBarycenters(target, other) {
+ if (!_.isUndefined(target.barycenter)) {
+ target.barycenter = (target.barycenter * target.weight +
+ other.barycenter * other.weight) /
+ (target.weight + other.weight);
+ target.weight += other.weight;
+ } else {
+ target.barycenter = other.barycenter;
+ target.weight = other.weight;
+ }
+}
+
+},{"../lodash":10,"./barycenter":14,"./resolve-conflicts":19,"./sort":21}],21:[function(require,module,exports){
+var _ = require("../lodash"),
+ util = require("../util");
+
+module.exports = sort;
+
+function sort(entries, biasRight) {
+ var parts = util.partition(entries, function(entry) {
+ return _.has(entry, "barycenter");
+ });
+ var sortable = parts.lhs,
+ unsortable = _.sortBy(parts.rhs, function(entry) { return -entry.i; }),
+ vs = [],
+ sum = 0,
+ weight = 0,
+ vsIndex = 0;
+
+ sortable.sort(compareWithBias(!!biasRight));
+
+ vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
+
+ _.each(sortable, function (entry) {
+ vsIndex += entry.vs.length;
+ vs.push(entry.vs);
+ sum += entry.barycenter * entry.weight;
+ weight += entry.weight;
+ vsIndex = consumeUnsortable(vs, unsortable, vsIndex);
+ });
+
+ var result = { vs: _.flatten(vs, true) };
+ if (weight) {
+ result.barycenter = sum / weight;
+ result.weight = weight;
+ }
+ return result;
+}
+
+function consumeUnsortable(vs, unsortable, index) {
+ var last;
+ while (unsortable.length && (last = _.last(unsortable)).i <= index) {
+ unsortable.pop();
+ vs.push(last.vs);
+ index++;
+ }
+ return index;
+}
+
+function compareWithBias(bias) {
+ return function(entryV, entryW) {
+ if (entryV.barycenter < entryW.barycenter) {
+ return -1;
+ } else if (entryV.barycenter > entryW.barycenter) {
+ return 1;
+ }
+
+ return !bias ? entryV.i - entryW.i : entryW.i - entryV.i;
+ };
+}
+
+},{"../lodash":10,"../util":29}],22:[function(require,module,exports){
+var _ = require("./lodash");
+
+module.exports = parentDummyChains;
+
+function parentDummyChains(g) {
+ var postorderNums = postorder(g);
+
+ _.each(g.graph().dummyChains, function(v) {
+ var node = g.node(v),
+ edgeObj = node.edgeObj,
+ pathData = findPath(g, postorderNums, edgeObj.v, edgeObj.w),
+ path = pathData.path,
+ lca = pathData.lca,
+ pathIdx = 0,
+ pathV = path[pathIdx],
+ ascending = true;
+
+ while (v !== edgeObj.w) {
+ node = g.node(v);
+
+ if (ascending) {
+ while ((pathV = path[pathIdx]) !== lca &&
+ g.node(pathV).maxRank < node.rank) {
+ pathIdx++;
+ }
+
+ if (pathV === lca) {
+ ascending = false;
+ }
+ }
+
+ if (!ascending) {
+ while (pathIdx < path.length - 1 &&
+ g.node(pathV = path[pathIdx + 1]).minRank <= node.rank) {
+ pathIdx++;
+ }
+ pathV = path[pathIdx];
+ }
+
+ g.setParent(v, pathV);
+ v = g.successors(v)[0];
+ }
+ });
+}
+
+// Find a path from v to w through the lowest common ancestor (LCA). Return the
+// full path and the LCA.
+function findPath(g, postorderNums, v, w) {
+ var vPath = [],
+ wPath = [],
+ low = Math.min(postorderNums[v].low, postorderNums[w].low),
+ lim = Math.max(postorderNums[v].lim, postorderNums[w].lim),
+ parent,
+ lca;
+
+ // Traverse up from v to find the LCA
+ parent = v;
+ do {
+ parent = g.parent(parent);
+ vPath.push(parent);
+ } while (parent &&
+ (postorderNums[parent].low > low || lim > postorderNums[parent].lim));
+ lca = parent;
+
+ // Traverse from w to LCA
+ parent = w;
+ while ((parent = g.parent(parent)) !== lca) {
+ wPath.push(parent);
+ }
+
+ return { path: vPath.concat(wPath.reverse()), lca: lca };
+}
+
+function postorder(g) {
+ var result = {},
+ lim = 0;
+
+ function dfs(v) {
+ var low = lim;
+ _.each(g.children(v), dfs);
+ result[v] = { low: low, lim: lim++ };
+ }
+ _.each(g.children(), dfs);
+
+ return result;
+}
+
+},{"./lodash":10}],23:[function(require,module,exports){
+"use strict";
+
+var _ = require("../lodash"),
+ Graph = require("../graphlib").Graph,
+ util = require("../util");
+
+/*
+ * This module provides coordinate assignment based on Brandes and Köpf, "Fast
+ * and Simple Horizontal Coordinate Assignment."
+ */
+
+module.exports = {
+ positionX: positionX,
+ findType1Conflicts: findType1Conflicts,
+ findType2Conflicts: findType2Conflicts,
+ addConflict: addConflict,
+ hasConflict: hasConflict,
+ verticalAlignment: verticalAlignment,
+ horizontalCompaction: horizontalCompaction,
+ alignCoordinates: alignCoordinates,
+ findSmallestWidthAlignment: findSmallestWidthAlignment,
+ balance: balance
+};
+
+/*
+ * Marks all edges in the graph with a type-1 conflict with the "type1Conflict"
+ * property. A type-1 conflict is one where a non-inner segment crosses an
+ * inner segment. An inner segment is an edge with both incident nodes marked
+ * with the "dummy" property.
+ *
+ * This algorithm scans layer by layer, starting with the second, for type-1
+ * conflicts between the current layer and the previous layer. For each layer
+ * it scans the nodes from left to right until it reaches one that is incident
+ * on an inner segment. It then scans predecessors to determine if they have
+ * edges that cross that inner segment. At the end a final scan is done for all
+ * nodes on the current rank to see if they cross the last visited inner
+ * segment.
+ *
+ * This algorithm (safely) assumes that a dummy node will only be incident on a
+ * single node in the layers being scanned.
+ */
+function findType1Conflicts(g, layering) {
+ var conflicts = {};
+
+ function visitLayer(prevLayer, layer) {
+ var
+ // last visited node in the previous layer that is incident on an inner
+ // segment.
+ k0 = 0,
+ // Tracks the last node in this layer scanned for crossings with a type-1
+ // segment.
+ scanPos = 0,
+ prevLayerLength = prevLayer.length,
+ lastNode = _.last(layer);
+
+ _.each(layer, function(v, i) {
+ var w = findOtherInnerSegmentNode(g, v),
+ k1 = w ? g.node(w).order : prevLayerLength;
+
+ if (w || v === lastNode) {
+ _.each(layer.slice(scanPos, i +1), function(scanNode) {
+ _.each(g.predecessors(scanNode), function(u) {
+ var uLabel = g.node(u),
+ uPos = uLabel.order;
+ if ((uPos < k0 || k1 < uPos) &&
+ !(uLabel.dummy && g.node(scanNode).dummy)) {
+ addConflict(conflicts, u, scanNode);
+ }
+ });
+ });
+ scanPos = i + 1;
+ k0 = k1;
+ }
+ });
+
+ return layer;
+ }
+
+ _.reduce(layering, visitLayer);
+ return conflicts;
+}
+
+function findType2Conflicts(g, layering) {
+ var conflicts = {};
+
+ function scan(south, southPos, southEnd, prevNorthBorder, nextNorthBorder) {
+ var v;
+ _.each(_.range(southPos, southEnd), function(i) {
+ v = south[i];
+ if (g.node(v).dummy) {
+ _.each(g.predecessors(v), function(u) {
+ var uNode = g.node(u);
+ if (uNode.dummy &&
+ (uNode.order < prevNorthBorder || uNode.order > nextNorthBorder)) {
+ addConflict(conflicts, u, v);
+ }
+ });
+ }
+ });
+ }
+
+
+ function visitLayer(north, south) {
+ var prevNorthPos = -1,
+ nextNorthPos,
+ southPos = 0;
+
+ _.each(south, function(v, southLookahead) {
+ if (g.node(v).dummy === "border") {
+ var predecessors = g.predecessors(v);
+ if (predecessors.length) {
+ nextNorthPos = g.node(predecessors[0]).order;
+ scan(south, southPos, southLookahead, prevNorthPos, nextNorthPos);
+ southPos = southLookahead;
+ prevNorthPos = nextNorthPos;
+ }
+ }
+ scan(south, southPos, south.length, nextNorthPos, north.length);
+ });
+
+ return south;
+ }
+
+ _.reduce(layering, visitLayer);
+ return conflicts;
+}
+
+function findOtherInnerSegmentNode(g, v) {
+ if (g.node(v).dummy) {
+ return _.find(g.predecessors(v), function(u) {
+ return g.node(u).dummy;
+ });
+ }
+}
+
+function addConflict(conflicts, v, w) {
+ if (v > w) {
+ var tmp = v;
+ v = w;
+ w = tmp;
+ }
+
+ var conflictsV = conflicts[v];
+ if (!conflictsV) {
+ conflicts[v] = conflictsV = {};
+ }
+ conflictsV[w] = true;
+}
+
+function hasConflict(conflicts, v, w) {
+ if (v > w) {
+ var tmp = v;
+ v = w;
+ w = tmp;
+ }
+ return _.has(conflicts[v], w);
+}
+
+/*
+ * Try to align nodes into vertical "blocks" where possible. This algorithm
+ * attempts to align a node with one of its median neighbors. If the edge
+ * connecting a neighbor is a type-1 conflict then we ignore that possibility.
+ * If a previous node has already formed a block with a node after the node
+ * we're trying to form a block with, we also ignore that possibility - our
+ * blocks would be split in that scenario.
+ */
+function verticalAlignment(g, layering, conflicts, neighborFn) {
+ var root = {},
+ align = {},
+ pos = {};
+
+ // We cache the position here based on the layering because the graph and
+ // layering may be out of sync. The layering matrix is manipulated to
+ // generate different extreme alignments.
+ _.each(layering, function(layer) {
+ _.each(layer, function(v, order) {
+ root[v] = v;
+ align[v] = v;
+ pos[v] = order;
+ });
+ });
+
+ _.each(layering, function(layer) {
+ var prevIdx = -1;
+ _.each(layer, function(v) {
+ var ws = neighborFn(v);
+ if (ws.length) {
+ ws = _.sortBy(ws, function(w) { return pos[w]; });
+ var mp = (ws.length - 1) / 2;
+ for (var i = Math.floor(mp), il = Math.ceil(mp); i <= il; ++i) {
+ var w = ws[i];
+ if (align[v] === v &&
+ prevIdx < pos[w] &&
+ !hasConflict(conflicts, v, w)) {
+ align[w] = v;
+ align[v] = root[v] = root[w];
+ prevIdx = pos[w];
+ }
+ }
+ }
+ });
+ });
+
+ return { root: root, align: align };
+}
+
+function horizontalCompaction(g, layering, root, align, reverseSep) {
+ // This portion of the algorithm differs from BK due to a number of problems.
+ // Instead of their algorithm we construct a new block graph and do two
+ // sweeps. The first sweep places blocks with the smallest possible
+ // coordinates. The second sweep removes unused space by moving blocks to the
+ // greatest coordinates without violating separation.
+ var xs = {},
+ blockG = buildBlockGraph(g, layering, root, reverseSep);
+
+ // First pass, assign smallest coordinates via DFS
+ var visited = {};
+ function pass1(v) {
+ if (!_.has(visited, v)) {
+ visited[v] = true;
+ xs[v] = _.reduce(blockG.inEdges(v), function(max, e) {
+ pass1(e.v);
+ return Math.max(max, xs[e.v] + blockG.edge(e));
+ }, 0);
+ }
+ }
+ _.each(blockG.nodes(), pass1);
+
+ var borderType = reverseSep ? "borderLeft" : "borderRight";
+ function pass2(v) {
+ if (visited[v] !== 2) {
+ visited[v]++;
+ var node = g.node(v);
+ var min = _.reduce(blockG.outEdges(v), function(min, e) {
+ pass2(e.w);
+ return Math.min(min, xs[e.w] - blockG.edge(e));
+ }, Number.POSITIVE_INFINITY);
+ if (min !== Number.POSITIVE_INFINITY && node.borderType !== borderType) {
+ xs[v] = Math.max(xs[v], min);
+ }
+ }
+ }
+ _.each(blockG.nodes(), pass2);
+
+ // Assign x coordinates to all nodes
+ _.each(align, function(v) {
+ xs[v] = xs[root[v]];
+ });
+
+ return xs;
+}
+
+
+function buildBlockGraph(g, layering, root, reverseSep) {
+ var blockGraph = new Graph(),
+ graphLabel = g.graph(),
+ sepFn = sep(graphLabel.nodesep, graphLabel.edgesep, reverseSep);
+
+ _.each(layering, function(layer) {
+ var u;
+ _.each(layer, function(v) {
+ var vRoot = root[v];
+ blockGraph.setNode(vRoot);
+ if (u) {
+ var uRoot = root[u],
+ prevMax = blockGraph.edge(uRoot, vRoot);
+ blockGraph.setEdge(uRoot, vRoot, Math.max(sepFn(g, v, u), prevMax || 0));
+ }
+ u = v;
+ });
+ });
+
+ return blockGraph;
+}
+
+/*
+ * Returns the alignment that has the smallest width of the given alignments.
+ */
+function findSmallestWidthAlignment(g, xss) {
+ return _.min(xss, function(xs) {
+ var min = _.min(xs, function(x, v) { return x - width(g, v) / 2; }),
+ max = _.max(xs, function(x, v) { return x + width(g, v) / 2; });
+ return max - min;
+ });
+}
+
+/*
+ * Align the coordinates of each of the layout alignments such that
+ * left-biased alignments have their minimum coordinate at the same point as
+ * the minimum coordinate of the smallest width alignment and right-biased
+ * alignments have their maximum coordinate at the same point as the maximum
+ * coordinate of the smallest width alignment.
+ */
+function alignCoordinates(xss, alignTo) {
+ var alignToMin = _.min(alignTo),
+ alignToMax = _.max(alignTo);
+
+ _.each(["u", "d"], function(vert) {
+ _.each(["l", "r"], function(horiz) {
+ var alignment = vert + horiz,
+ xs = xss[alignment],
+ delta;
+ if (xs === alignTo) return;
+
+ delta = horiz === "l" ? alignToMin - _.min(xs) : alignToMax - _.max(xs);
+
+ if (delta) {
+ xss[alignment] = _.mapValues(xs, function(x) { return x + delta; });
+ }
+ });
+ });
+}
+
+function balance(xss, align) {
+ return _.mapValues(xss.ul, function(ignore, v) {
+ if (align) {
+ return xss[align.toLowerCase()][v];
+ } else {
+ var xs = _.sortBy(_.pluck(xss, v));
+ return (xs[1] + xs[2]) / 2;
+ }
+ });
+}
+
+function positionX(g) {
+ var layering = util.buildLayerMatrix(g),
+ conflicts = _.merge(findType1Conflicts(g, layering),
+ findType2Conflicts(g, layering));
+
+ var xss = {},
+ adjustedLayering;
+ _.each(["u", "d"], function(vert) {
+ adjustedLayering = vert === "u" ? layering : _.values(layering).reverse();
+ _.each(["l", "r"], function(horiz) {
+ if (horiz === "r") {
+ adjustedLayering = _.map(adjustedLayering, function(inner) {
+ return _.values(inner).reverse();
+ });
+ }
+
+ var neighborFn = _.bind(vert === "u" ? g.predecessors : g.successors, g);
+ var align = verticalAlignment(g, adjustedLayering, conflicts, neighborFn);
+ var xs = horizontalCompaction(g, adjustedLayering,
+ align.root, align.align,
+ horiz === "r");
+ if (horiz === "r") {
+ xs = _.mapValues(xs, function(x) { return -x; });
+ }
+ xss[vert + horiz] = xs;
+ });
+ });
+
+ var smallestWidth = findSmallestWidthAlignment(g, xss);
+ alignCoordinates(xss, smallestWidth);
+ return balance(xss, g.graph().align);
+}
+
+function sep(nodeSep, edgeSep, reverseSep) {
+ return function(g, v, w) {
+ var vLabel = g.node(v),
+ wLabel = g.node(w),
+ sum = 0,
+ delta;
+
+ sum += vLabel.width / 2;
+ if (_.has(vLabel, "labelpos")) {
+ switch (vLabel.labelpos.toLowerCase()) {
+ case "l": delta = -vLabel.width / 2; break;
+ case "r": delta = vLabel.width / 2; break;
+ }
+ }
+ if (delta) {
+ sum += reverseSep ? delta : -delta;
+ }
+ delta = 0;
+
+ sum += (vLabel.dummy ? edgeSep : nodeSep) / 2;
+ sum += (wLabel.dummy ? edgeSep : nodeSep) / 2;
+
+ sum += wLabel.width / 2;
+ if (_.has(wLabel, "labelpos")) {
+ switch (wLabel.labelpos.toLowerCase()) {
+ case "l": delta = wLabel.width / 2; break;
+ case "r": delta = -wLabel.width / 2; break;
+ }
+ }
+ if (delta) {
+ sum += reverseSep ? delta : -delta;
+ }
+ delta = 0;
+
+ return sum;
+ };
+}
+
+function width(g, v) {
+ return g.node(v).width;
+}
+
+},{"../graphlib":7,"../lodash":10,"../util":29}],24:[function(require,module,exports){
+"use strict";
+
+var _ = require("../lodash"),
+ util = require("../util"),
+ positionX = require("./bk").positionX;
+
+module.exports = position;
+
+function position(g) {
+ g = util.asNonCompoundGraph(g);
+
+ positionY(g);
+ _.each(positionX(g), function(x, v) {
+ g.node(v).x = x;
+ });
+}
+
+function positionY(g) {
+ var layering = util.buildLayerMatrix(g),
+ rankSep = g.graph().ranksep,
+ prevY = 0;
+ _.each(layering, function(layer) {
+ var maxHeight = _.max(_.map(layer, function(v) { return g.node(v).height; }));
+ _.each(layer, function(v) {
+ g.node(v).y = prevY + maxHeight / 2;
+ });
+ prevY += maxHeight + rankSep;
+ });
+}
+
+
+},{"../lodash":10,"../util":29,"./bk":23}],25:[function(require,module,exports){
+"use strict";
+
+var _ = require("../lodash"),
+ Graph = require("../graphlib").Graph,
+ slack = require("./util").slack;
+
+module.exports = feasibleTree;
+
+/*
+ * Constructs a spanning tree with tight edges and adjusted the input node's
+ * ranks to achieve this. A tight edge is one that is has a length that matches
+ * its "minlen" attribute.
+ *
+ * The basic structure for this function is derived from Gansner, et al., "A
+ * Technique for Drawing Directed Graphs."
+ *
+ * Pre-conditions:
+ *
+ * 1. Graph must be a DAG.
+ * 2. Graph must be connected.
+ * 3. Graph must have at least one node.
+ * 5. Graph nodes must have been previously assigned a "rank" property that
+ * respects the "minlen" property of incident edges.
+ * 6. Graph edges must have a "minlen" property.
+ *
+ * Post-conditions:
+ *
+ * - Graph nodes will have their rank adjusted to ensure that all edges are
+ * tight.
+ *
+ * Returns a tree (undirected graph) that is constructed using only "tight"
+ * edges.
+ */
+function feasibleTree(g) {
+ var t = new Graph({ directed: false });
+
+ // Choose arbitrary node from which to start our tree
+ var start = g.nodes()[0],
+ size = g.nodeCount();
+ t.setNode(start, {});
+
+ var edge, delta;
+ while (tightTree(t, g) < size) {
+ edge = findMinSlackEdge(t, g);
+ delta = t.hasNode(edge.v) ? slack(g, edge) : -slack(g, edge);
+ shiftRanks(t, g, delta);
+ }
+
+ return t;
+}
+
+/*
+ * Finds a maximal tree of tight edges and returns the number of nodes in the
+ * tree.
+ */
+function tightTree(t, g) {
+ function dfs(v) {
+ _.each(g.nodeEdges(v), function(e) {
+ var edgeV = e.v,
+ w = (v === edgeV) ? e.w : edgeV;
+ if (!t.hasNode(w) && !slack(g, e)) {
+ t.setNode(w, {});
+ t.setEdge(v, w, {});
+ dfs(w);
+ }
+ });
+ }
+
+ _.each(t.nodes(), dfs);
+ return t.nodeCount();
+}
+
+/*
+ * Finds the edge with the smallest slack that is incident on tree and returns
+ * it.
+ */
+function findMinSlackEdge(t, g) {
+ return _.min(g.edges(), function(e) {
+ if (t.hasNode(e.v) !== t.hasNode(e.w)) {
+ return slack(g, e);
+ }
+ });
+}
+
+function shiftRanks(t, g, delta) {
+ _.each(t.nodes(), function(v) {
+ g.node(v).rank += delta;
+ });
+}
+
+},{"../graphlib":7,"../lodash":10,"./util":28}],26:[function(require,module,exports){
+"use strict";
+
+var rankUtil = require("./util"),
+ longestPath = rankUtil.longestPath,
+ feasibleTree = require("./feasible-tree"),
+ networkSimplex = require("./network-simplex");
+
+module.exports = rank;
+
+/*
+ * Assigns a rank to each node in the input graph that respects the "minlen"
+ * constraint specified on edges between nodes.
+ *
+ * This basic structure is derived from Gansner, et al., "A Technique for
+ * Drawing Directed Graphs."
+ *
+ * Pre-conditions:
+ *
+ * 1. Graph must be a connected DAG
+ * 2. Graph nodes must be objects
+ * 3. Graph edges must have "weight" and "minlen" attributes
+ *
+ * Post-conditions:
+ *
+ * 1. Graph nodes will have a "rank" attribute based on the results of the
+ * algorithm. Ranks can start at any index (including negative), we'll
+ * fix them up later.
+ */
+function rank(g) {
+ switch(g.graph().ranker) {
+ case "network-simplex": networkSimplexRanker(g); break;
+ case "tight-tree": tightTreeRanker(g); break;
+ case "longest-path": longestPathRanker(g); break;
+ default: networkSimplexRanker(g);
+ }
+}
+
+// A fast and simple ranker, but results are far from optimal.
+var longestPathRanker = longestPath;
+
+function tightTreeRanker(g) {
+ longestPath(g);
+ feasibleTree(g);
+}
+
+function networkSimplexRanker(g) {
+ networkSimplex(g);
+}
+
+},{"./feasible-tree":25,"./network-simplex":27,"./util":28}],27:[function(require,module,exports){
+"use strict";
+
+var _ = require("../lodash"),
+ feasibleTree = require("./feasible-tree"),
+ slack = require("./util").slack,
+ initRank = require("./util").longestPath,
+ preorder = require("../graphlib").alg.preorder,
+ postorder = require("../graphlib").alg.postorder,
+ simplify = require("../util").simplify;
+
+module.exports = networkSimplex;
+
+// Expose some internals for testing purposes
+networkSimplex.initLowLimValues = initLowLimValues;
+networkSimplex.initCutValues = initCutValues;
+networkSimplex.calcCutValue = calcCutValue;
+networkSimplex.leaveEdge = leaveEdge;
+networkSimplex.enterEdge = enterEdge;
+networkSimplex.exchangeEdges = exchangeEdges;
+
+/*
+ * The network simplex algorithm assigns ranks to each node in the input graph
+ * and iteratively improves the ranking to reduce the length of edges.
+ *
+ * Preconditions:
+ *
+ * 1. The input graph must be a DAG.
+ * 2. All nodes in the graph must have an object value.
+ * 3. All edges in the graph must have "minlen" and "weight" attributes.
+ *
+ * Postconditions:
+ *
+ * 1. All nodes in the graph will have an assigned "rank" attribute that has
+ * been optimized by the network simplex algorithm. Ranks start at 0.
+ *
+ *
+ * A rough sketch of the algorithm is as follows:
+ *
+ * 1. Assign initial ranks to each node. We use the longest path algorithm,
+ * which assigns ranks to the lowest position possible. In general this
+ * leads to very wide bottom ranks and unnecessarily long edges.
+ * 2. Construct a feasible tight tree. A tight tree is one such that all
+ * edges in the tree have no slack (difference between length of edge
+ * and minlen for the edge). This by itself greatly improves the assigned
+ * rankings by shorting edges.
+ * 3. Iteratively find edges that have negative cut values. Generally a
+ * negative cut value indicates that the edge could be removed and a new
+ * tree edge could be added to produce a more compact graph.
+ *
+ * Much of the algorithms here are derived from Gansner, et al., "A Technique
+ * for Drawing Directed Graphs." The structure of the file roughly follows the
+ * structure of the overall algorithm.
+ */
+function networkSimplex(g) {
+ g = simplify(g);
+ initRank(g);
+ var t = feasibleTree(g);
+ initLowLimValues(t);
+ initCutValues(t, g);
+
+ var e, f;
+ while ((e = leaveEdge(t))) {
+ f = enterEdge(t, g, e);
+ exchangeEdges(t, g, e, f);
+ }
+}
+
+/*
+ * Initializes cut values for all edges in the tree.
+ */
+function initCutValues(t, g) {
+ var vs = postorder(t, t.nodes());
+ vs = vs.slice(0, vs.length - 1);
+ _.each(vs, function(v) {
+ assignCutValue(t, g, v);
+ });
+}
+
+function assignCutValue(t, g, child) {
+ var childLab = t.node(child),
+ parent = childLab.parent;
+ t.edge(child, parent).cutvalue = calcCutValue(t, g, child);
+}
+
+/*
+ * Given the tight tree, its graph, and a child in the graph calculate and
+ * return the cut value for the edge between the child and its parent.
+ */
+function calcCutValue(t, g, child) {
+ var childLab = t.node(child),
+ parent = childLab.parent,
+ // True if the child is on the tail end of the edge in the directed graph
+ childIsTail = true,
+ // The graph's view of the tree edge we're inspecting
+ graphEdge = g.edge(child, parent),
+ // The accumulated cut value for the edge between this node and its parent
+ cutValue = 0;
+
+ if (!graphEdge) {
+ childIsTail = false;
+ graphEdge = g.edge(parent, child);
+ }
+
+ cutValue = graphEdge.weight;
+
+ _.each(g.nodeEdges(child), function(e) {
+ var isOutEdge = e.v === child,
+ other = isOutEdge ? e.w : e.v;
+
+ if (other !== parent) {
+ var pointsToHead = isOutEdge === childIsTail,
+ otherWeight = g.edge(e).weight;
+
+ cutValue += pointsToHead ? otherWeight : -otherWeight;
+ if (isTreeEdge(t, child, other)) {
+ var otherCutValue = t.edge(child, other).cutvalue;
+ cutValue += pointsToHead ? -otherCutValue : otherCutValue;
+ }
+ }
+ });
+
+ return cutValue;
+}
+
+function initLowLimValues(tree, root) {
+ if (arguments.length < 2) {
+ root = tree.nodes()[0];
+ }
+ dfsAssignLowLim(tree, {}, 1, root);
+}
+
+function dfsAssignLowLim(tree, visited, nextLim, v, parent) {
+ var low = nextLim,
+ label = tree.node(v);
+
+ visited[v] = true;
+ _.each(tree.neighbors(v), function(w) {
+ if (!_.has(visited, w)) {
+ nextLim = dfsAssignLowLim(tree, visited, nextLim, w, v);
+ }
+ });
+
+ label.low = low;
+ label.lim = nextLim++;
+ if (parent) {
+ label.parent = parent;
+ } else {
+ // TODO should be able to remove this when we incrementally update low lim
+ delete label.parent;
+ }
+
+ return nextLim;
+}
+
+function leaveEdge(tree) {
+ return _.find(tree.edges(), function(e) {
+ return tree.edge(e).cutvalue < 0;
+ });
+}
+
+function enterEdge(t, g, edge) {
+ var v = edge.v,
+ w = edge.w;
+
+ // For the rest of this function we assume that v is the tail and w is the
+ // head, so if we don't have this edge in the graph we should flip it to
+ // match the correct orientation.
+ if (!g.hasEdge(v, w)) {
+ v = edge.w;
+ w = edge.v;
+ }
+
+ var vLabel = t.node(v),
+ wLabel = t.node(w),
+ tailLabel = vLabel,
+ flip = false;
+
+ // If the root is in the tail of the edge then we need to flip the logic that
+ // checks for the head and tail nodes in the candidates function below.
+ if (vLabel.lim > wLabel.lim) {
+ tailLabel = wLabel;
+ flip = true;
+ }
+
+ var candidates = _.filter(g.edges(), function(edge) {
+ return flip === isDescendant(t, t.node(edge.v), tailLabel) &&
+ flip !== isDescendant(t, t.node(edge.w), tailLabel);
+ });
+
+ return _.min(candidates, function(edge) { return slack(g, edge); });
+}
+
+function exchangeEdges(t, g, e, f) {
+ var v = e.v,
+ w = e.w;
+ t.removeEdge(v, w);
+ t.setEdge(f.v, f.w, {});
+ initLowLimValues(t);
+ initCutValues(t, g);
+ updateRanks(t, g);
+}
+
+function updateRanks(t, g) {
+ var root = _.find(t.nodes(), function(v) { return !g.node(v).parent; }),
+ vs = preorder(t, root);
+ vs = vs.slice(1);
+ _.each(vs, function(v) {
+ var parent = t.node(v).parent,
+ edge = g.edge(v, parent),
+ flipped = false;
+
+ if (!edge) {
+ edge = g.edge(parent, v);
+ flipped = true;
+ }
+
+ g.node(v).rank = g.node(parent).rank + (flipped ? edge.minlen : -edge.minlen);
+ });
+}
+
+/*
+ * Returns true if the edge is in the tree.
+ */
+function isTreeEdge(tree, u, v) {
+ return tree.hasEdge(u, v);
+}
+
+/*
+ * Returns true if the specified node is descendant of the root node per the
+ * assigned low and lim attributes in the tree.
+ */
+function isDescendant(tree, vLabel, rootLabel) {
+ return rootLabel.low <= vLabel.lim && vLabel.lim <= rootLabel.lim;
+}
+
+},{"../graphlib":7,"../lodash":10,"../util":29,"./feasible-tree":25,"./util":28}],28:[function(require,module,exports){
+"use strict";
+
+var _ = require("../lodash");
+
+module.exports = {
+ longestPath: longestPath,
+ slack: slack
+};
+
+/*
+ * Initializes ranks for the input graph using the longest path algorithm. This
+ * algorithm scales well and is fast in practice, it yields rather poor
+ * solutions. Nodes are pushed to the lowest layer possible, leaving the bottom
+ * ranks wide and leaving edges longer than necessary. However, due to its
+ * speed, this algorithm is good for getting an initial ranking that can be fed
+ * into other algorithms.
+ *
+ * This algorithm does not normalize layers because it will be used by other
+ * algorithms in most cases. If using this algorithm directly, be sure to
+ * run normalize at the end.
+ *
+ * Pre-conditions:
+ *
+ * 1. Input graph is a DAG.
+ * 2. Input graph node labels can be assigned properties.
+ *
+ * Post-conditions:
+ *
+ * 1. Each node will be assign an (unnormalized) "rank" property.
+ */
+function longestPath(g) {
+ var visited = {};
+
+ function dfs(v) {
+ var label = g.node(v);
+ if (_.has(visited, v)) {
+ return label.rank;
+ }
+ visited[v] = true;
+
+ var rank = _.min(_.map(g.outEdges(v), function(e) {
+ return dfs(e.w) - g.edge(e).minlen;
+ }));
+
+ if (rank === Number.POSITIVE_INFINITY) {
+ rank = 0;
+ }
+
+ return (label.rank = rank);
+ }
+
+ _.each(g.sources(), dfs);
+}
+
+/*
+ * Returns the amount of slack for the given edge. The slack is defined as the
+ * difference between the length of the edge and its minimum length.
+ */
+function slack(g, e) {
+ return g.node(e.w).rank - g.node(e.v).rank - g.edge(e).minlen;
+}
+
+},{"../lodash":10}],29:[function(require,module,exports){
+"use strict";
+
+var _ = require("./lodash"),
+ Graph = require("./graphlib").Graph;
+
+module.exports = {
+ addDummyNode: addDummyNode,
+ simplify: simplify,
+ asNonCompoundGraph: asNonCompoundGraph,
+ successorWeights: successorWeights,
+ predecessorWeights: predecessorWeights,
+ intersectRect: intersectRect,
+ buildLayerMatrix: buildLayerMatrix,
+ normalizeRanks: normalizeRanks,
+ removeEmptyRanks: removeEmptyRanks,
+ addBorderNode: addBorderNode,
+ maxRank: maxRank,
+ partition: partition,
+ time: time,
+ notime: notime
+};
+
+/*
+ * Adds a dummy node to the graph and return v.
+ */
+function addDummyNode(g, type, attrs, name) {
+ var v;
+ do {
+ v = _.uniqueId(name);
+ } while (g.hasNode(v));
+
+ attrs.dummy = type;
+ g.setNode(v, attrs);
+ return v;
+}
+
+/*
+ * Returns a new graph with only simple edges. Handles aggregation of data
+ * associated with multi-edges.
+ */
+function simplify(g) {
+ var simplified = new Graph().setGraph(g.graph());
+ _.each(g.nodes(), function(v) { simplified.setNode(v, g.node(v)); });
+ _.each(g.edges(), function(e) {
+ var simpleLabel = simplified.edge(e.v, e.w) || { weight: 0, minlen: 1 },
+ label = g.edge(e);
+ simplified.setEdge(e.v, e.w, {
+ weight: simpleLabel.weight + label.weight,
+ minlen: Math.max(simpleLabel.minlen, label.minlen)
+ });
+ });
+ return simplified;
+}
+
+function asNonCompoundGraph(g) {
+ var simplified = new Graph({ multigraph: g.isMultigraph() }).setGraph(g.graph());
+ _.each(g.nodes(), function(v) {
+ if (!g.children(v).length) {
+ simplified.setNode(v, g.node(v));
+ }
+ });
+ _.each(g.edges(), function(e) {
+ simplified.setEdge(e, g.edge(e));
+ });
+ return simplified;
+}
+
+function successorWeights(g) {
+ var weightMap = _.map(g.nodes(), function(v) {
+ var sucs = {};
+ _.each(g.outEdges(v), function(e) {
+ sucs[e.w] = (sucs[e.w] || 0) + g.edge(e).weight;
+ });
+ return sucs;
+ });
+ return _.zipObject(g.nodes(), weightMap);
+}
+
+function predecessorWeights(g) {
+ var weightMap = _.map(g.nodes(), function(v) {
+ var preds = {};
+ _.each(g.inEdges(v), function(e) {
+ preds[e.v] = (preds[e.v] || 0) + g.edge(e).weight;
+ });
+ return preds;
+ });
+ return _.zipObject(g.nodes(), weightMap);
+}
+
+/*
+ * Finds where a line starting at point ({x, y}) would intersect a rectangle
+ * ({x, y, width, height}) if it were pointing at the rectangle's center.
+ */
+function intersectRect(rect, point) {
+ var x = rect.x;
+ var y = rect.y;
+
+ // Rectangle intersection algorithm from:
+ // http://math.stackexchange.com/questions/108113/find-edge-between-two-boxes
+ var dx = point.x - x;
+ var dy = point.y - y;
+ var w = rect.width / 2;
+ var h = rect.height / 2;
+
+ if (!dx && !dy) {
+ throw new Error("Not possible to find intersection inside of the rectangle");
+ }
+
+ var sx, sy;
+ if (Math.abs(dy) * w > Math.abs(dx) * h) {
+ // Intersection is top or bottom of rect.
+ if (dy < 0) {
+ h = -h;
+ }
+ sx = h * dx / dy;
+ sy = h;
+ } else {
+ // Intersection is left or right of rect.
+ if (dx < 0) {
+ w = -w;
+ }
+ sx = w;
+ sy = w * dy / dx;
+ }
+
+ return { x: x + sx, y: y + sy };
+}
+
+/*
+ * Given a DAG with each node assigned "rank" and "order" properties, this
+ * function will produce a matrix with the ids of each node.
+ */
+function buildLayerMatrix(g) {
+ var layering = _.map(_.range(maxRank(g) + 1), function() { return []; });
+ _.each(g.nodes(), function(v) {
+ var node = g.node(v),
+ rank = node.rank;
+ if (!_.isUndefined(rank)) {
+ layering[rank][node.order] = v;
+ }
+ });
+ return layering;
+}
+
+/*
+ * Adjusts the ranks for all nodes in the graph such that all nodes v have
+ * rank(v) >= 0 and at least one node w has rank(w) = 0.
+ */
+function normalizeRanks(g) {
+ var min = _.min(_.map(g.nodes(), function(v) { return g.node(v).rank; }));
+ _.each(g.nodes(), function(v) {
+ var node = g.node(v);
+ if (_.has(node, "rank")) {
+ node.rank -= min;
+ }
+ });
+}
+
+function removeEmptyRanks(g) {
+ // Ranks may not start at 0, so we need to offset them
+ var offset = _.min(_.map(g.nodes(), function(v) { return g.node(v).rank; }));
+
+ var layers = [];
+ _.each(g.nodes(), function(v) {
+ var rank = g.node(v).rank - offset;
+ if (!layers[rank]) {
+ layers[rank] = [];
+ }
+ layers[rank].push(v);
+ });
+
+ var delta = 0,
+ nodeRankFactor = g.graph().nodeRankFactor;
+ _.each(layers, function(vs, i) {
+ if (_.isUndefined(vs) && i % nodeRankFactor !== 0) {
+ --delta;
+ } else if (delta) {
+ _.each(vs, function(v) { g.node(v).rank += delta; });
+ }
+ });
+}
+
+function addBorderNode(g, prefix, rank, order) {
+ var node = {
+ width: 0,
+ height: 0
+ };
+ if (arguments.length >= 4) {
+ node.rank = rank;
+ node.order = order;
+ }
+ return addDummyNode(g, "border", node, prefix);
+}
+
+function maxRank(g) {
+ return _.max(_.map(g.nodes(), function(v) {
+ var rank = g.node(v).rank;
+ if (!_.isUndefined(rank)) {
+ return rank;
+ }
+ }));
+}
+
+/*
+ * Partition a collection into two groups: `lhs` and `rhs`. If the supplied
+ * function returns true for an entry it goes into `lhs`. Otherwise it goes
+ * into `rhs.
+ */
+function partition(collection, fn) {
+ var result = { lhs: [], rhs: [] };
+ _.each(collection, function(value) {
+ if (fn(value)) {
+ result.lhs.push(value);
+ } else {
+ result.rhs.push(value);
+ }
+ });
+ return result;
+}
+
+/*
+ * Returns a new function that wraps `fn` with a timer. The wrapper logs the
+ * time it takes to execute the function.
+ */
+function time(name, fn) {
+ var start = _.now();
+ try {
+ return fn();
+ } finally {
+ console.log(name + " time: " + (_.now() - start) + "ms");
+ }
+}
+
+function notime(name, fn) {
+ return fn();
+}
+
+},{"./graphlib":7,"./lodash":10}],30:[function(require,module,exports){
+module.exports = "0.7.4";
+
+},{}],31:[function(require,module,exports){
+/**
+ * Copyright (c) 2014, Chris Pettitt
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+var lib = require("./lib");
+
+module.exports = {
+ Graph: lib.Graph,
+ json: require("./lib/json"),
+ alg: require("./lib/alg"),
+ version: lib.version
+};
+
+},{"./lib":47,"./lib/alg":38,"./lib/json":48}],32:[function(require,module,exports){
+var _ = require("../lodash");
+
+module.exports = components;
+
+function components(g) {
+ var visited = {},
+ cmpts = [],
+ cmpt;
+
+ function dfs(v) {
+ if (_.has(visited, v)) return;
+ visited[v] = true;
+ cmpt.push(v);
+ _.each(g.successors(v), dfs);
+ _.each(g.predecessors(v), dfs);
+ }
+
+ _.each(g.nodes(), function(v) {
+ cmpt = [];
+ dfs(v);
+ if (cmpt.length) {
+ cmpts.push(cmpt);
+ }
+ });
+
+ return cmpts;
+}
+
+},{"../lodash":49}],33:[function(require,module,exports){
+var _ = require("../lodash");
+
+module.exports = dfs;
+
+/*
+ * A helper that preforms a pre- or post-order traversal on the input graph
+ * and returns the nodes in the order they were visited. This algorithm treats
+ * the input as undirected.
+ *
+ * Order must be one of "pre" or "post".
+ */
+function dfs(g, vs, order) {
+ if (!_.isArray(vs)) {
+ vs = [vs];
+ }
+
+ var acc = [],
+ visited = {};
+ _.each(vs, function(v) {
+ if (!g.hasNode(v)) {
+ throw new Error("Graph does not have node: " + v);
+ }
+
+ doDfs(g, v, order === "post", visited, acc);
+ });
+ return acc;
+}
+
+function doDfs(g, v, postorder, visited, acc) {
+ if (!_.has(visited, v)) {
+ visited[v] = true;
+
+ if (!postorder) { acc.push(v); }
+ _.each(g.neighbors(v), function(w) {
+ doDfs(g, w, postorder, visited, acc);
+ });
+ if (postorder) { acc.push(v); }
+ }
+}
+
+},{"../lodash":49}],34:[function(require,module,exports){
+var dijkstra = require("./dijkstra"),
+ _ = require("../lodash");
+
+module.exports = dijkstraAll;
+
+function dijkstraAll(g, weightFunc, edgeFunc) {
+ return _.transform(g.nodes(), function(acc, v) {
+ acc[v] = dijkstra(g, v, weightFunc, edgeFunc);
+ }, {});
+}
+
+},{"../lodash":49,"./dijkstra":35}],35:[function(require,module,exports){
+var _ = require("../lodash"),
+ PriorityQueue = require("../data/priority-queue");
+
+module.exports = dijkstra;
+
+var DEFAULT_WEIGHT_FUNC = _.constant(1);
+
+function dijkstra(g, source, weightFn, edgeFn) {
+ return runDijkstra(g, String(source),
+ weightFn || DEFAULT_WEIGHT_FUNC,
+ edgeFn || function(v) { return g.outEdges(v); });
+}
+
+function runDijkstra(g, source, weightFn, edgeFn) {
+ var results = {},
+ pq = new PriorityQueue(),
+ v, vEntry;
+
+ var updateNeighbors = function(edge) {
+ var w = edge.v !== v ? edge.v : edge.w,
+ wEntry = results[w],
+ weight = weightFn(edge),
+ distance = vEntry.distance + weight;
+
+ if (weight < 0) {
+ throw new Error("dijkstra does not allow negative edge weights. " +
+ "Bad edge: " + edge + " Weight: " + weight);
+ }
+
+ if (distance < wEntry.distance) {
+ wEntry.distance = distance;
+ wEntry.predecessor = v;
+ pq.decrease(w, distance);
+ }
+ };
+
+ g.nodes().forEach(function(v) {
+ var distance = v === source ? 0 : Number.POSITIVE_INFINITY;
+ results[v] = { distance: distance };
+ pq.add(v, distance);
+ });
+
+ while (pq.size() > 0) {
+ v = pq.removeMin();
+ vEntry = results[v];
+ if (vEntry.distance === Number.POSITIVE_INFINITY) {
+ break;
+ }
+
+ edgeFn(v).forEach(updateNeighbors);
+ }
+
+ return results;
+}
+
+},{"../data/priority-queue":45,"../lodash":49}],36:[function(require,module,exports){
+var _ = require("../lodash"),
+ tarjan = require("./tarjan");
+
+module.exports = findCycles;
+
+function findCycles(g) {
+ return _.filter(tarjan(g), function(cmpt) {
+ return cmpt.length > 1 || (cmpt.length === 1 && g.hasEdge(cmpt[0], cmpt[0]));
+ });
+}
+
+},{"../lodash":49,"./tarjan":43}],37:[function(require,module,exports){
+var _ = require("../lodash");
+
+module.exports = floydWarshall;
+
+var DEFAULT_WEIGHT_FUNC = _.constant(1);
+
+function floydWarshall(g, weightFn, edgeFn) {
+ return runFloydWarshall(g,
+ weightFn || DEFAULT_WEIGHT_FUNC,
+ edgeFn || function(v) { return g.outEdges(v); });
+}
+
+function runFloydWarshall(g, weightFn, edgeFn) {
+ var results = {},
+ nodes = g.nodes();
+
+ nodes.forEach(function(v) {
+ results[v] = {};
+ results[v][v] = { distance: 0 };
+ nodes.forEach(function(w) {
+ if (v !== w) {
+ results[v][w] = { distance: Number.POSITIVE_INFINITY };
+ }
+ });
+ edgeFn(v).forEach(function(edge) {
+ var w = edge.v === v ? edge.w : edge.v,
+ d = weightFn(edge);
+ results[v][w] = { distance: d, predecessor: v };
+ });
+ });
+
+ nodes.forEach(function(k) {
+ var rowK = results[k];
+ nodes.forEach(function(i) {
+ var rowI = results[i];
+ nodes.forEach(function(j) {
+ var ik = rowI[k];
+ var kj = rowK[j];
+ var ij = rowI[j];
+ var altDistance = ik.distance + kj.distance;
+ if (altDistance < ij.distance) {
+ ij.distance = altDistance;
+ ij.predecessor = kj.predecessor;
+ }
+ });
+ });
+ });
+
+ return results;
+}
+
+},{"../lodash":49}],38:[function(require,module,exports){
+module.exports = {
+ components: require("./components"),
+ dijkstra: require("./dijkstra"),
+ dijkstraAll: require("./dijkstra-all"),
+ findCycles: require("./find-cycles"),
+ floydWarshall: require("./floyd-warshall"),
+ isAcyclic: require("./is-acyclic"),
+ postorder: require("./postorder"),
+ preorder: require("./preorder"),
+ prim: require("./prim"),
+ tarjan: require("./tarjan"),
+ topsort: require("./topsort")
+};
+
+},{"./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){
+var topsort = require("./topsort");
+
+module.exports = isAcyclic;
+
+function isAcyclic(g) {
+ try {
+ topsort(g);
+ } catch (e) {
+ if (e instanceof topsort.CycleException) {
+ return false;
+ }
+ throw e;
+ }
+ return true;
+}
+
+},{"./topsort":44}],40:[function(require,module,exports){
+var dfs = require("./dfs");
+
+module.exports = postorder;
+
+function postorder(g, vs) {
+ return dfs(g, vs, "post");
+}
+
+},{"./dfs":33}],41:[function(require,module,exports){
+var dfs = require("./dfs");
+
+module.exports = preorder;
+
+function preorder(g, vs) {
+ return dfs(g, vs, "pre");
+}
+
+},{"./dfs":33}],42:[function(require,module,exports){
+var _ = require("../lodash"),
+ Graph = require("../graph"),
+ PriorityQueue = require("../data/priority-queue");
+
+module.exports = prim;
+
+function prim(g, weightFunc) {
+ var result = new Graph(),
+ parents = {},
+ pq = new PriorityQueue(),
+ v;
+
+ function updateNeighbors(edge) {
+ var w = edge.v === v ? edge.w : edge.v,
+ pri = pq.priority(w);
+ if (pri !== undefined) {
+ var edgeWeight = weightFunc(edge);
+ if (edgeWeight < pri) {
+ parents[w] = v;
+ pq.decrease(w, edgeWeight);
+ }
+ }
+ }
+
+ if (g.nodeCount() === 0) {
+ return result;
+ }
+
+ _.each(g.nodes(), function(v) {
+ pq.add(v, Number.POSITIVE_INFINITY);
+ result.setNode(v);
+ });
+
+ // Start from an arbitrary node
+ pq.decrease(g.nodes()[0], 0);
+
+ var init = false;
+ while (pq.size() > 0) {
+ v = pq.removeMin();
+ if (_.has(parents, v)) {
+ result.setEdge(v, parents[v]);
+ } else if (init) {
+ throw new Error("Input graph is not connected: " + g);
+ } else {
+ init = true;
+ }
+
+ g.nodeEdges(v).forEach(updateNeighbors);
+ }
+
+ return result;
+}
+
+},{"../data/priority-queue":45,"../graph":46,"../lodash":49}],43:[function(require,module,exports){
+var _ = require("../lodash");
+
+module.exports = tarjan;
+
+function tarjan(g) {
+ var index = 0,
+ stack = [],
+ visited = {}, // node id -> { onStack, lowlink, index }
+ results = [];
+
+ function dfs(v) {
+ var entry = visited[v] = {
+ onStack: true,
+ lowlink: index,
+ index: index++
+ };
+ stack.push(v);
+
+ g.successors(v).forEach(function(w) {
+ if (!_.has(visited, w)) {
+ dfs(w);
+ entry.lowlink = Math.min(entry.lowlink, visited[w].lowlink);
+ } else if (visited[w].onStack) {
+ entry.lowlink = Math.min(entry.lowlink, visited[w].index);
+ }
+ });
+
+ if (entry.lowlink === entry.index) {
+ var cmpt = [],
+ w;
+ do {
+ w = stack.pop();
+ visited[w].onStack = false;
+ cmpt.push(w);
+ } while (v !== w);
+ results.push(cmpt);
+ }
+ }
+
+ g.nodes().forEach(function(v) {
+ if (!_.has(visited, v)) {
+ dfs(v);
+ }
+ });
+
+ return results;
+}
+
+},{"../lodash":49}],44:[function(require,module,exports){
+var _ = require("../lodash");
+
+module.exports = topsort;
+topsort.CycleException = CycleException;
+
+function topsort(g) {
+ var visited = {},
+ stack = {},
+ results = [];
+
+ function visit(node) {
+ if (_.has(stack, node)) {
+ throw new CycleException();
+ }
+
+ if (!_.has(visited, node)) {
+ stack[node] = true;
+ visited[node] = true;
+ _.each(g.predecessors(node), visit);
+ delete stack[node];
+ results.push(node);
+ }
+ }
+
+ _.each(g.sinks(), visit);
+
+ if (_.size(visited) !== g.nodeCount()) {
+ throw new CycleException();
+ }
+
+ return results;
+}
+
+function CycleException() {}
+
+},{"../lodash":49}],45:[function(require,module,exports){
+var _ = require("../lodash");
+
+module.exports = PriorityQueue;
+
+/**
+ * A min-priority queue data structure. This algorithm is derived from Cormen,
+ * et al., "Introduction to Algorithms". The basic idea of a min-priority
+ * queue is that you can efficiently (in O(1) time) get the smallest key in
+ * the queue. Adding and removing elements takes O(log n) time. A key can
+ * have its priority decreased in O(log n) time.
+ */
+function PriorityQueue() {
+ this._arr = [];
+ this._keyIndices = {};
+}
+
+/**
+ * Returns the number of elements in the queue. Takes `O(1)` time.
+ */
+PriorityQueue.prototype.size = function() {
+ return this._arr.length;
+};
+
+/**
+ * Returns the keys that are in the queue. Takes `O(n)` time.
+ */
+PriorityQueue.prototype.keys = function() {
+ return this._arr.map(function(x) { return x.key; });
+};
+
+/**
+ * Returns `true` if **key** is in the queue and `false` if not.
+ */
+PriorityQueue.prototype.has = function(key) {
+ return _.has(this._keyIndices, key);
+};
+
+/**
+ * Returns the priority for **key**. If **key** is not present in the queue
+ * then this function returns `undefined`. Takes `O(1)` time.
+ *
+ * @param {Object} key
+ */
+PriorityQueue.prototype.priority = function(key) {
+ var index = this._keyIndices[key];
+ if (index !== undefined) {
+ return this._arr[index].priority;
+ }
+};
+
+/**
+ * Returns the key for the minimum element in this queue. If the queue is
+ * empty this function throws an Error. Takes `O(1)` time.
+ */
+PriorityQueue.prototype.min = function() {
+ if (this.size() === 0) {
+ throw new Error("Queue underflow");
+ }
+ return this._arr[0].key;
+};
+
+/**
+ * Inserts a new key into the priority queue. If the key already exists in
+ * the queue this function returns `false`; otherwise it will return `true`.
+ * Takes `O(n)` time.
+ *
+ * @param {Object} key the key to add
+ * @param {Number} priority the initial priority for the key
+ */
+PriorityQueue.prototype.add = function(key, priority) {
+ var keyIndices = this._keyIndices;
+ key = String(key);
+ if (!_.has(keyIndices, key)) {
+ var arr = this._arr;
+ var index = arr.length;
+ keyIndices[key] = index;
+ arr.push({key: key, priority: priority});
+ this._decrease(index);
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Removes and returns the smallest key in the queue. Takes `O(log n)` time.
+ */
+PriorityQueue.prototype.removeMin = function() {
+ this._swap(0, this._arr.length - 1);
+ var min = this._arr.pop();
+ delete this._keyIndices[min.key];
+ this._heapify(0);
+ return min.key;
+};
+
+/**
+ * Decreases the priority for **key** to **priority**. If the new priority is
+ * greater than the previous priority, this function will throw an Error.
+ *
+ * @param {Object} key the key for which to raise priority
+ * @param {Number} priority the new priority for the key
+ */
+PriorityQueue.prototype.decrease = function(key, priority) {
+ var index = this._keyIndices[key];
+ if (priority > this._arr[index].priority) {
+ throw new Error("New priority is greater than current priority. " +
+ "Key: " + key + " Old: " + this._arr[index].priority + " New: " + priority);
+ }
+ this._arr[index].priority = priority;
+ this._decrease(index);
+};
+
+PriorityQueue.prototype._heapify = function(i) {
+ var arr = this._arr;
+ var l = 2 * i,
+ r = l + 1,
+ largest = i;
+ if (l < arr.length) {
+ largest = arr[l].priority < arr[largest].priority ? l : largest;
+ if (r < arr.length) {
+ largest = arr[r].priority < arr[largest].priority ? r : largest;
+ }
+ if (largest !== i) {
+ this._swap(i, largest);
+ this._heapify(largest);
+ }
+ }
+};
+
+PriorityQueue.prototype._decrease = function(index) {
+ var arr = this._arr;
+ var priority = arr[index].priority;
+ var parent;
+ while (index !== 0) {
+ parent = index >> 1;
+ if (arr[parent].priority < priority) {
+ break;
+ }
+ this._swap(index, parent);
+ index = parent;
+ }
+};
+
+PriorityQueue.prototype._swap = function(i, j) {
+ var arr = this._arr;
+ var keyIndices = this._keyIndices;
+ var origArrI = arr[i];
+ var origArrJ = arr[j];
+ arr[i] = origArrJ;
+ arr[j] = origArrI;
+ keyIndices[origArrJ.key] = i;
+ keyIndices[origArrI.key] = j;
+};
+
+},{"../lodash":49}],46:[function(require,module,exports){
+"use strict";
+
+var _ = require("./lodash");
+
+module.exports = Graph;
+
+var DEFAULT_EDGE_NAME = "\x00",
+ GRAPH_NODE = "\x00",
+ EDGE_KEY_DELIM = "\x01";
+
+// Implementation notes:
+//
+// * Node id query functions should return string ids for the nodes
+// * Edge id query functions should return an "edgeObj", edge object, that is
+// composed of enough information to uniquely identify an edge: {v, w, name}.
+// * Internally we use an "edgeId", a stringified form of the edgeObj, to
+// reference edges. This is because we need a performant way to look these
+// edges up and, object properties, which have string keys, are the closest
+// we're going to get to a performant hashtable in JavaScript.
+
+function Graph(opts) {
+ this._isDirected = _.has(opts, "directed") ? opts.directed : true;
+ this._isMultigraph = _.has(opts, "multigraph") ? opts.multigraph : false;
+ this._isCompound = _.has(opts, "compound") ? opts.compound : false;
+
+ // Label for the graph itself
+ this._label = undefined;
+
+ // Defaults to be set when creating a new node
+ this._defaultNodeLabelFn = _.constant(undefined);
+
+ // Defaults to be set when creating a new edge
+ this._defaultEdgeLabelFn = _.constant(undefined);
+
+ // v -> label
+ this._nodes = {};
+
+ if (this._isCompound) {
+ // v -> parent
+ this._parent = {};
+
+ // v -> children
+ this._children = {};
+ this._children[GRAPH_NODE] = {};
+ }
+
+ // v -> edgeObj
+ this._in = {};
+
+ // u -> v -> Number
+ this._preds = {};
+
+ // v -> edgeObj
+ this._out = {};
+
+ // v -> w -> Number
+ this._sucs = {};
+
+ // e -> edgeObj
+ this._edgeObjs = {};
+
+ // e -> label
+ this._edgeLabels = {};
+}
+
+/* Number of nodes in the graph. Should only be changed by the implementation. */
+Graph.prototype._nodeCount = 0;
+
+/* Number of edges in the graph. Should only be changed by the implementation. */
+Graph.prototype._edgeCount = 0;
+
+
+/* === Graph functions ========= */
+
+Graph.prototype.isDirected = function() {
+ return this._isDirected;
+};
+
+Graph.prototype.isMultigraph = function() {
+ return this._isMultigraph;
+};
+
+Graph.prototype.isCompound = function() {
+ return this._isCompound;
+};
+
+Graph.prototype.setGraph = function(label) {
+ this._label = label;
+ return this;
+};
+
+Graph.prototype.graph = function() {
+ return this._label;
+};
+
+
+/* === Node functions ========== */
+
+Graph.prototype.setDefaultNodeLabel = function(newDefault) {
+ if (!_.isFunction(newDefault)) {
+ newDefault = _.constant(newDefault);
+ }
+ this._defaultNodeLabelFn = newDefault;
+ return this;
+};
+
+Graph.prototype.nodeCount = function() {
+ return this._nodeCount;
+};
+
+Graph.prototype.nodes = function() {
+ return _.keys(this._nodes);
+};
+
+Graph.prototype.sources = function() {
+ return _.filter(this.nodes(), function(v) {
+ return _.isEmpty(this._in[v]);
+ }, this);
+};
+
+Graph.prototype.sinks = function() {
+ return _.filter(this.nodes(), function(v) {
+ return _.isEmpty(this._out[v]);
+ }, this);
+};
+
+Graph.prototype.setNodes = function(vs, value) {
+ var args = arguments;
+ _.each(vs, function(v) {
+ if (args.length > 1) {
+ this.setNode(v, value);
+ } else {
+ this.setNode(v);
+ }
+ }, this);
+ return this;
+};
+
+Graph.prototype.setNode = function(v, value) {
+ if (_.has(this._nodes, v)) {
+ if (arguments.length > 1) {
+ this._nodes[v] = value;
+ }
+ return this;
+ }
+
+ this._nodes[v] = arguments.length > 1 ? value : this._defaultNodeLabelFn(v);
+ if (this._isCompound) {
+ this._parent[v] = GRAPH_NODE;
+ this._children[v] = {};
+ this._children[GRAPH_NODE][v] = true;
+ }
+ this._in[v] = {};
+ this._preds[v] = {};
+ this._out[v] = {};
+ this._sucs[v] = {};
+ ++this._nodeCount;
+ return this;
+};
+
+Graph.prototype.node = function(v) {
+ return this._nodes[v];
+};
+
+Graph.prototype.hasNode = function(v) {
+ return _.has(this._nodes, v);
+};
+
+Graph.prototype.removeNode = function(v) {
+ var self = this;
+ if (_.has(this._nodes, v)) {
+ var removeEdge = function(e) { self.removeEdge(self._edgeObjs[e]); };
+ delete this._nodes[v];
+ if (this._isCompound) {
+ this._removeFromParentsChildList(v);
+ delete this._parent[v];
+ _.each(this.children(v), function(child) {
+ this.setParent(child);
+ }, this);
+ delete this._children[v];
+ }
+ _.each(_.keys(this._in[v]), removeEdge);
+ delete this._in[v];
+ delete this._preds[v];
+ _.each(_.keys(this._out[v]), removeEdge);
+ delete this._out[v];
+ delete this._sucs[v];
+ --this._nodeCount;
+ }
+ return this;
+};
+
+Graph.prototype.setParent = function(v, parent) {
+ if (!this._isCompound) {
+ throw new Error("Cannot set parent in a non-compound graph");
+ }
+
+ if (_.isUndefined(parent)) {
+ parent = GRAPH_NODE;
+ } else {
+ // Coerce parent to string
+ parent += "";
+ for (var ancestor = parent;
+ !_.isUndefined(ancestor);
+ ancestor = this.parent(ancestor)) {
+ if (ancestor === v) {
+ throw new Error("Setting " + parent+ " as parent of " + v +
+ " would create create a cycle");
+ }
+ }
+
+ this.setNode(parent);
+ }
+
+ this.setNode(v);
+ this._removeFromParentsChildList(v);
+ this._parent[v] = parent;
+ this._children[parent][v] = true;
+ return this;
+};
+
+Graph.prototype._removeFromParentsChildList = function(v) {
+ delete this._children[this._parent[v]][v];
+};
+
+Graph.prototype.parent = function(v) {
+ if (this._isCompound) {
+ var parent = this._parent[v];
+ if (parent !== GRAPH_NODE) {
+ return parent;
+ }
+ }
+};
+
+Graph.prototype.children = function(v) {
+ if (_.isUndefined(v)) {
+ v = GRAPH_NODE;
+ }
+
+ if (this._isCompound) {
+ var children = this._children[v];
+ if (children) {
+ return _.keys(children);
+ }
+ } else if (v === GRAPH_NODE) {
+ return this.nodes();
+ } else if (this.hasNode(v)) {
+ return [];
+ }
+};
+
+Graph.prototype.predecessors = function(v) {
+ var predsV = this._preds[v];
+ if (predsV) {
+ return _.keys(predsV);
+ }
+};
+
+Graph.prototype.successors = function(v) {
+ var sucsV = this._sucs[v];
+ if (sucsV) {
+ return _.keys(sucsV);
+ }
+};
+
+Graph.prototype.neighbors = function(v) {
+ var preds = this.predecessors(v);
+ if (preds) {
+ return _.union(preds, this.successors(v));
+ }
+};
+
+/* === Edge functions ========== */
+
+Graph.prototype.setDefaultEdgeLabel = function(newDefault) {
+ if (!_.isFunction(newDefault)) {
+ newDefault = _.constant(newDefault);
+ }
+ this._defaultEdgeLabelFn = newDefault;
+ return this;
+};
+
+Graph.prototype.edgeCount = function() {
+ return this._edgeCount;
+};
+
+Graph.prototype.edges = function() {
+ return _.values(this._edgeObjs);
+};
+
+Graph.prototype.setPath = function(vs, value) {
+ var self = this,
+ args = arguments;
+ _.reduce(vs, function(v, w) {
+ if (args.length > 1) {
+ self.setEdge(v, w, value);
+ } else {
+ self.setEdge(v, w);
+ }
+ return w;
+ });
+ return this;
+};
+
+/*
+ * setEdge(v, w, [value, [name]])
+ * setEdge({ v, w, [name] }, [value])
+ */
+Graph.prototype.setEdge = function() {
+ var v, w, name, value,
+ valueSpecified = false;
+
+ if (_.isPlainObject(arguments[0])) {
+ v = arguments[0].v;
+ w = arguments[0].w;
+ name = arguments[0].name;
+ if (arguments.length === 2) {
+ value = arguments[1];
+ valueSpecified = true;
+ }
+ } else {
+ v = arguments[0];
+ w = arguments[1];
+ name = arguments[3];
+ if (arguments.length > 2) {
+ value = arguments[2];
+ valueSpecified = true;
+ }
+ }
+
+ v = "" + v;
+ w = "" + w;
+ if (!_.isUndefined(name)) {
+ name = "" + name;
+ }
+
+ var e = edgeArgsToId(this._isDirected, v, w, name);
+ if (_.has(this._edgeLabels, e)) {
+ if (valueSpecified) {
+ this._edgeLabels[e] = value;
+ }
+ return this;
+ }
+
+ if (!_.isUndefined(name) && !this._isMultigraph) {
+ throw new Error("Cannot set a named edge when isMultigraph = false");
+ }
+
+ // It didn't exist, so we need to create it.
+ // First ensure the nodes exist.
+ this.setNode(v);
+ this.setNode(w);
+
+ this._edgeLabels[e] = valueSpecified ? value : this._defaultEdgeLabelFn(v, w, name);
+
+ var edgeObj = edgeArgsToObj(this._isDirected, v, w, name);
+ // Ensure we add undirected edges in a consistent way.
+ v = edgeObj.v;
+ w = edgeObj.w;
+
+ Object.freeze(edgeObj);
+ this._edgeObjs[e] = edgeObj;
+ incrementOrInitEntry(this._preds[w], v);
+ incrementOrInitEntry(this._sucs[v], w);
+ this._in[w][e] = edgeObj;
+ this._out[v][e] = edgeObj;
+ this._edgeCount++;
+ return this;
+};
+
+Graph.prototype.edge = function(v, w, name) {
+ var e = (arguments.length === 1
+ ? edgeObjToId(this._isDirected, arguments[0])
+ : edgeArgsToId(this._isDirected, v, w, name));
+ return this._edgeLabels[e];
+};
+
+Graph.prototype.hasEdge = function(v, w, name) {
+ var e = (arguments.length === 1
+ ? edgeObjToId(this._isDirected, arguments[0])
+ : edgeArgsToId(this._isDirected, v, w, name));
+ return _.has(this._edgeLabels, e);
+};
+
+Graph.prototype.removeEdge = function(v, w, name) {
+ var e = (arguments.length === 1
+ ? edgeObjToId(this._isDirected, arguments[0])
+ : edgeArgsToId(this._isDirected, v, w, name)),
+ edge = this._edgeObjs[e];
+ if (edge) {
+ v = edge.v;
+ w = edge.w;
+ delete this._edgeLabels[e];
+ delete this._edgeObjs[e];
+ decrementOrRemoveEntry(this._preds[w], v);
+ decrementOrRemoveEntry(this._sucs[v], w);
+ delete this._in[w][e];
+ delete this._out[v][e];
+ this._edgeCount--;
+ }
+ return this;
+};
+
+Graph.prototype.inEdges = function(v, u) {
+ var inV = this._in[v];
+ if (inV) {
+ var edges = _.values(inV);
+ if (!u) {
+ return edges;
+ }
+ return _.filter(edges, function(edge) { return edge.v === u; });
+ }
+};
+
+Graph.prototype.outEdges = function(v, w) {
+ var outV = this._out[v];
+ if (outV) {
+ var edges = _.values(outV);
+ if (!w) {
+ return edges;
+ }
+ return _.filter(edges, function(edge) { return edge.w === w; });
+ }
+};
+
+Graph.prototype.nodeEdges = function(v, w) {
+ var inEdges = this.inEdges(v, w);
+ if (inEdges) {
+ return inEdges.concat(this.outEdges(v, w));
+ }
+};
+
+function incrementOrInitEntry(map, k) {
+ if (_.has(map, k)) {
+ map[k]++;
+ } else {
+ map[k] = 1;
+ }
+}
+
+function decrementOrRemoveEntry(map, k) {
+ if (!--map[k]) { delete map[k]; }
+}
+
+function edgeArgsToId(isDirected, v, w, name) {
+ if (!isDirected && v > w) {
+ var tmp = v;
+ v = w;
+ w = tmp;
+ }
+ return v + EDGE_KEY_DELIM + w + EDGE_KEY_DELIM +
+ (_.isUndefined(name) ? DEFAULT_EDGE_NAME : name);
+}
+
+function edgeArgsToObj(isDirected, v, w, name) {
+ if (!isDirected && v > w) {
+ var tmp = v;
+ v = w;
+ w = tmp;
+ }
+ var edgeObj = { v: v, w: w };
+ if (name) {
+ edgeObj.name = name;
+ }
+ return edgeObj;
+}
+
+function edgeObjToId(isDirected, edgeObj) {
+ return edgeArgsToId(isDirected, edgeObj.v, edgeObj.w, edgeObj.name);
+}
+
+},{"./lodash":49}],47:[function(require,module,exports){
+// Includes only the "core" of graphlib
+module.exports = {
+ Graph: require("./graph"),
+ version: require("./version")
+};
+
+},{"./graph":46,"./version":50}],48:[function(require,module,exports){
+var _ = require("./lodash"),
+ Graph = require("./graph");
+
+module.exports = {
+ write: write,
+ read: read
+};
+
+function write(g) {
+ var json = {
+ options: {
+ directed: g.isDirected(),
+ multigraph: g.isMultigraph(),
+ compound: g.isCompound()
+ },
+ nodes: writeNodes(g),
+ edges: writeEdges(g)
+ };
+ if (!_.isUndefined(g.graph())) {
+ json.value = _.clone(g.graph());
+ }
+ return json;
+}
+
+function writeNodes(g) {
+ return _.map(g.nodes(), function(v) {
+ var nodeValue = g.node(v),
+ parent = g.parent(v),
+ node = { v: v };
+ if (!_.isUndefined(nodeValue)) {
+ node.value = nodeValue;
+ }
+ if (!_.isUndefined(parent)) {
+ node.parent = parent;
+ }
+ return node;
+ });
+}
+
+function writeEdges(g) {
+ return _.map(g.edges(), function(e) {
+ var edgeValue = g.edge(e),
+ edge = { v: e.v, w: e.w };
+ if (!_.isUndefined(e.name)) {
+ edge.name = e.name;
+ }
+ if (!_.isUndefined(edgeValue)) {
+ edge.value = edgeValue;
+ }
+ return edge;
+ });
+}
+
+function read(json) {
+ var g = new Graph(json.options).setGraph(json.value);
+ _.each(json.nodes, function(entry) {
+ g.setNode(entry.v, entry.value);
+ if (entry.parent) {
+ g.setParent(entry.v, entry.parent);
+ }
+ });
+ _.each(json.edges, function(entry) {
+ g.setEdge({ v: entry.v, w: entry.w, name: entry.name }, entry.value);
+ });
+ return g;
+}
+
+},{"./graph":46,"./lodash":49}],49:[function(require,module,exports){
+module.exports=require(10)
+},{"/Users/cpettitt/projects/dagre/lib/lodash.js":10,"lodash":51}],50:[function(require,module,exports){
+module.exports = '1.0.5';
+
+},{}],51:[function(require,module,exports){
+(function (global){
+/**
+ * @license
+ * lodash 3.10.0 (Custom Build) <https://lodash.com/>
+ * Build: `lodash modern -d -o ./index.js`
+ * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
+ * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
+ * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
+ * Available under MIT license <https://lodash.com/license>
+ */
+;(function() {
+
+ /** Used as a safe reference for `undefined` in pre-ES5 environments. */
+ var undefined;
+
+ /** Used as the semantic version number. */
+ var VERSION = '3.10.0';
+
+ /** Used to compose bitmasks for wrapper metadata. */
+ var BIND_FLAG = 1,
+ BIND_KEY_FLAG = 2,
+ CURRY_BOUND_FLAG = 4,
+ CURRY_FLAG = 8,
+ CURRY_RIGHT_FLAG = 16,
+ PARTIAL_FLAG = 32,
+ PARTIAL_RIGHT_FLAG = 64,
+ ARY_FLAG = 128,
+ REARG_FLAG = 256;
+
+ /** Used as default options for `_.trunc`. */
+ var DEFAULT_TRUNC_LENGTH = 30,
+ DEFAULT_TRUNC_OMISSION = '...';
+
+ /** Used to detect when a function becomes hot. */
+ var HOT_COUNT = 150,
+ HOT_SPAN = 16;
+
+ /** Used as the size to enable large array optimizations. */
+ var LARGE_ARRAY_SIZE = 200;
+
+ /** Used to indicate the type of lazy iteratees. */
+ var LAZY_FILTER_FLAG = 1,
+ LAZY_MAP_FLAG = 2;
+
+ /** Used as the `TypeError` message for "Functions" methods. */
+ var FUNC_ERROR_TEXT = 'Expected a function';
+
+ /** Used as the internal argument placeholder. */
+ var PLACEHOLDER = '__lodash_placeholder__';
+
+ /** `Object#toString` result references. */
+ var argsTag = '[object Arguments]',
+ arrayTag = '[object Array]',
+ boolTag = '[object Boolean]',
+ dateTag = '[object Date]',
+ errorTag = '[object Error]',
+ funcTag = '[object Function]',
+ mapTag = '[object Map]',
+ numberTag = '[object Number]',
+ objectTag = '[object Object]',
+ regexpTag = '[object RegExp]',
+ setTag = '[object Set]',
+ stringTag = '[object String]',
+ weakMapTag = '[object WeakMap]';
+
+ var arrayBufferTag = '[object ArrayBuffer]',
+ float32Tag = '[object Float32Array]',
+ float64Tag = '[object Float64Array]',
+ int8Tag = '[object Int8Array]',
+ int16Tag = '[object Int16Array]',
+ int32Tag = '[object Int32Array]',
+ uint8Tag = '[object Uint8Array]',
+ uint8ClampedTag = '[object Uint8ClampedArray]',
+ uint16Tag = '[object Uint16Array]',
+ uint32Tag = '[object Uint32Array]';
+
+ /** Used to match empty string literals in compiled template source. */
+ var reEmptyStringLeading = /\b__p \+= '';/g,
+ reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
+ reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
+
+ /** Used to match HTML entities and HTML characters. */
+ var reEscapedHtml = /&(?:amp|lt|gt|quot|#39|#96);/g,
+ reUnescapedHtml = /[&<>"'`]/g,
+ reHasEscapedHtml = RegExp(reEscapedHtml.source),
+ reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
+
+ /** Used to match template delimiters. */
+ var reEscape = /<%-([\s\S]+?)%>/g,
+ reEvaluate = /<%([\s\S]+?)%>/g,
+ reInterpolate = /<%=([\s\S]+?)%>/g;
+
+ /** Used to match property names within property paths. */
+ var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,
+ reIsPlainProp = /^\w*$/,
+ rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
+
+ /**
+ * Used to match `RegExp` [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns)
+ * and those outlined by [`EscapeRegExpPattern`](http://ecma-international.org/ecma-262/6.0/#sec-escaperegexppattern).
+ */
+ var reRegExpChars = /^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,
+ reHasRegExpChars = RegExp(reRegExpChars.source);
+
+ /** Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). */
+ var reComboMark = /[\u0300-\u036f\ufe20-\ufe23]/g;
+
+ /** Used to match backslashes in property paths. */
+ var reEscapeChar = /\\(\\)?/g;
+
+ /** Used to match [ES template delimiters](http://ecma-international.org/ecma-262/6.0/#sec-template-literal-lexical-components). */
+ var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
+
+ /** Used to match `RegExp` flags from their coerced string values. */
+ var reFlags = /\w*$/;
+
+ /** Used to detect hexadecimal string values. */
+ var reHasHexPrefix = /^0[xX]/;
+
+ /** Used to detect host constructors (Safari > 5). */
+ var reIsHostCtor = /^\[object .+?Constructor\]$/;
+
+ /** Used to detect unsigned integer values. */
+ var reIsUint = /^\d+$/;
+
+ /** Used to match latin-1 supplementary letters (excluding mathematical operators). */
+ var reLatin1 = /[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;
+
+ /** Used to ensure capturing order of template delimiters. */
+ var reNoMatch = /($^)/;
+
+ /** Used to match unescaped characters in compiled string literals. */
+ var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
+
+ /** Used to match words to create compound words. */
+ var reWords = (function() {
+ var upper = '[A-Z\\xc0-\\xd6\\xd8-\\xde]',
+ lower = '[a-z\\xdf-\\xf6\\xf8-\\xff]+';
+
+ return RegExp(upper + '+(?=' + upper + lower + ')|' + upper + '?' + lower + '|' + upper + '+|[0-9]+', 'g');
+ }());
+
+ /** Used to assign default `context` object properties. */
+ var contextProps = [
+ 'Array', 'ArrayBuffer', 'Date', 'Error', 'Float32Array', 'Float64Array',
+ 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Math', 'Number',
+ 'Object', 'RegExp', 'Set', 'String', '_', 'clearTimeout', 'isFinite',
+ 'parseFloat', 'parseInt', 'setTimeout', 'TypeError', 'Uint8Array',
+ 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap'
+ ];
+
+ /** Used to make template sourceURLs easier to identify. */
+ var templateCounter = -1;
+
+ /** Used to identify `toStringTag` values of typed arrays. */
+ var typedArrayTags = {};
+ typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
+ typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
+ typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
+ typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
+ typedArrayTags[uint32Tag] = true;
+ typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
+ typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
+ typedArrayTags[dateTag] = typedArrayTags[errorTag] =
+ typedArrayTags[funcTag] = typedArrayTags[mapTag] =
+ typedArrayTags[numberTag] = typedArrayTags[objectTag] =
+ typedArrayTags[regexpTag] = typedArrayTags[setTag] =
+ typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
+
+ /** Used to identify `toStringTag` values supported by `_.clone`. */
+ var cloneableTags = {};
+ cloneableTags[argsTag] = cloneableTags[arrayTag] =
+ cloneableTags[arrayBufferTag] = cloneableTags[boolTag] =
+ cloneableTags[dateTag] = cloneableTags[float32Tag] =
+ cloneableTags[float64Tag] = cloneableTags[int8Tag] =
+ cloneableTags[int16Tag] = cloneableTags[int32Tag] =
+ cloneableTags[numberTag] = cloneableTags[objectTag] =
+ cloneableTags[regexpTag] = cloneableTags[stringTag] =
+ cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
+ cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
+ cloneableTags[errorTag] = cloneableTags[funcTag] =
+ cloneableTags[mapTag] = cloneableTags[setTag] =
+ cloneableTags[weakMapTag] = false;
+
+ /** Used to map latin-1 supplementary letters to basic latin letters. */
+ var deburredLetters = {
+ '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
+ '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
+ '\xc7': 'C', '\xe7': 'c',
+ '\xd0': 'D', '\xf0': 'd',
+ '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
+ '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
+ '\xcC': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
+ '\xeC': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i',
+ '\xd1': 'N', '\xf1': 'n',
+ '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
+ '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
+ '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
+ '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
+ '\xdd': 'Y', '\xfd': 'y', '\xff': 'y',
+ '\xc6': 'Ae', '\xe6': 'ae',
+ '\xde': 'Th', '\xfe': 'th',
+ '\xdf': 'ss'
+ };
+
+ /** Used to map characters to HTML entities. */
+ var htmlEscapes = {
+ '&': '&amp;',
+ '<': '&lt;',
+ '>': '&gt;',
+ '"': '&quot;',
+ "'": '&#39;',
+ '`': '&#96;'
+ };
+
+ /** Used to map HTML entities to characters. */
+ var htmlUnescapes = {
+ '&amp;': '&',
+ '&lt;': '<',
+ '&gt;': '>',
+ '&quot;': '"',
+ '&#39;': "'",
+ '&#96;': '`'
+ };
+
+ /** Used to determine if values are of the language type `Object`. */
+ var objectTypes = {
+ 'function': true,
+ 'object': true
+ };
+
+ /** Used to escape characters for inclusion in compiled regexes. */
+ var regexpEscapes = {
+ '0': 'x30', '1': 'x31', '2': 'x32', '3': 'x33', '4': 'x34',
+ '5': 'x35', '6': 'x36', '7': 'x37', '8': 'x38', '9': 'x39',
+ 'A': 'x41', 'B': 'x42', 'C': 'x43', 'D': 'x44', 'E': 'x45', 'F': 'x46',
+ 'a': 'x61', 'b': 'x62', 'c': 'x63', 'd': 'x64', 'e': 'x65', 'f': 'x66',
+ 'n': 'x6e', 'r': 'x72', 't': 'x74', 'u': 'x75', 'v': 'x76', 'x': 'x78'
+ };
+
+ /** Used to escape characters for inclusion in compiled string literals. */
+ var stringEscapes = {
+ '\\': '\\',
+ "'": "'",
+ '\n': 'n',
+ '\r': 'r',
+ '\u2028': 'u2028',
+ '\u2029': 'u2029'
+ };
+
+ /** Detect free variable `exports`. */
+ var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
+
+ /** Detect free variable `module`. */
+ var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
+
+ /** Detect free variable `global` from Node.js. */
+ var freeGlobal = freeExports && freeModule && typeof global == 'object' && global && global.Object && global;
+
+ /** Detect free variable `self`. */
+ var freeSelf = objectTypes[typeof self] && self && self.Object && self;
+
+ /** Detect free variable `window`. */
+ var freeWindow = objectTypes[typeof window] && window && window.Object && window;
+
+ /** Detect the popular CommonJS extension `module.exports`. */
+ var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
+
+ /**
+ * Used as a reference to the global object.
+ *
+ * The `this` value is used if it's the global object to avoid Greasemonkey's
+ * restricted `window` object, otherwise the `window` object is used.
+ */
+ var root = freeGlobal || ((freeWindow !== (this && this.window)) && freeWindow) || freeSelf || this;
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * The base implementation of `compareAscending` which compares values and
+ * sorts them in ascending order without guaranteeing a stable sort.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {number} Returns the sort order indicator for `value`.
+ */
+ function baseCompareAscending(value, other) {
+ if (value !== other) {
+ var valIsNull = value === null,
+ valIsUndef = value === undefined,
+ valIsReflexive = value === value;
+
+ var othIsNull = other === null,
+ othIsUndef = other === undefined,
+ othIsReflexive = other === other;
+
+ if ((value > other && !othIsNull) || !valIsReflexive ||
+ (valIsNull && !othIsUndef && othIsReflexive) ||
+ (valIsUndef && othIsReflexive)) {
+ return 1;
+ }
+ if ((value < other && !valIsNull) || !othIsReflexive ||
+ (othIsNull && !valIsUndef && valIsReflexive) ||
+ (othIsUndef && valIsReflexive)) {
+ return -1;
+ }
+ }
+ return 0;
+ }
+
+ /**
+ * The base implementation of `_.findIndex` and `_.findLastIndex` without
+ * support for callback shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseFindIndex(array, predicate, fromRight) {
+ var length = array.length,
+ index = fromRight ? length : -1;
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (predicate(array[index], index, array)) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * The base implementation of `_.indexOf` without support for binary searches.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @param {number} fromIndex The index to search from.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ */
+ function baseIndexOf(array, value, fromIndex) {
+ if (value !== value) {
+ return indexOfNaN(array, fromIndex);
+ }
+ var index = fromIndex - 1,
+ length = array.length;
+
+ while (++index < length) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * The base implementation of `_.isFunction` without support for environments
+ * with incorrect `typeof` results.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ */
+ function baseIsFunction(value) {
+ // Avoid a Chakra JIT bug in compatibility modes of IE 11.
+ // See https://github.com/jashkenas/underscore/issues/1621 for more details.
+ return typeof value == 'function' || false;
+ }
+
+ /**
+ * Converts `value` to a string if it's not one. An empty string is returned
+ * for `null` or `undefined` values.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {string} Returns the string.
+ */
+ function baseToString(value) {
+ return value == null ? '' : (value + '');
+ }
+
+ /**
+ * Used by `_.trim` and `_.trimLeft` to get the index of the first character
+ * of `string` that is not found in `chars`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @param {string} chars The characters to find.
+ * @returns {number} Returns the index of the first character not found in `chars`.
+ */
+ function charsLeftIndex(string, chars) {
+ var index = -1,
+ length = string.length;
+
+ while (++index < length && chars.indexOf(string.charAt(index)) > -1) {}
+ return index;
+ }
+
+ /**
+ * Used by `_.trim` and `_.trimRight` to get the index of the last character
+ * of `string` that is not found in `chars`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @param {string} chars The characters to find.
+ * @returns {number} Returns the index of the last character not found in `chars`.
+ */
+ function charsRightIndex(string, chars) {
+ var index = string.length;
+
+ while (index-- && chars.indexOf(string.charAt(index)) > -1) {}
+ return index;
+ }
+
+ /**
+ * Used by `_.sortBy` to compare transformed elements of a collection and stable
+ * sort them in ascending order.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @returns {number} Returns the sort order indicator for `object`.
+ */
+ function compareAscending(object, other) {
+ return baseCompareAscending(object.criteria, other.criteria) || (object.index - other.index);
+ }
+
+ /**
+ * Used by `_.sortByOrder` to compare multiple properties of a value to another
+ * and stable sort them.
+ *
+ * If `orders` is unspecified, all valuess are sorted in ascending order. Otherwise,
+ * a value is sorted in ascending order if its corresponding order is "asc", and
+ * descending if "desc".
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {boolean[]} orders The order to sort by for each property.
+ * @returns {number} Returns the sort order indicator for `object`.
+ */
+ function compareMultiple(object, other, orders) {
+ var index = -1,
+ objCriteria = object.criteria,
+ othCriteria = other.criteria,
+ length = objCriteria.length,
+ ordersLength = orders.length;
+
+ while (++index < length) {
+ var result = baseCompareAscending(objCriteria[index], othCriteria[index]);
+ if (result) {
+ if (index >= ordersLength) {
+ return result;
+ }
+ var order = orders[index];
+ return result * ((order === 'asc' || order === true) ? 1 : -1);
+ }
+ }
+ // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
+ // that causes it, under certain circumstances, to provide the same value for
+ // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
+ // for more details.
+ //
+ // This also ensures a stable sort in V8 and other engines.
+ // See https://code.google.com/p/v8/issues/detail?id=90 for more details.
+ return object.index - other.index;
+ }
+
+ /**
+ * Used by `_.deburr` to convert latin-1 supplementary letters to basic latin letters.
+ *
+ * @private
+ * @param {string} letter The matched letter to deburr.
+ * @returns {string} Returns the deburred letter.
+ */
+ function deburrLetter(letter) {
+ return deburredLetters[letter];
+ }
+
+ /**
+ * Used by `_.escape` to convert characters to HTML entities.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @returns {string} Returns the escaped character.
+ */
+ function escapeHtmlChar(chr) {
+ return htmlEscapes[chr];
+ }
+
+ /**
+ * Used by `_.escapeRegExp` to escape characters for inclusion in compiled regexes.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @param {string} leadingChar The capture group for a leading character.
+ * @param {string} whitespaceChar The capture group for a whitespace character.
+ * @returns {string} Returns the escaped character.
+ */
+ function escapeRegExpChar(chr, leadingChar, whitespaceChar) {
+ if (leadingChar) {
+ chr = regexpEscapes[chr];
+ } else if (whitespaceChar) {
+ chr = stringEscapes[chr];
+ }
+ return '\\' + chr;
+ }
+
+ /**
+ * Used by `_.template` to escape characters for inclusion in compiled string literals.
+ *
+ * @private
+ * @param {string} chr The matched character to escape.
+ * @returns {string} Returns the escaped character.
+ */
+ function escapeStringChar(chr) {
+ return '\\' + stringEscapes[chr];
+ }
+
+ /**
+ * Gets the index at which the first occurrence of `NaN` is found in `array`.
+ *
+ * @private
+ * @param {Array} array The array to search.
+ * @param {number} fromIndex The index to search from.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {number} Returns the index of the matched `NaN`, else `-1`.
+ */
+ function indexOfNaN(array, fromIndex, fromRight) {
+ var length = array.length,
+ index = fromIndex + (fromRight ? 0 : -1);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ var other = array[index];
+ if (other !== other) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Checks if `value` is object-like.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
+ */
+ function isObjectLike(value) {
+ return !!value && typeof value == 'object';
+ }
+
+ /**
+ * Used by `trimmedLeftIndex` and `trimmedRightIndex` to determine if a
+ * character code is whitespace.
+ *
+ * @private
+ * @param {number} charCode The character code to inspect.
+ * @returns {boolean} Returns `true` if `charCode` is whitespace, else `false`.
+ */
+ function isSpace(charCode) {
+ return ((charCode <= 160 && (charCode >= 9 && charCode <= 13) || charCode == 32 || charCode == 160) || charCode == 5760 || charCode == 6158 ||
+ (charCode >= 8192 && (charCode <= 8202 || charCode == 8232 || charCode == 8233 || charCode == 8239 || charCode == 8287 || charCode == 12288 || charCode == 65279)));
+ }
+
+ /**
+ * Replaces all `placeholder` elements in `array` with an internal placeholder
+ * and returns an array of their indexes.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {*} placeholder The placeholder to replace.
+ * @returns {Array} Returns the new array of placeholder indexes.
+ */
+ function replaceHolders(array, placeholder) {
+ var index = -1,
+ length = array.length,
+ resIndex = -1,
+ result = [];
+
+ while (++index < length) {
+ if (array[index] === placeholder) {
+ array[index] = PLACEHOLDER;
+ result[++resIndex] = index;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * An implementation of `_.uniq` optimized for sorted arrays without support
+ * for callback shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The function invoked per iteration.
+ * @returns {Array} Returns the new duplicate-value-free array.
+ */
+ function sortedUniq(array, iteratee) {
+ var seen,
+ index = -1,
+ length = array.length,
+ resIndex = -1,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value, index, array) : value;
+
+ if (!index || seen !== computed) {
+ seen = computed;
+ result[++resIndex] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Used by `_.trim` and `_.trimLeft` to get the index of the first non-whitespace
+ * character of `string`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the index of the first non-whitespace character.
+ */
+ function trimmedLeftIndex(string) {
+ var index = -1,
+ length = string.length;
+
+ while (++index < length && isSpace(string.charCodeAt(index))) {}
+ return index;
+ }
+
+ /**
+ * Used by `_.trim` and `_.trimRight` to get the index of the last non-whitespace
+ * character of `string`.
+ *
+ * @private
+ * @param {string} string The string to inspect.
+ * @returns {number} Returns the index of the last non-whitespace character.
+ */
+ function trimmedRightIndex(string) {
+ var index = string.length;
+
+ while (index-- && isSpace(string.charCodeAt(index))) {}
+ return index;
+ }
+
+ /**
+ * Used by `_.unescape` to convert HTML entities to characters.
+ *
+ * @private
+ * @param {string} chr The matched character to unescape.
+ * @returns {string} Returns the unescaped character.
+ */
+ function unescapeHtmlChar(chr) {
+ return htmlUnescapes[chr];
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Create a new pristine `lodash` function using the given `context` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {Object} [context=root] The context object.
+ * @returns {Function} Returns a new `lodash` function.
+ * @example
+ *
+ * _.mixin({ 'foo': _.constant('foo') });
+ *
+ * var lodash = _.runInContext();
+ * lodash.mixin({ 'bar': lodash.constant('bar') });
+ *
+ * _.isFunction(_.foo);
+ * // => true
+ * _.isFunction(_.bar);
+ * // => false
+ *
+ * lodash.isFunction(lodash.foo);
+ * // => false
+ * lodash.isFunction(lodash.bar);
+ * // => true
+ *
+ * // using `context` to mock `Date#getTime` use in `_.now`
+ * var mock = _.runInContext({
+ * 'Date': function() {
+ * return { 'getTime': getTimeMock };
+ * }
+ * });
+ *
+ * // or creating a suped-up `defer` in Node.js
+ * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
+ */
+ function runInContext(context) {
+ // Avoid issues with some ES3 environments that attempt to use values, named
+ // after built-in constructors like `Object`, for the creation of literals.
+ // ES5 clears this up by stating that literals must use built-in constructors.
+ // See https://es5.github.io/#x11.1.5 for more details.
+ context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
+
+ /** Native constructor references. */
+ var Array = context.Array,
+ Date = context.Date,
+ Error = context.Error,
+ Function = context.Function,
+ Math = context.Math,
+ Number = context.Number,
+ Object = context.Object,
+ RegExp = context.RegExp,
+ String = context.String,
+ TypeError = context.TypeError;
+
+ /** Used for native method references. */
+ var arrayProto = Array.prototype,
+ objectProto = Object.prototype,
+ stringProto = String.prototype;
+
+ /** Used to resolve the decompiled source of functions. */
+ var fnToString = Function.prototype.toString;
+
+ /** Used to check objects for own properties. */
+ var hasOwnProperty = objectProto.hasOwnProperty;
+
+ /** Used to generate unique IDs. */
+ var idCounter = 0;
+
+ /**
+ * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
+ * of values.
+ */
+ var objToString = objectProto.toString;
+
+ /** Used to restore the original `_` reference in `_.noConflict`. */
+ var oldDash = root._;
+
+ /** Used to detect if a method is native. */
+ var reIsNative = RegExp('^' +
+ fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
+ .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
+ );
+
+ /** Native method references. */
+ var ArrayBuffer = context.ArrayBuffer,
+ clearTimeout = context.clearTimeout,
+ parseFloat = context.parseFloat,
+ pow = Math.pow,
+ propertyIsEnumerable = objectProto.propertyIsEnumerable,
+ Set = getNative(context, 'Set'),
+ setTimeout = context.setTimeout,
+ splice = arrayProto.splice,
+ Uint8Array = context.Uint8Array,
+ WeakMap = getNative(context, 'WeakMap');
+
+ /* Native method references for those with the same name as other `lodash` methods. */
+ var nativeCeil = Math.ceil,
+ nativeCreate = getNative(Object, 'create'),
+ nativeFloor = Math.floor,
+ nativeIsArray = getNative(Array, 'isArray'),
+ nativeIsFinite = context.isFinite,
+ nativeKeys = getNative(Object, 'keys'),
+ nativeMax = Math.max,
+ nativeMin = Math.min,
+ nativeNow = getNative(Date, 'now'),
+ nativeParseInt = context.parseInt,
+ nativeRandom = Math.random;
+
+ /** Used as references for `-Infinity` and `Infinity`. */
+ var NEGATIVE_INFINITY = Number.NEGATIVE_INFINITY,
+ POSITIVE_INFINITY = Number.POSITIVE_INFINITY;
+
+ /** Used as references for the maximum length and index of an array. */
+ var MAX_ARRAY_LENGTH = 4294967295,
+ MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
+ HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
+
+ /**
+ * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
+ * of an array-like value.
+ */
+ var MAX_SAFE_INTEGER = 9007199254740991;
+
+ /** Used to store function metadata. */
+ var metaMap = WeakMap && new WeakMap;
+
+ /** Used to lookup unminified function names. */
+ var realNames = {};
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a `lodash` object which wraps `value` to enable implicit chaining.
+ * Methods that operate on and return arrays, collections, and functions can
+ * be chained together. Methods that retrieve a single value or may return a
+ * primitive value will automatically end the chain returning the unwrapped
+ * value. Explicit chaining may be enabled using `_.chain`. The execution of
+ * chained methods is lazy, that is, execution is deferred until `_#value`
+ * is implicitly or explicitly called.
+ *
+ * Lazy evaluation allows several methods to support shortcut fusion. Shortcut
+ * fusion is an optimization strategy which merge iteratee calls; this can help
+ * to avoid the creation of intermediate data structures and greatly reduce the
+ * number of iteratee executions.
+ *
+ * Chaining is supported in custom builds as long as the `_#value` method is
+ * directly or indirectly included in the build.
+ *
+ * In addition to lodash methods, wrappers have `Array` and `String` methods.
+ *
+ * The wrapper `Array` methods are:
+ * `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`,
+ * `splice`, and `unshift`
+ *
+ * The wrapper `String` methods are:
+ * `replace` and `split`
+ *
+ * The wrapper methods that support shortcut fusion are:
+ * `compact`, `drop`, `dropRight`, `dropRightWhile`, `dropWhile`, `filter`,
+ * `first`, `initial`, `last`, `map`, `pluck`, `reject`, `rest`, `reverse`,
+ * `slice`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, `toArray`,
+ * and `where`
+ *
+ * The chainable wrapper methods are:
+ * `after`, `ary`, `assign`, `at`, `before`, `bind`, `bindAll`, `bindKey`,
+ * `callback`, `chain`, `chunk`, `commit`, `compact`, `concat`, `constant`,
+ * `countBy`, `create`, `curry`, `debounce`, `defaults`, `defaultsDeep`,
+ * `defer`, `delay`, `difference`, `drop`, `dropRight`, `dropRightWhile`,
+ * `dropWhile`, `fill`, `filter`, `flatten`, `flattenDeep`, `flow`, `flowRight`,
+ * `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
+ * `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
+ * `invoke`, `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`,
+ * `matchesProperty`, `memoize`, `merge`, `method`, `methodOf`, `mixin`,
+ * `modArgs`, `negate`, `omit`, `once`, `pairs`, `partial`, `partialRight`,
+ * `partition`, `pick`, `plant`, `pluck`, `property`, `propertyOf`, `pull`,
+ * `pullAt`, `push`, `range`, `rearg`, `reject`, `remove`, `rest`, `restParam`,
+ * `reverse`, `set`, `shuffle`, `slice`, `sort`, `sortBy`, `sortByAll`,
+ * `sortByOrder`, `splice`, `spread`, `take`, `takeRight`, `takeRightWhile`,
+ * `takeWhile`, `tap`, `throttle`, `thru`, `times`, `toArray`, `toPlainObject`,
+ * `transform`, `union`, `uniq`, `unshift`, `unzip`, `unzipWith`, `values`,
+ * `valuesIn`, `where`, `without`, `wrap`, `xor`, `zip`, `zipObject`, `zipWith`
+ *
+ * The wrapper methods that are **not** chainable by default are:
+ * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clone`, `cloneDeep`,
+ * `deburr`, `endsWith`, `escape`, `escapeRegExp`, `every`, `find`, `findIndex`,
+ * `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `findWhere`, `first`,
+ * `floor`, `get`, `gt`, `gte`, `has`, `identity`, `includes`, `indexOf`,
+ * `inRange`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
+ * `isEmpty`, `isEqual`, `isError`, `isFinite` `isFunction`, `isMatch`,
+ * `isNative`, `isNaN`, `isNull`, `isNumber`, `isObject`, `isPlainObject`,
+ * `isRegExp`, `isString`, `isUndefined`, `isTypedArray`, `join`, `kebabCase`,
+ * `last`, `lastIndexOf`, `lt`, `lte`, `max`, `min`, `noConflict`, `noop`,
+ * `now`, `pad`, `padLeft`, `padRight`, `parseInt`, `pop`, `random`, `reduce`,
+ * `reduceRight`, `repeat`, `result`, `round`, `runInContext`, `shift`, `size`,
+ * `snakeCase`, `some`, `sortedIndex`, `sortedLastIndex`, `startCase`,
+ * `startsWith`, `sum`, `template`, `trim`, `trimLeft`, `trimRight`, `trunc`,
+ * `unescape`, `uniqueId`, `value`, and `words`
+ *
+ * The wrapper method `sample` will return a wrapped value when `n` is provided,
+ * otherwise an unwrapped value is returned.
+ *
+ * @name _
+ * @constructor
+ * @category Chain
+ * @param {*} value The value to wrap in a `lodash` instance.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var wrapped = _([1, 2, 3]);
+ *
+ * // returns an unwrapped value
+ * wrapped.reduce(function(total, n) {
+ * return total + n;
+ * });
+ * // => 6
+ *
+ * // returns a wrapped value
+ * var squares = wrapped.map(function(n) {
+ * return n * n;
+ * });
+ *
+ * _.isArray(squares);
+ * // => false
+ *
+ * _.isArray(squares.value());
+ * // => true
+ */
+ function lodash(value) {
+ if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
+ if (value instanceof LodashWrapper) {
+ return value;
+ }
+ if (hasOwnProperty.call(value, '__chain__') && hasOwnProperty.call(value, '__wrapped__')) {
+ return wrapperClone(value);
+ }
+ }
+ return new LodashWrapper(value);
+ }
+
+ /**
+ * The function whose prototype all chaining wrappers inherit from.
+ *
+ * @private
+ */
+ function baseLodash() {
+ // No operation performed.
+ }
+
+ /**
+ * The base constructor for creating `lodash` wrapper objects.
+ *
+ * @private
+ * @param {*} value The value to wrap.
+ * @param {boolean} [chainAll] Enable chaining for all wrapper methods.
+ * @param {Array} [actions=[]] Actions to peform to resolve the unwrapped value.
+ */
+ function LodashWrapper(value, chainAll, actions) {
+ this.__wrapped__ = value;
+ this.__actions__ = actions || [];
+ this.__chain__ = !!chainAll;
+ }
+
+ /**
+ * An object environment feature flags.
+ *
+ * @static
+ * @memberOf _
+ * @type Object
+ */
+ var support = lodash.support = {};
+
+ /**
+ * By default, the template delimiters used by lodash are like those in
+ * embedded Ruby (ERB). Change the following template settings to use
+ * alternative delimiters.
+ *
+ * @static
+ * @memberOf _
+ * @type Object
+ */
+ lodash.templateSettings = {
+
+ /**
+ * Used to detect `data` property values to be HTML-escaped.
+ *
+ * @memberOf _.templateSettings
+ * @type RegExp
+ */
+ 'escape': reEscape,
+
+ /**
+ * Used to detect code to be evaluated.
+ *
+ * @memberOf _.templateSettings
+ * @type RegExp
+ */
+ 'evaluate': reEvaluate,
+
+ /**
+ * Used to detect `data` property values to inject.
+ *
+ * @memberOf _.templateSettings
+ * @type RegExp
+ */
+ 'interpolate': reInterpolate,
+
+ /**
+ * Used to reference the data object in the template text.
+ *
+ * @memberOf _.templateSettings
+ * @type string
+ */
+ 'variable': '',
+
+ /**
+ * Used to import variables into the compiled template.
+ *
+ * @memberOf _.templateSettings
+ * @type Object
+ */
+ 'imports': {
+
+ /**
+ * A reference to the `lodash` function.
+ *
+ * @memberOf _.templateSettings.imports
+ * @type Function
+ */
+ '_': lodash
+ }
+ };
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
+ *
+ * @private
+ * @param {*} value The value to wrap.
+ */
+ function LazyWrapper(value) {
+ this.__wrapped__ = value;
+ this.__actions__ = [];
+ this.__dir__ = 1;
+ this.__filtered__ = false;
+ this.__iteratees__ = [];
+ this.__takeCount__ = POSITIVE_INFINITY;
+ this.__views__ = [];
+ }
+
+ /**
+ * Creates a clone of the lazy wrapper object.
+ *
+ * @private
+ * @name clone
+ * @memberOf LazyWrapper
+ * @returns {Object} Returns the cloned `LazyWrapper` object.
+ */
+ function lazyClone() {
+ var result = new LazyWrapper(this.__wrapped__);
+ result.__actions__ = arrayCopy(this.__actions__);
+ result.__dir__ = this.__dir__;
+ result.__filtered__ = this.__filtered__;
+ result.__iteratees__ = arrayCopy(this.__iteratees__);
+ result.__takeCount__ = this.__takeCount__;
+ result.__views__ = arrayCopy(this.__views__);
+ return result;
+ }
+
+ /**
+ * Reverses the direction of lazy iteration.
+ *
+ * @private
+ * @name reverse
+ * @memberOf LazyWrapper
+ * @returns {Object} Returns the new reversed `LazyWrapper` object.
+ */
+ function lazyReverse() {
+ if (this.__filtered__) {
+ var result = new LazyWrapper(this);
+ result.__dir__ = -1;
+ result.__filtered__ = true;
+ } else {
+ result = this.clone();
+ result.__dir__ *= -1;
+ }
+ return result;
+ }
+
+ /**
+ * Extracts the unwrapped value from its lazy wrapper.
+ *
+ * @private
+ * @name value
+ * @memberOf LazyWrapper
+ * @returns {*} Returns the unwrapped value.
+ */
+ function lazyValue() {
+ var array = this.__wrapped__.value(),
+ dir = this.__dir__,
+ isArr = isArray(array),
+ isRight = dir < 0,
+ arrLength = isArr ? array.length : 0,
+ view = getView(0, arrLength, this.__views__),
+ start = view.start,
+ end = view.end,
+ length = end - start,
+ index = isRight ? end : (start - 1),
+ iteratees = this.__iteratees__,
+ iterLength = iteratees.length,
+ resIndex = 0,
+ takeCount = nativeMin(length, this.__takeCount__);
+
+ if (!isArr || arrLength < LARGE_ARRAY_SIZE || (arrLength == length && takeCount == length)) {
+ return baseWrapperValue((isRight && isArr) ? array.reverse() : array, this.__actions__);
+ }
+ var result = [];
+
+ outer:
+ while (length-- && resIndex < takeCount) {
+ index += dir;
+
+ var iterIndex = -1,
+ value = array[index];
+
+ while (++iterIndex < iterLength) {
+ var data = iteratees[iterIndex],
+ iteratee = data.iteratee,
+ type = data.type,
+ computed = iteratee(value);
+
+ if (type == LAZY_MAP_FLAG) {
+ value = computed;
+ } else if (!computed) {
+ if (type == LAZY_FILTER_FLAG) {
+ continue outer;
+ } else {
+ break outer;
+ }
+ }
+ }
+ result[resIndex++] = value;
+ }
+ return result;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a cache object to store key/value pairs.
+ *
+ * @private
+ * @static
+ * @name Cache
+ * @memberOf _.memoize
+ */
+ function MapCache() {
+ this.__data__ = {};
+ }
+
+ /**
+ * Removes `key` and its value from the cache.
+ *
+ * @private
+ * @name delete
+ * @memberOf _.memoize.Cache
+ * @param {string} key The key of the value to remove.
+ * @returns {boolean} Returns `true` if the entry was removed successfully, else `false`.
+ */
+ function mapDelete(key) {
+ return this.has(key) && delete this.__data__[key];
+ }
+
+ /**
+ * Gets the cached value for `key`.
+ *
+ * @private
+ * @name get
+ * @memberOf _.memoize.Cache
+ * @param {string} key The key of the value to get.
+ * @returns {*} Returns the cached value.
+ */
+ function mapGet(key) {
+ return key == '__proto__' ? undefined : this.__data__[key];
+ }
+
+ /**
+ * Checks if a cached value for `key` exists.
+ *
+ * @private
+ * @name has
+ * @memberOf _.memoize.Cache
+ * @param {string} key The key of the entry to check.
+ * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
+ */
+ function mapHas(key) {
+ return key != '__proto__' && hasOwnProperty.call(this.__data__, key);
+ }
+
+ /**
+ * Sets `value` to `key` of the cache.
+ *
+ * @private
+ * @name set
+ * @memberOf _.memoize.Cache
+ * @param {string} key The key of the value to cache.
+ * @param {*} value The value to cache.
+ * @returns {Object} Returns the cache object.
+ */
+ function mapSet(key, value) {
+ if (key != '__proto__') {
+ this.__data__[key] = value;
+ }
+ return this;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ *
+ * Creates a cache object to store unique values.
+ *
+ * @private
+ * @param {Array} [values] The values to cache.
+ */
+ function SetCache(values) {
+ var length = values ? values.length : 0;
+
+ this.data = { 'hash': nativeCreate(null), 'set': new Set };
+ while (length--) {
+ this.push(values[length]);
+ }
+ }
+
+ /**
+ * Checks if `value` is in `cache` mimicking the return signature of
+ * `_.indexOf` by returning `0` if the value is found, else `-1`.
+ *
+ * @private
+ * @param {Object} cache The cache to search.
+ * @param {*} value The value to search for.
+ * @returns {number} Returns `0` if `value` is found, else `-1`.
+ */
+ function cacheIndexOf(cache, value) {
+ var data = cache.data,
+ result = (typeof value == 'string' || isObject(value)) ? data.set.has(value) : data.hash[value];
+
+ return result ? 0 : -1;
+ }
+
+ /**
+ * Adds `value` to the cache.
+ *
+ * @private
+ * @name push
+ * @memberOf SetCache
+ * @param {*} value The value to cache.
+ */
+ function cachePush(value) {
+ var data = this.data;
+ if (typeof value == 'string' || isObject(value)) {
+ data.set.add(value);
+ } else {
+ data.hash[value] = true;
+ }
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a new array joining `array` with `other`.
+ *
+ * @private
+ * @param {Array} array The array to join.
+ * @param {Array} other The other array to join.
+ * @returns {Array} Returns the new concatenated array.
+ */
+ function arrayConcat(array, other) {
+ var index = -1,
+ length = array.length,
+ othIndex = -1,
+ othLength = other.length,
+ result = Array(length + othLength);
+
+ while (++index < length) {
+ result[index] = array[index];
+ }
+ while (++othIndex < othLength) {
+ result[index++] = other[othIndex];
+ }
+ return result;
+ }
+
+ /**
+ * Copies the values of `source` to `array`.
+ *
+ * @private
+ * @param {Array} source The array to copy values from.
+ * @param {Array} [array=[]] The array to copy values to.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayCopy(source, array) {
+ var index = -1,
+ length = source.length;
+
+ array || (array = Array(length));
+ while (++index < length) {
+ array[index] = source[index];
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.forEach` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEach(array, iteratee) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (iteratee(array[index], index, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.forEachRight` for arrays without support for
+ * callback shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayEachRight(array, iteratee) {
+ var length = array.length;
+
+ while (length--) {
+ if (iteratee(array[length], length, array) === false) {
+ break;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.every` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`.
+ */
+ function arrayEvery(array, predicate) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (!predicate(array[index], index, array)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * A specialized version of `baseExtremum` for arrays which invokes `iteratee`
+ * with one argument: (value).
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} comparator The function used to compare values.
+ * @param {*} exValue The initial extremum value.
+ * @returns {*} Returns the extremum value.
+ */
+ function arrayExtremum(array, iteratee, comparator, exValue) {
+ var index = -1,
+ length = array.length,
+ computed = exValue,
+ result = computed;
+
+ while (++index < length) {
+ var value = array[index],
+ current = +iteratee(value);
+
+ if (comparator(current, computed)) {
+ computed = current;
+ result = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.filter` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function arrayFilter(array, predicate) {
+ var index = -1,
+ length = array.length,
+ resIndex = -1,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result[++resIndex] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.map` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function arrayMap(array, iteratee) {
+ var index = -1,
+ length = array.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = iteratee(array[index], index, array);
+ }
+ return result;
+ }
+
+ /**
+ * Appends the elements of `values` to `array`.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {Array} values The values to append.
+ * @returns {Array} Returns `array`.
+ */
+ function arrayPush(array, values) {
+ var index = -1,
+ length = values.length,
+ offset = array.length;
+
+ while (++index < length) {
+ array[offset + index] = values[index];
+ }
+ return array;
+ }
+
+ /**
+ * A specialized version of `_.reduce` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initFromArray] Specify using the first element of `array`
+ * as the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduce(array, iteratee, accumulator, initFromArray) {
+ var index = -1,
+ length = array.length;
+
+ if (initFromArray && length) {
+ accumulator = array[++index];
+ }
+ while (++index < length) {
+ accumulator = iteratee(accumulator, array[index], index, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.reduceRight` for arrays without support for
+ * callback shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {boolean} [initFromArray] Specify using the last element of `array`
+ * as the initial value.
+ * @returns {*} Returns the accumulated value.
+ */
+ function arrayReduceRight(array, iteratee, accumulator, initFromArray) {
+ var length = array.length;
+ if (initFromArray && length) {
+ accumulator = array[--length];
+ }
+ while (length--) {
+ accumulator = iteratee(accumulator, array[length], length, array);
+ }
+ return accumulator;
+ }
+
+ /**
+ * A specialized version of `_.some` for arrays without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+ function arraySome(array, predicate) {
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ if (predicate(array[index], index, array)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A specialized version of `_.sum` for arrays without support for callback
+ * shorthands and `this` binding..
+ *
+ * @private
+ * @param {Array} array The array to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {number} Returns the sum.
+ */
+ function arraySum(array, iteratee) {
+ var length = array.length,
+ result = 0;
+
+ while (length--) {
+ result += +iteratee(array[length]) || 0;
+ }
+ return result;
+ }
+
+ /**
+ * Used by `_.defaults` to customize its `_.assign` use.
+ *
+ * @private
+ * @param {*} objectValue The destination object property value.
+ * @param {*} sourceValue The source object property value.
+ * @returns {*} Returns the value to assign to the destination object.
+ */
+ function assignDefaults(objectValue, sourceValue) {
+ return objectValue === undefined ? sourceValue : objectValue;
+ }
+
+ /**
+ * Used by `_.template` to customize its `_.assign` use.
+ *
+ * **Note:** This function is like `assignDefaults` except that it ignores
+ * inherited property values when checking if a property is `undefined`.
+ *
+ * @private
+ * @param {*} objectValue The destination object property value.
+ * @param {*} sourceValue The source object property value.
+ * @param {string} key The key associated with the object and source values.
+ * @param {Object} object The destination object.
+ * @returns {*} Returns the value to assign to the destination object.
+ */
+ function assignOwnDefaults(objectValue, sourceValue, key, object) {
+ return (objectValue === undefined || !hasOwnProperty.call(object, key))
+ ? sourceValue
+ : objectValue;
+ }
+
+ /**
+ * A specialized version of `_.assign` for customizing assigned values without
+ * support for argument juggling, multiple sources, and `this` binding `customizer`
+ * functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {Function} customizer The function to customize assigned values.
+ * @returns {Object} Returns `object`.
+ */
+ function assignWith(object, source, customizer) {
+ var index = -1,
+ props = keys(source),
+ length = props.length;
+
+ while (++index < length) {
+ var key = props[index],
+ value = object[key],
+ result = customizer(value, source[key], key, object, source);
+
+ if ((result === result ? (result !== value) : (value === value)) ||
+ (value === undefined && !(key in object))) {
+ object[key] = result;
+ }
+ }
+ return object;
+ }
+
+ /**
+ * The base implementation of `_.assign` without support for argument juggling,
+ * multiple sources, and `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @returns {Object} Returns `object`.
+ */
+ function baseAssign(object, source) {
+ return source == null
+ ? object
+ : baseCopy(source, keys(source), object);
+ }
+
+ /**
+ * The base implementation of `_.at` without support for string collections
+ * and individual key arguments.
+ *
+ * @private
+ * @param {Array|Object} collection The collection to iterate over.
+ * @param {number[]|string[]} props The property names or indexes of elements to pick.
+ * @returns {Array} Returns the new array of picked elements.
+ */
+ function baseAt(collection, props) {
+ var index = -1,
+ isNil = collection == null,
+ isArr = !isNil && isArrayLike(collection),
+ length = isArr ? collection.length : 0,
+ propsLength = props.length,
+ result = Array(propsLength);
+
+ while(++index < propsLength) {
+ var key = props[index];
+ if (isArr) {
+ result[index] = isIndex(key, length) ? collection[key] : undefined;
+ } else {
+ result[index] = isNil ? undefined : collection[key];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Copies properties of `source` to `object`.
+ *
+ * @private
+ * @param {Object} source The object to copy properties from.
+ * @param {Array} props The property names to copy.
+ * @param {Object} [object={}] The object to copy properties to.
+ * @returns {Object} Returns `object`.
+ */
+ function baseCopy(source, props, object) {
+ object || (object = {});
+
+ var index = -1,
+ length = props.length;
+
+ while (++index < length) {
+ var key = props[index];
+ object[key] = source[key];
+ }
+ return object;
+ }
+
+ /**
+ * The base implementation of `_.callback` which supports specifying the
+ * number of arguments to provide to `func`.
+ *
+ * @private
+ * @param {*} [func=_.identity] The value to convert to a callback.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {number} [argCount] The number of arguments to provide to `func`.
+ * @returns {Function} Returns the callback.
+ */
+ function baseCallback(func, thisArg, argCount) {
+ var type = typeof func;
+ if (type == 'function') {
+ return thisArg === undefined
+ ? func
+ : bindCallback(func, thisArg, argCount);
+ }
+ if (func == null) {
+ return identity;
+ }
+ if (type == 'object') {
+ return baseMatches(func);
+ }
+ return thisArg === undefined
+ ? property(func)
+ : baseMatchesProperty(func, thisArg);
+ }
+
+ /**
+ * The base implementation of `_.clone` without support for argument juggling
+ * and `this` binding `customizer` functions.
+ *
+ * @private
+ * @param {*} value The value to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @param {Function} [customizer] The function to customize cloning values.
+ * @param {string} [key] The key of `value`.
+ * @param {Object} [object] The object `value` belongs to.
+ * @param {Array} [stackA=[]] Tracks traversed source objects.
+ * @param {Array} [stackB=[]] Associates clones with source counterparts.
+ * @returns {*} Returns the cloned value.
+ */
+ function baseClone(value, isDeep, customizer, key, object, stackA, stackB) {
+ var result;
+ if (customizer) {
+ result = object ? customizer(value, key, object) : customizer(value);
+ }
+ if (result !== undefined) {
+ return result;
+ }
+ if (!isObject(value)) {
+ return value;
+ }
+ var isArr = isArray(value);
+ if (isArr) {
+ result = initCloneArray(value);
+ if (!isDeep) {
+ return arrayCopy(value, result);
+ }
+ } else {
+ var tag = objToString.call(value),
+ isFunc = tag == funcTag;
+
+ if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
+ result = initCloneObject(isFunc ? {} : value);
+ if (!isDeep) {
+ return baseAssign(result, value);
+ }
+ } else {
+ return cloneableTags[tag]
+ ? initCloneByTag(value, tag, isDeep)
+ : (object ? value : {});
+ }
+ }
+ // Check for circular references and return its corresponding clone.
+ stackA || (stackA = []);
+ stackB || (stackB = []);
+
+ var length = stackA.length;
+ while (length--) {
+ if (stackA[length] == value) {
+ return stackB[length];
+ }
+ }
+ // Add the source value to the stack of traversed objects and associate it with its clone.
+ stackA.push(value);
+ stackB.push(result);
+
+ // Recursively populate clone (susceptible to call stack limits).
+ (isArr ? arrayEach : baseForOwn)(value, function(subValue, key) {
+ result[key] = baseClone(subValue, isDeep, customizer, key, value, stackA, stackB);
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.create` without support for assigning
+ * properties to the created object.
+ *
+ * @private
+ * @param {Object} prototype The object to inherit from.
+ * @returns {Object} Returns the new object.
+ */
+ var baseCreate = (function() {
+ function object() {}
+ return function(prototype) {
+ if (isObject(prototype)) {
+ object.prototype = prototype;
+ var result = new object;
+ object.prototype = undefined;
+ }
+ return result || {};
+ };
+ }());
+
+ /**
+ * The base implementation of `_.delay` and `_.defer` which accepts an index
+ * of where to slice the arguments to provide to `func`.
+ *
+ * @private
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @param {Object} args The arguments provide to `func`.
+ * @returns {number} Returns the timer id.
+ */
+ function baseDelay(func, wait, args) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return setTimeout(function() { func.apply(undefined, args); }, wait);
+ }
+
+ /**
+ * The base implementation of `_.difference` which accepts a single array
+ * of values to exclude.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Array} values The values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ */
+ function baseDifference(array, values) {
+ var length = array ? array.length : 0,
+ result = [];
+
+ if (!length) {
+ return result;
+ }
+ var index = -1,
+ indexOf = getIndexOf(),
+ isCommon = indexOf == baseIndexOf,
+ cache = (isCommon && values.length >= LARGE_ARRAY_SIZE) ? createCache(values) : null,
+ valuesLength = values.length;
+
+ if (cache) {
+ indexOf = cacheIndexOf;
+ isCommon = false;
+ values = cache;
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index];
+
+ if (isCommon && value === value) {
+ var valuesIndex = valuesLength;
+ while (valuesIndex--) {
+ if (values[valuesIndex] === value) {
+ continue outer;
+ }
+ }
+ result.push(value);
+ }
+ else if (indexOf(values, value, 0) < 0) {
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.forEach` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object|string} Returns `collection`.
+ */
+ var baseEach = createBaseEach(baseForOwn);
+
+ /**
+ * The base implementation of `_.forEachRight` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array|Object|string} Returns `collection`.
+ */
+ var baseEachRight = createBaseEach(baseForOwnRight, true);
+
+ /**
+ * The base implementation of `_.every` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`
+ */
+ function baseEvery(collection, predicate) {
+ var result = true;
+ baseEach(collection, function(value, index, collection) {
+ result = !!predicate(value, index, collection);
+ return result;
+ });
+ return result;
+ }
+
+ /**
+ * Gets the extremum value of `collection` invoking `iteratee` for each value
+ * in `collection` to generate the criterion by which the value is ranked.
+ * The `iteratee` is invoked with three arguments: (value, index|key, collection).
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} comparator The function used to compare values.
+ * @param {*} exValue The initial extremum value.
+ * @returns {*} Returns the extremum value.
+ */
+ function baseExtremum(collection, iteratee, comparator, exValue) {
+ var computed = exValue,
+ result = computed;
+
+ baseEach(collection, function(value, index, collection) {
+ var current = +iteratee(value, index, collection);
+ if (comparator(current, computed) || (current === exValue && current === result)) {
+ computed = current;
+ result = value;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.fill` without an iteratee call guard.
+ *
+ * @private
+ * @param {Array} array The array to fill.
+ * @param {*} value The value to fill `array` with.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns `array`.
+ */
+ function baseFill(array, value, start, end) {
+ var length = array.length;
+
+ start = start == null ? 0 : (+start || 0);
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = (end === undefined || end > length) ? length : (+end || 0);
+ if (end < 0) {
+ end += length;
+ }
+ length = start > end ? 0 : (end >>> 0);
+ start >>>= 0;
+
+ while (start < length) {
+ array[start++] = value;
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.filter` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Array} Returns the new filtered array.
+ */
+ function baseFilter(collection, predicate) {
+ var result = [];
+ baseEach(collection, function(value, index, collection) {
+ if (predicate(value, index, collection)) {
+ result.push(value);
+ }
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`,
+ * without support for callback shorthands and `this` binding, which iterates
+ * over `collection` using the provided `eachFunc`.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {Function} eachFunc The function to iterate over `collection`.
+ * @param {boolean} [retKey] Specify returning the key of the found element
+ * instead of the element itself.
+ * @returns {*} Returns the found element or its key, else `undefined`.
+ */
+ function baseFind(collection, predicate, eachFunc, retKey) {
+ var result;
+ eachFunc(collection, function(value, key, collection) {
+ if (predicate(value, key, collection)) {
+ result = retKey ? key : value;
+ return false;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.flatten` with added support for restricting
+ * flattening and specifying the start index.
+ *
+ * @private
+ * @param {Array} array The array to flatten.
+ * @param {boolean} [isDeep] Specify a deep flatten.
+ * @param {boolean} [isStrict] Restrict flattening to arrays-like objects.
+ * @param {Array} [result=[]] The initial result value.
+ * @returns {Array} Returns the new flattened array.
+ */
+ function baseFlatten(array, isDeep, isStrict, result) {
+ result || (result = []);
+
+ var index = -1,
+ length = array.length;
+
+ while (++index < length) {
+ var value = array[index];
+ if (isObjectLike(value) && isArrayLike(value) &&
+ (isStrict || isArray(value) || isArguments(value))) {
+ if (isDeep) {
+ // Recursively flatten arrays (susceptible to call stack limits).
+ baseFlatten(value, isDeep, isStrict, result);
+ } else {
+ arrayPush(result, value);
+ }
+ } else if (!isStrict) {
+ result[result.length] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `baseForIn` and `baseForOwn` which iterates
+ * over `object` properties returned by `keysFunc` invoking `iteratee` for
+ * each property. Iteratee functions may exit iteration early by explicitly
+ * returning `false`.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @returns {Object} Returns `object`.
+ */
+ var baseFor = createBaseFor();
+
+ /**
+ * This function is like `baseFor` except that it iterates over properties
+ * in the opposite order.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {Function} keysFunc The function to get the keys of `object`.
+ * @returns {Object} Returns `object`.
+ */
+ var baseForRight = createBaseFor(true);
+
+ /**
+ * The base implementation of `_.forIn` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+ function baseForIn(object, iteratee) {
+ return baseFor(object, iteratee, keysIn);
+ }
+
+ /**
+ * The base implementation of `_.forOwn` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+ function baseForOwn(object, iteratee) {
+ return baseFor(object, iteratee, keys);
+ }
+
+ /**
+ * The base implementation of `_.forOwnRight` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Object} object The object to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Object} Returns `object`.
+ */
+ function baseForOwnRight(object, iteratee) {
+ return baseForRight(object, iteratee, keys);
+ }
+
+ /**
+ * The base implementation of `_.functions` which creates an array of
+ * `object` function property names filtered from those provided.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Array} props The property names to filter.
+ * @returns {Array} Returns the new array of filtered property names.
+ */
+ function baseFunctions(object, props) {
+ var index = -1,
+ length = props.length,
+ resIndex = -1,
+ result = [];
+
+ while (++index < length) {
+ var key = props[index];
+ if (isFunction(object[key])) {
+ result[++resIndex] = key;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `get` without support for string paths
+ * and default values.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} path The path of the property to get.
+ * @param {string} [pathKey] The key representation of path.
+ * @returns {*} Returns the resolved value.
+ */
+ function baseGet(object, path, pathKey) {
+ if (object == null) {
+ return;
+ }
+ if (pathKey !== undefined && pathKey in toObject(object)) {
+ path = [pathKey];
+ }
+ var index = 0,
+ length = path.length;
+
+ while (object != null && index < length) {
+ object = object[path[index++]];
+ }
+ return (index && index == length) ? object : undefined;
+ }
+
+ /**
+ * The base implementation of `_.isEqual` without support for `this` binding
+ * `customizer` functions.
+ *
+ * @private
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @param {Function} [customizer] The function to customize comparing values.
+ * @param {boolean} [isLoose] Specify performing partial comparisons.
+ * @param {Array} [stackA] Tracks traversed `value` objects.
+ * @param {Array} [stackB] Tracks traversed `other` objects.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ */
+ function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
+ if (value === other) {
+ return true;
+ }
+ if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
+ return value !== value && other !== other;
+ }
+ return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);
+ }
+
+ /**
+ * A specialized version of `baseIsEqual` for arrays and objects which performs
+ * deep comparisons and tracks traversed objects enabling objects with circular
+ * references to be compared.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Function} [customizer] The function to customize comparing objects.
+ * @param {boolean} [isLoose] Specify performing partial comparisons.
+ * @param {Array} [stackA=[]] Tracks traversed `value` objects.
+ * @param {Array} [stackB=[]] Tracks traversed `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
+ var objIsArr = isArray(object),
+ othIsArr = isArray(other),
+ objTag = arrayTag,
+ othTag = arrayTag;
+
+ if (!objIsArr) {
+ objTag = objToString.call(object);
+ if (objTag == argsTag) {
+ objTag = objectTag;
+ } else if (objTag != objectTag) {
+ objIsArr = isTypedArray(object);
+ }
+ }
+ if (!othIsArr) {
+ othTag = objToString.call(other);
+ if (othTag == argsTag) {
+ othTag = objectTag;
+ } else if (othTag != objectTag) {
+ othIsArr = isTypedArray(other);
+ }
+ }
+ var objIsObj = objTag == objectTag,
+ othIsObj = othTag == objectTag,
+ isSameTag = objTag == othTag;
+
+ if (isSameTag && !(objIsArr || objIsObj)) {
+ return equalByTag(object, other, objTag);
+ }
+ if (!isLoose) {
+ var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
+ othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
+
+ if (objIsWrapped || othIsWrapped) {
+ return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);
+ }
+ }
+ if (!isSameTag) {
+ return false;
+ }
+ // Assume cyclic values are equal.
+ // For more information on detecting circular references see https://es5.github.io/#JO.
+ stackA || (stackA = []);
+ stackB || (stackB = []);
+
+ var length = stackA.length;
+ while (length--) {
+ if (stackA[length] == object) {
+ return stackB[length] == other;
+ }
+ }
+ // Add `object` and `other` to the stack of traversed objects.
+ stackA.push(object);
+ stackB.push(other);
+
+ var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);
+
+ stackA.pop();
+ stackB.pop();
+
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.isMatch` without support for callback
+ * shorthands and `this` binding.
+ *
+ * @private
+ * @param {Object} object The object to inspect.
+ * @param {Array} matchData The propery names, values, and compare flags to match.
+ * @param {Function} [customizer] The function to customize comparing objects.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ */
+ function baseIsMatch(object, matchData, customizer) {
+ var index = matchData.length,
+ length = index,
+ noCustomizer = !customizer;
+
+ if (object == null) {
+ return !length;
+ }
+ object = toObject(object);
+ while (index--) {
+ var data = matchData[index];
+ if ((noCustomizer && data[2])
+ ? data[1] !== object[data[0]]
+ : !(data[0] in object)
+ ) {
+ return false;
+ }
+ }
+ while (++index < length) {
+ data = matchData[index];
+ var key = data[0],
+ objValue = object[key],
+ srcValue = data[1];
+
+ if (noCustomizer && data[2]) {
+ if (objValue === undefined && !(key in object)) {
+ return false;
+ }
+ } else {
+ var result = customizer ? customizer(objValue, srcValue, key) : undefined;
+ if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * The base implementation of `_.map` without support for callback shorthands
+ * and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {Array} Returns the new mapped array.
+ */
+ function baseMap(collection, iteratee) {
+ var index = -1,
+ result = isArrayLike(collection) ? Array(collection.length) : [];
+
+ baseEach(collection, function(value, key, collection) {
+ result[++index] = iteratee(value, key, collection);
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.matches` which does not clone `source`.
+ *
+ * @private
+ * @param {Object} source The object of property values to match.
+ * @returns {Function} Returns the new function.
+ */
+ function baseMatches(source) {
+ var matchData = getMatchData(source);
+ if (matchData.length == 1 && matchData[0][2]) {
+ var key = matchData[0][0],
+ value = matchData[0][1];
+
+ return function(object) {
+ if (object == null) {
+ return false;
+ }
+ return object[key] === value && (value !== undefined || (key in toObject(object)));
+ };
+ }
+ return function(object) {
+ return baseIsMatch(object, matchData);
+ };
+ }
+
+ /**
+ * The base implementation of `_.matchesProperty` which does not clone `srcValue`.
+ *
+ * @private
+ * @param {string} path The path of the property to get.
+ * @param {*} srcValue The value to compare.
+ * @returns {Function} Returns the new function.
+ */
+ function baseMatchesProperty(path, srcValue) {
+ var isArr = isArray(path),
+ isCommon = isKey(path) && isStrictComparable(srcValue),
+ pathKey = (path + '');
+
+ path = toPath(path);
+ return function(object) {
+ if (object == null) {
+ return false;
+ }
+ var key = pathKey;
+ object = toObject(object);
+ if ((isArr || !isCommon) && !(key in object)) {
+ object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+ if (object == null) {
+ return false;
+ }
+ key = last(path);
+ object = toObject(object);
+ }
+ return object[key] === srcValue
+ ? (srcValue !== undefined || (key in object))
+ : baseIsEqual(srcValue, object[key], undefined, true);
+ };
+ }
+
+ /**
+ * The base implementation of `_.merge` without support for argument juggling,
+ * multiple sources, and `this` binding `customizer` functions.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {Function} [customizer] The function to customize merged values.
+ * @param {Array} [stackA=[]] Tracks traversed source objects.
+ * @param {Array} [stackB=[]] Associates values with source counterparts.
+ * @returns {Object} Returns `object`.
+ */
+ function baseMerge(object, source, customizer, stackA, stackB) {
+ if (!isObject(object)) {
+ return object;
+ }
+ var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)),
+ props = isSrcArr ? undefined : keys(source);
+
+ arrayEach(props || source, function(srcValue, key) {
+ if (props) {
+ key = srcValue;
+ srcValue = source[key];
+ }
+ if (isObjectLike(srcValue)) {
+ stackA || (stackA = []);
+ stackB || (stackB = []);
+ baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);
+ }
+ else {
+ var value = object[key],
+ result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
+ isCommon = result === undefined;
+
+ if (isCommon) {
+ result = srcValue;
+ }
+ if ((result !== undefined || (isSrcArr && !(key in object))) &&
+ (isCommon || (result === result ? (result !== value) : (value === value)))) {
+ object[key] = result;
+ }
+ }
+ });
+ return object;
+ }
+
+ /**
+ * A specialized version of `baseMerge` for arrays and objects which performs
+ * deep merges and tracks traversed objects enabling objects with circular
+ * references to be merged.
+ *
+ * @private
+ * @param {Object} object The destination object.
+ * @param {Object} source The source object.
+ * @param {string} key The key of the value to merge.
+ * @param {Function} mergeFunc The function to merge values.
+ * @param {Function} [customizer] The function to customize merged values.
+ * @param {Array} [stackA=[]] Tracks traversed source objects.
+ * @param {Array} [stackB=[]] Associates values with source counterparts.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {
+ var length = stackA.length,
+ srcValue = source[key];
+
+ while (length--) {
+ if (stackA[length] == srcValue) {
+ object[key] = stackB[length];
+ return;
+ }
+ }
+ var value = object[key],
+ result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
+ isCommon = result === undefined;
+
+ if (isCommon) {
+ result = srcValue;
+ if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) {
+ result = isArray(value)
+ ? value
+ : (isArrayLike(value) ? arrayCopy(value) : []);
+ }
+ else if (isPlainObject(srcValue) || isArguments(srcValue)) {
+ result = isArguments(value)
+ ? toPlainObject(value)
+ : (isPlainObject(value) ? value : {});
+ }
+ else {
+ isCommon = false;
+ }
+ }
+ // Add the source value to the stack of traversed objects and associate
+ // it with its merged value.
+ stackA.push(srcValue);
+ stackB.push(result);
+
+ if (isCommon) {
+ // Recursively merge objects and arrays (susceptible to call stack limits).
+ object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);
+ } else if (result === result ? (result !== value) : (value === value)) {
+ object[key] = result;
+ }
+ }
+
+ /**
+ * The base implementation of `_.property` without support for deep paths.
+ *
+ * @private
+ * @param {string} key The key of the property to get.
+ * @returns {Function} Returns the new function.
+ */
+ function baseProperty(key) {
+ return function(object) {
+ return object == null ? undefined : object[key];
+ };
+ }
+
+ /**
+ * A specialized version of `baseProperty` which supports deep paths.
+ *
+ * @private
+ * @param {Array|string} path The path of the property to get.
+ * @returns {Function} Returns the new function.
+ */
+ function basePropertyDeep(path) {
+ var pathKey = (path + '');
+ path = toPath(path);
+ return function(object) {
+ return baseGet(object, path, pathKey);
+ };
+ }
+
+ /**
+ * The base implementation of `_.pullAt` without support for individual
+ * index arguments and capturing the removed elements.
+ *
+ * @private
+ * @param {Array} array The array to modify.
+ * @param {number[]} indexes The indexes of elements to remove.
+ * @returns {Array} Returns `array`.
+ */
+ function basePullAt(array, indexes) {
+ var length = array ? indexes.length : 0;
+ while (length--) {
+ var index = indexes[length];
+ if (index != previous && isIndex(index)) {
+ var previous = index;
+ splice.call(array, index, 1);
+ }
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.random` without support for argument juggling
+ * and returning floating-point numbers.
+ *
+ * @private
+ * @param {number} min The minimum possible value.
+ * @param {number} max The maximum possible value.
+ * @returns {number} Returns the random number.
+ */
+ function baseRandom(min, max) {
+ return min + nativeFloor(nativeRandom() * (max - min + 1));
+ }
+
+ /**
+ * The base implementation of `_.reduce` and `_.reduceRight` without support
+ * for callback shorthands and `this` binding, which iterates over `collection`
+ * using the provided `eachFunc`.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {*} accumulator The initial value.
+ * @param {boolean} initFromCollection Specify using the first or last element
+ * of `collection` as the initial value.
+ * @param {Function} eachFunc The function to iterate over `collection`.
+ * @returns {*} Returns the accumulated value.
+ */
+ function baseReduce(collection, iteratee, accumulator, initFromCollection, eachFunc) {
+ eachFunc(collection, function(value, index, collection) {
+ accumulator = initFromCollection
+ ? (initFromCollection = false, value)
+ : iteratee(accumulator, value, index, collection);
+ });
+ return accumulator;
+ }
+
+ /**
+ * The base implementation of `setData` without support for hot loop detection.
+ *
+ * @private
+ * @param {Function} func The function to associate metadata with.
+ * @param {*} data The metadata.
+ * @returns {Function} Returns `func`.
+ */
+ var baseSetData = !metaMap ? identity : function(func, data) {
+ metaMap.set(func, data);
+ return func;
+ };
+
+ /**
+ * The base implementation of `_.slice` without an iteratee call guard.
+ *
+ * @private
+ * @param {Array} array The array to slice.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseSlice(array, start, end) {
+ var index = -1,
+ length = array.length;
+
+ start = start == null ? 0 : (+start || 0);
+ if (start < 0) {
+ start = -start > length ? 0 : (length + start);
+ }
+ end = (end === undefined || end > length) ? length : (+end || 0);
+ if (end < 0) {
+ end += length;
+ }
+ length = start > end ? 0 : ((end - start) >>> 0);
+ start >>>= 0;
+
+ var result = Array(length);
+ while (++index < length) {
+ result[index] = array[index + start];
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.some` without support for callback shorthands
+ * and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ */
+ function baseSome(collection, predicate) {
+ var result;
+
+ baseEach(collection, function(value, index, collection) {
+ result = predicate(value, index, collection);
+ return !result;
+ });
+ return !!result;
+ }
+
+ /**
+ * The base implementation of `_.sortBy` which uses `comparer` to define
+ * the sort order of `array` and replaces criteria objects with their
+ * corresponding values.
+ *
+ * @private
+ * @param {Array} array The array to sort.
+ * @param {Function} comparer The function to define sort order.
+ * @returns {Array} Returns `array`.
+ */
+ function baseSortBy(array, comparer) {
+ var length = array.length;
+
+ array.sort(comparer);
+ while (length--) {
+ array[length] = array[length].value;
+ }
+ return array;
+ }
+
+ /**
+ * The base implementation of `_.sortByOrder` without param guards.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
+ * @param {boolean[]} orders The sort orders of `iteratees`.
+ * @returns {Array} Returns the new sorted array.
+ */
+ function baseSortByOrder(collection, iteratees, orders) {
+ var callback = getCallback(),
+ index = -1;
+
+ iteratees = arrayMap(iteratees, function(iteratee) { return callback(iteratee); });
+
+ var result = baseMap(collection, function(value) {
+ var criteria = arrayMap(iteratees, function(iteratee) { return iteratee(value); });
+ return { 'criteria': criteria, 'index': ++index, 'value': value };
+ });
+
+ return baseSortBy(result, function(object, other) {
+ return compareMultiple(object, other, orders);
+ });
+ }
+
+ /**
+ * The base implementation of `_.sum` without support for callback shorthands
+ * and `this` binding.
+ *
+ * @private
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @returns {number} Returns the sum.
+ */
+ function baseSum(collection, iteratee) {
+ var result = 0;
+ baseEach(collection, function(value, index, collection) {
+ result += +iteratee(value, index, collection) || 0;
+ });
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.uniq` without support for callback shorthands
+ * and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to inspect.
+ * @param {Function} [iteratee] The function invoked per iteration.
+ * @returns {Array} Returns the new duplicate-value-free array.
+ */
+ function baseUniq(array, iteratee) {
+ var index = -1,
+ indexOf = getIndexOf(),
+ length = array.length,
+ isCommon = indexOf == baseIndexOf,
+ isLarge = isCommon && length >= LARGE_ARRAY_SIZE,
+ seen = isLarge ? createCache() : null,
+ result = [];
+
+ if (seen) {
+ indexOf = cacheIndexOf;
+ isCommon = false;
+ } else {
+ isLarge = false;
+ seen = iteratee ? [] : result;
+ }
+ outer:
+ while (++index < length) {
+ var value = array[index],
+ computed = iteratee ? iteratee(value, index, array) : value;
+
+ if (isCommon && value === value) {
+ var seenIndex = seen.length;
+ while (seenIndex--) {
+ if (seen[seenIndex] === computed) {
+ continue outer;
+ }
+ }
+ if (iteratee) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ else if (indexOf(seen, computed, 0) < 0) {
+ if (iteratee || isLarge) {
+ seen.push(computed);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.values` and `_.valuesIn` which creates an
+ * array of `object` property values corresponding to the property names
+ * of `props`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array} props The property names to get values for.
+ * @returns {Object} Returns the array of property values.
+ */
+ function baseValues(object, props) {
+ var index = -1,
+ length = props.length,
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = object[props[index]];
+ }
+ return result;
+ }
+
+ /**
+ * The base implementation of `_.dropRightWhile`, `_.dropWhile`, `_.takeRightWhile`,
+ * and `_.takeWhile` without support for callback shorthands and `this` binding.
+ *
+ * @private
+ * @param {Array} array The array to query.
+ * @param {Function} predicate The function invoked per iteration.
+ * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function baseWhile(array, predicate, isDrop, fromRight) {
+ var length = array.length,
+ index = fromRight ? length : -1;
+
+ while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}
+ return isDrop
+ ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
+ : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
+ }
+
+ /**
+ * The base implementation of `wrapperValue` which returns the result of
+ * performing a sequence of actions on the unwrapped `value`, where each
+ * successive action is supplied the return value of the previous.
+ *
+ * @private
+ * @param {*} value The unwrapped value.
+ * @param {Array} actions Actions to peform to resolve the unwrapped value.
+ * @returns {*} Returns the resolved value.
+ */
+ function baseWrapperValue(value, actions) {
+ var result = value;
+ if (result instanceof LazyWrapper) {
+ result = result.value();
+ }
+ var index = -1,
+ length = actions.length;
+
+ while (++index < length) {
+ var action = actions[index];
+ result = action.func.apply(action.thisArg, arrayPush([result], action.args));
+ }
+ return result;
+ }
+
+ /**
+ * Performs a binary search of `array` to determine the index at which `value`
+ * should be inserted into `array` in order to maintain its sort order.
+ *
+ * @private
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ */
+ function binaryIndex(array, value, retHighest) {
+ var low = 0,
+ high = array ? array.length : low;
+
+ if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
+ while (low < high) {
+ var mid = (low + high) >>> 1,
+ computed = array[mid];
+
+ if ((retHighest ? (computed <= value) : (computed < value)) && computed !== null) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return high;
+ }
+ return binaryIndexBy(array, value, identity, retHighest);
+ }
+
+ /**
+ * This function is like `binaryIndex` except that it invokes `iteratee` for
+ * `value` and each element of `array` to compute their sort ranking. The
+ * iteratee is invoked with one argument; (value).
+ *
+ * @private
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function} iteratee The function invoked per iteration.
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ */
+ function binaryIndexBy(array, value, iteratee, retHighest) {
+ value = iteratee(value);
+
+ var low = 0,
+ high = array ? array.length : 0,
+ valIsNaN = value !== value,
+ valIsNull = value === null,
+ valIsUndef = value === undefined;
+
+ while (low < high) {
+ var mid = nativeFloor((low + high) / 2),
+ computed = iteratee(array[mid]),
+ isDef = computed !== undefined,
+ isReflexive = computed === computed;
+
+ if (valIsNaN) {
+ var setLow = isReflexive || retHighest;
+ } else if (valIsNull) {
+ setLow = isReflexive && isDef && (retHighest || computed != null);
+ } else if (valIsUndef) {
+ setLow = isReflexive && (retHighest || isDef);
+ } else if (computed == null) {
+ setLow = false;
+ } else {
+ setLow = retHighest ? (computed <= value) : (computed < value);
+ }
+ if (setLow) {
+ low = mid + 1;
+ } else {
+ high = mid;
+ }
+ }
+ return nativeMin(high, MAX_ARRAY_INDEX);
+ }
+
+ /**
+ * A specialized version of `baseCallback` which only supports `this` binding
+ * and specifying the number of arguments to provide to `func`.
+ *
+ * @private
+ * @param {Function} func The function to bind.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {number} [argCount] The number of arguments to provide to `func`.
+ * @returns {Function} Returns the callback.
+ */
+ function bindCallback(func, thisArg, argCount) {
+ if (typeof func != 'function') {
+ return identity;
+ }
+ if (thisArg === undefined) {
+ return func;
+ }
+ switch (argCount) {
+ case 1: return function(value) {
+ return func.call(thisArg, value);
+ };
+ case 3: return function(value, index, collection) {
+ return func.call(thisArg, value, index, collection);
+ };
+ case 4: return function(accumulator, value, index, collection) {
+ return func.call(thisArg, accumulator, value, index, collection);
+ };
+ case 5: return function(value, other, key, object, source) {
+ return func.call(thisArg, value, other, key, object, source);
+ };
+ }
+ return function() {
+ return func.apply(thisArg, arguments);
+ };
+ }
+
+ /**
+ * Creates a clone of the given array buffer.
+ *
+ * @private
+ * @param {ArrayBuffer} buffer The array buffer to clone.
+ * @returns {ArrayBuffer} Returns the cloned array buffer.
+ */
+ function bufferClone(buffer) {
+ var result = new ArrayBuffer(buffer.byteLength),
+ view = new Uint8Array(result);
+
+ view.set(new Uint8Array(buffer));
+ return result;
+ }
+
+ /**
+ * Creates an array that is the composition of partially applied arguments,
+ * placeholders, and provided arguments into a single array of arguments.
+ *
+ * @private
+ * @param {Array|Object} args The provided arguments.
+ * @param {Array} partials The arguments to prepend to those provided.
+ * @param {Array} holders The `partials` placeholder indexes.
+ * @returns {Array} Returns the new array of composed arguments.
+ */
+ function composeArgs(args, partials, holders) {
+ var holdersLength = holders.length,
+ argsIndex = -1,
+ argsLength = nativeMax(args.length - holdersLength, 0),
+ leftIndex = -1,
+ leftLength = partials.length,
+ result = Array(leftLength + argsLength);
+
+ while (++leftIndex < leftLength) {
+ result[leftIndex] = partials[leftIndex];
+ }
+ while (++argsIndex < holdersLength) {
+ result[holders[argsIndex]] = args[argsIndex];
+ }
+ while (argsLength--) {
+ result[leftIndex++] = args[argsIndex++];
+ }
+ return result;
+ }
+
+ /**
+ * This function is like `composeArgs` except that the arguments composition
+ * is tailored for `_.partialRight`.
+ *
+ * @private
+ * @param {Array|Object} args The provided arguments.
+ * @param {Array} partials The arguments to append to those provided.
+ * @param {Array} holders The `partials` placeholder indexes.
+ * @returns {Array} Returns the new array of composed arguments.
+ */
+ function composeArgsRight(args, partials, holders) {
+ var holdersIndex = -1,
+ holdersLength = holders.length,
+ argsIndex = -1,
+ argsLength = nativeMax(args.length - holdersLength, 0),
+ rightIndex = -1,
+ rightLength = partials.length,
+ result = Array(argsLength + rightLength);
+
+ while (++argsIndex < argsLength) {
+ result[argsIndex] = args[argsIndex];
+ }
+ var offset = argsIndex;
+ while (++rightIndex < rightLength) {
+ result[offset + rightIndex] = partials[rightIndex];
+ }
+ while (++holdersIndex < holdersLength) {
+ result[offset + holders[holdersIndex]] = args[argsIndex++];
+ }
+ return result;
+ }
+
+ /**
+ * Creates a `_.countBy`, `_.groupBy`, `_.indexBy`, or `_.partition` function.
+ *
+ * @private
+ * @param {Function} setter The function to set keys and values of the accumulator object.
+ * @param {Function} [initializer] The function to initialize the accumulator object.
+ * @returns {Function} Returns the new aggregator function.
+ */
+ function createAggregator(setter, initializer) {
+ return function(collection, iteratee, thisArg) {
+ var result = initializer ? initializer() : {};
+ iteratee = getCallback(iteratee, thisArg, 3);
+
+ if (isArray(collection)) {
+ var index = -1,
+ length = collection.length;
+
+ while (++index < length) {
+ var value = collection[index];
+ setter(result, value, iteratee(value, index, collection), collection);
+ }
+ } else {
+ baseEach(collection, function(value, key, collection) {
+ setter(result, value, iteratee(value, key, collection), collection);
+ });
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Creates a `_.assign`, `_.defaults`, or `_.merge` function.
+ *
+ * @private
+ * @param {Function} assigner The function to assign values.
+ * @returns {Function} Returns the new assigner function.
+ */
+ function createAssigner(assigner) {
+ return restParam(function(object, sources) {
+ var index = -1,
+ length = object == null ? 0 : sources.length,
+ customizer = length > 2 ? sources[length - 2] : undefined,
+ guard = length > 2 ? sources[2] : undefined,
+ thisArg = length > 1 ? sources[length - 1] : undefined;
+
+ if (typeof customizer == 'function') {
+ customizer = bindCallback(customizer, thisArg, 5);
+ length -= 2;
+ } else {
+ customizer = typeof thisArg == 'function' ? thisArg : undefined;
+ length -= (customizer ? 1 : 0);
+ }
+ if (guard && isIterateeCall(sources[0], sources[1], guard)) {
+ customizer = length < 3 ? undefined : customizer;
+ length = 1;
+ }
+ while (++index < length) {
+ var source = sources[index];
+ if (source) {
+ assigner(object, source, customizer);
+ }
+ }
+ return object;
+ });
+ }
+
+ /**
+ * Creates a `baseEach` or `baseEachRight` function.
+ *
+ * @private
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+ function createBaseEach(eachFunc, fromRight) {
+ return function(collection, iteratee) {
+ var length = collection ? getLength(collection) : 0;
+ if (!isLength(length)) {
+ return eachFunc(collection, iteratee);
+ }
+ var index = fromRight ? length : -1,
+ iterable = toObject(collection);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ if (iteratee(iterable[index], index, iterable) === false) {
+ break;
+ }
+ }
+ return collection;
+ };
+ }
+
+ /**
+ * Creates a base function for `_.forIn` or `_.forInRight`.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new base function.
+ */
+ function createBaseFor(fromRight) {
+ return function(object, iteratee, keysFunc) {
+ var iterable = toObject(object),
+ props = keysFunc(object),
+ length = props.length,
+ index = fromRight ? length : -1;
+
+ while ((fromRight ? index-- : ++index < length)) {
+ var key = props[index];
+ if (iteratee(iterable[key], key, iterable) === false) {
+ break;
+ }
+ }
+ return object;
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` and invokes it with the `this`
+ * binding of `thisArg`.
+ *
+ * @private
+ * @param {Function} func The function to bind.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @returns {Function} Returns the new bound function.
+ */
+ function createBindWrapper(func, thisArg) {
+ var Ctor = createCtorWrapper(func);
+
+ function wrapper() {
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return fn.apply(thisArg, arguments);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a `Set` cache object to optimize linear searches of large arrays.
+ *
+ * @private
+ * @param {Array} [values] The values to cache.
+ * @returns {null|Object} Returns the new cache object if `Set` is supported, else `null`.
+ */
+ function createCache(values) {
+ return (nativeCreate && Set) ? new SetCache(values) : null;
+ }
+
+ /**
+ * Creates a function that produces compound words out of the words in a
+ * given string.
+ *
+ * @private
+ * @param {Function} callback The function to combine each word.
+ * @returns {Function} Returns the new compounder function.
+ */
+ function createCompounder(callback) {
+ return function(string) {
+ var index = -1,
+ array = words(deburr(string)),
+ length = array.length,
+ result = '';
+
+ while (++index < length) {
+ result = callback(result, array[index], index);
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function that produces an instance of `Ctor` regardless of
+ * whether it was invoked as part of a `new` expression or by `call` or `apply`.
+ *
+ * @private
+ * @param {Function} Ctor The constructor to wrap.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createCtorWrapper(Ctor) {
+ return function() {
+ // Use a `switch` statement to work with class constructors.
+ // See http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
+ // for more details.
+ var args = arguments;
+ switch (args.length) {
+ case 0: return new Ctor;
+ case 1: return new Ctor(args[0]);
+ case 2: return new Ctor(args[0], args[1]);
+ case 3: return new Ctor(args[0], args[1], args[2]);
+ case 4: return new Ctor(args[0], args[1], args[2], args[3]);
+ case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
+ case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
+ case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+ }
+ var thisBinding = baseCreate(Ctor.prototype),
+ result = Ctor.apply(thisBinding, args);
+
+ // Mimic the constructor's `return` behavior.
+ // See https://es5.github.io/#x13.2.2 for more details.
+ return isObject(result) ? result : thisBinding;
+ };
+ }
+
+ /**
+ * Creates a `_.curry` or `_.curryRight` function.
+ *
+ * @private
+ * @param {boolean} flag The curry bit flag.
+ * @returns {Function} Returns the new curry function.
+ */
+ function createCurry(flag) {
+ function curryFunc(func, arity, guard) {
+ if (guard && isIterateeCall(func, arity, guard)) {
+ arity = undefined;
+ }
+ var result = createWrapper(func, flag, undefined, undefined, undefined, undefined, undefined, arity);
+ result.placeholder = curryFunc.placeholder;
+ return result;
+ }
+ return curryFunc;
+ }
+
+ /**
+ * Creates a `_.defaults` or `_.defaultsDeep` function.
+ *
+ * @private
+ * @param {Function} assigner The function to assign values.
+ * @param {Function} customizer The function to customize assigned values.
+ * @returns {Function} Returns the new defaults function.
+ */
+ function createDefaults(assigner, customizer) {
+ return restParam(function(args) {
+ var object = args[0];
+ if (object == null) {
+ return object;
+ }
+ args.push(customizer);
+ return assigner.apply(undefined, args);
+ });
+ }
+
+ /**
+ * Creates a `_.max` or `_.min` function.
+ *
+ * @private
+ * @param {Function} comparator The function used to compare values.
+ * @param {*} exValue The initial extremum value.
+ * @returns {Function} Returns the new extremum function.
+ */
+ function createExtremum(comparator, exValue) {
+ return function(collection, iteratee, thisArg) {
+ if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
+ iteratee = undefined;
+ }
+ iteratee = getCallback(iteratee, thisArg, 3);
+ if (iteratee.length == 1) {
+ collection = isArray(collection) ? collection : toIterable(collection);
+ var result = arrayExtremum(collection, iteratee, comparator, exValue);
+ if (!(collection.length && result === exValue)) {
+ return result;
+ }
+ }
+ return baseExtremum(collection, iteratee, comparator, exValue);
+ };
+ }
+
+ /**
+ * Creates a `_.find` or `_.findLast` function.
+ *
+ * @private
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new find function.
+ */
+ function createFind(eachFunc, fromRight) {
+ return function(collection, predicate, thisArg) {
+ predicate = getCallback(predicate, thisArg, 3);
+ if (isArray(collection)) {
+ var index = baseFindIndex(collection, predicate, fromRight);
+ return index > -1 ? collection[index] : undefined;
+ }
+ return baseFind(collection, predicate, eachFunc);
+ };
+ }
+
+ /**
+ * Creates a `_.findIndex` or `_.findLastIndex` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new find function.
+ */
+ function createFindIndex(fromRight) {
+ return function(array, predicate, thisArg) {
+ if (!(array && array.length)) {
+ return -1;
+ }
+ predicate = getCallback(predicate, thisArg, 3);
+ return baseFindIndex(array, predicate, fromRight);
+ };
+ }
+
+ /**
+ * Creates a `_.findKey` or `_.findLastKey` function.
+ *
+ * @private
+ * @param {Function} objectFunc The function to iterate over an object.
+ * @returns {Function} Returns the new find function.
+ */
+ function createFindKey(objectFunc) {
+ return function(object, predicate, thisArg) {
+ predicate = getCallback(predicate, thisArg, 3);
+ return baseFind(object, predicate, objectFunc, true);
+ };
+ }
+
+ /**
+ * Creates a `_.flow` or `_.flowRight` function.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify iterating from right to left.
+ * @returns {Function} Returns the new flow function.
+ */
+ function createFlow(fromRight) {
+ return function() {
+ var wrapper,
+ length = arguments.length,
+ index = fromRight ? length : -1,
+ leftIndex = 0,
+ funcs = Array(length);
+
+ while ((fromRight ? index-- : ++index < length)) {
+ var func = funcs[leftIndex++] = arguments[index];
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ if (!wrapper && LodashWrapper.prototype.thru && getFuncName(func) == 'wrapper') {
+ wrapper = new LodashWrapper([], true);
+ }
+ }
+ index = wrapper ? -1 : length;
+ while (++index < length) {
+ func = funcs[index];
+
+ var funcName = getFuncName(func),
+ data = funcName == 'wrapper' ? getData(func) : undefined;
+
+ if (data && isLaziable(data[0]) && data[1] == (ARY_FLAG | CURRY_FLAG | PARTIAL_FLAG | REARG_FLAG) && !data[4].length && data[9] == 1) {
+ wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
+ } else {
+ wrapper = (func.length == 1 && isLaziable(func)) ? wrapper[funcName]() : wrapper.thru(func);
+ }
+ }
+ return function() {
+ var args = arguments,
+ value = args[0];
+
+ if (wrapper && args.length == 1 && isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
+ return wrapper.plant(value).value();
+ }
+ var index = 0,
+ result = length ? funcs[index].apply(this, args) : value;
+
+ while (++index < length) {
+ result = funcs[index].call(this, result);
+ }
+ return result;
+ };
+ };
+ }
+
+ /**
+ * Creates a function for `_.forEach` or `_.forEachRight`.
+ *
+ * @private
+ * @param {Function} arrayFunc The function to iterate over an array.
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @returns {Function} Returns the new each function.
+ */
+ function createForEach(arrayFunc, eachFunc) {
+ return function(collection, iteratee, thisArg) {
+ return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
+ ? arrayFunc(collection, iteratee)
+ : eachFunc(collection, bindCallback(iteratee, thisArg, 3));
+ };
+ }
+
+ /**
+ * Creates a function for `_.forIn` or `_.forInRight`.
+ *
+ * @private
+ * @param {Function} objectFunc The function to iterate over an object.
+ * @returns {Function} Returns the new each function.
+ */
+ function createForIn(objectFunc) {
+ return function(object, iteratee, thisArg) {
+ if (typeof iteratee != 'function' || thisArg !== undefined) {
+ iteratee = bindCallback(iteratee, thisArg, 3);
+ }
+ return objectFunc(object, iteratee, keysIn);
+ };
+ }
+
+ /**
+ * Creates a function for `_.forOwn` or `_.forOwnRight`.
+ *
+ * @private
+ * @param {Function} objectFunc The function to iterate over an object.
+ * @returns {Function} Returns the new each function.
+ */
+ function createForOwn(objectFunc) {
+ return function(object, iteratee, thisArg) {
+ if (typeof iteratee != 'function' || thisArg !== undefined) {
+ iteratee = bindCallback(iteratee, thisArg, 3);
+ }
+ return objectFunc(object, iteratee);
+ };
+ }
+
+ /**
+ * Creates a function for `_.mapKeys` or `_.mapValues`.
+ *
+ * @private
+ * @param {boolean} [isMapKeys] Specify mapping keys instead of values.
+ * @returns {Function} Returns the new map function.
+ */
+ function createObjectMapper(isMapKeys) {
+ return function(object, iteratee, thisArg) {
+ var result = {};
+ iteratee = getCallback(iteratee, thisArg, 3);
+
+ baseForOwn(object, function(value, key, object) {
+ var mapped = iteratee(value, key, object);
+ key = isMapKeys ? mapped : key;
+ value = isMapKeys ? value : mapped;
+ result[key] = value;
+ });
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function for `_.padLeft` or `_.padRight`.
+ *
+ * @private
+ * @param {boolean} [fromRight] Specify padding from the right.
+ * @returns {Function} Returns the new pad function.
+ */
+ function createPadDir(fromRight) {
+ return function(string, length, chars) {
+ string = baseToString(string);
+ return (fromRight ? string : '') + createPadding(string, length, chars) + (fromRight ? '' : string);
+ };
+ }
+
+ /**
+ * Creates a `_.partial` or `_.partialRight` function.
+ *
+ * @private
+ * @param {boolean} flag The partial bit flag.
+ * @returns {Function} Returns the new partial function.
+ */
+ function createPartial(flag) {
+ var partialFunc = restParam(function(func, partials) {
+ var holders = replaceHolders(partials, partialFunc.placeholder);
+ return createWrapper(func, flag, undefined, partials, holders);
+ });
+ return partialFunc;
+ }
+
+ /**
+ * Creates a function for `_.reduce` or `_.reduceRight`.
+ *
+ * @private
+ * @param {Function} arrayFunc The function to iterate over an array.
+ * @param {Function} eachFunc The function to iterate over a collection.
+ * @returns {Function} Returns the new each function.
+ */
+ function createReduce(arrayFunc, eachFunc) {
+ return function(collection, iteratee, accumulator, thisArg) {
+ var initFromArray = arguments.length < 3;
+ return (typeof iteratee == 'function' && thisArg === undefined && isArray(collection))
+ ? arrayFunc(collection, iteratee, accumulator, initFromArray)
+ : baseReduce(collection, getCallback(iteratee, thisArg, 4), accumulator, initFromArray, eachFunc);
+ };
+ }
+
+ /**
+ * Creates a function that wraps `func` and invokes it with optional `this`
+ * binding of, partial application, and currying.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to reference.
+ * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to prepend to those provided to the new function.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [partialsRight] The arguments to append to those provided to the new function.
+ * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
+ var isAry = bitmask & ARY_FLAG,
+ isBind = bitmask & BIND_FLAG,
+ isBindKey = bitmask & BIND_KEY_FLAG,
+ isCurry = bitmask & CURRY_FLAG,
+ isCurryBound = bitmask & CURRY_BOUND_FLAG,
+ isCurryRight = bitmask & CURRY_RIGHT_FLAG,
+ Ctor = isBindKey ? undefined : createCtorWrapper(func);
+
+ function wrapper() {
+ // Avoid `arguments` object use disqualifying optimizations by
+ // converting it to an array before providing it to other functions.
+ var length = arguments.length,
+ index = length,
+ args = Array(length);
+
+ while (index--) {
+ args[index] = arguments[index];
+ }
+ if (partials) {
+ args = composeArgs(args, partials, holders);
+ }
+ if (partialsRight) {
+ args = composeArgsRight(args, partialsRight, holdersRight);
+ }
+ if (isCurry || isCurryRight) {
+ var placeholder = wrapper.placeholder,
+ argsHolders = replaceHolders(args, placeholder);
+
+ length -= argsHolders.length;
+ if (length < arity) {
+ var newArgPos = argPos ? arrayCopy(argPos) : undefined,
+ newArity = nativeMax(arity - length, 0),
+ newsHolders = isCurry ? argsHolders : undefined,
+ newHoldersRight = isCurry ? undefined : argsHolders,
+ newPartials = isCurry ? args : undefined,
+ newPartialsRight = isCurry ? undefined : args;
+
+ bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
+ bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
+
+ if (!isCurryBound) {
+ bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
+ }
+ var newData = [func, bitmask, thisArg, newPartials, newsHolders, newPartialsRight, newHoldersRight, newArgPos, ary, newArity],
+ result = createHybridWrapper.apply(undefined, newData);
+
+ if (isLaziable(func)) {
+ setData(result, newData);
+ }
+ result.placeholder = placeholder;
+ return result;
+ }
+ }
+ var thisBinding = isBind ? thisArg : this,
+ fn = isBindKey ? thisBinding[func] : func;
+
+ if (argPos) {
+ args = reorder(args, argPos);
+ }
+ if (isAry && ary < args.length) {
+ args.length = ary;
+ }
+ if (this && this !== root && this instanceof wrapper) {
+ fn = Ctor || createCtorWrapper(func);
+ }
+ return fn.apply(thisBinding, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates the padding required for `string` based on the given `length`.
+ * The `chars` string is truncated if the number of characters exceeds `length`.
+ *
+ * @private
+ * @param {string} string The string to create padding for.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the pad for `string`.
+ */
+ function createPadding(string, length, chars) {
+ var strLength = string.length;
+ length = +length;
+
+ if (strLength >= length || !nativeIsFinite(length)) {
+ return '';
+ }
+ var padLength = length - strLength;
+ chars = chars == null ? ' ' : (chars + '');
+ return repeat(chars, nativeCeil(padLength / chars.length)).slice(0, padLength);
+ }
+
+ /**
+ * Creates a function that wraps `func` and invokes it with the optional `this`
+ * binding of `thisArg` and the `partials` prepended to those provided to
+ * the wrapper.
+ *
+ * @private
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {number} bitmask The bitmask of flags. See `createWrapper` for more details.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {Array} partials The arguments to prepend to those provided to the new function.
+ * @returns {Function} Returns the new bound function.
+ */
+ function createPartialWrapper(func, bitmask, thisArg, partials) {
+ var isBind = bitmask & BIND_FLAG,
+ Ctor = createCtorWrapper(func);
+
+ function wrapper() {
+ // Avoid `arguments` object use disqualifying optimizations by
+ // converting it to an array before providing it `func`.
+ var argsIndex = -1,
+ argsLength = arguments.length,
+ leftIndex = -1,
+ leftLength = partials.length,
+ args = Array(leftLength + argsLength);
+
+ while (++leftIndex < leftLength) {
+ args[leftIndex] = partials[leftIndex];
+ }
+ while (argsLength--) {
+ args[leftIndex++] = arguments[++argsIndex];
+ }
+ var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
+ return fn.apply(isBind ? thisArg : this, args);
+ }
+ return wrapper;
+ }
+
+ /**
+ * Creates a `_.ceil`, `_.floor`, or `_.round` function.
+ *
+ * @private
+ * @param {string} methodName The name of the `Math` method to use when rounding.
+ * @returns {Function} Returns the new round function.
+ */
+ function createRound(methodName) {
+ var func = Math[methodName];
+ return function(number, precision) {
+ precision = precision === undefined ? 0 : (+precision || 0);
+ if (precision) {
+ precision = pow(10, precision);
+ return func(number * precision) / precision;
+ }
+ return func(number);
+ };
+ }
+
+ /**
+ * Creates a `_.sortedIndex` or `_.sortedLastIndex` function.
+ *
+ * @private
+ * @param {boolean} [retHighest] Specify returning the highest qualified index.
+ * @returns {Function} Returns the new index function.
+ */
+ function createSortedIndex(retHighest) {
+ return function(array, value, iteratee, thisArg) {
+ var callback = getCallback(iteratee);
+ return (iteratee == null && callback === baseCallback)
+ ? binaryIndex(array, value, retHighest)
+ : binaryIndexBy(array, value, callback(iteratee, thisArg, 1), retHighest);
+ };
+ }
+
+ /**
+ * Creates a function that either curries or invokes `func` with optional
+ * `this` binding and partially applied arguments.
+ *
+ * @private
+ * @param {Function|string} func The function or method name to reference.
+ * @param {number} bitmask The bitmask of flags.
+ * The bitmask may be composed of the following flags:
+ * 1 - `_.bind`
+ * 2 - `_.bindKey`
+ * 4 - `_.curry` or `_.curryRight` of a bound function
+ * 8 - `_.curry`
+ * 16 - `_.curryRight`
+ * 32 - `_.partial`
+ * 64 - `_.partialRight`
+ * 128 - `_.rearg`
+ * 256 - `_.ary`
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param {Array} [partials] The arguments to be partially applied.
+ * @param {Array} [holders] The `partials` placeholder indexes.
+ * @param {Array} [argPos] The argument positions of the new function.
+ * @param {number} [ary] The arity cap of `func`.
+ * @param {number} [arity] The arity of `func`.
+ * @returns {Function} Returns the new wrapped function.
+ */
+ function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
+ var isBindKey = bitmask & BIND_KEY_FLAG;
+ if (!isBindKey && typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var length = partials ? partials.length : 0;
+ if (!length) {
+ bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
+ partials = holders = undefined;
+ }
+ length -= (holders ? holders.length : 0);
+ if (bitmask & PARTIAL_RIGHT_FLAG) {
+ var partialsRight = partials,
+ holdersRight = holders;
+
+ partials = holders = undefined;
+ }
+ var data = isBindKey ? undefined : getData(func),
+ newData = [func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity];
+
+ if (data) {
+ mergeData(newData, data);
+ bitmask = newData[1];
+ arity = newData[9];
+ }
+ newData[9] = arity == null
+ ? (isBindKey ? 0 : func.length)
+ : (nativeMax(arity - length, 0) || 0);
+
+ if (bitmask == BIND_FLAG) {
+ var result = createBindWrapper(newData[0], newData[2]);
+ } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !newData[4].length) {
+ result = createPartialWrapper.apply(undefined, newData);
+ } else {
+ result = createHybridWrapper.apply(undefined, newData);
+ }
+ var setter = data ? baseSetData : setData;
+ return setter(result, newData);
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for arrays with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Array} array The array to compare.
+ * @param {Array} other The other array to compare.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Function} [customizer] The function to customize comparing arrays.
+ * @param {boolean} [isLoose] Specify performing partial comparisons.
+ * @param {Array} [stackA] Tracks traversed `value` objects.
+ * @param {Array} [stackB] Tracks traversed `other` objects.
+ * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
+ */
+ function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
+ var index = -1,
+ arrLength = array.length,
+ othLength = other.length;
+
+ if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
+ return false;
+ }
+ // Ignore non-index properties.
+ while (++index < arrLength) {
+ var arrValue = array[index],
+ othValue = other[index],
+ result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined;
+
+ if (result !== undefined) {
+ if (result) {
+ continue;
+ }
+ return false;
+ }
+ // Recursively compare arrays (susceptible to call stack limits).
+ if (isLoose) {
+ if (!arraySome(other, function(othValue) {
+ return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
+ })) {
+ return false;
+ }
+ } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for comparing objects of
+ * the same `toStringTag`.
+ *
+ * **Note:** This function only supports comparing values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {string} tag The `toStringTag` of the objects to compare.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function equalByTag(object, other, tag) {
+ switch (tag) {
+ case boolTag:
+ case dateTag:
+ // Coerce dates and booleans to numbers, dates to milliseconds and booleans
+ // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
+ return +object == +other;
+
+ case errorTag:
+ return object.name == other.name && object.message == other.message;
+
+ case numberTag:
+ // Treat `NaN` vs. `NaN` as equal.
+ return (object != +object)
+ ? other != +other
+ : object == +other;
+
+ case regexpTag:
+ case stringTag:
+ // Coerce regexes to strings and treat strings primitives and string
+ // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
+ return object == (other + '');
+ }
+ return false;
+ }
+
+ /**
+ * A specialized version of `baseIsEqualDeep` for objects with support for
+ * partial deep comparisons.
+ *
+ * @private
+ * @param {Object} object The object to compare.
+ * @param {Object} other The other object to compare.
+ * @param {Function} equalFunc The function to determine equivalents of values.
+ * @param {Function} [customizer] The function to customize comparing values.
+ * @param {boolean} [isLoose] Specify performing partial comparisons.
+ * @param {Array} [stackA] Tracks traversed `value` objects.
+ * @param {Array} [stackB] Tracks traversed `other` objects.
+ * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
+ */
+ function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
+ var objProps = keys(object),
+ objLength = objProps.length,
+ othProps = keys(other),
+ othLength = othProps.length;
+
+ if (objLength != othLength && !isLoose) {
+ return false;
+ }
+ var index = objLength;
+ while (index--) {
+ var key = objProps[index];
+ if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) {
+ return false;
+ }
+ }
+ var skipCtor = isLoose;
+ while (++index < objLength) {
+ key = objProps[index];
+ var objValue = object[key],
+ othValue = other[key],
+ result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined;
+
+ // Recursively compare objects (susceptible to call stack limits).
+ if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) {
+ return false;
+ }
+ skipCtor || (skipCtor = key == 'constructor');
+ }
+ if (!skipCtor) {
+ var objCtor = object.constructor,
+ othCtor = other.constructor;
+
+ // Non `Object` object instances with different constructors are not equal.
+ if (objCtor != othCtor &&
+ ('constructor' in object && 'constructor' in other) &&
+ !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
+ typeof othCtor == 'function' && othCtor instanceof othCtor)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Gets the appropriate "callback" function. If the `_.callback` method is
+ * customized this function returns the custom method, otherwise it returns
+ * the `baseCallback` function. If arguments are provided the chosen function
+ * is invoked with them and its result is returned.
+ *
+ * @private
+ * @returns {Function} Returns the chosen function or its result.
+ */
+ function getCallback(func, thisArg, argCount) {
+ var result = lodash.callback || callback;
+ result = result === callback ? baseCallback : result;
+ return argCount ? result(func, thisArg, argCount) : result;
+ }
+
+ /**
+ * Gets metadata for `func`.
+ *
+ * @private
+ * @param {Function} func The function to query.
+ * @returns {*} Returns the metadata for `func`.
+ */
+ var getData = !metaMap ? noop : function(func) {
+ return metaMap.get(func);
+ };
+
+ /**
+ * Gets the name of `func`.
+ *
+ * @private
+ * @param {Function} func The function to query.
+ * @returns {string} Returns the function name.
+ */
+ function getFuncName(func) {
+ var result = func.name,
+ array = realNames[result],
+ length = array ? array.length : 0;
+
+ while (length--) {
+ var data = array[length],
+ otherFunc = data.func;
+ if (otherFunc == null || otherFunc == func) {
+ return data.name;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Gets the appropriate "indexOf" function. If the `_.indexOf` method is
+ * customized this function returns the custom method, otherwise it returns
+ * the `baseIndexOf` function. If arguments are provided the chosen function
+ * is invoked with them and its result is returned.
+ *
+ * @private
+ * @returns {Function|number} Returns the chosen function or its result.
+ */
+ function getIndexOf(collection, target, fromIndex) {
+ var result = lodash.indexOf || indexOf;
+ result = result === indexOf ? baseIndexOf : result;
+ return collection ? result(collection, target, fromIndex) : result;
+ }
+
+ /**
+ * Gets the "length" property value of `object`.
+ *
+ * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
+ * that affects Safari on at least iOS 8.1-8.3 ARM64.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {*} Returns the "length" value.
+ */
+ var getLength = baseProperty('length');
+
+ /**
+ * Gets the propery names, values, and compare flags of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the match data of `object`.
+ */
+ function getMatchData(object) {
+ var result = pairs(object),
+ length = result.length;
+
+ while (length--) {
+ result[length][2] = isStrictComparable(result[length][1]);
+ }
+ return result;
+ }
+
+ /**
+ * Gets the native function at `key` of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {string} key The key of the method to get.
+ * @returns {*} Returns the function if it's native, else `undefined`.
+ */
+ function getNative(object, key) {
+ var value = object == null ? undefined : object[key];
+ return isNative(value) ? value : undefined;
+ }
+
+ /**
+ * Gets the view, applying any `transforms` to the `start` and `end` positions.
+ *
+ * @private
+ * @param {number} start The start of the view.
+ * @param {number} end The end of the view.
+ * @param {Array} transforms The transformations to apply to the view.
+ * @returns {Object} Returns an object containing the `start` and `end`
+ * positions of the view.
+ */
+ function getView(start, end, transforms) {
+ var index = -1,
+ length = transforms.length;
+
+ while (++index < length) {
+ var data = transforms[index],
+ size = data.size;
+
+ switch (data.type) {
+ case 'drop': start += size; break;
+ case 'dropRight': end -= size; break;
+ case 'take': end = nativeMin(end, start + size); break;
+ case 'takeRight': start = nativeMax(start, end - size); break;
+ }
+ }
+ return { 'start': start, 'end': end };
+ }
+
+ /**
+ * Initializes an array clone.
+ *
+ * @private
+ * @param {Array} array The array to clone.
+ * @returns {Array} Returns the initialized clone.
+ */
+ function initCloneArray(array) {
+ var length = array.length,
+ result = new array.constructor(length);
+
+ // Add array properties assigned by `RegExp#exec`.
+ if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
+ result.index = array.index;
+ result.input = array.input;
+ }
+ return result;
+ }
+
+ /**
+ * Initializes an object clone.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+ function initCloneObject(object) {
+ var Ctor = object.constructor;
+ if (!(typeof Ctor == 'function' && Ctor instanceof Ctor)) {
+ Ctor = Object;
+ }
+ return new Ctor;
+ }
+
+ /**
+ * Initializes an object clone based on its `toStringTag`.
+ *
+ * **Note:** This function only supports cloning values with tags of
+ * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
+ *
+ * @private
+ * @param {Object} object The object to clone.
+ * @param {string} tag The `toStringTag` of the object to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @returns {Object} Returns the initialized clone.
+ */
+ function initCloneByTag(object, tag, isDeep) {
+ var Ctor = object.constructor;
+ switch (tag) {
+ case arrayBufferTag:
+ return bufferClone(object);
+
+ case boolTag:
+ case dateTag:
+ return new Ctor(+object);
+
+ case float32Tag: case float64Tag:
+ case int8Tag: case int16Tag: case int32Tag:
+ case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
+ var buffer = object.buffer;
+ return new Ctor(isDeep ? bufferClone(buffer) : buffer, object.byteOffset, object.length);
+
+ case numberTag:
+ case stringTag:
+ return new Ctor(object);
+
+ case regexpTag:
+ var result = new Ctor(object.source, reFlags.exec(object));
+ result.lastIndex = object.lastIndex;
+ }
+ return result;
+ }
+
+ /**
+ * Invokes the method at `path` on `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {Array} args The arguments to invoke the method with.
+ * @returns {*} Returns the result of the invoked method.
+ */
+ function invokePath(object, path, args) {
+ if (object != null && !isKey(path, object)) {
+ path = toPath(path);
+ object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+ path = last(path);
+ }
+ var func = object == null ? object : object[path];
+ return func == null ? undefined : func.apply(object, args);
+ }
+
+ /**
+ * Checks if `value` is array-like.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
+ */
+ function isArrayLike(value) {
+ return value != null && isLength(getLength(value));
+ }
+
+ /**
+ * Checks if `value` is a valid array-like index.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
+ * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
+ */
+ function isIndex(value, length) {
+ value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
+ length = length == null ? MAX_SAFE_INTEGER : length;
+ return value > -1 && value % 1 == 0 && value < length;
+ }
+
+ /**
+ * Checks if the provided arguments are from an iteratee call.
+ *
+ * @private
+ * @param {*} value The potential iteratee value argument.
+ * @param {*} index The potential iteratee index or key argument.
+ * @param {*} object The potential iteratee object argument.
+ * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
+ */
+ function isIterateeCall(value, index, object) {
+ if (!isObject(object)) {
+ return false;
+ }
+ var type = typeof index;
+ if (type == 'number'
+ ? (isArrayLike(object) && isIndex(index, object.length))
+ : (type == 'string' && index in object)) {
+ var other = object[index];
+ return value === value ? (value === other) : (other !== other);
+ }
+ return false;
+ }
+
+ /**
+ * Checks if `value` is a property name and not a property path.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @param {Object} [object] The object to query keys on.
+ * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
+ */
+ function isKey(value, object) {
+ var type = typeof value;
+ if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {
+ return true;
+ }
+ if (isArray(value)) {
+ return false;
+ }
+ var result = !reIsDeepProp.test(value);
+ return result || (object != null && value in toObject(object));
+ }
+
+ /**
+ * Checks if `func` has a lazy counterpart.
+ *
+ * @private
+ * @param {Function} func The function to check.
+ * @returns {boolean} Returns `true` if `func` has a lazy counterpart, else `false`.
+ */
+ function isLaziable(func) {
+ var funcName = getFuncName(func);
+ if (!(funcName in LazyWrapper.prototype)) {
+ return false;
+ }
+ var other = lodash[funcName];
+ if (func === other) {
+ return true;
+ }
+ var data = getData(other);
+ return !!data && func === data[0];
+ }
+
+ /**
+ * Checks if `value` is a valid array-like length.
+ *
+ * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
+ */
+ function isLength(value) {
+ return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
+ }
+
+ /**
+ * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
+ *
+ * @private
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` if suitable for strict
+ * equality comparisons, else `false`.
+ */
+ function isStrictComparable(value) {
+ return value === value && !isObject(value);
+ }
+
+ /**
+ * Merges the function metadata of `source` into `data`.
+ *
+ * Merging metadata reduces the number of wrappers required to invoke a function.
+ * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
+ * may be applied regardless of execution order. Methods like `_.ary` and `_.rearg`
+ * augment function arguments, making the order in which they are executed important,
+ * preventing the merging of metadata. However, we make an exception for a safe
+ * common case where curried functions have `_.ary` and or `_.rearg` applied.
+ *
+ * @private
+ * @param {Array} data The destination metadata.
+ * @param {Array} source The source metadata.
+ * @returns {Array} Returns `data`.
+ */
+ function mergeData(data, source) {
+ var bitmask = data[1],
+ srcBitmask = source[1],
+ newBitmask = bitmask | srcBitmask,
+ isCommon = newBitmask < ARY_FLAG;
+
+ var isCombo =
+ (srcBitmask == ARY_FLAG && bitmask == CURRY_FLAG) ||
+ (srcBitmask == ARY_FLAG && bitmask == REARG_FLAG && data[7].length <= source[8]) ||
+ (srcBitmask == (ARY_FLAG | REARG_FLAG) && bitmask == CURRY_FLAG);
+
+ // Exit early if metadata can't be merged.
+ if (!(isCommon || isCombo)) {
+ return data;
+ }
+ // Use source `thisArg` if available.
+ if (srcBitmask & BIND_FLAG) {
+ data[2] = source[2];
+ // Set when currying a bound function.
+ newBitmask |= (bitmask & BIND_FLAG) ? 0 : CURRY_BOUND_FLAG;
+ }
+ // Compose partial arguments.
+ var value = source[3];
+ if (value) {
+ var partials = data[3];
+ data[3] = partials ? composeArgs(partials, value, source[4]) : arrayCopy(value);
+ data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : arrayCopy(source[4]);
+ }
+ // Compose partial right arguments.
+ value = source[5];
+ if (value) {
+ partials = data[5];
+ data[5] = partials ? composeArgsRight(partials, value, source[6]) : arrayCopy(value);
+ data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : arrayCopy(source[6]);
+ }
+ // Use source `argPos` if available.
+ value = source[7];
+ if (value) {
+ data[7] = arrayCopy(value);
+ }
+ // Use source `ary` if it's smaller.
+ if (srcBitmask & ARY_FLAG) {
+ data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
+ }
+ // Use source `arity` if one is not provided.
+ if (data[9] == null) {
+ data[9] = source[9];
+ }
+ // Use source `func` and merge bitmasks.
+ data[0] = source[0];
+ data[1] = newBitmask;
+
+ return data;
+ }
+
+ /**
+ * Used by `_.defaultsDeep` to customize its `_.merge` use.
+ *
+ * @private
+ * @param {*} objectValue The destination object property value.
+ * @param {*} sourceValue The source object property value.
+ * @returns {*} Returns the value to assign to the destination object.
+ */
+ function mergeDefaults(objectValue, sourceValue) {
+ return objectValue === undefined ? sourceValue : merge(objectValue, sourceValue, mergeDefaults);
+ }
+
+ /**
+ * A specialized version of `_.pick` which picks `object` properties specified
+ * by `props`.
+ *
+ * @private
+ * @param {Object} object The source object.
+ * @param {string[]} props The property names to pick.
+ * @returns {Object} Returns the new object.
+ */
+ function pickByArray(object, props) {
+ object = toObject(object);
+
+ var index = -1,
+ length = props.length,
+ result = {};
+
+ while (++index < length) {
+ var key = props[index];
+ if (key in object) {
+ result[key] = object[key];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * A specialized version of `_.pick` which picks `object` properties `predicate`
+ * returns truthy for.
+ *
+ * @private
+ * @param {Object} object The source object.
+ * @param {Function} predicate The function invoked per iteration.
+ * @returns {Object} Returns the new object.
+ */
+ function pickByCallback(object, predicate) {
+ var result = {};
+ baseForIn(object, function(value, key, object) {
+ if (predicate(value, key, object)) {
+ result[key] = value;
+ }
+ });
+ return result;
+ }
+
+ /**
+ * Reorder `array` according to the specified indexes where the element at
+ * the first index is assigned as the first element, the element at
+ * the second index is assigned as the second element, and so on.
+ *
+ * @private
+ * @param {Array} array The array to reorder.
+ * @param {Array} indexes The arranged array indexes.
+ * @returns {Array} Returns `array`.
+ */
+ function reorder(array, indexes) {
+ var arrLength = array.length,
+ length = nativeMin(indexes.length, arrLength),
+ oldArray = arrayCopy(array);
+
+ while (length--) {
+ var index = indexes[length];
+ array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
+ }
+ return array;
+ }
+
+ /**
+ * Sets metadata for `func`.
+ *
+ * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
+ * period of time, it will trip its breaker and transition to an identity function
+ * to avoid garbage collection pauses in V8. See [V8 issue 2070](https://code.google.com/p/v8/issues/detail?id=2070)
+ * for more details.
+ *
+ * @private
+ * @param {Function} func The function to associate metadata with.
+ * @param {*} data The metadata.
+ * @returns {Function} Returns `func`.
+ */
+ var setData = (function() {
+ var count = 0,
+ lastCalled = 0;
+
+ return function(key, value) {
+ var stamp = now(),
+ remaining = HOT_SPAN - (stamp - lastCalled);
+
+ lastCalled = stamp;
+ if (remaining > 0) {
+ if (++count >= HOT_COUNT) {
+ return key;
+ }
+ } else {
+ count = 0;
+ }
+ return baseSetData(key, value);
+ };
+ }());
+
+ /**
+ * A fallback implementation of `Object.keys` which creates an array of the
+ * own enumerable property names of `object`.
+ *
+ * @private
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ */
+ function shimKeys(object) {
+ var props = keysIn(object),
+ propsLength = props.length,
+ length = propsLength && object.length;
+
+ var allowIndexes = !!length && isLength(length) &&
+ (isArray(object) || isArguments(object));
+
+ var index = -1,
+ result = [];
+
+ while (++index < propsLength) {
+ var key = props[index];
+ if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Converts `value` to an array-like object if it's not one.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {Array|Object} Returns the array-like object.
+ */
+ function toIterable(value) {
+ if (value == null) {
+ return [];
+ }
+ if (!isArrayLike(value)) {
+ return values(value);
+ }
+ return isObject(value) ? value : Object(value);
+ }
+
+ /**
+ * Converts `value` to an object if it's not one.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {Object} Returns the object.
+ */
+ function toObject(value) {
+ return isObject(value) ? value : Object(value);
+ }
+
+ /**
+ * Converts `value` to property path array if it's not one.
+ *
+ * @private
+ * @param {*} value The value to process.
+ * @returns {Array} Returns the property path array.
+ */
+ function toPath(value) {
+ if (isArray(value)) {
+ return value;
+ }
+ var result = [];
+ baseToString(value).replace(rePropName, function(match, number, quote, string) {
+ result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
+ });
+ return result;
+ }
+
+ /**
+ * Creates a clone of `wrapper`.
+ *
+ * @private
+ * @param {Object} wrapper The wrapper to clone.
+ * @returns {Object} Returns the cloned wrapper.
+ */
+ function wrapperClone(wrapper) {
+ return wrapper instanceof LazyWrapper
+ ? wrapper.clone()
+ : new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__, arrayCopy(wrapper.__actions__));
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an array of elements split into groups the length of `size`.
+ * If `collection` can't be split evenly, the final chunk will be the remaining
+ * elements.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to process.
+ * @param {number} [size=1] The length of each chunk.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the new array containing chunks.
+ * @example
+ *
+ * _.chunk(['a', 'b', 'c', 'd'], 2);
+ * // => [['a', 'b'], ['c', 'd']]
+ *
+ * _.chunk(['a', 'b', 'c', 'd'], 3);
+ * // => [['a', 'b', 'c'], ['d']]
+ */
+ function chunk(array, size, guard) {
+ if (guard ? isIterateeCall(array, size, guard) : size == null) {
+ size = 1;
+ } else {
+ size = nativeMax(nativeFloor(size) || 1, 1);
+ }
+ var index = 0,
+ length = array ? array.length : 0,
+ resIndex = -1,
+ result = Array(nativeCeil(length / size));
+
+ while (index < length) {
+ result[++resIndex] = baseSlice(array, index, (index += size));
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array with all falsey values removed. The values `false`, `null`,
+ * `0`, `""`, `undefined`, and `NaN` are falsey.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to compact.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.compact([0, 1, false, 2, '', 3]);
+ * // => [1, 2, 3]
+ */
+ function compact(array) {
+ var index = -1,
+ length = array ? array.length : 0,
+ resIndex = -1,
+ result = [];
+
+ while (++index < length) {
+ var value = array[index];
+ if (value) {
+ result[++resIndex] = value;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array of unique `array` values not included in the other
+ * provided arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {...Array} [values] The arrays of values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.difference([1, 2, 3], [4, 2]);
+ * // => [1, 3]
+ */
+ var difference = restParam(function(array, values) {
+ return (isObjectLike(array) && isArrayLike(array))
+ ? baseDifference(array, baseFlatten(values, false, true))
+ : [];
+ });
+
+ /**
+ * Creates a slice of `array` with `n` elements dropped from the beginning.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to drop.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.drop([1, 2, 3]);
+ * // => [2, 3]
+ *
+ * _.drop([1, 2, 3], 2);
+ * // => [3]
+ *
+ * _.drop([1, 2, 3], 5);
+ * // => []
+ *
+ * _.drop([1, 2, 3], 0);
+ * // => [1, 2, 3]
+ */
+ function drop(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (guard ? isIterateeCall(array, n, guard) : n == null) {
+ n = 1;
+ }
+ return baseSlice(array, n < 0 ? 0 : n);
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements dropped from the end.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to drop.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.dropRight([1, 2, 3]);
+ * // => [1, 2]
+ *
+ * _.dropRight([1, 2, 3], 2);
+ * // => [1]
+ *
+ * _.dropRight([1, 2, 3], 5);
+ * // => []
+ *
+ * _.dropRight([1, 2, 3], 0);
+ * // => [1, 2, 3]
+ */
+ function dropRight(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (guard ? isIterateeCall(array, n, guard) : n == null) {
+ n = 1;
+ }
+ n = length - (+n || 0);
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+
+ /**
+ * Creates a slice of `array` excluding elements dropped from the end.
+ * Elements are dropped until `predicate` returns falsey. The predicate is
+ * bound to `thisArg` and invoked with three arguments: (value, index, array).
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that match the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.dropRightWhile([1, 2, 3], function(n) {
+ * return n > 1;
+ * });
+ * // => [1]
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.dropRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');
+ * // => ['barney', 'fred']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.dropRightWhile(users, 'active', false), 'user');
+ * // => ['barney']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.dropRightWhile(users, 'active'), 'user');
+ * // => ['barney', 'fred', 'pebbles']
+ */
+ function dropRightWhile(array, predicate, thisArg) {
+ return (array && array.length)
+ ? baseWhile(array, getCallback(predicate, thisArg, 3), true, true)
+ : [];
+ }
+
+ /**
+ * Creates a slice of `array` excluding elements dropped from the beginning.
+ * Elements are dropped until `predicate` returns falsey. The predicate is
+ * bound to `thisArg` and invoked with three arguments: (value, index, array).
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.dropWhile([1, 2, 3], function(n) {
+ * return n < 3;
+ * });
+ * // => [3]
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.dropWhile(users, { 'user': 'barney', 'active': false }), 'user');
+ * // => ['fred', 'pebbles']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.dropWhile(users, 'active', false), 'user');
+ * // => ['pebbles']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.dropWhile(users, 'active'), 'user');
+ * // => ['barney', 'fred', 'pebbles']
+ */
+ function dropWhile(array, predicate, thisArg) {
+ return (array && array.length)
+ ? baseWhile(array, getCallback(predicate, thisArg, 3), true)
+ : [];
+ }
+
+ /**
+ * Fills elements of `array` with `value` from `start` up to, but not
+ * including, `end`.
+ *
+ * **Note:** This method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to fill.
+ * @param {*} value The value to fill `array` with.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _.fill(array, 'a');
+ * console.log(array);
+ * // => ['a', 'a', 'a']
+ *
+ * _.fill(Array(3), 2);
+ * // => [2, 2, 2]
+ *
+ * _.fill([4, 6, 8], '*', 1, 2);
+ * // => [4, '*', 8]
+ */
+ function fill(array, value, start, end) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
+ start = 0;
+ end = length;
+ }
+ return baseFill(array, value, start, end);
+ }
+
+ /**
+ * This method is like `_.find` except that it returns the index of the first
+ * element `predicate` returns truthy for instead of the element itself.
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * _.findIndex(users, function(chr) {
+ * return chr.user == 'barney';
+ * });
+ * // => 0
+ *
+ * // using the `_.matches` callback shorthand
+ * _.findIndex(users, { 'user': 'fred', 'active': false });
+ * // => 1
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.findIndex(users, 'active', false);
+ * // => 0
+ *
+ * // using the `_.property` callback shorthand
+ * _.findIndex(users, 'active');
+ * // => 2
+ */
+ var findIndex = createFindIndex();
+
+ /**
+ * This method is like `_.findIndex` except that it iterates over elements
+ * of `collection` from right to left.
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {number} Returns the index of the found element, else `-1`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * _.findLastIndex(users, function(chr) {
+ * return chr.user == 'pebbles';
+ * });
+ * // => 2
+ *
+ * // using the `_.matches` callback shorthand
+ * _.findLastIndex(users, { 'user': 'barney', 'active': true });
+ * // => 0
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.findLastIndex(users, 'active', false);
+ * // => 2
+ *
+ * // using the `_.property` callback shorthand
+ * _.findLastIndex(users, 'active');
+ * // => 0
+ */
+ var findLastIndex = createFindIndex(true);
+
+ /**
+ * Gets the first element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @alias head
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the first element of `array`.
+ * @example
+ *
+ * _.first([1, 2, 3]);
+ * // => 1
+ *
+ * _.first([]);
+ * // => undefined
+ */
+ function first(array) {
+ return array ? array[0] : undefined;
+ }
+
+ /**
+ * Flattens a nested array. If `isDeep` is `true` the array is recursively
+ * flattened, otherwise it is only flattened a single level.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to flatten.
+ * @param {boolean} [isDeep] Specify a deep flatten.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flatten([1, [2, 3, [4]]]);
+ * // => [1, 2, 3, [4]]
+ *
+ * // using `isDeep`
+ * _.flatten([1, [2, 3, [4]]], true);
+ * // => [1, 2, 3, 4]
+ */
+ function flatten(array, isDeep, guard) {
+ var length = array ? array.length : 0;
+ if (guard && isIterateeCall(array, isDeep, guard)) {
+ isDeep = false;
+ }
+ return length ? baseFlatten(array, isDeep) : [];
+ }
+
+ /**
+ * Recursively flattens a nested array.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to recursively flatten.
+ * @returns {Array} Returns the new flattened array.
+ * @example
+ *
+ * _.flattenDeep([1, [2, 3, [4]]]);
+ * // => [1, 2, 3, 4]
+ */
+ function flattenDeep(array) {
+ var length = array ? array.length : 0;
+ return length ? baseFlatten(array, true) : [];
+ }
+
+ /**
+ * Gets the index at which the first occurrence of `value` is found in `array`
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons. If `fromIndex` is negative, it is used as the offset
+ * from the end of `array`. If `array` is sorted providing `true` for `fromIndex`
+ * performs a faster binary search.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @param {boolean|number} [fromIndex=0] The index to search from or `true`
+ * to perform a binary search on a sorted array.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.indexOf([1, 2, 1, 2], 2);
+ * // => 1
+ *
+ * // using `fromIndex`
+ * _.indexOf([1, 2, 1, 2], 2, 2);
+ * // => 3
+ *
+ * // performing a binary search
+ * _.indexOf([1, 1, 2, 2], 2, true);
+ * // => 2
+ */
+ function indexOf(array, value, fromIndex) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return -1;
+ }
+ if (typeof fromIndex == 'number') {
+ fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : fromIndex;
+ } else if (fromIndex) {
+ var index = binaryIndex(array, value);
+ if (index < length &&
+ (value === value ? (value === array[index]) : (array[index] !== array[index]))) {
+ return index;
+ }
+ return -1;
+ }
+ return baseIndexOf(array, value, fromIndex || 0);
+ }
+
+ /**
+ * Gets all but the last element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.initial([1, 2, 3]);
+ * // => [1, 2]
+ */
+ function initial(array) {
+ return dropRight(array, 1);
+ }
+
+ /**
+ * Creates an array of unique values that are included in all of the provided
+ * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of shared values.
+ * @example
+ * _.intersection([1, 2], [4, 2], [2, 1]);
+ * // => [2]
+ */
+ var intersection = restParam(function(arrays) {
+ var othLength = arrays.length,
+ othIndex = othLength,
+ caches = Array(length),
+ indexOf = getIndexOf(),
+ isCommon = indexOf == baseIndexOf,
+ result = [];
+
+ while (othIndex--) {
+ var value = arrays[othIndex] = isArrayLike(value = arrays[othIndex]) ? value : [];
+ caches[othIndex] = (isCommon && value.length >= 120) ? createCache(othIndex && value) : null;
+ }
+ var array = arrays[0],
+ index = -1,
+ length = array ? array.length : 0,
+ seen = caches[0];
+
+ outer:
+ while (++index < length) {
+ value = array[index];
+ if ((seen ? cacheIndexOf(seen, value) : indexOf(result, value, 0)) < 0) {
+ var othIndex = othLength;
+ while (--othIndex) {
+ var cache = caches[othIndex];
+ if ((cache ? cacheIndexOf(cache, value) : indexOf(arrays[othIndex], value, 0)) < 0) {
+ continue outer;
+ }
+ }
+ if (seen) {
+ seen.push(value);
+ }
+ result.push(value);
+ }
+ }
+ return result;
+ });
+
+ /**
+ * Gets the last element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {*} Returns the last element of `array`.
+ * @example
+ *
+ * _.last([1, 2, 3]);
+ * // => 3
+ */
+ function last(array) {
+ var length = array ? array.length : 0;
+ return length ? array[length - 1] : undefined;
+ }
+
+ /**
+ * This method is like `_.indexOf` except that it iterates over elements of
+ * `array` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to search.
+ * @param {*} value The value to search for.
+ * @param {boolean|number} [fromIndex=array.length-1] The index to search from
+ * or `true` to perform a binary search on a sorted array.
+ * @returns {number} Returns the index of the matched value, else `-1`.
+ * @example
+ *
+ * _.lastIndexOf([1, 2, 1, 2], 2);
+ * // => 3
+ *
+ * // using `fromIndex`
+ * _.lastIndexOf([1, 2, 1, 2], 2, 2);
+ * // => 1
+ *
+ * // performing a binary search
+ * _.lastIndexOf([1, 1, 2, 2], 2, true);
+ * // => 3
+ */
+ function lastIndexOf(array, value, fromIndex) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return -1;
+ }
+ var index = length;
+ if (typeof fromIndex == 'number') {
+ index = (fromIndex < 0 ? nativeMax(length + fromIndex, 0) : nativeMin(fromIndex || 0, length - 1)) + 1;
+ } else if (fromIndex) {
+ index = binaryIndex(array, value, true) - 1;
+ var other = array[index];
+ if (value === value ? (value === other) : (other !== other)) {
+ return index;
+ }
+ return -1;
+ }
+ if (value !== value) {
+ return indexOfNaN(array, index, true);
+ }
+ while (index--) {
+ if (array[index] === value) {
+ return index;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Removes all provided values from `array` using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * **Note:** Unlike `_.without`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {...*} [values] The values to remove.
+ * @returns {Array} Returns `array`.
+ * @example
+ *
+ * var array = [1, 2, 3, 1, 2, 3];
+ *
+ * _.pull(array, 2, 3);
+ * console.log(array);
+ * // => [1, 1]
+ */
+ function pull() {
+ var args = arguments,
+ array = args[0];
+
+ if (!(array && array.length)) {
+ return array;
+ }
+ var index = 0,
+ indexOf = getIndexOf(),
+ length = args.length;
+
+ while (++index < length) {
+ var fromIndex = 0,
+ value = args[index];
+
+ while ((fromIndex = indexOf(array, value, fromIndex)) > -1) {
+ splice.call(array, fromIndex, 1);
+ }
+ }
+ return array;
+ }
+
+ /**
+ * Removes elements from `array` corresponding to the given indexes and returns
+ * an array of the removed elements. Indexes may be specified as an array of
+ * indexes or as individual arguments.
+ *
+ * **Note:** Unlike `_.at`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {...(number|number[])} [indexes] The indexes of elements to remove,
+ * specified as individual indexes or arrays of indexes.
+ * @returns {Array} Returns the new array of removed elements.
+ * @example
+ *
+ * var array = [5, 10, 15, 20];
+ * var evens = _.pullAt(array, 1, 3);
+ *
+ * console.log(array);
+ * // => [5, 15]
+ *
+ * console.log(evens);
+ * // => [10, 20]
+ */
+ var pullAt = restParam(function(array, indexes) {
+ indexes = baseFlatten(indexes);
+
+ var result = baseAt(array, indexes);
+ basePullAt(array, indexes.sort(baseCompareAscending));
+ return result;
+ });
+
+ /**
+ * Removes all elements from `array` that `predicate` returns truthy for
+ * and returns an array of the removed elements. The predicate is bound to
+ * `thisArg` and invoked with three arguments: (value, index, array).
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * **Note:** Unlike `_.filter`, this method mutates `array`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to modify.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the new array of removed elements.
+ * @example
+ *
+ * var array = [1, 2, 3, 4];
+ * var evens = _.remove(array, function(n) {
+ * return n % 2 == 0;
+ * });
+ *
+ * console.log(array);
+ * // => [1, 3]
+ *
+ * console.log(evens);
+ * // => [2, 4]
+ */
+ function remove(array, predicate, thisArg) {
+ var result = [];
+ if (!(array && array.length)) {
+ return result;
+ }
+ var index = -1,
+ indexes = [],
+ length = array.length;
+
+ predicate = getCallback(predicate, thisArg, 3);
+ while (++index < length) {
+ var value = array[index];
+ if (predicate(value, index, array)) {
+ result.push(value);
+ indexes.push(index);
+ }
+ }
+ basePullAt(array, indexes);
+ return result;
+ }
+
+ /**
+ * Gets all but the first element of `array`.
+ *
+ * @static
+ * @memberOf _
+ * @alias tail
+ * @category Array
+ * @param {Array} array The array to query.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.rest([1, 2, 3]);
+ * // => [2, 3]
+ */
+ function rest(array) {
+ return drop(array, 1);
+ }
+
+ /**
+ * Creates a slice of `array` from `start` up to, but not including, `end`.
+ *
+ * **Note:** This method is used instead of `Array#slice` to support node
+ * lists in IE < 9 and to ensure dense arrays are returned.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to slice.
+ * @param {number} [start=0] The start position.
+ * @param {number} [end=array.length] The end position.
+ * @returns {Array} Returns the slice of `array`.
+ */
+ function slice(array, start, end) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
+ start = 0;
+ end = length;
+ }
+ return baseSlice(array, start, end);
+ }
+
+ /**
+ * Uses a binary search to determine the lowest index at which `value` should
+ * be inserted into `array` in order to maintain its sort order. If an iteratee
+ * function is provided it is invoked for `value` and each element of `array`
+ * to compute their sort ranking. The iteratee is bound to `thisArg` and
+ * invoked with one argument; (value).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * _.sortedIndex([30, 50], 40);
+ * // => 1
+ *
+ * _.sortedIndex([4, 4, 5, 5], 5);
+ * // => 2
+ *
+ * var dict = { 'data': { 'thirty': 30, 'forty': 40, 'fifty': 50 } };
+ *
+ * // using an iteratee function
+ * _.sortedIndex(['thirty', 'fifty'], 'forty', function(word) {
+ * return this.data[word];
+ * }, dict);
+ * // => 1
+ *
+ * // using the `_.property` callback shorthand
+ * _.sortedIndex([{ 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
+ * // => 1
+ */
+ var sortedIndex = createSortedIndex();
+
+ /**
+ * This method is like `_.sortedIndex` except that it returns the highest
+ * index at which `value` should be inserted into `array` in order to
+ * maintain its sort order.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The sorted array to inspect.
+ * @param {*} value The value to evaluate.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {number} Returns the index at which `value` should be inserted
+ * into `array`.
+ * @example
+ *
+ * _.sortedLastIndex([4, 4, 5, 5], 5);
+ * // => 4
+ */
+ var sortedLastIndex = createSortedIndex(true);
+
+ /**
+ * Creates a slice of `array` with `n` elements taken from the beginning.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to take.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.take([1, 2, 3]);
+ * // => [1]
+ *
+ * _.take([1, 2, 3], 2);
+ * // => [1, 2]
+ *
+ * _.take([1, 2, 3], 5);
+ * // => [1, 2, 3]
+ *
+ * _.take([1, 2, 3], 0);
+ * // => []
+ */
+ function take(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (guard ? isIterateeCall(array, n, guard) : n == null) {
+ n = 1;
+ }
+ return baseSlice(array, 0, n < 0 ? 0 : n);
+ }
+
+ /**
+ * Creates a slice of `array` with `n` elements taken from the end.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {number} [n=1] The number of elements to take.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.takeRight([1, 2, 3]);
+ * // => [3]
+ *
+ * _.takeRight([1, 2, 3], 2);
+ * // => [2, 3]
+ *
+ * _.takeRight([1, 2, 3], 5);
+ * // => [1, 2, 3]
+ *
+ * _.takeRight([1, 2, 3], 0);
+ * // => []
+ */
+ function takeRight(array, n, guard) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (guard ? isIterateeCall(array, n, guard) : n == null) {
+ n = 1;
+ }
+ n = length - (+n || 0);
+ return baseSlice(array, n < 0 ? 0 : n);
+ }
+
+ /**
+ * Creates a slice of `array` with elements taken from the end. Elements are
+ * taken until `predicate` returns falsey. The predicate is bound to `thisArg`
+ * and invoked with three arguments: (value, index, array).
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.takeRightWhile([1, 2, 3], function(n) {
+ * return n > 1;
+ * });
+ * // => [2, 3]
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false },
+ * { 'user': 'pebbles', 'active': false }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.takeRightWhile(users, { 'user': 'pebbles', 'active': false }), 'user');
+ * // => ['pebbles']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.takeRightWhile(users, 'active', false), 'user');
+ * // => ['fred', 'pebbles']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.takeRightWhile(users, 'active'), 'user');
+ * // => []
+ */
+ function takeRightWhile(array, predicate, thisArg) {
+ return (array && array.length)
+ ? baseWhile(array, getCallback(predicate, thisArg, 3), false, true)
+ : [];
+ }
+
+ /**
+ * Creates a slice of `array` with elements taken from the beginning. Elements
+ * are taken until `predicate` returns falsey. The predicate is bound to
+ * `thisArg` and invoked with three arguments: (value, index, array).
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to query.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the slice of `array`.
+ * @example
+ *
+ * _.takeWhile([1, 2, 3], function(n) {
+ * return n < 3;
+ * });
+ * // => [1, 2]
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false},
+ * { 'user': 'pebbles', 'active': true }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.takeWhile(users, { 'user': 'barney', 'active': false }), 'user');
+ * // => ['barney']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.takeWhile(users, 'active', false), 'user');
+ * // => ['barney', 'fred']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.takeWhile(users, 'active'), 'user');
+ * // => []
+ */
+ function takeWhile(array, predicate, thisArg) {
+ return (array && array.length)
+ ? baseWhile(array, getCallback(predicate, thisArg, 3))
+ : [];
+ }
+
+ /**
+ * Creates an array of unique values, in order, from all of the provided arrays
+ * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of combined values.
+ * @example
+ *
+ * _.union([1, 2], [4, 2], [2, 1]);
+ * // => [1, 2, 4]
+ */
+ var union = restParam(function(arrays) {
+ return baseUniq(baseFlatten(arrays, false, true));
+ });
+
+ /**
+ * Creates a duplicate-free version of an array, using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons, in which only the first occurence of each element
+ * is kept. Providing `true` for `isSorted` performs a faster search algorithm
+ * for sorted arrays. If an iteratee function is provided it is invoked for
+ * each element in the array to generate the criterion by which uniqueness
+ * is computed. The `iteratee` is bound to `thisArg` and invoked with three
+ * arguments: (value, index, array).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias unique
+ * @category Array
+ * @param {Array} array The array to inspect.
+ * @param {boolean} [isSorted] Specify the array is sorted.
+ * @param {Function|Object|string} [iteratee] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the new duplicate-value-free array.
+ * @example
+ *
+ * _.uniq([2, 1, 2]);
+ * // => [2, 1]
+ *
+ * // using `isSorted`
+ * _.uniq([1, 1, 2], true);
+ * // => [1, 2]
+ *
+ * // using an iteratee function
+ * _.uniq([1, 2.5, 1.5, 2], function(n) {
+ * return this.floor(n);
+ * }, Math);
+ * // => [1, 2.5]
+ *
+ * // using the `_.property` callback shorthand
+ * _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
+ * // => [{ 'x': 1 }, { 'x': 2 }]
+ */
+ function uniq(array, isSorted, iteratee, thisArg) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ if (isSorted != null && typeof isSorted != 'boolean') {
+ thisArg = iteratee;
+ iteratee = isIterateeCall(array, isSorted, thisArg) ? undefined : isSorted;
+ isSorted = false;
+ }
+ var callback = getCallback();
+ if (!(iteratee == null && callback === baseCallback)) {
+ iteratee = callback(iteratee, thisArg, 3);
+ }
+ return (isSorted && getIndexOf() == baseIndexOf)
+ ? sortedUniq(array, iteratee)
+ : baseUniq(array, iteratee);
+ }
+
+ /**
+ * This method is like `_.zip` except that it accepts an array of grouped
+ * elements and creates an array regrouping the elements to their pre-zip
+ * configuration.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array of grouped elements to process.
+ * @returns {Array} Returns the new array of regrouped elements.
+ * @example
+ *
+ * var zipped = _.zip(['fred', 'barney'], [30, 40], [true, false]);
+ * // => [['fred', 30, true], ['barney', 40, false]]
+ *
+ * _.unzip(zipped);
+ * // => [['fred', 'barney'], [30, 40], [true, false]]
+ */
+ function unzip(array) {
+ if (!(array && array.length)) {
+ return [];
+ }
+ var index = -1,
+ length = 0;
+
+ array = arrayFilter(array, function(group) {
+ if (isArrayLike(group)) {
+ length = nativeMax(group.length, length);
+ return true;
+ }
+ });
+ var result = Array(length);
+ while (++index < length) {
+ result[index] = arrayMap(array, baseProperty(index));
+ }
+ return result;
+ }
+
+ /**
+ * This method is like `_.unzip` except that it accepts an iteratee to specify
+ * how regrouped values should be combined. The `iteratee` is bound to `thisArg`
+ * and invoked with four arguments: (accumulator, value, index, group).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array of grouped elements to process.
+ * @param {Function} [iteratee] The function to combine regrouped values.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the new array of regrouped elements.
+ * @example
+ *
+ * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
+ * // => [[1, 10, 100], [2, 20, 200]]
+ *
+ * _.unzipWith(zipped, _.add);
+ * // => [3, 30, 300]
+ */
+ function unzipWith(array, iteratee, thisArg) {
+ var length = array ? array.length : 0;
+ if (!length) {
+ return [];
+ }
+ var result = unzip(array);
+ if (iteratee == null) {
+ return result;
+ }
+ iteratee = bindCallback(iteratee, thisArg, 4);
+ return arrayMap(result, function(group) {
+ return arrayReduce(group, iteratee, undefined, true);
+ });
+ }
+
+ /**
+ * Creates an array excluding all provided values using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {Array} array The array to filter.
+ * @param {...*} [values] The values to exclude.
+ * @returns {Array} Returns the new array of filtered values.
+ * @example
+ *
+ * _.without([1, 2, 1, 3], 1, 2);
+ * // => [3]
+ */
+ var without = restParam(function(array, values) {
+ return isArrayLike(array)
+ ? baseDifference(array, values)
+ : [];
+ });
+
+ /**
+ * Creates an array of unique values that is the [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
+ * of the provided arrays.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to inspect.
+ * @returns {Array} Returns the new array of values.
+ * @example
+ *
+ * _.xor([1, 2], [4, 2]);
+ * // => [1, 4]
+ */
+ function xor() {
+ var index = -1,
+ length = arguments.length;
+
+ while (++index < length) {
+ var array = arguments[index];
+ if (isArrayLike(array)) {
+ var result = result
+ ? arrayPush(baseDifference(result, array), baseDifference(array, result))
+ : array;
+ }
+ }
+ return result ? baseUniq(result) : [];
+ }
+
+ /**
+ * Creates an array of grouped elements, the first of which contains the first
+ * elements of the given arrays, the second of which contains the second elements
+ * of the given arrays, and so on.
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to process.
+ * @returns {Array} Returns the new array of grouped elements.
+ * @example
+ *
+ * _.zip(['fred', 'barney'], [30, 40], [true, false]);
+ * // => [['fred', 30, true], ['barney', 40, false]]
+ */
+ var zip = restParam(unzip);
+
+ /**
+ * The inverse of `_.pairs`; this method returns an object composed from arrays
+ * of property names and values. Provide either a single two dimensional array,
+ * e.g. `[[key1, value1], [key2, value2]]` or two arrays, one of property names
+ * and one of corresponding values.
+ *
+ * @static
+ * @memberOf _
+ * @alias object
+ * @category Array
+ * @param {Array} props The property names.
+ * @param {Array} [values=[]] The property values.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * _.zipObject([['fred', 30], ['barney', 40]]);
+ * // => { 'fred': 30, 'barney': 40 }
+ *
+ * _.zipObject(['fred', 'barney'], [30, 40]);
+ * // => { 'fred': 30, 'barney': 40 }
+ */
+ function zipObject(props, values) {
+ var index = -1,
+ length = props ? props.length : 0,
+ result = {};
+
+ if (length && !values && !isArray(props[0])) {
+ values = [];
+ }
+ while (++index < length) {
+ var key = props[index];
+ if (values) {
+ result[key] = values[index];
+ } else if (key) {
+ result[key[0]] = key[1];
+ }
+ }
+ return result;
+ }
+
+ /**
+ * This method is like `_.zip` except that it accepts an iteratee to specify
+ * how grouped values should be combined. The `iteratee` is bound to `thisArg`
+ * and invoked with four arguments: (accumulator, value, index, group).
+ *
+ * @static
+ * @memberOf _
+ * @category Array
+ * @param {...Array} [arrays] The arrays to process.
+ * @param {Function} [iteratee] The function to combine grouped values.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the new array of grouped elements.
+ * @example
+ *
+ * _.zipWith([1, 2], [10, 20], [100, 200], _.add);
+ * // => [111, 222]
+ */
+ var zipWith = restParam(function(arrays) {
+ var length = arrays.length,
+ iteratee = length > 2 ? arrays[length - 2] : undefined,
+ thisArg = length > 1 ? arrays[length - 1] : undefined;
+
+ if (length > 2 && typeof iteratee == 'function') {
+ length -= 2;
+ } else {
+ iteratee = (length > 1 && typeof thisArg == 'function') ? (--length, thisArg) : undefined;
+ thisArg = undefined;
+ }
+ arrays.length = length;
+ return unzipWith(arrays, iteratee, thisArg);
+ });
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a `lodash` object that wraps `value` with explicit method
+ * chaining enabled.
+ *
+ * @static
+ * @memberOf _
+ * @category Chain
+ * @param {*} value The value to wrap.
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 },
+ * { 'user': 'pebbles', 'age': 1 }
+ * ];
+ *
+ * var youngest = _.chain(users)
+ * .sortBy('age')
+ * .map(function(chr) {
+ * return chr.user + ' is ' + chr.age;
+ * })
+ * .first()
+ * .value();
+ * // => 'pebbles is 1'
+ */
+ function chain(value) {
+ var result = lodash(value);
+ result.__chain__ = true;
+ return result;
+ }
+
+ /**
+ * This method invokes `interceptor` and returns `value`. The interceptor is
+ * bound to `thisArg` and invoked with one argument; (value). The purpose of
+ * this method is to "tap into" a method chain in order to perform operations
+ * on intermediate results within the chain.
+ *
+ * @static
+ * @memberOf _
+ * @category Chain
+ * @param {*} value The value to provide to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @param {*} [thisArg] The `this` binding of `interceptor`.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * _([1, 2, 3])
+ * .tap(function(array) {
+ * array.pop();
+ * })
+ * .reverse()
+ * .value();
+ * // => [2, 1]
+ */
+ function tap(value, interceptor, thisArg) {
+ interceptor.call(thisArg, value);
+ return value;
+ }
+
+ /**
+ * This method is like `_.tap` except that it returns the result of `interceptor`.
+ *
+ * @static
+ * @memberOf _
+ * @category Chain
+ * @param {*} value The value to provide to `interceptor`.
+ * @param {Function} interceptor The function to invoke.
+ * @param {*} [thisArg] The `this` binding of `interceptor`.
+ * @returns {*} Returns the result of `interceptor`.
+ * @example
+ *
+ * _(' abc ')
+ * .chain()
+ * .trim()
+ * .thru(function(value) {
+ * return [value];
+ * })
+ * .value();
+ * // => ['abc']
+ */
+ function thru(value, interceptor, thisArg) {
+ return interceptor.call(thisArg, value);
+ }
+
+ /**
+ * Enables explicit method chaining on the wrapper object.
+ *
+ * @name chain
+ * @memberOf _
+ * @category Chain
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * // without explicit chaining
+ * _(users).first();
+ * // => { 'user': 'barney', 'age': 36 }
+ *
+ * // with explicit chaining
+ * _(users).chain()
+ * .first()
+ * .pick('user')
+ * .value();
+ * // => { 'user': 'barney' }
+ */
+ function wrapperChain() {
+ return chain(this);
+ }
+
+ /**
+ * Executes the chained sequence and returns the wrapped result.
+ *
+ * @name commit
+ * @memberOf _
+ * @category Chain
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2];
+ * var wrapped = _(array).push(3);
+ *
+ * console.log(array);
+ * // => [1, 2]
+ *
+ * wrapped = wrapped.commit();
+ * console.log(array);
+ * // => [1, 2, 3]
+ *
+ * wrapped.last();
+ * // => 3
+ *
+ * console.log(array);
+ * // => [1, 2, 3]
+ */
+ function wrapperCommit() {
+ return new LodashWrapper(this.value(), this.__chain__);
+ }
+
+ /**
+ * Creates a new array joining a wrapped array with any additional arrays
+ * and/or values.
+ *
+ * @name concat
+ * @memberOf _
+ * @category Chain
+ * @param {...*} [values] The values to concatenate.
+ * @returns {Array} Returns the new concatenated array.
+ * @example
+ *
+ * var array = [1];
+ * var wrapped = _(array).concat(2, [3], [[4]]);
+ *
+ * console.log(wrapped.value());
+ * // => [1, 2, 3, [4]]
+ *
+ * console.log(array);
+ * // => [1]
+ */
+ var wrapperConcat = restParam(function(values) {
+ values = baseFlatten(values);
+ return this.thru(function(array) {
+ return arrayConcat(isArray(array) ? array : [toObject(array)], values);
+ });
+ });
+
+ /**
+ * Creates a clone of the chained sequence planting `value` as the wrapped value.
+ *
+ * @name plant
+ * @memberOf _
+ * @category Chain
+ * @returns {Object} Returns the new `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2];
+ * var wrapped = _(array).map(function(value) {
+ * return Math.pow(value, 2);
+ * });
+ *
+ * var other = [3, 4];
+ * var otherWrapped = wrapped.plant(other);
+ *
+ * otherWrapped.value();
+ * // => [9, 16]
+ *
+ * wrapped.value();
+ * // => [1, 4]
+ */
+ function wrapperPlant(value) {
+ var result,
+ parent = this;
+
+ while (parent instanceof baseLodash) {
+ var clone = wrapperClone(parent);
+ if (result) {
+ previous.__wrapped__ = clone;
+ } else {
+ result = clone;
+ }
+ var previous = clone;
+ parent = parent.__wrapped__;
+ }
+ previous.__wrapped__ = value;
+ return result;
+ }
+
+ /**
+ * Reverses the wrapped array so the first element becomes the last, the
+ * second element becomes the second to last, and so on.
+ *
+ * **Note:** This method mutates the wrapped array.
+ *
+ * @name reverse
+ * @memberOf _
+ * @category Chain
+ * @returns {Object} Returns the new reversed `lodash` wrapper instance.
+ * @example
+ *
+ * var array = [1, 2, 3];
+ *
+ * _(array).reverse().value()
+ * // => [3, 2, 1]
+ *
+ * console.log(array);
+ * // => [3, 2, 1]
+ */
+ function wrapperReverse() {
+ var value = this.__wrapped__;
+
+ var interceptor = function(value) {
+ return (wrapped && wrapped.__dir__ < 0) ? value : value.reverse();
+ };
+ if (value instanceof LazyWrapper) {
+ var wrapped = value;
+ if (this.__actions__.length) {
+ wrapped = new LazyWrapper(this);
+ }
+ wrapped = wrapped.reverse();
+ wrapped.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
+ return new LodashWrapper(wrapped, this.__chain__);
+ }
+ return this.thru(interceptor);
+ }
+
+ /**
+ * Produces the result of coercing the unwrapped value to a string.
+ *
+ * @name toString
+ * @memberOf _
+ * @category Chain
+ * @returns {string} Returns the coerced string value.
+ * @example
+ *
+ * _([1, 2, 3]).toString();
+ * // => '1,2,3'
+ */
+ function wrapperToString() {
+ return (this.value() + '');
+ }
+
+ /**
+ * Executes the chained sequence to extract the unwrapped value.
+ *
+ * @name value
+ * @memberOf _
+ * @alias run, toJSON, valueOf
+ * @category Chain
+ * @returns {*} Returns the resolved unwrapped value.
+ * @example
+ *
+ * _([1, 2, 3]).value();
+ * // => [1, 2, 3]
+ */
+ function wrapperValue() {
+ return baseWrapperValue(this.__wrapped__, this.__actions__);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates an array of elements corresponding to the given keys, or indexes,
+ * of `collection`. Keys may be specified as individual arguments or as arrays
+ * of keys.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {...(number|number[]|string|string[])} [props] The property names
+ * or indexes of elements to pick, specified individually or in arrays.
+ * @returns {Array} Returns the new array of picked elements.
+ * @example
+ *
+ * _.at(['a', 'b', 'c'], [0, 2]);
+ * // => ['a', 'c']
+ *
+ * _.at(['barney', 'fred', 'pebbles'], 0, 2);
+ * // => ['barney', 'pebbles']
+ */
+ var at = restParam(function(collection, props) {
+ return baseAt(collection, baseFlatten(props));
+ });
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` through `iteratee`. The corresponding value
+ * of each key is the number of times the key was returned by `iteratee`.
+ * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.countBy([4.3, 6.1, 6.4], function(n) {
+ * return Math.floor(n);
+ * });
+ * // => { '4': 1, '6': 2 }
+ *
+ * _.countBy([4.3, 6.1, 6.4], function(n) {
+ * return this.floor(n);
+ * }, Math);
+ * // => { '4': 1, '6': 2 }
+ *
+ * _.countBy(['one', 'two', 'three'], 'length');
+ * // => { '3': 2, '5': 1 }
+ */
+ var countBy = createAggregator(function(result, value, key) {
+ hasOwnProperty.call(result, key) ? ++result[key] : (result[key] = 1);
+ });
+
+ /**
+ * Checks if `predicate` returns truthy for **all** elements of `collection`.
+ * The predicate is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias all
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {boolean} Returns `true` if all elements pass the predicate check,
+ * else `false`.
+ * @example
+ *
+ * _.every([true, 1, null, 'yes'], Boolean);
+ * // => false
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': false },
+ * { 'user': 'fred', 'active': false }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.every(users, { 'user': 'barney', 'active': false });
+ * // => false
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.every(users, 'active', false);
+ * // => true
+ *
+ * // using the `_.property` callback shorthand
+ * _.every(users, 'active');
+ * // => false
+ */
+ function every(collection, predicate, thisArg) {
+ var func = isArray(collection) ? arrayEvery : baseEvery;
+ if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
+ predicate = undefined;
+ }
+ if (typeof predicate != 'function' || thisArg !== undefined) {
+ predicate = getCallback(predicate, thisArg, 3);
+ }
+ return func(collection, predicate);
+ }
+
+ /**
+ * Iterates over elements of `collection`, returning an array of all elements
+ * `predicate` returns truthy for. The predicate is bound to `thisArg` and
+ * invoked with three arguments: (value, index|key, collection).
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias select
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the new filtered array.
+ * @example
+ *
+ * _.filter([4, 5, 6], function(n) {
+ * return n % 2 == 0;
+ * });
+ * // => [4, 6]
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.filter(users, { 'age': 36, 'active': true }), 'user');
+ * // => ['barney']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.filter(users, 'active', false), 'user');
+ * // => ['fred']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.filter(users, 'active'), 'user');
+ * // => ['barney']
+ */
+ function filter(collection, predicate, thisArg) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ predicate = getCallback(predicate, thisArg, 3);
+ return func(collection, predicate);
+ }
+
+ /**
+ * Iterates over elements of `collection`, returning the first element
+ * `predicate` returns truthy for. The predicate is bound to `thisArg` and
+ * invoked with three arguments: (value, index|key, collection).
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias detect
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false },
+ * { 'user': 'pebbles', 'age': 1, 'active': true }
+ * ];
+ *
+ * _.result(_.find(users, function(chr) {
+ * return chr.age < 40;
+ * }), 'user');
+ * // => 'barney'
+ *
+ * // using the `_.matches` callback shorthand
+ * _.result(_.find(users, { 'age': 1, 'active': true }), 'user');
+ * // => 'pebbles'
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.result(_.find(users, 'active', false), 'user');
+ * // => 'fred'
+ *
+ * // using the `_.property` callback shorthand
+ * _.result(_.find(users, 'active'), 'user');
+ * // => 'barney'
+ */
+ var find = createFind(baseEach);
+
+ /**
+ * This method is like `_.find` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * _.findLast([1, 2, 3, 4], function(n) {
+ * return n % 2 == 1;
+ * });
+ * // => 3
+ */
+ var findLast = createFind(baseEachRight, true);
+
+ /**
+ * Performs a deep comparison between each element in `collection` and the
+ * source object, returning the first element that has equivalent property
+ * values.
+ *
+ * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+ * numbers, `Object` objects, regexes, and strings. Objects are compared by
+ * their own, not inherited, enumerable properties. For comparing a single
+ * own or inherited property value see `_.matchesProperty`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {Object} source The object of property values to match.
+ * @returns {*} Returns the matched element, else `undefined`.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * _.result(_.findWhere(users, { 'age': 36, 'active': true }), 'user');
+ * // => 'barney'
+ *
+ * _.result(_.findWhere(users, { 'age': 40, 'active': false }), 'user');
+ * // => 'fred'
+ */
+ function findWhere(collection, source) {
+ return find(collection, baseMatches(source));
+ }
+
+ /**
+ * Iterates over elements of `collection` invoking `iteratee` for each element.
+ * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection). Iteratee functions may exit iteration early
+ * by explicitly returning `false`.
+ *
+ * **Note:** As with other "Collections" methods, objects with a "length" property
+ * are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
+ * may be used for object iteration.
+ *
+ * @static
+ * @memberOf _
+ * @alias each
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array|Object|string} Returns `collection`.
+ * @example
+ *
+ * _([1, 2]).forEach(function(n) {
+ * console.log(n);
+ * }).value();
+ * // => logs each value from left to right and returns the array
+ *
+ * _.forEach({ 'a': 1, 'b': 2 }, function(n, key) {
+ * console.log(n, key);
+ * });
+ * // => logs each value-key pair and returns the object (iteration order is not guaranteed)
+ */
+ var forEach = createForEach(arrayEach, baseEach);
+
+ /**
+ * This method is like `_.forEach` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @alias eachRight
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array|Object|string} Returns `collection`.
+ * @example
+ *
+ * _([1, 2]).forEachRight(function(n) {
+ * console.log(n);
+ * }).value();
+ * // => logs each value from right to left and returns the array
+ */
+ var forEachRight = createForEach(arrayEachRight, baseEachRight);
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` through `iteratee`. The corresponding value
+ * of each key is an array of the elements responsible for generating the key.
+ * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * _.groupBy([4.2, 6.1, 6.4], function(n) {
+ * return Math.floor(n);
+ * });
+ * // => { '4': [4.2], '6': [6.1, 6.4] }
+ *
+ * _.groupBy([4.2, 6.1, 6.4], function(n) {
+ * return this.floor(n);
+ * }, Math);
+ * // => { '4': [4.2], '6': [6.1, 6.4] }
+ *
+ * // using the `_.property` callback shorthand
+ * _.groupBy(['one', 'two', 'three'], 'length');
+ * // => { '3': ['one', 'two'], '5': ['three'] }
+ */
+ var groupBy = createAggregator(function(result, value, key) {
+ if (hasOwnProperty.call(result, key)) {
+ result[key].push(value);
+ } else {
+ result[key] = [value];
+ }
+ });
+
+ /**
+ * Checks if `value` is in `collection` using
+ * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
+ * for equality comparisons. If `fromIndex` is negative, it is used as the offset
+ * from the end of `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @alias contains, include
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {*} target The value to search for.
+ * @param {number} [fromIndex=0] The index to search from.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
+ * @returns {boolean} Returns `true` if a matching element is found, else `false`.
+ * @example
+ *
+ * _.includes([1, 2, 3], 1);
+ * // => true
+ *
+ * _.includes([1, 2, 3], 1, 2);
+ * // => false
+ *
+ * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
+ * // => true
+ *
+ * _.includes('pebbles', 'eb');
+ * // => true
+ */
+ function includes(collection, target, fromIndex, guard) {
+ var length = collection ? getLength(collection) : 0;
+ if (!isLength(length)) {
+ collection = values(collection);
+ length = collection.length;
+ }
+ if (typeof fromIndex != 'number' || (guard && isIterateeCall(target, fromIndex, guard))) {
+ fromIndex = 0;
+ } else {
+ fromIndex = fromIndex < 0 ? nativeMax(length + fromIndex, 0) : (fromIndex || 0);
+ }
+ return (typeof collection == 'string' || !isArray(collection) && isString(collection))
+ ? (fromIndex <= length && collection.indexOf(target, fromIndex) > -1)
+ : (!!length && getIndexOf(collection, target, fromIndex) > -1);
+ }
+
+ /**
+ * Creates an object composed of keys generated from the results of running
+ * each element of `collection` through `iteratee`. The corresponding value
+ * of each key is the last element responsible for generating the key. The
+ * iteratee function is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns the composed aggregate object.
+ * @example
+ *
+ * var keyData = [
+ * { 'dir': 'left', 'code': 97 },
+ * { 'dir': 'right', 'code': 100 }
+ * ];
+ *
+ * _.indexBy(keyData, 'dir');
+ * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
+ *
+ * _.indexBy(keyData, function(object) {
+ * return String.fromCharCode(object.code);
+ * });
+ * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+ *
+ * _.indexBy(keyData, function(object) {
+ * return this.fromCharCode(object.code);
+ * }, String);
+ * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
+ */
+ var indexBy = createAggregator(function(result, value, key) {
+ result[key] = value;
+ });
+
+ /**
+ * Invokes the method at `path` of each element in `collection`, returning
+ * an array of the results of each invoked method. Any additional arguments
+ * are provided to each invoked method. If `methodName` is a function it is
+ * invoked for, and `this` bound to, each element in `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Array|Function|string} path The path of the method to invoke or
+ * the function invoked per iteration.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {Array} Returns the array of results.
+ * @example
+ *
+ * _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
+ * // => [[1, 5, 7], [1, 2, 3]]
+ *
+ * _.invoke([123, 456], String.prototype.split, '');
+ * // => [['1', '2', '3'], ['4', '5', '6']]
+ */
+ var invoke = restParam(function(collection, path, args) {
+ var index = -1,
+ isFunc = typeof path == 'function',
+ isProp = isKey(path),
+ result = isArrayLike(collection) ? Array(collection.length) : [];
+
+ baseEach(collection, function(value) {
+ var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined);
+ result[++index] = func ? func.apply(value, args) : invokePath(value, path, args);
+ });
+ return result;
+ });
+
+ /**
+ * Creates an array of values by running each element in `collection` through
+ * `iteratee`. The `iteratee` is bound to `thisArg` and invoked with three
+ * arguments: (value, index|key, collection).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * Many lodash methods are guarded to work as iteratees for methods like
+ * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
+ *
+ * The guarded methods are:
+ * `ary`, `callback`, `chunk`, `clone`, `create`, `curry`, `curryRight`,
+ * `drop`, `dropRight`, `every`, `fill`, `flatten`, `invert`, `max`, `min`,
+ * `parseInt`, `slice`, `sortBy`, `take`, `takeRight`, `template`, `trim`,
+ * `trimLeft`, `trimRight`, `trunc`, `random`, `range`, `sample`, `some`,
+ * `sum`, `uniq`, and `words`
+ *
+ * @static
+ * @memberOf _
+ * @alias collect
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the new mapped array.
+ * @example
+ *
+ * function timesThree(n) {
+ * return n * 3;
+ * }
+ *
+ * _.map([1, 2], timesThree);
+ * // => [3, 6]
+ *
+ * _.map({ 'a': 1, 'b': 2 }, timesThree);
+ * // => [3, 6] (iteration order is not guaranteed)
+ *
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * // using the `_.property` callback shorthand
+ * _.map(users, 'user');
+ * // => ['barney', 'fred']
+ */
+ function map(collection, iteratee, thisArg) {
+ var func = isArray(collection) ? arrayMap : baseMap;
+ iteratee = getCallback(iteratee, thisArg, 3);
+ return func(collection, iteratee);
+ }
+
+ /**
+ * Creates an array of elements split into two groups, the first of which
+ * contains elements `predicate` returns truthy for, while the second of which
+ * contains elements `predicate` returns falsey for. The predicate is bound
+ * to `thisArg` and invoked with three arguments: (value, index|key, collection).
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the array of grouped elements.
+ * @example
+ *
+ * _.partition([1, 2, 3], function(n) {
+ * return n % 2;
+ * });
+ * // => [[1, 3], [2]]
+ *
+ * _.partition([1.2, 2.3, 3.4], function(n) {
+ * return this.floor(n) % 2;
+ * }, Math);
+ * // => [[1.2, 3.4], [2.3]]
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': true },
+ * { 'user': 'pebbles', 'age': 1, 'active': false }
+ * ];
+ *
+ * var mapper = function(array) {
+ * return _.pluck(array, 'user');
+ * };
+ *
+ * // using the `_.matches` callback shorthand
+ * _.map(_.partition(users, { 'age': 1, 'active': false }), mapper);
+ * // => [['pebbles'], ['barney', 'fred']]
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.map(_.partition(users, 'active', false), mapper);
+ * // => [['barney', 'pebbles'], ['fred']]
+ *
+ * // using the `_.property` callback shorthand
+ * _.map(_.partition(users, 'active'), mapper);
+ * // => [['fred'], ['barney', 'pebbles']]
+ */
+ var partition = createAggregator(function(result, value, key) {
+ result[key ? 0 : 1].push(value);
+ }, function() { return [[], []]; });
+
+ /**
+ * Gets the property value of `path` from all elements in `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Array|string} path The path of the property to pluck.
+ * @returns {Array} Returns the property values.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * _.pluck(users, 'user');
+ * // => ['barney', 'fred']
+ *
+ * var userIndex = _.indexBy(users, 'user');
+ * _.pluck(userIndex, 'age');
+ * // => [36, 40] (iteration order is not guaranteed)
+ */
+ function pluck(collection, path) {
+ return map(collection, property(path));
+ }
+
+ /**
+ * Reduces `collection` to a value which is the accumulated result of running
+ * each element in `collection` through `iteratee`, where each successive
+ * invocation is supplied the return value of the previous. If `accumulator`
+ * is not provided the first element of `collection` is used as the initial
+ * value. The `iteratee` is bound to `thisArg` and invoked with four arguments:
+ * (accumulator, value, index|key, collection).
+ *
+ * Many lodash methods are guarded to work as iteratees for methods like
+ * `_.reduce`, `_.reduceRight`, and `_.transform`.
+ *
+ * The guarded methods are:
+ * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `sortByAll`,
+ * and `sortByOrder`
+ *
+ * @static
+ * @memberOf _
+ * @alias foldl, inject
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * _.reduce([1, 2], function(total, n) {
+ * return total + n;
+ * });
+ * // => 3
+ *
+ * _.reduce({ 'a': 1, 'b': 2 }, function(result, n, key) {
+ * result[key] = n * 3;
+ * return result;
+ * }, {});
+ * // => { 'a': 3, 'b': 6 } (iteration order is not guaranteed)
+ */
+ var reduce = createReduce(arrayReduce, baseEach);
+
+ /**
+ * This method is like `_.reduce` except that it iterates over elements of
+ * `collection` from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @alias foldr
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The initial value.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * var array = [[0, 1], [2, 3], [4, 5]];
+ *
+ * _.reduceRight(array, function(flattened, other) {
+ * return flattened.concat(other);
+ * }, []);
+ * // => [4, 5, 2, 3, 0, 1]
+ */
+ var reduceRight = createReduce(arrayReduceRight, baseEachRight);
+
+ /**
+ * The opposite of `_.filter`; this method returns the elements of `collection`
+ * that `predicate` does **not** return truthy for.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Array} Returns the new filtered array.
+ * @example
+ *
+ * _.reject([1, 2, 3, 4], function(n) {
+ * return n % 2 == 0;
+ * });
+ * // => [1, 3]
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false },
+ * { 'user': 'fred', 'age': 40, 'active': true }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.pluck(_.reject(users, { 'age': 40, 'active': true }), 'user');
+ * // => ['barney']
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.pluck(_.reject(users, 'active', false), 'user');
+ * // => ['fred']
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.reject(users, 'active'), 'user');
+ * // => ['barney']
+ */
+ function reject(collection, predicate, thisArg) {
+ var func = isArray(collection) ? arrayFilter : baseFilter;
+ predicate = getCallback(predicate, thisArg, 3);
+ return func(collection, function(value, index, collection) {
+ return !predicate(value, index, collection);
+ });
+ }
+
+ /**
+ * Gets a random element or `n` random elements from a collection.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to sample.
+ * @param {number} [n] The number of elements to sample.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {*} Returns the random sample(s).
+ * @example
+ *
+ * _.sample([1, 2, 3, 4]);
+ * // => 2
+ *
+ * _.sample([1, 2, 3, 4], 2);
+ * // => [3, 1]
+ */
+ function sample(collection, n, guard) {
+ if (guard ? isIterateeCall(collection, n, guard) : n == null) {
+ collection = toIterable(collection);
+ var length = collection.length;
+ return length > 0 ? collection[baseRandom(0, length - 1)] : undefined;
+ }
+ var index = -1,
+ result = toArray(collection),
+ length = result.length,
+ lastIndex = length - 1;
+
+ n = nativeMin(n < 0 ? 0 : (+n || 0), length);
+ while (++index < n) {
+ var rand = baseRandom(index, lastIndex),
+ value = result[rand];
+
+ result[rand] = result[index];
+ result[index] = value;
+ }
+ result.length = n;
+ return result;
+ }
+
+ /**
+ * Creates an array of shuffled values, using a version of the
+ * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to shuffle.
+ * @returns {Array} Returns the new shuffled array.
+ * @example
+ *
+ * _.shuffle([1, 2, 3, 4]);
+ * // => [4, 1, 3, 2]
+ */
+ function shuffle(collection) {
+ return sample(collection, POSITIVE_INFINITY);
+ }
+
+ /**
+ * Gets the size of `collection` by returning its length for array-like
+ * values or the number of own enumerable properties for objects.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to inspect.
+ * @returns {number} Returns the size of `collection`.
+ * @example
+ *
+ * _.size([1, 2, 3]);
+ * // => 3
+ *
+ * _.size({ 'a': 1, 'b': 2 });
+ * // => 2
+ *
+ * _.size('pebbles');
+ * // => 7
+ */
+ function size(collection) {
+ var length = collection ? getLength(collection) : 0;
+ return isLength(length) ? length : keys(collection).length;
+ }
+
+ /**
+ * Checks if `predicate` returns truthy for **any** element of `collection`.
+ * The function returns as soon as it finds a passing value and does not iterate
+ * over the entire collection. The predicate is bound to `thisArg` and invoked
+ * with three arguments: (value, index|key, collection).
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias any
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {boolean} Returns `true` if any element passes the predicate check,
+ * else `false`.
+ * @example
+ *
+ * _.some([null, 0, 'yes', false], Boolean);
+ * // => true
+ *
+ * var users = [
+ * { 'user': 'barney', 'active': true },
+ * { 'user': 'fred', 'active': false }
+ * ];
+ *
+ * // using the `_.matches` callback shorthand
+ * _.some(users, { 'user': 'barney', 'active': false });
+ * // => false
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.some(users, 'active', false);
+ * // => true
+ *
+ * // using the `_.property` callback shorthand
+ * _.some(users, 'active');
+ * // => true
+ */
+ function some(collection, predicate, thisArg) {
+ var func = isArray(collection) ? arraySome : baseSome;
+ if (thisArg && isIterateeCall(collection, predicate, thisArg)) {
+ predicate = undefined;
+ }
+ if (typeof predicate != 'function' || thisArg !== undefined) {
+ predicate = getCallback(predicate, thisArg, 3);
+ }
+ return func(collection, predicate);
+ }
+
+ /**
+ * Creates an array of elements, sorted in ascending order by the results of
+ * running each element in a collection through `iteratee`. This method performs
+ * a stable sort, that is, it preserves the original sort order of equal elements.
+ * The `iteratee` is bound to `thisArg` and invoked with three arguments:
+ * (value, index|key, collection).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * _.sortBy([1, 2, 3], function(n) {
+ * return Math.sin(n);
+ * });
+ * // => [3, 1, 2]
+ *
+ * _.sortBy([1, 2, 3], function(n) {
+ * return this.sin(n);
+ * }, Math);
+ * // => [3, 1, 2]
+ *
+ * var users = [
+ * { 'user': 'fred' },
+ * { 'user': 'pebbles' },
+ * { 'user': 'barney' }
+ * ];
+ *
+ * // using the `_.property` callback shorthand
+ * _.pluck(_.sortBy(users, 'user'), 'user');
+ * // => ['barney', 'fred', 'pebbles']
+ */
+ function sortBy(collection, iteratee, thisArg) {
+ if (collection == null) {
+ return [];
+ }
+ if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
+ iteratee = undefined;
+ }
+ var index = -1;
+ iteratee = getCallback(iteratee, thisArg, 3);
+
+ var result = baseMap(collection, function(value, key, collection) {
+ return { 'criteria': iteratee(value, key, collection), 'index': ++index, 'value': value };
+ });
+ return baseSortBy(result, compareAscending);
+ }
+
+ /**
+ * This method is like `_.sortBy` except that it can sort by multiple iteratees
+ * or property names.
+ *
+ * If a property name is provided for an iteratee the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If an object is provided for an iteratee the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {...(Function|Function[]|Object|Object[]|string|string[])} iteratees
+ * The iteratees to sort by, specified as individual values or arrays of values.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 42 },
+ * { 'user': 'barney', 'age': 34 }
+ * ];
+ *
+ * _.map(_.sortByAll(users, ['user', 'age']), _.values);
+ * // => [['barney', 34], ['barney', 36], ['fred', 42], ['fred', 48]]
+ *
+ * _.map(_.sortByAll(users, 'user', function(chr) {
+ * return Math.floor(chr.age / 10);
+ * }), _.values);
+ * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
+ */
+ var sortByAll = restParam(function(collection, iteratees) {
+ if (collection == null) {
+ return [];
+ }
+ var guard = iteratees[2];
+ if (guard && isIterateeCall(iteratees[0], iteratees[1], guard)) {
+ iteratees.length = 1;
+ }
+ return baseSortByOrder(collection, baseFlatten(iteratees), []);
+ });
+
+ /**
+ * This method is like `_.sortByAll` except that it allows specifying the
+ * sort orders of the iteratees to sort by. If `orders` is unspecified, all
+ * values are sorted in ascending order. Otherwise, a value is sorted in
+ * ascending order if its corresponding order is "asc", and descending if "desc".
+ *
+ * If a property name is provided for an iteratee the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If an object is provided for an iteratee the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
+ * @param {boolean[]} [orders] The sort orders of `iteratees`.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.reduce`.
+ * @returns {Array} Returns the new sorted array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'fred', 'age': 48 },
+ * { 'user': 'barney', 'age': 34 },
+ * { 'user': 'fred', 'age': 42 },
+ * { 'user': 'barney', 'age': 36 }
+ * ];
+ *
+ * // sort by `user` in ascending order and by `age` in descending order
+ * _.map(_.sortByOrder(users, ['user', 'age'], ['asc', 'desc']), _.values);
+ * // => [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 42]]
+ */
+ function sortByOrder(collection, iteratees, orders, guard) {
+ if (collection == null) {
+ return [];
+ }
+ if (guard && isIterateeCall(iteratees, orders, guard)) {
+ orders = undefined;
+ }
+ if (!isArray(iteratees)) {
+ iteratees = iteratees == null ? [] : [iteratees];
+ }
+ if (!isArray(orders)) {
+ orders = orders == null ? [] : [orders];
+ }
+ return baseSortByOrder(collection, iteratees, orders);
+ }
+
+ /**
+ * Performs a deep comparison between each element in `collection` and the
+ * source object, returning an array of all elements that have equivalent
+ * property values.
+ *
+ * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+ * numbers, `Object` objects, regexes, and strings. Objects are compared by
+ * their own, not inherited, enumerable properties. For comparing a single
+ * own or inherited property value see `_.matchesProperty`.
+ *
+ * @static
+ * @memberOf _
+ * @category Collection
+ * @param {Array|Object|string} collection The collection to search.
+ * @param {Object} source The object of property values to match.
+ * @returns {Array} Returns the new filtered array.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': false, 'pets': ['hoppy'] },
+ * { 'user': 'fred', 'age': 40, 'active': true, 'pets': ['baby puss', 'dino'] }
+ * ];
+ *
+ * _.pluck(_.where(users, { 'age': 36, 'active': false }), 'user');
+ * // => ['barney']
+ *
+ * _.pluck(_.where(users, { 'pets': ['dino'] }), 'user');
+ * // => ['fred']
+ */
+ function where(collection, source) {
+ return filter(collection, baseMatches(source));
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Gets the number of milliseconds that have elapsed since the Unix epoch
+ * (1 January 1970 00:00:00 UTC).
+ *
+ * @static
+ * @memberOf _
+ * @category Date
+ * @example
+ *
+ * _.defer(function(stamp) {
+ * console.log(_.now() - stamp);
+ * }, _.now());
+ * // => logs the number of milliseconds it took for the deferred function to be invoked
+ */
+ var now = nativeNow || function() {
+ return new Date().getTime();
+ };
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The opposite of `_.before`; this method creates a function that invokes
+ * `func` once it is called `n` or more times.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {number} n The number of calls before `func` is invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var saves = ['profile', 'settings'];
+ *
+ * var done = _.after(saves.length, function() {
+ * console.log('done saving!');
+ * });
+ *
+ * _.forEach(saves, function(type) {
+ * asyncSave({ 'type': type, 'complete': done });
+ * });
+ * // => logs 'done saving!' after the two async saves have completed
+ */
+ function after(n, func) {
+ if (typeof func != 'function') {
+ if (typeof n == 'function') {
+ var temp = n;
+ n = func;
+ func = temp;
+ } else {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ }
+ n = nativeIsFinite(n = +n) ? n : 0;
+ return function() {
+ if (--n < 1) {
+ return func.apply(this, arguments);
+ }
+ };
+ }
+
+ /**
+ * Creates a function that accepts up to `n` arguments ignoring any
+ * additional arguments.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to cap arguments for.
+ * @param {number} [n=func.length] The arity cap.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * _.map(['6', '8', '10'], _.ary(parseInt, 1));
+ * // => [6, 8, 10]
+ */
+ function ary(func, n, guard) {
+ if (guard && isIterateeCall(func, n, guard)) {
+ n = undefined;
+ }
+ n = (func && n == null) ? func.length : nativeMax(+n || 0, 0);
+ return createWrapper(func, ARY_FLAG, undefined, undefined, undefined, undefined, n);
+ }
+
+ /**
+ * Creates a function that invokes `func`, with the `this` binding and arguments
+ * of the created function, while it is called less than `n` times. Subsequent
+ * calls to the created function return the result of the last `func` invocation.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {number} n The number of calls at which `func` is no longer invoked.
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * jQuery('#add').on('click', _.before(5, addContactToList));
+ * // => allows adding up to 4 contacts to the list
+ */
+ function before(n, func) {
+ var result;
+ if (typeof func != 'function') {
+ if (typeof n == 'function') {
+ var temp = n;
+ n = func;
+ func = temp;
+ } else {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ }
+ return function() {
+ if (--n > 0) {
+ result = func.apply(this, arguments);
+ }
+ if (n <= 1) {
+ func = undefined;
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of `thisArg`
+ * and prepends any additional `_.bind` arguments to those provided to the
+ * bound function.
+ *
+ * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
+ * may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** Unlike native `Function#bind` this method does not set the "length"
+ * property of bound functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to bind.
+ * @param {*} thisArg The `this` binding of `func`.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * var greet = function(greeting, punctuation) {
+ * return greeting + ' ' + this.user + punctuation;
+ * };
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * var bound = _.bind(greet, object, 'hi');
+ * bound('!');
+ * // => 'hi fred!'
+ *
+ * // using placeholders
+ * var bound = _.bind(greet, object, _, '!');
+ * bound('hi');
+ * // => 'hi fred!'
+ */
+ var bind = restParam(function(func, thisArg, partials) {
+ var bitmask = BIND_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, bind.placeholder);
+ bitmask |= PARTIAL_FLAG;
+ }
+ return createWrapper(func, bitmask, thisArg, partials, holders);
+ });
+
+ /**
+ * Binds methods of an object to the object itself, overwriting the existing
+ * method. Method names may be specified as individual arguments or as arrays
+ * of method names. If no method names are provided all enumerable function
+ * properties, own and inherited, of `object` are bound.
+ *
+ * **Note:** This method does not set the "length" property of bound functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Object} object The object to bind and assign the bound methods to.
+ * @param {...(string|string[])} [methodNames] The object method names to bind,
+ * specified as individual method names or arrays of method names.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var view = {
+ * 'label': 'docs',
+ * 'onClick': function() {
+ * console.log('clicked ' + this.label);
+ * }
+ * };
+ *
+ * _.bindAll(view);
+ * jQuery('#docs').on('click', view.onClick);
+ * // => logs 'clicked docs' when the element is clicked
+ */
+ var bindAll = restParam(function(object, methodNames) {
+ methodNames = methodNames.length ? baseFlatten(methodNames) : functions(object);
+
+ var index = -1,
+ length = methodNames.length;
+
+ while (++index < length) {
+ var key = methodNames[index];
+ object[key] = createWrapper(object[key], BIND_FLAG, object);
+ }
+ return object;
+ });
+
+ /**
+ * Creates a function that invokes the method at `object[key]` and prepends
+ * any additional `_.bindKey` arguments to those provided to the bound function.
+ *
+ * This method differs from `_.bind` by allowing bound functions to reference
+ * methods that may be redefined or don't yet exist.
+ * See [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
+ * for more details.
+ *
+ * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Object} object The object the method belongs to.
+ * @param {string} key The key of the method.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new bound function.
+ * @example
+ *
+ * var object = {
+ * 'user': 'fred',
+ * 'greet': function(greeting, punctuation) {
+ * return greeting + ' ' + this.user + punctuation;
+ * }
+ * };
+ *
+ * var bound = _.bindKey(object, 'greet', 'hi');
+ * bound('!');
+ * // => 'hi fred!'
+ *
+ * object.greet = function(greeting, punctuation) {
+ * return greeting + 'ya ' + this.user + punctuation;
+ * };
+ *
+ * bound('!');
+ * // => 'hiya fred!'
+ *
+ * // using placeholders
+ * var bound = _.bindKey(object, 'greet', _, '!');
+ * bound('hi');
+ * // => 'hiya fred!'
+ */
+ var bindKey = restParam(function(object, key, partials) {
+ var bitmask = BIND_FLAG | BIND_KEY_FLAG;
+ if (partials.length) {
+ var holders = replaceHolders(partials, bindKey.placeholder);
+ bitmask |= PARTIAL_FLAG;
+ }
+ return createWrapper(key, bitmask, object, partials, holders);
+ });
+
+ /**
+ * Creates a function that accepts one or more arguments of `func` that when
+ * called either invokes `func` returning its result, if all `func` arguments
+ * have been provided, or returns a function that accepts one or more of the
+ * remaining `func` arguments, and so on. The arity of `func` may be specified
+ * if `func.length` is not sufficient.
+ *
+ * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
+ * may be used as a placeholder for provided arguments.
+ *
+ * **Note:** This method does not set the "length" property of curried functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to curry.
+ * @param {number} [arity=func.length] The arity of `func`.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Function} Returns the new curried function.
+ * @example
+ *
+ * var abc = function(a, b, c) {
+ * return [a, b, c];
+ * };
+ *
+ * var curried = _.curry(abc);
+ *
+ * curried(1)(2)(3);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2)(3);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2, 3);
+ * // => [1, 2, 3]
+ *
+ * // using placeholders
+ * curried(1)(_, 3)(2);
+ * // => [1, 2, 3]
+ */
+ var curry = createCurry(CURRY_FLAG);
+
+ /**
+ * This method is like `_.curry` except that arguments are applied to `func`
+ * in the manner of `_.partialRight` instead of `_.partial`.
+ *
+ * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for provided arguments.
+ *
+ * **Note:** This method does not set the "length" property of curried functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to curry.
+ * @param {number} [arity=func.length] The arity of `func`.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Function} Returns the new curried function.
+ * @example
+ *
+ * var abc = function(a, b, c) {
+ * return [a, b, c];
+ * };
+ *
+ * var curried = _.curryRight(abc);
+ *
+ * curried(3)(2)(1);
+ * // => [1, 2, 3]
+ *
+ * curried(2, 3)(1);
+ * // => [1, 2, 3]
+ *
+ * curried(1, 2, 3);
+ * // => [1, 2, 3]
+ *
+ * // using placeholders
+ * curried(3)(1, _)(2);
+ * // => [1, 2, 3]
+ */
+ var curryRight = createCurry(CURRY_RIGHT_FLAG);
+
+ /**
+ * Creates a debounced function that delays invoking `func` until after `wait`
+ * milliseconds have elapsed since the last time the debounced function was
+ * invoked. The debounced function comes with a `cancel` method to cancel
+ * delayed invocations. Provide an options object to indicate that `func`
+ * should be invoked on the leading and/or trailing edge of the `wait` timeout.
+ * Subsequent calls to the debounced function return the result of the last
+ * `func` invocation.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
+ * on the trailing edge of the timeout only if the the debounced function is
+ * invoked more than once during the `wait` timeout.
+ *
+ * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
+ * for details over the differences between `_.debounce` and `_.throttle`.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to debounce.
+ * @param {number} [wait=0] The number of milliseconds to delay.
+ * @param {Object} [options] The options object.
+ * @param {boolean} [options.leading=false] Specify invoking on the leading
+ * edge of the timeout.
+ * @param {number} [options.maxWait] The maximum time `func` is allowed to be
+ * delayed before it is invoked.
+ * @param {boolean} [options.trailing=true] Specify invoking on the trailing
+ * edge of the timeout.
+ * @returns {Function} Returns the new debounced function.
+ * @example
+ *
+ * // avoid costly calculations while the window size is in flux
+ * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
+ *
+ * // invoke `sendMail` when the click event is fired, debouncing subsequent calls
+ * jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
+ * 'leading': true,
+ * 'trailing': false
+ * }));
+ *
+ * // ensure `batchLog` is invoked once after 1 second of debounced calls
+ * var source = new EventSource('/stream');
+ * jQuery(source).on('message', _.debounce(batchLog, 250, {
+ * 'maxWait': 1000
+ * }));
+ *
+ * // cancel a debounced call
+ * var todoChanges = _.debounce(batchLog, 1000);
+ * Object.observe(models.todo, todoChanges);
+ *
+ * Object.observe(models, function(changes) {
+ * if (_.find(changes, { 'user': 'todo', 'type': 'delete'})) {
+ * todoChanges.cancel();
+ * }
+ * }, ['delete']);
+ *
+ * // ...at some point `models.todo` is changed
+ * models.todo.completed = true;
+ *
+ * // ...before 1 second has passed `models.todo` is deleted
+ * // which cancels the debounced `todoChanges` call
+ * delete models.todo;
+ */
+ function debounce(func, wait, options) {
+ var args,
+ maxTimeoutId,
+ result,
+ stamp,
+ thisArg,
+ timeoutId,
+ trailingCall,
+ lastCalled = 0,
+ maxWait = false,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ wait = wait < 0 ? 0 : (+wait || 0);
+ if (options === true) {
+ var leading = true;
+ trailing = false;
+ } else if (isObject(options)) {
+ leading = !!options.leading;
+ maxWait = 'maxWait' in options && nativeMax(+options.maxWait || 0, wait);
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
+ }
+
+ function cancel() {
+ if (timeoutId) {
+ clearTimeout(timeoutId);
+ }
+ if (maxTimeoutId) {
+ clearTimeout(maxTimeoutId);
+ }
+ lastCalled = 0;
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ }
+
+ function complete(isCalled, id) {
+ if (id) {
+ clearTimeout(id);
+ }
+ maxTimeoutId = timeoutId = trailingCall = undefined;
+ if (isCalled) {
+ lastCalled = now();
+ result = func.apply(thisArg, args);
+ if (!timeoutId && !maxTimeoutId) {
+ args = thisArg = undefined;
+ }
+ }
+ }
+
+ function delayed() {
+ var remaining = wait - (now() - stamp);
+ if (remaining <= 0 || remaining > wait) {
+ complete(trailingCall, maxTimeoutId);
+ } else {
+ timeoutId = setTimeout(delayed, remaining);
+ }
+ }
+
+ function maxDelayed() {
+ complete(trailing, timeoutId);
+ }
+
+ function debounced() {
+ args = arguments;
+ stamp = now();
+ thisArg = this;
+ trailingCall = trailing && (timeoutId || !leading);
+
+ if (maxWait === false) {
+ var leadingCall = leading && !timeoutId;
+ } else {
+ if (!maxTimeoutId && !leading) {
+ lastCalled = stamp;
+ }
+ var remaining = maxWait - (stamp - lastCalled),
+ isCalled = remaining <= 0 || remaining > maxWait;
+
+ if (isCalled) {
+ if (maxTimeoutId) {
+ maxTimeoutId = clearTimeout(maxTimeoutId);
+ }
+ lastCalled = stamp;
+ result = func.apply(thisArg, args);
+ }
+ else if (!maxTimeoutId) {
+ maxTimeoutId = setTimeout(maxDelayed, remaining);
+ }
+ }
+ if (isCalled && timeoutId) {
+ timeoutId = clearTimeout(timeoutId);
+ }
+ else if (!timeoutId && wait !== maxWait) {
+ timeoutId = setTimeout(delayed, wait);
+ }
+ if (leadingCall) {
+ isCalled = true;
+ result = func.apply(thisArg, args);
+ }
+ if (isCalled && !timeoutId && !maxTimeoutId) {
+ args = thisArg = undefined;
+ }
+ return result;
+ }
+ debounced.cancel = cancel;
+ return debounced;
+ }
+
+ /**
+ * Defers invoking the `func` until the current call stack has cleared. Any
+ * additional arguments are provided to `func` when it is invoked.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to defer.
+ * @param {...*} [args] The arguments to invoke the function with.
+ * @returns {number} Returns the timer id.
+ * @example
+ *
+ * _.defer(function(text) {
+ * console.log(text);
+ * }, 'deferred');
+ * // logs 'deferred' after one or more milliseconds
+ */
+ var defer = restParam(function(func, args) {
+ return baseDelay(func, 1, args);
+ });
+
+ /**
+ * Invokes `func` after `wait` milliseconds. Any additional arguments are
+ * provided to `func` when it is invoked.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to delay.
+ * @param {number} wait The number of milliseconds to delay invocation.
+ * @param {...*} [args] The arguments to invoke the function with.
+ * @returns {number} Returns the timer id.
+ * @example
+ *
+ * _.delay(function(text) {
+ * console.log(text);
+ * }, 1000, 'later');
+ * // => logs 'later' after one second
+ */
+ var delay = restParam(function(func, wait, args) {
+ return baseDelay(func, wait, args);
+ });
+
+ /**
+ * Creates a function that returns the result of invoking the provided
+ * functions with the `this` binding of the created function, where each
+ * successive invocation is supplied the return value of the previous.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {...Function} [funcs] Functions to invoke.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var addSquare = _.flow(_.add, square);
+ * addSquare(1, 2);
+ * // => 9
+ */
+ var flow = createFlow();
+
+ /**
+ * This method is like `_.flow` except that it creates a function that
+ * invokes the provided functions from right to left.
+ *
+ * @static
+ * @memberOf _
+ * @alias backflow, compose
+ * @category Function
+ * @param {...Function} [funcs] Functions to invoke.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var addSquare = _.flowRight(square, _.add);
+ * addSquare(1, 2);
+ * // => 9
+ */
+ var flowRight = createFlow(true);
+
+ /**
+ * Creates a function that memoizes the result of `func`. If `resolver` is
+ * provided it determines the cache key for storing the result based on the
+ * arguments provided to the memoized function. By default, the first argument
+ * provided to the memoized function is coerced to a string and used as the
+ * cache key. The `func` is invoked with the `this` binding of the memoized
+ * function.
+ *
+ * **Note:** The cache is exposed as the `cache` property on the memoized
+ * function. Its creation may be customized by replacing the `_.memoize.Cache`
+ * constructor with one whose instances implement the [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object)
+ * method interface of `get`, `has`, and `set`.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to have its output memoized.
+ * @param {Function} [resolver] The function to resolve the cache key.
+ * @returns {Function} Returns the new memoizing function.
+ * @example
+ *
+ * var upperCase = _.memoize(function(string) {
+ * return string.toUpperCase();
+ * });
+ *
+ * upperCase('fred');
+ * // => 'FRED'
+ *
+ * // modifying the result cache
+ * upperCase.cache.set('fred', 'BARNEY');
+ * upperCase('fred');
+ * // => 'BARNEY'
+ *
+ * // replacing `_.memoize.Cache`
+ * var object = { 'user': 'fred' };
+ * var other = { 'user': 'barney' };
+ * var identity = _.memoize(_.identity);
+ *
+ * identity(object);
+ * // => { 'user': 'fred' }
+ * identity(other);
+ * // => { 'user': 'fred' }
+ *
+ * _.memoize.Cache = WeakMap;
+ * var identity = _.memoize(_.identity);
+ *
+ * identity(object);
+ * // => { 'user': 'fred' }
+ * identity(other);
+ * // => { 'user': 'barney' }
+ */
+ function memoize(func, resolver) {
+ if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var memoized = function() {
+ var args = arguments,
+ key = resolver ? resolver.apply(this, args) : args[0],
+ cache = memoized.cache;
+
+ if (cache.has(key)) {
+ return cache.get(key);
+ }
+ var result = func.apply(this, args);
+ memoized.cache = cache.set(key, result);
+ return result;
+ };
+ memoized.cache = new memoize.Cache;
+ return memoized;
+ }
+
+ /**
+ * Creates a function that runs each argument through a corresponding
+ * transform function.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to wrap.
+ * @param {...(Function|Function[])} [transforms] The functions to transform
+ * arguments, specified as individual functions or arrays of functions.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * function doubled(n) {
+ * return n * 2;
+ * }
+ *
+ * function square(n) {
+ * return n * n;
+ * }
+ *
+ * var modded = _.modArgs(function(x, y) {
+ * return [x, y];
+ * }, square, doubled);
+ *
+ * modded(1, 2);
+ * // => [1, 4]
+ *
+ * modded(5, 10);
+ * // => [25, 20]
+ */
+ var modArgs = restParam(function(func, transforms) {
+ transforms = baseFlatten(transforms);
+ if (typeof func != 'function' || !arrayEvery(transforms, baseIsFunction)) {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ var length = transforms.length;
+ return restParam(function(args) {
+ var index = nativeMin(args.length, length);
+ while (index--) {
+ args[index] = transforms[index](args[index]);
+ }
+ return func.apply(this, args);
+ });
+ });
+
+ /**
+ * Creates a function that negates the result of the predicate `func`. The
+ * `func` predicate is invoked with the `this` binding and arguments of the
+ * created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} predicate The predicate to negate.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * function isEven(n) {
+ * return n % 2 == 0;
+ * }
+ *
+ * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
+ * // => [1, 3, 5]
+ */
+ function negate(predicate) {
+ if (typeof predicate != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return function() {
+ return !predicate.apply(this, arguments);
+ };
+ }
+
+ /**
+ * Creates a function that is restricted to invoking `func` once. Repeat calls
+ * to the function return the value of the first call. The `func` is invoked
+ * with the `this` binding and arguments of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to restrict.
+ * @returns {Function} Returns the new restricted function.
+ * @example
+ *
+ * var initialize = _.once(createApplication);
+ * initialize();
+ * initialize();
+ * // `initialize` invokes `createApplication` once
+ */
+ function once(func) {
+ return before(2, func);
+ }
+
+ /**
+ * Creates a function that invokes `func` with `partial` arguments prepended
+ * to those provided to the new function. This method is like `_.bind` except
+ * it does **not** alter the `this` binding.
+ *
+ * The `_.partial.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** This method does not set the "length" property of partially
+ * applied functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
+ * @example
+ *
+ * var greet = function(greeting, name) {
+ * return greeting + ' ' + name;
+ * };
+ *
+ * var sayHelloTo = _.partial(greet, 'hello');
+ * sayHelloTo('fred');
+ * // => 'hello fred'
+ *
+ * // using placeholders
+ * var greetFred = _.partial(greet, _, 'fred');
+ * greetFred('hi');
+ * // => 'hi fred'
+ */
+ var partial = createPartial(PARTIAL_FLAG);
+
+ /**
+ * This method is like `_.partial` except that partially applied arguments
+ * are appended to those provided to the new function.
+ *
+ * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
+ * builds, may be used as a placeholder for partially applied arguments.
+ *
+ * **Note:** This method does not set the "length" property of partially
+ * applied functions.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to partially apply arguments to.
+ * @param {...*} [partials] The arguments to be partially applied.
+ * @returns {Function} Returns the new partially applied function.
+ * @example
+ *
+ * var greet = function(greeting, name) {
+ * return greeting + ' ' + name;
+ * };
+ *
+ * var greetFred = _.partialRight(greet, 'fred');
+ * greetFred('hi');
+ * // => 'hi fred'
+ *
+ * // using placeholders
+ * var sayHelloTo = _.partialRight(greet, 'hello', _);
+ * sayHelloTo('fred');
+ * // => 'hello fred'
+ */
+ var partialRight = createPartial(PARTIAL_RIGHT_FLAG);
+
+ /**
+ * Creates a function that invokes `func` with arguments arranged according
+ * to the specified indexes where the argument value at the first index is
+ * provided as the first argument, the argument value at the second index is
+ * provided as the second argument, and so on.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to rearrange arguments for.
+ * @param {...(number|number[])} indexes The arranged argument indexes,
+ * specified as individual indexes or arrays of indexes.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var rearged = _.rearg(function(a, b, c) {
+ * return [a, b, c];
+ * }, 2, 0, 1);
+ *
+ * rearged('b', 'c', 'a')
+ * // => ['a', 'b', 'c']
+ *
+ * var map = _.rearg(_.map, [1, 0]);
+ * map(function(n) {
+ * return n * 3;
+ * }, [1, 2, 3]);
+ * // => [3, 6, 9]
+ */
+ var rearg = restParam(function(func, indexes) {
+ return createWrapper(func, REARG_FLAG, undefined, undefined, undefined, baseFlatten(indexes));
+ });
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of the
+ * created function and arguments from `start` and beyond provided as an array.
+ *
+ * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to apply a rest parameter to.
+ * @param {number} [start=func.length-1] The start position of the rest parameter.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var say = _.restParam(function(what, names) {
+ * return what + ' ' + _.initial(names).join(', ') +
+ * (_.size(names) > 1 ? ', & ' : '') + _.last(names);
+ * });
+ *
+ * say('hello', 'fred', 'barney', 'pebbles');
+ * // => 'hello fred, barney, & pebbles'
+ */
+ function restParam(func, start) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
+ return function() {
+ var args = arguments,
+ index = -1,
+ length = nativeMax(args.length - start, 0),
+ rest = Array(length);
+
+ while (++index < length) {
+ rest[index] = args[start + index];
+ }
+ switch (start) {
+ case 0: return func.call(this, rest);
+ case 1: return func.call(this, args[0], rest);
+ case 2: return func.call(this, args[0], args[1], rest);
+ }
+ var otherArgs = Array(start + 1);
+ index = -1;
+ while (++index < start) {
+ otherArgs[index] = args[index];
+ }
+ otherArgs[start] = rest;
+ return func.apply(this, otherArgs);
+ };
+ }
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of the created
+ * function and an array of arguments much like [`Function#apply`](https://es5.github.io/#x15.3.4.3).
+ *
+ * **Note:** This method is based on the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator).
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to spread arguments over.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var say = _.spread(function(who, what) {
+ * return who + ' says ' + what;
+ * });
+ *
+ * say(['fred', 'hello']);
+ * // => 'fred says hello'
+ *
+ * // with a Promise
+ * var numbers = Promise.all([
+ * Promise.resolve(40),
+ * Promise.resolve(36)
+ * ]);
+ *
+ * numbers.then(_.spread(function(x, y) {
+ * return x + y;
+ * }));
+ * // => a Promise of 76
+ */
+ function spread(func) {
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ return function(array) {
+ return func.apply(this, array);
+ };
+ }
+
+ /**
+ * Creates a throttled function that only invokes `func` at most once per
+ * every `wait` milliseconds. The throttled function comes with a `cancel`
+ * method to cancel delayed invocations. Provide an options object to indicate
+ * that `func` should be invoked on the leading and/or trailing edge of the
+ * `wait` timeout. Subsequent calls to the throttled function return the
+ * result of the last `func` call.
+ *
+ * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
+ * on the trailing edge of the timeout only if the the throttled function is
+ * invoked more than once during the `wait` timeout.
+ *
+ * See [David Corbacho's article](http://drupalmotion.com/article/debounce-and-throttle-visual-explanation)
+ * for details over the differences between `_.throttle` and `_.debounce`.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {Function} func The function to throttle.
+ * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
+ * @param {Object} [options] The options object.
+ * @param {boolean} [options.leading=true] Specify invoking on the leading
+ * edge of the timeout.
+ * @param {boolean} [options.trailing=true] Specify invoking on the trailing
+ * edge of the timeout.
+ * @returns {Function} Returns the new throttled function.
+ * @example
+ *
+ * // avoid excessively updating the position while scrolling
+ * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
+ *
+ * // invoke `renewToken` when the click event is fired, but not more than once every 5 minutes
+ * jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
+ * 'trailing': false
+ * }));
+ *
+ * // cancel a trailing throttled call
+ * jQuery(window).on('popstate', throttled.cancel);
+ */
+ function throttle(func, wait, options) {
+ var leading = true,
+ trailing = true;
+
+ if (typeof func != 'function') {
+ throw new TypeError(FUNC_ERROR_TEXT);
+ }
+ if (options === false) {
+ leading = false;
+ } else if (isObject(options)) {
+ leading = 'leading' in options ? !!options.leading : leading;
+ trailing = 'trailing' in options ? !!options.trailing : trailing;
+ }
+ return debounce(func, wait, { 'leading': leading, 'maxWait': +wait, 'trailing': trailing });
+ }
+
+ /**
+ * Creates a function that provides `value` to the wrapper function as its
+ * first argument. Any additional arguments provided to the function are
+ * appended to those provided to the wrapper function. The wrapper is invoked
+ * with the `this` binding of the created function.
+ *
+ * @static
+ * @memberOf _
+ * @category Function
+ * @param {*} value The value to wrap.
+ * @param {Function} wrapper The wrapper function.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var p = _.wrap(_.escape, function(func, text) {
+ * return '<p>' + func(text) + '</p>';
+ * });
+ *
+ * p('fred, barney, & pebbles');
+ * // => '<p>fred, barney, &amp; pebbles</p>'
+ */
+ function wrap(value, wrapper) {
+ wrapper = wrapper == null ? identity : wrapper;
+ return createWrapper(wrapper, PARTIAL_FLAG, undefined, [value], []);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Creates a clone of `value`. If `isDeep` is `true` nested objects are cloned,
+ * otherwise they are assigned by reference. If `customizer` is provided it is
+ * invoked to produce the cloned values. If `customizer` returns `undefined`
+ * cloning is handled by the method instead. The `customizer` is bound to
+ * `thisArg` and invoked with two argument; (value [, index|key, object]).
+ *
+ * **Note:** This method is loosely based on the
+ * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).
+ * The enumerable properties of `arguments` objects and objects created by
+ * constructors other than `Object` are cloned to plain `Object` objects. An
+ * empty object is returned for uncloneable values such as functions, DOM nodes,
+ * Maps, Sets, and WeakMaps.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to clone.
+ * @param {boolean} [isDeep] Specify a deep clone.
+ * @param {Function} [customizer] The function to customize cloning values.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {*} Returns the cloned value.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * var shallow = _.clone(users);
+ * shallow[0] === users[0];
+ * // => true
+ *
+ * var deep = _.clone(users, true);
+ * deep[0] === users[0];
+ * // => false
+ *
+ * // using a customizer callback
+ * var el = _.clone(document.body, function(value) {
+ * if (_.isElement(value)) {
+ * return value.cloneNode(false);
+ * }
+ * });
+ *
+ * el === document.body
+ * // => false
+ * el.nodeName
+ * // => BODY
+ * el.childNodes.length;
+ * // => 0
+ */
+ function clone(value, isDeep, customizer, thisArg) {
+ if (isDeep && typeof isDeep != 'boolean' && isIterateeCall(value, isDeep, customizer)) {
+ isDeep = false;
+ }
+ else if (typeof isDeep == 'function') {
+ thisArg = customizer;
+ customizer = isDeep;
+ isDeep = false;
+ }
+ return typeof customizer == 'function'
+ ? baseClone(value, isDeep, bindCallback(customizer, thisArg, 1))
+ : baseClone(value, isDeep);
+ }
+
+ /**
+ * Creates a deep clone of `value`. If `customizer` is provided it is invoked
+ * to produce the cloned values. If `customizer` returns `undefined` cloning
+ * is handled by the method instead. The `customizer` is bound to `thisArg`
+ * and invoked with two argument; (value [, index|key, object]).
+ *
+ * **Note:** This method is loosely based on the
+ * [structured clone algorithm](http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm).
+ * The enumerable properties of `arguments` objects and objects created by
+ * constructors other than `Object` are cloned to plain `Object` objects. An
+ * empty object is returned for uncloneable values such as functions, DOM nodes,
+ * Maps, Sets, and WeakMaps.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to deep clone.
+ * @param {Function} [customizer] The function to customize cloning values.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {*} Returns the deep cloned value.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * var deep = _.cloneDeep(users);
+ * deep[0] === users[0];
+ * // => false
+ *
+ * // using a customizer callback
+ * var el = _.cloneDeep(document.body, function(value) {
+ * if (_.isElement(value)) {
+ * return value.cloneNode(true);
+ * }
+ * });
+ *
+ * el === document.body
+ * // => false
+ * el.nodeName
+ * // => BODY
+ * el.childNodes.length;
+ * // => 20
+ */
+ function cloneDeep(value, customizer, thisArg) {
+ return typeof customizer == 'function'
+ ? baseClone(value, true, bindCallback(customizer, thisArg, 1))
+ : baseClone(value, true);
+ }
+
+ /**
+ * Checks if `value` is greater than `other`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than `other`, else `false`.
+ * @example
+ *
+ * _.gt(3, 1);
+ * // => true
+ *
+ * _.gt(3, 3);
+ * // => false
+ *
+ * _.gt(1, 3);
+ * // => false
+ */
+ function gt(value, other) {
+ return value > other;
+ }
+
+ /**
+ * Checks if `value` is greater than or equal to `other`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is greater than or equal to `other`, else `false`.
+ * @example
+ *
+ * _.gte(3, 1);
+ * // => true
+ *
+ * _.gte(3, 3);
+ * // => true
+ *
+ * _.gte(1, 3);
+ * // => false
+ */
+ function gte(value, other) {
+ return value >= other;
+ }
+
+ /**
+ * Checks if `value` is classified as an `arguments` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isArguments(function() { return arguments; }());
+ * // => true
+ *
+ * _.isArguments([1, 2, 3]);
+ * // => false
+ */
+ function isArguments(value) {
+ return isObjectLike(value) && isArrayLike(value) &&
+ hasOwnProperty.call(value, 'callee') && !propertyIsEnumerable.call(value, 'callee');
+ }
+
+ /**
+ * Checks if `value` is classified as an `Array` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isArray([1, 2, 3]);
+ * // => true
+ *
+ * _.isArray(function() { return arguments; }());
+ * // => false
+ */
+ var isArray = nativeIsArray || function(value) {
+ return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
+ };
+
+ /**
+ * Checks if `value` is classified as a boolean primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isBoolean(false);
+ * // => true
+ *
+ * _.isBoolean(null);
+ * // => false
+ */
+ function isBoolean(value) {
+ return value === true || value === false || (isObjectLike(value) && objToString.call(value) == boolTag);
+ }
+
+ /**
+ * Checks if `value` is classified as a `Date` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isDate(new Date);
+ * // => true
+ *
+ * _.isDate('Mon April 23 2012');
+ * // => false
+ */
+ function isDate(value) {
+ return isObjectLike(value) && objToString.call(value) == dateTag;
+ }
+
+ /**
+ * Checks if `value` is a DOM element.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
+ * @example
+ *
+ * _.isElement(document.body);
+ * // => true
+ *
+ * _.isElement('<body>');
+ * // => false
+ */
+ function isElement(value) {
+ return !!value && value.nodeType === 1 && isObjectLike(value) && !isPlainObject(value);
+ }
+
+ /**
+ * Checks if `value` is empty. A value is considered empty unless it is an
+ * `arguments` object, array, string, or jQuery-like collection with a length
+ * greater than `0` or an object with own enumerable properties.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {Array|Object|string} value The value to inspect.
+ * @returns {boolean} Returns `true` if `value` is empty, else `false`.
+ * @example
+ *
+ * _.isEmpty(null);
+ * // => true
+ *
+ * _.isEmpty(true);
+ * // => true
+ *
+ * _.isEmpty(1);
+ * // => true
+ *
+ * _.isEmpty([1, 2, 3]);
+ * // => false
+ *
+ * _.isEmpty({ 'a': 1 });
+ * // => false
+ */
+ function isEmpty(value) {
+ if (value == null) {
+ return true;
+ }
+ if (isArrayLike(value) && (isArray(value) || isString(value) || isArguments(value) ||
+ (isObjectLike(value) && isFunction(value.splice)))) {
+ return !value.length;
+ }
+ return !keys(value).length;
+ }
+
+ /**
+ * Performs a deep comparison between two values to determine if they are
+ * equivalent. If `customizer` is provided it is invoked to compare values.
+ * If `customizer` returns `undefined` comparisons are handled by the method
+ * instead. The `customizer` is bound to `thisArg` and invoked with three
+ * arguments: (value, other [, index|key]).
+ *
+ * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+ * numbers, `Object` objects, regexes, and strings. Objects are compared by
+ * their own, not inherited, enumerable properties. Functions and DOM nodes
+ * are **not** supported. Provide a customizer function to extend support
+ * for comparing other values.
+ *
+ * @static
+ * @memberOf _
+ * @alias eq
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @param {Function} [customizer] The function to customize value comparisons.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ * var other = { 'user': 'fred' };
+ *
+ * object == other;
+ * // => false
+ *
+ * _.isEqual(object, other);
+ * // => true
+ *
+ * // using a customizer callback
+ * var array = ['hello', 'goodbye'];
+ * var other = ['hi', 'goodbye'];
+ *
+ * _.isEqual(array, other, function(value, other) {
+ * if (_.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/)) {
+ * return true;
+ * }
+ * });
+ * // => true
+ */
+ function isEqual(value, other, customizer, thisArg) {
+ customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined;
+ var result = customizer ? customizer(value, other) : undefined;
+ return result === undefined ? baseIsEqual(value, other, customizer) : !!result;
+ }
+
+ /**
+ * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
+ * `SyntaxError`, `TypeError`, or `URIError` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
+ * @example
+ *
+ * _.isError(new Error);
+ * // => true
+ *
+ * _.isError(Error);
+ * // => false
+ */
+ function isError(value) {
+ return isObjectLike(value) && typeof value.message == 'string' && objToString.call(value) == errorTag;
+ }
+
+ /**
+ * Checks if `value` is a finite primitive number.
+ *
+ * **Note:** This method is based on [`Number.isFinite`](http://ecma-international.org/ecma-262/6.0/#sec-number.isfinite).
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
+ * @example
+ *
+ * _.isFinite(10);
+ * // => true
+ *
+ * _.isFinite('10');
+ * // => false
+ *
+ * _.isFinite(true);
+ * // => false
+ *
+ * _.isFinite(Object(10));
+ * // => false
+ *
+ * _.isFinite(Infinity);
+ * // => false
+ */
+ function isFinite(value) {
+ return typeof value == 'number' && nativeIsFinite(value);
+ }
+
+ /**
+ * Checks if `value` is classified as a `Function` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isFunction(_);
+ * // => true
+ *
+ * _.isFunction(/abc/);
+ * // => false
+ */
+ function isFunction(value) {
+ // The use of `Object#toString` avoids issues with the `typeof` operator
+ // in older versions of Chrome and Safari which return 'function' for regexes
+ // and Safari 8 equivalents which return 'object' for typed array constructors.
+ return isObject(value) && objToString.call(value) == funcTag;
+ }
+
+ /**
+ * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
+ * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is an object, else `false`.
+ * @example
+ *
+ * _.isObject({});
+ * // => true
+ *
+ * _.isObject([1, 2, 3]);
+ * // => true
+ *
+ * _.isObject(1);
+ * // => false
+ */
+ function isObject(value) {
+ // Avoid a V8 JIT bug in Chrome 19-20.
+ // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
+ var type = typeof value;
+ return !!value && (type == 'object' || type == 'function');
+ }
+
+ /**
+ * Performs a deep comparison between `object` and `source` to determine if
+ * `object` contains equivalent property values. If `customizer` is provided
+ * it is invoked to compare values. If `customizer` returns `undefined`
+ * comparisons are handled by the method instead. The `customizer` is bound
+ * to `thisArg` and invoked with three arguments: (value, other, index|key).
+ *
+ * **Note:** This method supports comparing properties of arrays, booleans,
+ * `Date` objects, numbers, `Object` objects, regexes, and strings. Functions
+ * and DOM nodes are **not** supported. Provide a customizer function to extend
+ * support for comparing other values.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {Object} object The object to inspect.
+ * @param {Object} source The object of property values to match.
+ * @param {Function} [customizer] The function to customize value comparisons.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {boolean} Returns `true` if `object` is a match, else `false`.
+ * @example
+ *
+ * var object = { 'user': 'fred', 'age': 40 };
+ *
+ * _.isMatch(object, { 'age': 40 });
+ * // => true
+ *
+ * _.isMatch(object, { 'age': 36 });
+ * // => false
+ *
+ * // using a customizer callback
+ * var object = { 'greeting': 'hello' };
+ * var source = { 'greeting': 'hi' };
+ *
+ * _.isMatch(object, source, function(value, other) {
+ * return _.every([value, other], RegExp.prototype.test, /^h(?:i|ello)$/) || undefined;
+ * });
+ * // => true
+ */
+ function isMatch(object, source, customizer, thisArg) {
+ customizer = typeof customizer == 'function' ? bindCallback(customizer, thisArg, 3) : undefined;
+ return baseIsMatch(object, getMatchData(source), customizer);
+ }
+
+ /**
+ * Checks if `value` is `NaN`.
+ *
+ * **Note:** This method is not the same as [`isNaN`](https://es5.github.io/#x15.1.2.4)
+ * which returns `true` for `undefined` and other non-numeric values.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
+ * @example
+ *
+ * _.isNaN(NaN);
+ * // => true
+ *
+ * _.isNaN(new Number(NaN));
+ * // => true
+ *
+ * isNaN(undefined);
+ * // => true
+ *
+ * _.isNaN(undefined);
+ * // => false
+ */
+ function isNaN(value) {
+ // An `NaN` primitive is the only value that is not equal to itself.
+ // Perform the `toStringTag` check first to avoid errors with some host objects in IE.
+ return isNumber(value) && value != +value;
+ }
+
+ /**
+ * Checks if `value` is a native function.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
+ * @example
+ *
+ * _.isNative(Array.prototype.push);
+ * // => true
+ *
+ * _.isNative(_);
+ * // => false
+ */
+ function isNative(value) {
+ if (value == null) {
+ return false;
+ }
+ if (isFunction(value)) {
+ return reIsNative.test(fnToString.call(value));
+ }
+ return isObjectLike(value) && reIsHostCtor.test(value);
+ }
+
+ /**
+ * Checks if `value` is `null`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
+ * @example
+ *
+ * _.isNull(null);
+ * // => true
+ *
+ * _.isNull(void 0);
+ * // => false
+ */
+ function isNull(value) {
+ return value === null;
+ }
+
+ /**
+ * Checks if `value` is classified as a `Number` primitive or object.
+ *
+ * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are classified
+ * as numbers, use the `_.isFinite` method.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isNumber(8.4);
+ * // => true
+ *
+ * _.isNumber(NaN);
+ * // => true
+ *
+ * _.isNumber('8.4');
+ * // => false
+ */
+ function isNumber(value) {
+ return typeof value == 'number' || (isObjectLike(value) && objToString.call(value) == numberTag);
+ }
+
+ /**
+ * Checks if `value` is a plain object, that is, an object created by the
+ * `Object` constructor or one with a `[[Prototype]]` of `null`.
+ *
+ * **Note:** This method assumes objects created by the `Object` constructor
+ * have no inherited enumerable properties.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * }
+ *
+ * _.isPlainObject(new Foo);
+ * // => false
+ *
+ * _.isPlainObject([1, 2, 3]);
+ * // => false
+ *
+ * _.isPlainObject({ 'x': 0, 'y': 0 });
+ * // => true
+ *
+ * _.isPlainObject(Object.create(null));
+ * // => true
+ */
+ function isPlainObject(value) {
+ var Ctor;
+
+ // Exit early for non `Object` objects.
+ if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) ||
+ (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
+ return false;
+ }
+ // IE < 9 iterates inherited properties before own properties. If the first
+ // iterated property is an object's own property then there are no inherited
+ // enumerable properties.
+ var result;
+ // In most environments an object's own properties are iterated before
+ // its inherited properties. If the last iterated property is an object's
+ // own property then there are no inherited enumerable properties.
+ baseForIn(value, function(subValue, key) {
+ result = key;
+ });
+ return result === undefined || hasOwnProperty.call(value, result);
+ }
+
+ /**
+ * Checks if `value` is classified as a `RegExp` object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isRegExp(/abc/);
+ * // => true
+ *
+ * _.isRegExp('/abc/');
+ * // => false
+ */
+ function isRegExp(value) {
+ return isObject(value) && objToString.call(value) == regexpTag;
+ }
+
+ /**
+ * Checks if `value` is classified as a `String` primitive or object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isString('abc');
+ * // => true
+ *
+ * _.isString(1);
+ * // => false
+ */
+ function isString(value) {
+ return typeof value == 'string' || (isObjectLike(value) && objToString.call(value) == stringTag);
+ }
+
+ /**
+ * Checks if `value` is classified as a typed array.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
+ * @example
+ *
+ * _.isTypedArray(new Uint8Array);
+ * // => true
+ *
+ * _.isTypedArray([]);
+ * // => false
+ */
+ function isTypedArray(value) {
+ return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[objToString.call(value)];
+ }
+
+ /**
+ * Checks if `value` is `undefined`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to check.
+ * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
+ * @example
+ *
+ * _.isUndefined(void 0);
+ * // => true
+ *
+ * _.isUndefined(null);
+ * // => false
+ */
+ function isUndefined(value) {
+ return value === undefined;
+ }
+
+ /**
+ * Checks if `value` is less than `other`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than `other`, else `false`.
+ * @example
+ *
+ * _.lt(1, 3);
+ * // => true
+ *
+ * _.lt(3, 3);
+ * // => false
+ *
+ * _.lt(3, 1);
+ * // => false
+ */
+ function lt(value, other) {
+ return value < other;
+ }
+
+ /**
+ * Checks if `value` is less than or equal to `other`.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to compare.
+ * @param {*} other The other value to compare.
+ * @returns {boolean} Returns `true` if `value` is less than or equal to `other`, else `false`.
+ * @example
+ *
+ * _.lte(1, 3);
+ * // => true
+ *
+ * _.lte(3, 3);
+ * // => true
+ *
+ * _.lte(3, 1);
+ * // => false
+ */
+ function lte(value, other) {
+ return value <= other;
+ }
+
+ /**
+ * Converts `value` to an array.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Array} Returns the converted array.
+ * @example
+ *
+ * (function() {
+ * return _.toArray(arguments).slice(1);
+ * }(1, 2, 3));
+ * // => [2, 3]
+ */
+ function toArray(value) {
+ var length = value ? getLength(value) : 0;
+ if (!isLength(length)) {
+ return values(value);
+ }
+ if (!length) {
+ return [];
+ }
+ return arrayCopy(value);
+ }
+
+ /**
+ * Converts `value` to a plain object flattening inherited enumerable
+ * properties of `value` to own properties of the plain object.
+ *
+ * @static
+ * @memberOf _
+ * @category Lang
+ * @param {*} value The value to convert.
+ * @returns {Object} Returns the converted plain object.
+ * @example
+ *
+ * function Foo() {
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.assign({ 'a': 1 }, new Foo);
+ * // => { 'a': 1, 'b': 2 }
+ *
+ * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
+ * // => { 'a': 1, 'b': 2, 'c': 3 }
+ */
+ function toPlainObject(value) {
+ return baseCopy(value, keysIn(value));
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Recursively merges own enumerable properties of the source object(s), that
+ * don't resolve to `undefined` into the destination object. Subsequent sources
+ * overwrite property assignments of previous sources. If `customizer` is
+ * provided it is invoked to produce the merged values of the destination and
+ * source properties. If `customizer` returns `undefined` merging is handled
+ * by the method instead. The `customizer` is bound to `thisArg` and invoked
+ * with five arguments: (objectValue, sourceValue, key, object, source).
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var users = {
+ * 'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
+ * };
+ *
+ * var ages = {
+ * 'data': [{ 'age': 36 }, { 'age': 40 }]
+ * };
+ *
+ * _.merge(users, ages);
+ * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
+ *
+ * // using a customizer callback
+ * var object = {
+ * 'fruits': ['apple'],
+ * 'vegetables': ['beet']
+ * };
+ *
+ * var other = {
+ * 'fruits': ['banana'],
+ * 'vegetables': ['carrot']
+ * };
+ *
+ * _.merge(object, other, function(a, b) {
+ * if (_.isArray(a)) {
+ * return a.concat(b);
+ * }
+ * });
+ * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
+ */
+ var merge = createAssigner(baseMerge);
+
+ /**
+ * Assigns own enumerable properties of source object(s) to the destination
+ * object. Subsequent sources overwrite property assignments of previous sources.
+ * If `customizer` is provided it is invoked to produce the assigned values.
+ * The `customizer` is bound to `thisArg` and invoked with five arguments:
+ * (objectValue, sourceValue, key, object, source).
+ *
+ * **Note:** This method mutates `object` and is based on
+ * [`Object.assign`](http://ecma-international.org/ecma-262/6.0/#sec-object.assign).
+ *
+ * @static
+ * @memberOf _
+ * @alias extend
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @param {Function} [customizer] The function to customize assigned values.
+ * @param {*} [thisArg] The `this` binding of `customizer`.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * _.assign({ 'user': 'barney' }, { 'age': 40 }, { 'user': 'fred' });
+ * // => { 'user': 'fred', 'age': 40 }
+ *
+ * // using a customizer callback
+ * var defaults = _.partialRight(_.assign, function(value, other) {
+ * return _.isUndefined(value) ? other : value;
+ * });
+ *
+ * defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
+ * // => { 'user': 'barney', 'age': 36 }
+ */
+ var assign = createAssigner(function(object, source, customizer) {
+ return customizer
+ ? assignWith(object, source, customizer)
+ : baseAssign(object, source);
+ });
+
+ /**
+ * Creates an object that inherits from the given `prototype` object. If a
+ * `properties` object is provided its own enumerable properties are assigned
+ * to the created object.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} prototype The object to inherit from.
+ * @param {Object} [properties] The properties to assign to the object.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * function Shape() {
+ * this.x = 0;
+ * this.y = 0;
+ * }
+ *
+ * function Circle() {
+ * Shape.call(this);
+ * }
+ *
+ * Circle.prototype = _.create(Shape.prototype, {
+ * 'constructor': Circle
+ * });
+ *
+ * var circle = new Circle;
+ * circle instanceof Circle;
+ * // => true
+ *
+ * circle instanceof Shape;
+ * // => true
+ */
+ function create(prototype, properties, guard) {
+ var result = baseCreate(prototype);
+ if (guard && isIterateeCall(prototype, properties, guard)) {
+ properties = undefined;
+ }
+ return properties ? baseAssign(result, properties) : result;
+ }
+
+ /**
+ * Assigns own enumerable properties of source object(s) to the destination
+ * object for all destination properties that resolve to `undefined`. Once a
+ * property is set, additional values of the same property are ignored.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * _.defaults({ 'user': 'barney' }, { 'age': 36 }, { 'user': 'fred' });
+ * // => { 'user': 'barney', 'age': 36 }
+ */
+ var defaults = createDefaults(assign, assignDefaults);
+
+ /**
+ * This method is like `_.defaults` except that it recursively assigns
+ * default properties.
+ *
+ * **Note:** This method mutates `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The destination object.
+ * @param {...Object} [sources] The source objects.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * _.defaultsDeep({ 'user': { 'name': 'barney' } }, { 'user': { 'name': 'fred', 'age': 36 } });
+ * // => { 'user': { 'name': 'barney', 'age': 36 } }
+ *
+ */
+ var defaultsDeep = createDefaults(merge, mergeDefaults);
+
+ /**
+ * This method is like `_.find` except that it returns the key of the first
+ * element `predicate` returns truthy for instead of the element itself.
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {string|undefined} Returns the key of the matched element, else `undefined`.
+ * @example
+ *
+ * var users = {
+ * 'barney': { 'age': 36, 'active': true },
+ * 'fred': { 'age': 40, 'active': false },
+ * 'pebbles': { 'age': 1, 'active': true }
+ * };
+ *
+ * _.findKey(users, function(chr) {
+ * return chr.age < 40;
+ * });
+ * // => 'barney' (iteration order is not guaranteed)
+ *
+ * // using the `_.matches` callback shorthand
+ * _.findKey(users, { 'age': 1, 'active': true });
+ * // => 'pebbles'
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.findKey(users, 'active', false);
+ * // => 'fred'
+ *
+ * // using the `_.property` callback shorthand
+ * _.findKey(users, 'active');
+ * // => 'barney'
+ */
+ var findKey = createFindKey(baseForOwn);
+
+ /**
+ * This method is like `_.findKey` except that it iterates over elements of
+ * a collection in the opposite order.
+ *
+ * If a property name is provided for `predicate` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `predicate` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to search.
+ * @param {Function|Object|string} [predicate=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {string|undefined} Returns the key of the matched element, else `undefined`.
+ * @example
+ *
+ * var users = {
+ * 'barney': { 'age': 36, 'active': true },
+ * 'fred': { 'age': 40, 'active': false },
+ * 'pebbles': { 'age': 1, 'active': true }
+ * };
+ *
+ * _.findLastKey(users, function(chr) {
+ * return chr.age < 40;
+ * });
+ * // => returns `pebbles` assuming `_.findKey` returns `barney`
+ *
+ * // using the `_.matches` callback shorthand
+ * _.findLastKey(users, { 'age': 36, 'active': true });
+ * // => 'barney'
+ *
+ * // using the `_.matchesProperty` callback shorthand
+ * _.findLastKey(users, 'active', false);
+ * // => 'fred'
+ *
+ * // using the `_.property` callback shorthand
+ * _.findLastKey(users, 'active');
+ * // => 'pebbles'
+ */
+ var findLastKey = createFindKey(baseForOwnRight);
+
+ /**
+ * Iterates over own and inherited enumerable properties of an object invoking
+ * `iteratee` for each property. The `iteratee` is bound to `thisArg` and invoked
+ * with three arguments: (value, key, object). Iteratee functions may exit
+ * iteration early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forIn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'a', 'b', and 'c' (iteration order is not guaranteed)
+ */
+ var forIn = createForIn(baseFor);
+
+ /**
+ * This method is like `_.forIn` except that it iterates over properties of
+ * `object` in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forInRight(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'c', 'b', and 'a' assuming `_.forIn ` logs 'a', 'b', and 'c'
+ */
+ var forInRight = createForIn(baseForRight);
+
+ /**
+ * Iterates over own enumerable properties of an object invoking `iteratee`
+ * for each property. The `iteratee` is bound to `thisArg` and invoked with
+ * three arguments: (value, key, object). Iteratee functions may exit iteration
+ * early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forOwn(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'a' and 'b' (iteration order is not guaranteed)
+ */
+ var forOwn = createForOwn(baseForOwn);
+
+ /**
+ * This method is like `_.forOwn` except that it iterates over properties of
+ * `object` in the opposite order.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.forOwnRight(new Foo, function(value, key) {
+ * console.log(key);
+ * });
+ * // => logs 'b' and 'a' assuming `_.forOwn` logs 'a' and 'b'
+ */
+ var forOwnRight = createForOwn(baseForOwnRight);
+
+ /**
+ * Creates an array of function property names from all enumerable properties,
+ * own and inherited, of `object`.
+ *
+ * @static
+ * @memberOf _
+ * @alias methods
+ * @category Object
+ * @param {Object} object The object to inspect.
+ * @returns {Array} Returns the new array of property names.
+ * @example
+ *
+ * _.functions(_);
+ * // => ['after', 'ary', 'assign', ...]
+ */
+ function functions(object) {
+ return baseFunctions(object, keysIn(object));
+ }
+
+ /**
+ * Gets the property value at `path` of `object`. If the resolved value is
+ * `undefined` the `defaultValue` is used in its place.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to get.
+ * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
+ * @returns {*} Returns the resolved value.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.get(object, 'a[0].b.c');
+ * // => 3
+ *
+ * _.get(object, ['a', '0', 'b', 'c']);
+ * // => 3
+ *
+ * _.get(object, 'a.b.c', 'default');
+ * // => 'default'
+ */
+ function get(object, path, defaultValue) {
+ var result = object == null ? undefined : baseGet(object, toPath(path), path + '');
+ return result === undefined ? defaultValue : result;
+ }
+
+ /**
+ * Checks if `path` is a direct property.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path to check.
+ * @returns {boolean} Returns `true` if `path` is a direct property, else `false`.
+ * @example
+ *
+ * var object = { 'a': { 'b': { 'c': 3 } } };
+ *
+ * _.has(object, 'a');
+ * // => true
+ *
+ * _.has(object, 'a.b.c');
+ * // => true
+ *
+ * _.has(object, ['a', 'b', 'c']);
+ * // => true
+ */
+ function has(object, path) {
+ if (object == null) {
+ return false;
+ }
+ var result = hasOwnProperty.call(object, path);
+ if (!result && !isKey(path)) {
+ path = toPath(path);
+ object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+ if (object == null) {
+ return false;
+ }
+ path = last(path);
+ result = hasOwnProperty.call(object, path);
+ }
+ return result || (isLength(object.length) && isIndex(path, object.length) &&
+ (isArray(object) || isArguments(object)));
+ }
+
+ /**
+ * Creates an object composed of the inverted keys and values of `object`.
+ * If `object` contains duplicate values, subsequent values overwrite property
+ * assignments of previous values unless `multiValue` is `true`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to invert.
+ * @param {boolean} [multiValue] Allow multiple values per key.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Object} Returns the new inverted object.
+ * @example
+ *
+ * var object = { 'a': 1, 'b': 2, 'c': 1 };
+ *
+ * _.invert(object);
+ * // => { '1': 'c', '2': 'b' }
+ *
+ * // with `multiValue`
+ * _.invert(object, true);
+ * // => { '1': ['a', 'c'], '2': ['b'] }
+ */
+ function invert(object, multiValue, guard) {
+ if (guard && isIterateeCall(object, multiValue, guard)) {
+ multiValue = undefined;
+ }
+ var index = -1,
+ props = keys(object),
+ length = props.length,
+ result = {};
+
+ while (++index < length) {
+ var key = props[index],
+ value = object[key];
+
+ if (multiValue) {
+ if (hasOwnProperty.call(result, value)) {
+ result[value].push(key);
+ } else {
+ result[value] = [key];
+ }
+ }
+ else {
+ result[value] = key;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Creates an array of the own enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects. See the
+ * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
+ * for more details.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keys(new Foo);
+ * // => ['a', 'b'] (iteration order is not guaranteed)
+ *
+ * _.keys('hi');
+ * // => ['0', '1']
+ */
+ var keys = !nativeKeys ? shimKeys : function(object) {
+ var Ctor = object == null ? undefined : object.constructor;
+ if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
+ (typeof object != 'function' && isArrayLike(object))) {
+ return shimKeys(object);
+ }
+ return isObject(object) ? nativeKeys(object) : [];
+ };
+
+ /**
+ * Creates an array of the own and inherited enumerable property names of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property names.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.keysIn(new Foo);
+ * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
+ */
+ function keysIn(object) {
+ if (object == null) {
+ return [];
+ }
+ if (!isObject(object)) {
+ object = Object(object);
+ }
+ var length = object.length;
+ length = (length && isLength(length) &&
+ (isArray(object) || isArguments(object)) && length) || 0;
+
+ var Ctor = object.constructor,
+ index = -1,
+ isProto = typeof Ctor == 'function' && Ctor.prototype === object,
+ result = Array(length),
+ skipIndexes = length > 0;
+
+ while (++index < length) {
+ result[index] = (index + '');
+ }
+ for (var key in object) {
+ if (!(skipIndexes && isIndex(key, length)) &&
+ !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
+ result.push(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * The opposite of `_.mapValues`; this method creates an object with the
+ * same values as `object` and keys generated by running each own enumerable
+ * property of `object` through `iteratee`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns the new mapped object.
+ * @example
+ *
+ * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
+ * return key + value;
+ * });
+ * // => { 'a1': 1, 'b2': 2 }
+ */
+ var mapKeys = createObjectMapper(true);
+
+ /**
+ * Creates an object with the same keys as `object` and values generated by
+ * running each own enumerable property of `object` through `iteratee`. The
+ * iteratee function is bound to `thisArg` and invoked with three arguments:
+ * (value, key, object).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to iterate over.
+ * @param {Function|Object|string} [iteratee=_.identity] The function invoked
+ * per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Object} Returns the new mapped object.
+ * @example
+ *
+ * _.mapValues({ 'a': 1, 'b': 2 }, function(n) {
+ * return n * 3;
+ * });
+ * // => { 'a': 3, 'b': 6 }
+ *
+ * var users = {
+ * 'fred': { 'user': 'fred', 'age': 40 },
+ * 'pebbles': { 'user': 'pebbles', 'age': 1 }
+ * };
+ *
+ * // using the `_.property` callback shorthand
+ * _.mapValues(users, 'age');
+ * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
+ */
+ var mapValues = createObjectMapper();
+
+ /**
+ * The opposite of `_.pick`; this method creates an object composed of the
+ * own and inherited enumerable properties of `object` that are not omitted.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {Function|...(string|string[])} [predicate] The function invoked per
+ * iteration or property names to omit, specified as individual property
+ * names or arrays of property names.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'user': 'fred', 'age': 40 };
+ *
+ * _.omit(object, 'age');
+ * // => { 'user': 'fred' }
+ *
+ * _.omit(object, _.isNumber);
+ * // => { 'user': 'fred' }
+ */
+ var omit = restParam(function(object, props) {
+ if (object == null) {
+ return {};
+ }
+ if (typeof props[0] != 'function') {
+ var props = arrayMap(baseFlatten(props), String);
+ return pickByArray(object, baseDifference(keysIn(object), props));
+ }
+ var predicate = bindCallback(props[0], props[1], 3);
+ return pickByCallback(object, function(value, key, object) {
+ return !predicate(value, key, object);
+ });
+ });
+
+ /**
+ * Creates a two dimensional array of the key-value pairs for `object`,
+ * e.g. `[[key1, value1], [key2, value2]]`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the new array of key-value pairs.
+ * @example
+ *
+ * _.pairs({ 'barney': 36, 'fred': 40 });
+ * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed)
+ */
+ function pairs(object) {
+ object = toObject(object);
+
+ var index = -1,
+ props = keys(object),
+ length = props.length,
+ result = Array(length);
+
+ while (++index < length) {
+ var key = props[index];
+ result[index] = [key, object[key]];
+ }
+ return result;
+ }
+
+ /**
+ * Creates an object composed of the picked `object` properties. Property
+ * names may be specified as individual arguments or as arrays of property
+ * names. If `predicate` is provided it is invoked for each property of `object`
+ * picking the properties `predicate` returns truthy for. The predicate is
+ * bound to `thisArg` and invoked with three arguments: (value, key, object).
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The source object.
+ * @param {Function|...(string|string[])} [predicate] The function invoked per
+ * iteration or property names to pick, specified as individual property
+ * names or arrays of property names.
+ * @param {*} [thisArg] The `this` binding of `predicate`.
+ * @returns {Object} Returns the new object.
+ * @example
+ *
+ * var object = { 'user': 'fred', 'age': 40 };
+ *
+ * _.pick(object, 'user');
+ * // => { 'user': 'fred' }
+ *
+ * _.pick(object, _.isString);
+ * // => { 'user': 'fred' }
+ */
+ var pick = restParam(function(object, props) {
+ if (object == null) {
+ return {};
+ }
+ return typeof props[0] == 'function'
+ ? pickByCallback(object, bindCallback(props[0], props[1], 3))
+ : pickByArray(object, baseFlatten(props));
+ });
+
+ /**
+ * This method is like `_.get` except that if the resolved value is a function
+ * it is invoked with the `this` binding of its parent object and its result
+ * is returned.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @param {Array|string} path The path of the property to resolve.
+ * @param {*} [defaultValue] The value returned if the resolved value is `undefined`.
+ * @returns {*} Returns the resolved value.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
+ *
+ * _.result(object, 'a[0].b.c1');
+ * // => 3
+ *
+ * _.result(object, 'a[0].b.c2');
+ * // => 4
+ *
+ * _.result(object, 'a.b.c', 'default');
+ * // => 'default'
+ *
+ * _.result(object, 'a.b.c', _.constant('default'));
+ * // => 'default'
+ */
+ function result(object, path, defaultValue) {
+ var result = object == null ? undefined : object[path];
+ if (result === undefined) {
+ if (object != null && !isKey(path, object)) {
+ path = toPath(path);
+ object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
+ result = object == null ? undefined : object[last(path)];
+ }
+ result = result === undefined ? defaultValue : result;
+ }
+ return isFunction(result) ? result.call(object) : result;
+ }
+
+ /**
+ * Sets the property value of `path` on `object`. If a portion of `path`
+ * does not exist it is created.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to augment.
+ * @param {Array|string} path The path of the property to set.
+ * @param {*} value The value to set.
+ * @returns {Object} Returns `object`.
+ * @example
+ *
+ * var object = { 'a': [{ 'b': { 'c': 3 } }] };
+ *
+ * _.set(object, 'a[0].b.c', 4);
+ * console.log(object.a[0].b.c);
+ * // => 4
+ *
+ * _.set(object, 'x[0].y.z', 5);
+ * console.log(object.x[0].y.z);
+ * // => 5
+ */
+ function set(object, path, value) {
+ if (object == null) {
+ return object;
+ }
+ var pathKey = (path + '');
+ path = (object[pathKey] != null || isKey(path, object)) ? [pathKey] : toPath(path);
+
+ var index = -1,
+ length = path.length,
+ lastIndex = length - 1,
+ nested = object;
+
+ while (nested != null && ++index < length) {
+ var key = path[index];
+ if (isObject(nested)) {
+ if (index == lastIndex) {
+ nested[key] = value;
+ } else if (nested[key] == null) {
+ nested[key] = isIndex(path[index + 1]) ? [] : {};
+ }
+ }
+ nested = nested[key];
+ }
+ return object;
+ }
+
+ /**
+ * An alternative to `_.reduce`; this method transforms `object` to a new
+ * `accumulator` object which is the result of running each of its own enumerable
+ * properties through `iteratee`, with each invocation potentially mutating
+ * the `accumulator` object. The `iteratee` is bound to `thisArg` and invoked
+ * with four arguments: (accumulator, value, key, object). Iteratee functions
+ * may exit iteration early by explicitly returning `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Array|Object} object The object to iterate over.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [accumulator] The custom accumulator value.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {*} Returns the accumulated value.
+ * @example
+ *
+ * _.transform([2, 3, 4], function(result, n) {
+ * result.push(n *= n);
+ * return n % 2 == 0;
+ * });
+ * // => [4, 9]
+ *
+ * _.transform({ 'a': 1, 'b': 2 }, function(result, n, key) {
+ * result[key] = n * 3;
+ * });
+ * // => { 'a': 3, 'b': 6 }
+ */
+ function transform(object, iteratee, accumulator, thisArg) {
+ var isArr = isArray(object) || isTypedArray(object);
+ iteratee = getCallback(iteratee, thisArg, 4);
+
+ if (accumulator == null) {
+ if (isArr || isObject(object)) {
+ var Ctor = object.constructor;
+ if (isArr) {
+ accumulator = isArray(object) ? new Ctor : [];
+ } else {
+ accumulator = baseCreate(isFunction(Ctor) ? Ctor.prototype : undefined);
+ }
+ } else {
+ accumulator = {};
+ }
+ }
+ (isArr ? arrayEach : baseForOwn)(object, function(value, index, object) {
+ return iteratee(accumulator, value, index, object);
+ });
+ return accumulator;
+ }
+
+ /**
+ * Creates an array of the own enumerable property values of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property values.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.values(new Foo);
+ * // => [1, 2] (iteration order is not guaranteed)
+ *
+ * _.values('hi');
+ * // => ['h', 'i']
+ */
+ function values(object) {
+ return baseValues(object, keys(object));
+ }
+
+ /**
+ * Creates an array of the own and inherited enumerable property values
+ * of `object`.
+ *
+ * **Note:** Non-object values are coerced to objects.
+ *
+ * @static
+ * @memberOf _
+ * @category Object
+ * @param {Object} object The object to query.
+ * @returns {Array} Returns the array of property values.
+ * @example
+ *
+ * function Foo() {
+ * this.a = 1;
+ * this.b = 2;
+ * }
+ *
+ * Foo.prototype.c = 3;
+ *
+ * _.valuesIn(new Foo);
+ * // => [1, 2, 3] (iteration order is not guaranteed)
+ */
+ function valuesIn(object) {
+ return baseValues(object, keysIn(object));
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Checks if `n` is between `start` and up to but not including, `end`. If
+ * `end` is not specified it is set to `start` with `start` then set to `0`.
+ *
+ * @static
+ * @memberOf _
+ * @category Number
+ * @param {number} n The number to check.
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @returns {boolean} Returns `true` if `n` is in the range, else `false`.
+ * @example
+ *
+ * _.inRange(3, 2, 4);
+ * // => true
+ *
+ * _.inRange(4, 8);
+ * // => true
+ *
+ * _.inRange(4, 2);
+ * // => false
+ *
+ * _.inRange(2, 2);
+ * // => false
+ *
+ * _.inRange(1.2, 2);
+ * // => true
+ *
+ * _.inRange(5.2, 4);
+ * // => false
+ */
+ function inRange(value, start, end) {
+ start = +start || 0;
+ if (end === undefined) {
+ end = start;
+ start = 0;
+ } else {
+ end = +end || 0;
+ }
+ return value >= nativeMin(start, end) && value < nativeMax(start, end);
+ }
+
+ /**
+ * Produces a random number between `min` and `max` (inclusive). If only one
+ * argument is provided a number between `0` and the given number is returned.
+ * If `floating` is `true`, or either `min` or `max` are floats, a floating-point
+ * number is returned instead of an integer.
+ *
+ * @static
+ * @memberOf _
+ * @category Number
+ * @param {number} [min=0] The minimum possible value.
+ * @param {number} [max=1] The maximum possible value.
+ * @param {boolean} [floating] Specify returning a floating-point number.
+ * @returns {number} Returns the random number.
+ * @example
+ *
+ * _.random(0, 5);
+ * // => an integer between 0 and 5
+ *
+ * _.random(5);
+ * // => also an integer between 0 and 5
+ *
+ * _.random(5, true);
+ * // => a floating-point number between 0 and 5
+ *
+ * _.random(1.2, 5.2);
+ * // => a floating-point number between 1.2 and 5.2
+ */
+ function random(min, max, floating) {
+ if (floating && isIterateeCall(min, max, floating)) {
+ max = floating = undefined;
+ }
+ var noMin = min == null,
+ noMax = max == null;
+
+ if (floating == null) {
+ if (noMax && typeof min == 'boolean') {
+ floating = min;
+ min = 1;
+ }
+ else if (typeof max == 'boolean') {
+ floating = max;
+ noMax = true;
+ }
+ }
+ if (noMin && noMax) {
+ max = 1;
+ noMax = false;
+ }
+ min = +min || 0;
+ if (noMax) {
+ max = min;
+ min = 0;
+ } else {
+ max = +max || 0;
+ }
+ if (floating || min % 1 || max % 1) {
+ var rand = nativeRandom();
+ return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand + '').length - 1)))), max);
+ }
+ return baseRandom(min, max);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the camel cased string.
+ * @example
+ *
+ * _.camelCase('Foo Bar');
+ * // => 'fooBar'
+ *
+ * _.camelCase('--foo-bar');
+ * // => 'fooBar'
+ *
+ * _.camelCase('__foo_bar__');
+ * // => 'fooBar'
+ */
+ var camelCase = createCompounder(function(result, word, index) {
+ word = word.toLowerCase();
+ return result + (index ? (word.charAt(0).toUpperCase() + word.slice(1)) : word);
+ });
+
+ /**
+ * Capitalizes the first character of `string`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to capitalize.
+ * @returns {string} Returns the capitalized string.
+ * @example
+ *
+ * _.capitalize('fred');
+ * // => 'Fred'
+ */
+ function capitalize(string) {
+ string = baseToString(string);
+ return string && (string.charAt(0).toUpperCase() + string.slice(1));
+ }
+
+ /**
+ * Deburrs `string` by converting [latin-1 supplementary letters](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
+ * to basic latin letters and removing [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to deburr.
+ * @returns {string} Returns the deburred string.
+ * @example
+ *
+ * _.deburr('déjà vu');
+ * // => 'deja vu'
+ */
+ function deburr(string) {
+ string = baseToString(string);
+ return string && string.replace(reLatin1, deburrLetter).replace(reComboMark, '');
+ }
+
+ /**
+ * Checks if `string` ends with the given target string.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to search.
+ * @param {string} [target] The string to search for.
+ * @param {number} [position=string.length] The position to search from.
+ * @returns {boolean} Returns `true` if `string` ends with `target`, else `false`.
+ * @example
+ *
+ * _.endsWith('abc', 'c');
+ * // => true
+ *
+ * _.endsWith('abc', 'b');
+ * // => false
+ *
+ * _.endsWith('abc', 'b', 2);
+ * // => true
+ */
+ function endsWith(string, target, position) {
+ string = baseToString(string);
+ target = (target + '');
+
+ var length = string.length;
+ position = position === undefined
+ ? length
+ : nativeMin(position < 0 ? 0 : (+position || 0), length);
+
+ position -= target.length;
+ return position >= 0 && string.indexOf(target, position) == position;
+ }
+
+ /**
+ * Converts the characters "&", "<", ">", '"', "'", and "\`", in `string` to
+ * their corresponding HTML entities.
+ *
+ * **Note:** No other characters are escaped. To escape additional characters
+ * use a third-party library like [_he_](https://mths.be/he).
+ *
+ * Though the ">" character is escaped for symmetry, characters like
+ * ">" and "/" don't need escaping in HTML and have no special meaning
+ * unless they're part of a tag or unquoted attribute value.
+ * See [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
+ * (under "semi-related fun fact") for more details.
+ *
+ * Backticks are escaped because in Internet Explorer < 9, they can break out
+ * of attribute values or HTML comments. See [#59](https://html5sec.org/#59),
+ * [#102](https://html5sec.org/#102), [#108](https://html5sec.org/#108), and
+ * [#133](https://html5sec.org/#133) of the [HTML5 Security Cheatsheet](https://html5sec.org/)
+ * for more details.
+ *
+ * When working with HTML you should always [quote attribute values](http://wonko.com/post/html-escaping)
+ * to reduce XSS vectors.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to escape.
+ * @returns {string} Returns the escaped string.
+ * @example
+ *
+ * _.escape('fred, barney, & pebbles');
+ * // => 'fred, barney, &amp; pebbles'
+ */
+ function escape(string) {
+ // Reset `lastIndex` because in IE < 9 `String#replace` does not.
+ string = baseToString(string);
+ return (string && reHasUnescapedHtml.test(string))
+ ? string.replace(reUnescapedHtml, escapeHtmlChar)
+ : string;
+ }
+
+ /**
+ * Escapes the `RegExp` special characters "\", "/", "^", "$", ".", "|", "?",
+ * "*", "+", "(", ")", "[", "]", "{" and "}" in `string`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to escape.
+ * @returns {string} Returns the escaped string.
+ * @example
+ *
+ * _.escapeRegExp('[lodash](https://lodash.com/)');
+ * // => '\[lodash\]\(https:\/\/lodash\.com\/\)'
+ */
+ function escapeRegExp(string) {
+ string = baseToString(string);
+ return (string && reHasRegExpChars.test(string))
+ ? string.replace(reRegExpChars, escapeRegExpChar)
+ : (string || '(?:)');
+ }
+
+ /**
+ * Converts `string` to [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the kebab cased string.
+ * @example
+ *
+ * _.kebabCase('Foo Bar');
+ * // => 'foo-bar'
+ *
+ * _.kebabCase('fooBar');
+ * // => 'foo-bar'
+ *
+ * _.kebabCase('__foo_bar__');
+ * // => 'foo-bar'
+ */
+ var kebabCase = createCompounder(function(result, word, index) {
+ return result + (index ? '-' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Pads `string` on the left and right sides if it's shorter than `length`.
+ * Padding characters are truncated if they can't be evenly divided by `length`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.pad('abc', 8);
+ * // => ' abc '
+ *
+ * _.pad('abc', 8, '_-');
+ * // => '_-abc_-_'
+ *
+ * _.pad('abc', 3);
+ * // => 'abc'
+ */
+ function pad(string, length, chars) {
+ string = baseToString(string);
+ length = +length;
+
+ var strLength = string.length;
+ if (strLength >= length || !nativeIsFinite(length)) {
+ return string;
+ }
+ var mid = (length - strLength) / 2,
+ leftLength = nativeFloor(mid),
+ rightLength = nativeCeil(mid);
+
+ chars = createPadding('', rightLength, chars);
+ return chars.slice(0, leftLength) + string + chars;
+ }
+
+ /**
+ * Pads `string` on the left side if it's shorter than `length`. Padding
+ * characters are truncated if they exceed `length`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.padLeft('abc', 6);
+ * // => ' abc'
+ *
+ * _.padLeft('abc', 6, '_-');
+ * // => '_-_abc'
+ *
+ * _.padLeft('abc', 3);
+ * // => 'abc'
+ */
+ var padLeft = createPadDir();
+
+ /**
+ * Pads `string` on the right side if it's shorter than `length`. Padding
+ * characters are truncated if they exceed `length`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to pad.
+ * @param {number} [length=0] The padding length.
+ * @param {string} [chars=' '] The string used as padding.
+ * @returns {string} Returns the padded string.
+ * @example
+ *
+ * _.padRight('abc', 6);
+ * // => 'abc '
+ *
+ * _.padRight('abc', 6, '_-');
+ * // => 'abc_-_'
+ *
+ * _.padRight('abc', 3);
+ * // => 'abc'
+ */
+ var padRight = createPadDir(true);
+
+ /**
+ * Converts `string` to an integer of the specified radix. If `radix` is
+ * `undefined` or `0`, a `radix` of `10` is used unless `value` is a hexadecimal,
+ * in which case a `radix` of `16` is used.
+ *
+ * **Note:** This method aligns with the [ES5 implementation](https://es5.github.io/#E)
+ * of `parseInt`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} string The string to convert.
+ * @param {number} [radix] The radix to interpret `value` by.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {number} Returns the converted integer.
+ * @example
+ *
+ * _.parseInt('08');
+ * // => 8
+ *
+ * _.map(['6', '08', '10'], _.parseInt);
+ * // => [6, 8, 10]
+ */
+ function parseInt(string, radix, guard) {
+ // Firefox < 21 and Opera < 15 follow ES3 for `parseInt`.
+ // Chrome fails to trim leading <BOM> whitespace characters.
+ // See https://code.google.com/p/v8/issues/detail?id=3109 for more details.
+ if (guard ? isIterateeCall(string, radix, guard) : radix == null) {
+ radix = 0;
+ } else if (radix) {
+ radix = +radix;
+ }
+ string = trim(string);
+ return nativeParseInt(string, radix || (reHasHexPrefix.test(string) ? 16 : 10));
+ }
+
+ /**
+ * Repeats the given string `n` times.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to repeat.
+ * @param {number} [n=0] The number of times to repeat the string.
+ * @returns {string} Returns the repeated string.
+ * @example
+ *
+ * _.repeat('*', 3);
+ * // => '***'
+ *
+ * _.repeat('abc', 2);
+ * // => 'abcabc'
+ *
+ * _.repeat('abc', 0);
+ * // => ''
+ */
+ function repeat(string, n) {
+ var result = '';
+ string = baseToString(string);
+ n = +n;
+ if (n < 1 || !string || !nativeIsFinite(n)) {
+ return result;
+ }
+ // Leverage the exponentiation by squaring algorithm for a faster repeat.
+ // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
+ do {
+ if (n % 2) {
+ result += string;
+ }
+ n = nativeFloor(n / 2);
+ string += string;
+ } while (n);
+
+ return result;
+ }
+
+ /**
+ * Converts `string` to [snake case](https://en.wikipedia.org/wiki/Snake_case).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the snake cased string.
+ * @example
+ *
+ * _.snakeCase('Foo Bar');
+ * // => 'foo_bar'
+ *
+ * _.snakeCase('fooBar');
+ * // => 'foo_bar'
+ *
+ * _.snakeCase('--foo-bar');
+ * // => 'foo_bar'
+ */
+ var snakeCase = createCompounder(function(result, word, index) {
+ return result + (index ? '_' : '') + word.toLowerCase();
+ });
+
+ /**
+ * Converts `string` to [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to convert.
+ * @returns {string} Returns the start cased string.
+ * @example
+ *
+ * _.startCase('--foo-bar');
+ * // => 'Foo Bar'
+ *
+ * _.startCase('fooBar');
+ * // => 'Foo Bar'
+ *
+ * _.startCase('__foo_bar__');
+ * // => 'Foo Bar'
+ */
+ var startCase = createCompounder(function(result, word, index) {
+ return result + (index ? ' ' : '') + (word.charAt(0).toUpperCase() + word.slice(1));
+ });
+
+ /**
+ * Checks if `string` starts with the given target string.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to search.
+ * @param {string} [target] The string to search for.
+ * @param {number} [position=0] The position to search from.
+ * @returns {boolean} Returns `true` if `string` starts with `target`, else `false`.
+ * @example
+ *
+ * _.startsWith('abc', 'a');
+ * // => true
+ *
+ * _.startsWith('abc', 'b');
+ * // => false
+ *
+ * _.startsWith('abc', 'b', 1);
+ * // => true
+ */
+ function startsWith(string, target, position) {
+ string = baseToString(string);
+ position = position == null
+ ? 0
+ : nativeMin(position < 0 ? 0 : (+position || 0), string.length);
+
+ return string.lastIndexOf(target, position) == position;
+ }
+
+ /**
+ * Creates a compiled template function that can interpolate data properties
+ * in "interpolate" delimiters, HTML-escape interpolated data properties in
+ * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
+ * properties may be accessed as free variables in the template. If a setting
+ * object is provided it takes precedence over `_.templateSettings` values.
+ *
+ * **Note:** In the development build `_.template` utilizes
+ * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
+ * for easier debugging.
+ *
+ * For more information on precompiling templates see
+ * [lodash's custom builds documentation](https://lodash.com/custom-builds).
+ *
+ * For more information on Chrome extension sandboxes see
+ * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The template string.
+ * @param {Object} [options] The options object.
+ * @param {RegExp} [options.escape] The HTML "escape" delimiter.
+ * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
+ * @param {Object} [options.imports] An object to import into the template as free variables.
+ * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
+ * @param {string} [options.sourceURL] The sourceURL of the template's compiled source.
+ * @param {string} [options.variable] The data object variable name.
+ * @param- {Object} [otherOptions] Enables the legacy `options` param signature.
+ * @returns {Function} Returns the compiled template function.
+ * @example
+ *
+ * // using the "interpolate" delimiter to create a compiled template
+ * var compiled = _.template('hello <%= user %>!');
+ * compiled({ 'user': 'fred' });
+ * // => 'hello fred!'
+ *
+ * // using the HTML "escape" delimiter to escape data property values
+ * var compiled = _.template('<b><%- value %></b>');
+ * compiled({ 'value': '<script>' });
+ * // => '<b>&lt;script&gt;</b>'
+ *
+ * // using the "evaluate" delimiter to execute JavaScript and generate HTML
+ * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
+ * compiled({ 'users': ['fred', 'barney'] });
+ * // => '<li>fred</li><li>barney</li>'
+ *
+ * // using the internal `print` function in "evaluate" delimiters
+ * var compiled = _.template('<% print("hello " + user); %>!');
+ * compiled({ 'user': 'barney' });
+ * // => 'hello barney!'
+ *
+ * // using the ES delimiter as an alternative to the default "interpolate" delimiter
+ * var compiled = _.template('hello ${ user }!');
+ * compiled({ 'user': 'pebbles' });
+ * // => 'hello pebbles!'
+ *
+ * // using custom template delimiters
+ * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
+ * var compiled = _.template('hello {{ user }}!');
+ * compiled({ 'user': 'mustache' });
+ * // => 'hello mustache!'
+ *
+ * // using backslashes to treat delimiters as plain text
+ * var compiled = _.template('<%= "\\<%- value %\\>" %>');
+ * compiled({ 'value': 'ignored' });
+ * // => '<%- value %>'
+ *
+ * // using the `imports` option to import `jQuery` as `jq`
+ * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
+ * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
+ * compiled({ 'users': ['fred', 'barney'] });
+ * // => '<li>fred</li><li>barney</li>'
+ *
+ * // using the `sourceURL` option to specify a custom sourceURL for the template
+ * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
+ * compiled(data);
+ * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
+ *
+ * // using the `variable` option to ensure a with-statement isn't used in the compiled template
+ * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
+ * compiled.source;
+ * // => function(data) {
+ * // var __t, __p = '';
+ * // __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
+ * // return __p;
+ * // }
+ *
+ * // using the `source` property to inline compiled templates for meaningful
+ * // line numbers in error messages and a stack trace
+ * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
+ * var JST = {\
+ * "main": ' + _.template(mainText).source + '\
+ * };\
+ * ');
+ */
+ function template(string, options, otherOptions) {
+ // Based on John Resig's `tmpl` implementation (http://ejohn.org/blog/javascript-micro-templating/)
+ // and Laura Doktorova's doT.js (https://github.com/olado/doT).
+ var settings = lodash.templateSettings;
+
+ if (otherOptions && isIterateeCall(string, options, otherOptions)) {
+ options = otherOptions = undefined;
+ }
+ string = baseToString(string);
+ options = assignWith(baseAssign({}, otherOptions || options), settings, assignOwnDefaults);
+
+ var imports = assignWith(baseAssign({}, options.imports), settings.imports, assignOwnDefaults),
+ importsKeys = keys(imports),
+ importsValues = baseValues(imports, importsKeys);
+
+ var isEscaping,
+ isEvaluating,
+ index = 0,
+ interpolate = options.interpolate || reNoMatch,
+ source = "__p += '";
+
+ // Compile the regexp to match each delimiter.
+ var reDelimiters = RegExp(
+ (options.escape || reNoMatch).source + '|' +
+ interpolate.source + '|' +
+ (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
+ (options.evaluate || reNoMatch).source + '|$'
+ , 'g');
+
+ // Use a sourceURL for easier debugging.
+ var sourceURL = '//# sourceURL=' +
+ ('sourceURL' in options
+ ? options.sourceURL
+ : ('lodash.templateSources[' + (++templateCounter) + ']')
+ ) + '\n';
+
+ string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
+ interpolateValue || (interpolateValue = esTemplateValue);
+
+ // Escape characters that can't be included in string literals.
+ source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
+
+ // Replace delimiters with snippets.
+ if (escapeValue) {
+ isEscaping = true;
+ source += "' +\n__e(" + escapeValue + ") +\n'";
+ }
+ if (evaluateValue) {
+ isEvaluating = true;
+ source += "';\n" + evaluateValue + ";\n__p += '";
+ }
+ if (interpolateValue) {
+ source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
+ }
+ index = offset + match.length;
+
+ // The JS engine embedded in Adobe products requires returning the `match`
+ // string in order to produce the correct `offset` value.
+ return match;
+ });
+
+ source += "';\n";
+
+ // If `variable` is not specified wrap a with-statement around the generated
+ // code to add the data object to the top of the scope chain.
+ var variable = options.variable;
+ if (!variable) {
+ source = 'with (obj) {\n' + source + '\n}\n';
+ }
+ // Cleanup code by stripping empty strings.
+ source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
+ .replace(reEmptyStringMiddle, '$1')
+ .replace(reEmptyStringTrailing, '$1;');
+
+ // Frame code as the function body.
+ source = 'function(' + (variable || 'obj') + ') {\n' +
+ (variable
+ ? ''
+ : 'obj || (obj = {});\n'
+ ) +
+ "var __t, __p = ''" +
+ (isEscaping
+ ? ', __e = _.escape'
+ : ''
+ ) +
+ (isEvaluating
+ ? ', __j = Array.prototype.join;\n' +
+ "function print() { __p += __j.call(arguments, '') }\n"
+ : ';\n'
+ ) +
+ source +
+ 'return __p\n}';
+
+ var result = attempt(function() {
+ return Function(importsKeys, sourceURL + 'return ' + source).apply(undefined, importsValues);
+ });
+
+ // Provide the compiled function's source by its `toString` method or
+ // the `source` property as a convenience for inlining compiled templates.
+ result.source = source;
+ if (isError(result)) {
+ throw result;
+ }
+ return result;
+ }
+
+ /**
+ * Removes leading and trailing whitespace or specified characters from `string`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {string} Returns the trimmed string.
+ * @example
+ *
+ * _.trim(' abc ');
+ * // => 'abc'
+ *
+ * _.trim('-_-abc-_-', '_-');
+ * // => 'abc'
+ *
+ * _.map([' foo ', ' bar '], _.trim);
+ * // => ['foo', 'bar']
+ */
+ function trim(string, chars, guard) {
+ var value = string;
+ string = baseToString(string);
+ if (!string) {
+ return string;
+ }
+ if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
+ return string.slice(trimmedLeftIndex(string), trimmedRightIndex(string) + 1);
+ }
+ chars = (chars + '');
+ return string.slice(charsLeftIndex(string, chars), charsRightIndex(string, chars) + 1);
+ }
+
+ /**
+ * Removes leading whitespace or specified characters from `string`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {string} Returns the trimmed string.
+ * @example
+ *
+ * _.trimLeft(' abc ');
+ * // => 'abc '
+ *
+ * _.trimLeft('-_-abc-_-', '_-');
+ * // => 'abc-_-'
+ */
+ function trimLeft(string, chars, guard) {
+ var value = string;
+ string = baseToString(string);
+ if (!string) {
+ return string;
+ }
+ if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
+ return string.slice(trimmedLeftIndex(string));
+ }
+ return string.slice(charsLeftIndex(string, (chars + '')));
+ }
+
+ /**
+ * Removes trailing whitespace or specified characters from `string`.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to trim.
+ * @param {string} [chars=whitespace] The characters to trim.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {string} Returns the trimmed string.
+ * @example
+ *
+ * _.trimRight(' abc ');
+ * // => ' abc'
+ *
+ * _.trimRight('-_-abc-_-', '_-');
+ * // => '-_-abc'
+ */
+ function trimRight(string, chars, guard) {
+ var value = string;
+ string = baseToString(string);
+ if (!string) {
+ return string;
+ }
+ if (guard ? isIterateeCall(value, chars, guard) : chars == null) {
+ return string.slice(0, trimmedRightIndex(string) + 1);
+ }
+ return string.slice(0, charsRightIndex(string, (chars + '')) + 1);
+ }
+
+ /**
+ * Truncates `string` if it's longer than the given maximum string length.
+ * The last characters of the truncated string are replaced with the omission
+ * string which defaults to "...".
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to truncate.
+ * @param {Object|number} [options] The options object or maximum string length.
+ * @param {number} [options.length=30] The maximum string length.
+ * @param {string} [options.omission='...'] The string to indicate text is omitted.
+ * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {string} Returns the truncated string.
+ * @example
+ *
+ * _.trunc('hi-diddly-ho there, neighborino');
+ * // => 'hi-diddly-ho there, neighbo...'
+ *
+ * _.trunc('hi-diddly-ho there, neighborino', 24);
+ * // => 'hi-diddly-ho there, n...'
+ *
+ * _.trunc('hi-diddly-ho there, neighborino', {
+ * 'length': 24,
+ * 'separator': ' '
+ * });
+ * // => 'hi-diddly-ho there,...'
+ *
+ * _.trunc('hi-diddly-ho there, neighborino', {
+ * 'length': 24,
+ * 'separator': /,? +/
+ * });
+ * // => 'hi-diddly-ho there...'
+ *
+ * _.trunc('hi-diddly-ho there, neighborino', {
+ * 'omission': ' [...]'
+ * });
+ * // => 'hi-diddly-ho there, neig [...]'
+ */
+ function trunc(string, options, guard) {
+ if (guard && isIterateeCall(string, options, guard)) {
+ options = undefined;
+ }
+ var length = DEFAULT_TRUNC_LENGTH,
+ omission = DEFAULT_TRUNC_OMISSION;
+
+ if (options != null) {
+ if (isObject(options)) {
+ var separator = 'separator' in options ? options.separator : separator;
+ length = 'length' in options ? (+options.length || 0) : length;
+ omission = 'omission' in options ? baseToString(options.omission) : omission;
+ } else {
+ length = +options || 0;
+ }
+ }
+ string = baseToString(string);
+ if (length >= string.length) {
+ return string;
+ }
+ var end = length - omission.length;
+ if (end < 1) {
+ return omission;
+ }
+ var result = string.slice(0, end);
+ if (separator == null) {
+ return result + omission;
+ }
+ if (isRegExp(separator)) {
+ if (string.slice(end).search(separator)) {
+ var match,
+ newEnd,
+ substring = string.slice(0, end);
+
+ if (!separator.global) {
+ separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g');
+ }
+ separator.lastIndex = 0;
+ while ((match = separator.exec(substring))) {
+ newEnd = match.index;
+ }
+ result = result.slice(0, newEnd == null ? end : newEnd);
+ }
+ } else if (string.indexOf(separator, end) != end) {
+ var index = result.lastIndexOf(separator);
+ if (index > -1) {
+ result = result.slice(0, index);
+ }
+ }
+ return result + omission;
+ }
+
+ /**
+ * The inverse of `_.escape`; this method converts the HTML entities
+ * `&amp;`, `&lt;`, `&gt;`, `&quot;`, `&#39;`, and `&#96;` in `string` to their
+ * corresponding characters.
+ *
+ * **Note:** No other HTML entities are unescaped. To unescape additional HTML
+ * entities use a third-party library like [_he_](https://mths.be/he).
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to unescape.
+ * @returns {string} Returns the unescaped string.
+ * @example
+ *
+ * _.unescape('fred, barney, &amp; pebbles');
+ * // => 'fred, barney, & pebbles'
+ */
+ function unescape(string) {
+ string = baseToString(string);
+ return (string && reHasEscapedHtml.test(string))
+ ? string.replace(reEscapedHtml, unescapeHtmlChar)
+ : string;
+ }
+
+ /**
+ * Splits `string` into an array of its words.
+ *
+ * @static
+ * @memberOf _
+ * @category String
+ * @param {string} [string=''] The string to inspect.
+ * @param {RegExp|string} [pattern] The pattern to match words.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Array} Returns the words of `string`.
+ * @example
+ *
+ * _.words('fred, barney, & pebbles');
+ * // => ['fred', 'barney', 'pebbles']
+ *
+ * _.words('fred, barney, & pebbles', /[^, ]+/g);
+ * // => ['fred', 'barney', '&', 'pebbles']
+ */
+ function words(string, pattern, guard) {
+ if (guard && isIterateeCall(string, pattern, guard)) {
+ pattern = undefined;
+ }
+ string = baseToString(string);
+ return string.match(pattern || reWords) || [];
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Attempts to invoke `func`, returning either the result or the caught error
+ * object. Any additional arguments are provided to `func` when it is invoked.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {Function} func The function to attempt.
+ * @returns {*} Returns the `func` result or error object.
+ * @example
+ *
+ * // avoid throwing errors for invalid selectors
+ * var elements = _.attempt(function(selector) {
+ * return document.querySelectorAll(selector);
+ * }, '>_>');
+ *
+ * if (_.isError(elements)) {
+ * elements = [];
+ * }
+ */
+ var attempt = restParam(function(func, args) {
+ try {
+ return func.apply(undefined, args);
+ } catch(e) {
+ return isError(e) ? e : new Error(e);
+ }
+ });
+
+ /**
+ * Creates a function that invokes `func` with the `this` binding of `thisArg`
+ * and arguments of the created function. If `func` is a property name the
+ * created callback returns the property value for a given element. If `func`
+ * is an object the created callback returns `true` for elements that contain
+ * the equivalent object properties, otherwise it returns `false`.
+ *
+ * @static
+ * @memberOf _
+ * @alias iteratee
+ * @category Utility
+ * @param {*} [func=_.identity] The value to convert to a callback.
+ * @param {*} [thisArg] The `this` binding of `func`.
+ * @param- {Object} [guard] Enables use as a callback for functions like `_.map`.
+ * @returns {Function} Returns the callback.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * // wrap to create custom callback shorthands
+ * _.callback = _.wrap(_.callback, function(callback, func, thisArg) {
+ * var match = /^(.+?)__([gl]t)(.+)$/.exec(func);
+ * if (!match) {
+ * return callback(func, thisArg);
+ * }
+ * return function(object) {
+ * return match[2] == 'gt'
+ * ? object[match[1]] > match[3]
+ * : object[match[1]] < match[3];
+ * };
+ * });
+ *
+ * _.filter(users, 'age__gt36');
+ * // => [{ 'user': 'fred', 'age': 40 }]
+ */
+ function callback(func, thisArg, guard) {
+ if (guard && isIterateeCall(func, thisArg, guard)) {
+ thisArg = undefined;
+ }
+ return isObjectLike(func)
+ ? matches(func)
+ : baseCallback(func, thisArg);
+ }
+
+ /**
+ * Creates a function that returns `value`.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {*} value The value to return from the new function.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ * var getter = _.constant(object);
+ *
+ * getter() === object;
+ * // => true
+ */
+ function constant(value) {
+ return function() {
+ return value;
+ };
+ }
+
+ /**
+ * This method returns the first argument provided to it.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {*} value Any value.
+ * @returns {*} Returns `value`.
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * _.identity(object) === object;
+ * // => true
+ */
+ function identity(value) {
+ return value;
+ }
+
+ /**
+ * Creates a function that performs a deep comparison between a given object
+ * and `source`, returning `true` if the given object has equivalent property
+ * values, else `false`.
+ *
+ * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+ * numbers, `Object` objects, regexes, and strings. Objects are compared by
+ * their own, not inherited, enumerable properties. For comparing a single
+ * own or inherited property value see `_.matchesProperty`.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {Object} source The object of property values to match.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36, 'active': true },
+ * { 'user': 'fred', 'age': 40, 'active': false }
+ * ];
+ *
+ * _.filter(users, _.matches({ 'age': 40, 'active': false }));
+ * // => [{ 'user': 'fred', 'age': 40, 'active': false }]
+ */
+ function matches(source) {
+ return baseMatches(baseClone(source, true));
+ }
+
+ /**
+ * Creates a function that compares the property value of `path` on a given
+ * object to `value`.
+ *
+ * **Note:** This method supports comparing arrays, booleans, `Date` objects,
+ * numbers, `Object` objects, regexes, and strings. Objects are compared by
+ * their own, not inherited, enumerable properties.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {Array|string} path The path of the property to get.
+ * @param {*} srcValue The value to match.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var users = [
+ * { 'user': 'barney' },
+ * { 'user': 'fred' }
+ * ];
+ *
+ * _.find(users, _.matchesProperty('user', 'fred'));
+ * // => { 'user': 'fred' }
+ */
+ function matchesProperty(path, srcValue) {
+ return baseMatchesProperty(path, baseClone(srcValue, true));
+ }
+
+ /**
+ * Creates a function that invokes the method at `path` on a given object.
+ * Any additional arguments are provided to the invoked method.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {Array|string} path The path of the method to invoke.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var objects = [
+ * { 'a': { 'b': { 'c': _.constant(2) } } },
+ * { 'a': { 'b': { 'c': _.constant(1) } } }
+ * ];
+ *
+ * _.map(objects, _.method('a.b.c'));
+ * // => [2, 1]
+ *
+ * _.invoke(_.sortBy(objects, _.method(['a', 'b', 'c'])), 'a.b.c');
+ * // => [1, 2]
+ */
+ var method = restParam(function(path, args) {
+ return function(object) {
+ return invokePath(object, path, args);
+ };
+ });
+
+ /**
+ * The opposite of `_.method`; this method creates a function that invokes
+ * the method at a given path on `object`. Any additional arguments are
+ * provided to the invoked method.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {Object} object The object to query.
+ * @param {...*} [args] The arguments to invoke the method with.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var array = _.times(3, _.constant),
+ * object = { 'a': array, 'b': array, 'c': array };
+ *
+ * _.map(['a[2]', 'c[0]'], _.methodOf(object));
+ * // => [2, 0]
+ *
+ * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
+ * // => [2, 0]
+ */
+ var methodOf = restParam(function(object, args) {
+ return function(path) {
+ return invokePath(object, path, args);
+ };
+ });
+
+ /**
+ * Adds all own enumerable function properties of a source object to the
+ * destination object. If `object` is a function then methods are added to
+ * its prototype as well.
+ *
+ * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
+ * avoid conflicts caused by modifying the original.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {Function|Object} [object=lodash] The destination object.
+ * @param {Object} source The object of functions to add.
+ * @param {Object} [options] The options object.
+ * @param {boolean} [options.chain=true] Specify whether the functions added
+ * are chainable.
+ * @returns {Function|Object} Returns `object`.
+ * @example
+ *
+ * function vowels(string) {
+ * return _.filter(string, function(v) {
+ * return /[aeiou]/i.test(v);
+ * });
+ * }
+ *
+ * _.mixin({ 'vowels': vowels });
+ * _.vowels('fred');
+ * // => ['e']
+ *
+ * _('fred').vowels().value();
+ * // => ['e']
+ *
+ * _.mixin({ 'vowels': vowels }, { 'chain': false });
+ * _('fred').vowels();
+ * // => ['e']
+ */
+ function mixin(object, source, options) {
+ if (options == null) {
+ var isObj = isObject(source),
+ props = isObj ? keys(source) : undefined,
+ methodNames = (props && props.length) ? baseFunctions(source, props) : undefined;
+
+ if (!(methodNames ? methodNames.length : isObj)) {
+ methodNames = false;
+ options = source;
+ source = object;
+ object = this;
+ }
+ }
+ if (!methodNames) {
+ methodNames = baseFunctions(source, keys(source));
+ }
+ var chain = true,
+ index = -1,
+ isFunc = isFunction(object),
+ length = methodNames.length;
+
+ if (options === false) {
+ chain = false;
+ } else if (isObject(options) && 'chain' in options) {
+ chain = options.chain;
+ }
+ while (++index < length) {
+ var methodName = methodNames[index],
+ func = source[methodName];
+
+ object[methodName] = func;
+ if (isFunc) {
+ object.prototype[methodName] = (function(func) {
+ return function() {
+ var chainAll = this.__chain__;
+ if (chain || chainAll) {
+ var result = object(this.__wrapped__),
+ actions = result.__actions__ = arrayCopy(this.__actions__);
+
+ actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
+ result.__chain__ = chainAll;
+ return result;
+ }
+ return func.apply(object, arrayPush([this.value()], arguments));
+ };
+ }(func));
+ }
+ }
+ return object;
+ }
+
+ /**
+ * Reverts the `_` variable to its previous value and returns a reference to
+ * the `lodash` function.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @returns {Function} Returns the `lodash` function.
+ * @example
+ *
+ * var lodash = _.noConflict();
+ */
+ function noConflict() {
+ root._ = oldDash;
+ return this;
+ }
+
+ /**
+ * A no-operation function that returns `undefined` regardless of the
+ * arguments it receives.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @example
+ *
+ * var object = { 'user': 'fred' };
+ *
+ * _.noop(object) === undefined;
+ * // => true
+ */
+ function noop() {
+ // No operation performed.
+ }
+
+ /**
+ * Creates a function that returns the property value at `path` on a
+ * given object.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {Array|string} path The path of the property to get.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var objects = [
+ * { 'a': { 'b': { 'c': 2 } } },
+ * { 'a': { 'b': { 'c': 1 } } }
+ * ];
+ *
+ * _.map(objects, _.property('a.b.c'));
+ * // => [2, 1]
+ *
+ * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');
+ * // => [1, 2]
+ */
+ function property(path) {
+ return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
+ }
+
+ /**
+ * The opposite of `_.property`; this method creates a function that returns
+ * the property value at a given path on `object`.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {Object} object The object to query.
+ * @returns {Function} Returns the new function.
+ * @example
+ *
+ * var array = [0, 1, 2],
+ * object = { 'a': array, 'b': array, 'c': array };
+ *
+ * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
+ * // => [2, 0]
+ *
+ * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
+ * // => [2, 0]
+ */
+ function propertyOf(object) {
+ return function(path) {
+ return baseGet(object, toPath(path), path + '');
+ };
+ }
+
+ /**
+ * Creates an array of numbers (positive and/or negative) progressing from
+ * `start` up to, but not including, `end`. If `end` is not specified it is
+ * set to `start` with `start` then set to `0`. If `end` is less than `start`
+ * a zero-length range is created unless a negative `step` is specified.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {number} [start=0] The start of the range.
+ * @param {number} end The end of the range.
+ * @param {number} [step=1] The value to increment or decrement by.
+ * @returns {Array} Returns the new array of numbers.
+ * @example
+ *
+ * _.range(4);
+ * // => [0, 1, 2, 3]
+ *
+ * _.range(1, 5);
+ * // => [1, 2, 3, 4]
+ *
+ * _.range(0, 20, 5);
+ * // => [0, 5, 10, 15]
+ *
+ * _.range(0, -4, -1);
+ * // => [0, -1, -2, -3]
+ *
+ * _.range(1, 4, 0);
+ * // => [1, 1, 1]
+ *
+ * _.range(0);
+ * // => []
+ */
+ function range(start, end, step) {
+ if (step && isIterateeCall(start, end, step)) {
+ end = step = undefined;
+ }
+ start = +start || 0;
+ step = step == null ? 1 : (+step || 0);
+
+ if (end == null) {
+ end = start;
+ start = 0;
+ } else {
+ end = +end || 0;
+ }
+ // Use `Array(length)` so engines like Chakra and V8 avoid slower modes.
+ // See https://youtu.be/XAqIpGU8ZZk#t=17m25s for more details.
+ var index = -1,
+ length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
+ result = Array(length);
+
+ while (++index < length) {
+ result[index] = start;
+ start += step;
+ }
+ return result;
+ }
+
+ /**
+ * Invokes the iteratee function `n` times, returning an array of the results
+ * of each invocation. The `iteratee` is bound to `thisArg` and invoked with
+ * one argument; (index).
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {number} n The number of times to invoke `iteratee`.
+ * @param {Function} [iteratee=_.identity] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {Array} Returns the array of results.
+ * @example
+ *
+ * var diceRolls = _.times(3, _.partial(_.random, 1, 6, false));
+ * // => [3, 6, 4]
+ *
+ * _.times(3, function(n) {
+ * mage.castSpell(n);
+ * });
+ * // => invokes `mage.castSpell(n)` three times with `n` of `0`, `1`, and `2`
+ *
+ * _.times(3, function(n) {
+ * this.cast(n);
+ * }, mage);
+ * // => also invokes `mage.castSpell(n)` three times
+ */
+ function times(n, iteratee, thisArg) {
+ n = nativeFloor(n);
+
+ // Exit early to avoid a JSC JIT bug in Safari 8
+ // where `Array(0)` is treated as `Array(1)`.
+ if (n < 1 || !nativeIsFinite(n)) {
+ return [];
+ }
+ var index = -1,
+ result = Array(nativeMin(n, MAX_ARRAY_LENGTH));
+
+ iteratee = bindCallback(iteratee, thisArg, 1);
+ while (++index < n) {
+ if (index < MAX_ARRAY_LENGTH) {
+ result[index] = iteratee(index);
+ } else {
+ iteratee(index);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Generates a unique ID. If `prefix` is provided the ID is appended to it.
+ *
+ * @static
+ * @memberOf _
+ * @category Utility
+ * @param {string} [prefix] The value to prefix the ID with.
+ * @returns {string} Returns the unique ID.
+ * @example
+ *
+ * _.uniqueId('contact_');
+ * // => 'contact_104'
+ *
+ * _.uniqueId();
+ * // => '105'
+ */
+ function uniqueId(prefix) {
+ var id = ++idCounter;
+ return baseToString(prefix) + id;
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * Adds two numbers.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {number} augend The first number to add.
+ * @param {number} addend The second number to add.
+ * @returns {number} Returns the sum.
+ * @example
+ *
+ * _.add(6, 4);
+ * // => 10
+ */
+ function add(augend, addend) {
+ return (+augend || 0) + (+addend || 0);
+ }
+
+ /**
+ * Calculates `n` rounded up to `precision`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {number} n The number to round up.
+ * @param {number} [precision=0] The precision to round up to.
+ * @returns {number} Returns the rounded up number.
+ * @example
+ *
+ * _.ceil(4.006);
+ * // => 5
+ *
+ * _.ceil(6.004, 2);
+ * // => 6.01
+ *
+ * _.ceil(6040, -2);
+ * // => 6100
+ */
+ var ceil = createRound('ceil');
+
+ /**
+ * Calculates `n` rounded down to `precision`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {number} n The number to round down.
+ * @param {number} [precision=0] The precision to round down to.
+ * @returns {number} Returns the rounded down number.
+ * @example
+ *
+ * _.floor(4.006);
+ * // => 4
+ *
+ * _.floor(0.046, 2);
+ * // => 0.04
+ *
+ * _.floor(4060, -2);
+ * // => 4000
+ */
+ var floor = createRound('floor');
+
+ /**
+ * Gets the maximum value of `collection`. If `collection` is empty or falsey
+ * `-Infinity` is returned. If an iteratee function is provided it is invoked
+ * for each value in `collection` to generate the criterion by which the value
+ * is ranked. The `iteratee` is bound to `thisArg` and invoked with three
+ * arguments: (value, index, collection).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {*} Returns the maximum value.
+ * @example
+ *
+ * _.max([4, 2, 8, 6]);
+ * // => 8
+ *
+ * _.max([]);
+ * // => -Infinity
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * _.max(users, function(chr) {
+ * return chr.age;
+ * });
+ * // => { 'user': 'fred', 'age': 40 }
+ *
+ * // using the `_.property` callback shorthand
+ * _.max(users, 'age');
+ * // => { 'user': 'fred', 'age': 40 }
+ */
+ var max = createExtremum(gt, NEGATIVE_INFINITY);
+
+ /**
+ * Gets the minimum value of `collection`. If `collection` is empty or falsey
+ * `Infinity` is returned. If an iteratee function is provided it is invoked
+ * for each value in `collection` to generate the criterion by which the value
+ * is ranked. The `iteratee` is bound to `thisArg` and invoked with three
+ * arguments: (value, index, collection).
+ *
+ * If a property name is provided for `iteratee` the created `_.property`
+ * style callback returns the property value of the given element.
+ *
+ * If a value is also provided for `thisArg` the created `_.matchesProperty`
+ * style callback returns `true` for elements that have a matching property
+ * value, else `false`.
+ *
+ * If an object is provided for `iteratee` the created `_.matches` style
+ * callback returns `true` for elements that have the properties of the given
+ * object, else `false`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {*} Returns the minimum value.
+ * @example
+ *
+ * _.min([4, 2, 8, 6]);
+ * // => 2
+ *
+ * _.min([]);
+ * // => Infinity
+ *
+ * var users = [
+ * { 'user': 'barney', 'age': 36 },
+ * { 'user': 'fred', 'age': 40 }
+ * ];
+ *
+ * _.min(users, function(chr) {
+ * return chr.age;
+ * });
+ * // => { 'user': 'barney', 'age': 36 }
+ *
+ * // using the `_.property` callback shorthand
+ * _.min(users, 'age');
+ * // => { 'user': 'barney', 'age': 36 }
+ */
+ var min = createExtremum(lt, POSITIVE_INFINITY);
+
+ /**
+ * Calculates `n` rounded to `precision`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {number} n The number to round.
+ * @param {number} [precision=0] The precision to round to.
+ * @returns {number} Returns the rounded number.
+ * @example
+ *
+ * _.round(4.006);
+ * // => 4
+ *
+ * _.round(4.006, 2);
+ * // => 4.01
+ *
+ * _.round(4060, -2);
+ * // => 4100
+ */
+ var round = createRound('round');
+
+ /**
+ * Gets the sum of the values in `collection`.
+ *
+ * @static
+ * @memberOf _
+ * @category Math
+ * @param {Array|Object|string} collection The collection to iterate over.
+ * @param {Function|Object|string} [iteratee] The function invoked per iteration.
+ * @param {*} [thisArg] The `this` binding of `iteratee`.
+ * @returns {number} Returns the sum.
+ * @example
+ *
+ * _.sum([4, 6]);
+ * // => 10
+ *
+ * _.sum({ 'a': 4, 'b': 6 });
+ * // => 10
+ *
+ * var objects = [
+ * { 'n': 4 },
+ * { 'n': 6 }
+ * ];
+ *
+ * _.sum(objects, function(object) {
+ * return object.n;
+ * });
+ * // => 10
+ *
+ * // using the `_.property` callback shorthand
+ * _.sum(objects, 'n');
+ * // => 10
+ */
+ function sum(collection, iteratee, thisArg) {
+ if (thisArg && isIterateeCall(collection, iteratee, thisArg)) {
+ iteratee = undefined;
+ }
+ iteratee = getCallback(iteratee, thisArg, 3);
+ return iteratee.length == 1
+ ? arraySum(isArray(collection) ? collection : toIterable(collection), iteratee)
+ : baseSum(collection, iteratee);
+ }
+
+ /*------------------------------------------------------------------------*/
+
+ // Ensure wrappers are instances of `baseLodash`.
+ lodash.prototype = baseLodash.prototype;
+
+ LodashWrapper.prototype = baseCreate(baseLodash.prototype);
+ LodashWrapper.prototype.constructor = LodashWrapper;
+
+ LazyWrapper.prototype = baseCreate(baseLodash.prototype);
+ LazyWrapper.prototype.constructor = LazyWrapper;
+
+ // Add functions to the `Map` cache.
+ MapCache.prototype['delete'] = mapDelete;
+ MapCache.prototype.get = mapGet;
+ MapCache.prototype.has = mapHas;
+ MapCache.prototype.set = mapSet;
+
+ // Add functions to the `Set` cache.
+ SetCache.prototype.push = cachePush;
+
+ // Assign cache to `_.memoize`.
+ memoize.Cache = MapCache;
+
+ // Add functions that return wrapped values when chaining.
+ lodash.after = after;
+ lodash.ary = ary;
+ lodash.assign = assign;
+ lodash.at = at;
+ lodash.before = before;
+ lodash.bind = bind;
+ lodash.bindAll = bindAll;
+ lodash.bindKey = bindKey;
+ lodash.callback = callback;
+ lodash.chain = chain;
+ lodash.chunk = chunk;
+ lodash.compact = compact;
+ lodash.constant = constant;
+ lodash.countBy = countBy;
+ lodash.create = create;
+ lodash.curry = curry;
+ lodash.curryRight = curryRight;
+ lodash.debounce = debounce;
+ lodash.defaults = defaults;
+ lodash.defaultsDeep = defaultsDeep;
+ lodash.defer = defer;
+ lodash.delay = delay;
+ lodash.difference = difference;
+ lodash.drop = drop;
+ lodash.dropRight = dropRight;
+ lodash.dropRightWhile = dropRightWhile;
+ lodash.dropWhile = dropWhile;
+ lodash.fill = fill;
+ lodash.filter = filter;
+ lodash.flatten = flatten;
+ lodash.flattenDeep = flattenDeep;
+ lodash.flow = flow;
+ lodash.flowRight = flowRight;
+ lodash.forEach = forEach;
+ lodash.forEachRight = forEachRight;
+ lodash.forIn = forIn;
+ lodash.forInRight = forInRight;
+ lodash.forOwn = forOwn;
+ lodash.forOwnRight = forOwnRight;
+ lodash.functions = functions;
+ lodash.groupBy = groupBy;
+ lodash.indexBy = indexBy;
+ lodash.initial = initial;
+ lodash.intersection = intersection;
+ lodash.invert = invert;
+ lodash.invoke = invoke;
+ lodash.keys = keys;
+ lodash.keysIn = keysIn;
+ lodash.map = map;
+ lodash.mapKeys = mapKeys;
+ lodash.mapValues = mapValues;
+ lodash.matches = matches;
+ lodash.matchesProperty = matchesProperty;
+ lodash.memoize = memoize;
+ lodash.merge = merge;
+ lodash.method = method;
+ lodash.methodOf = methodOf;
+ lodash.mixin = mixin;
+ lodash.modArgs = modArgs;
+ lodash.negate = negate;
+ lodash.omit = omit;
+ lodash.once = once;
+ lodash.pairs = pairs;
+ lodash.partial = partial;
+ lodash.partialRight = partialRight;
+ lodash.partition = partition;
+ lodash.pick = pick;
+ lodash.pluck = pluck;
+ lodash.property = property;
+ lodash.propertyOf = propertyOf;
+ lodash.pull = pull;
+ lodash.pullAt = pullAt;
+ lodash.range = range;
+ lodash.rearg = rearg;
+ lodash.reject = reject;
+ lodash.remove = remove;
+ lodash.rest = rest;
+ lodash.restParam = restParam;
+ lodash.set = set;
+ lodash.shuffle = shuffle;
+ lodash.slice = slice;
+ lodash.sortBy = sortBy;
+ lodash.sortByAll = sortByAll;
+ lodash.sortByOrder = sortByOrder;
+ lodash.spread = spread;
+ lodash.take = take;
+ lodash.takeRight = takeRight;
+ lodash.takeRightWhile = takeRightWhile;
+ lodash.takeWhile = takeWhile;
+ lodash.tap = tap;
+ lodash.throttle = throttle;
+ lodash.thru = thru;
+ lodash.times = times;
+ lodash.toArray = toArray;
+ lodash.toPlainObject = toPlainObject;
+ lodash.transform = transform;
+ lodash.union = union;
+ lodash.uniq = uniq;
+ lodash.unzip = unzip;
+ lodash.unzipWith = unzipWith;
+ lodash.values = values;
+ lodash.valuesIn = valuesIn;
+ lodash.where = where;
+ lodash.without = without;
+ lodash.wrap = wrap;
+ lodash.xor = xor;
+ lodash.zip = zip;
+ lodash.zipObject = zipObject;
+ lodash.zipWith = zipWith;
+
+ // Add aliases.
+ lodash.backflow = flowRight;
+ lodash.collect = map;
+ lodash.compose = flowRight;
+ lodash.each = forEach;
+ lodash.eachRight = forEachRight;
+ lodash.extend = assign;
+ lodash.iteratee = callback;
+ lodash.methods = functions;
+ lodash.object = zipObject;
+ lodash.select = filter;
+ lodash.tail = rest;
+ lodash.unique = uniq;
+
+ // Add functions to `lodash.prototype`.
+ mixin(lodash, lodash);
+
+ /*------------------------------------------------------------------------*/
+
+ // Add functions that return unwrapped values when chaining.
+ lodash.add = add;
+ lodash.attempt = attempt;
+ lodash.camelCase = camelCase;
+ lodash.capitalize = capitalize;
+ lodash.ceil = ceil;
+ lodash.clone = clone;
+ lodash.cloneDeep = cloneDeep;
+ lodash.deburr = deburr;
+ lodash.endsWith = endsWith;
+ lodash.escape = escape;
+ lodash.escapeRegExp = escapeRegExp;
+ lodash.every = every;
+ lodash.find = find;
+ lodash.findIndex = findIndex;
+ lodash.findKey = findKey;
+ lodash.findLast = findLast;
+ lodash.findLastIndex = findLastIndex;
+ lodash.findLastKey = findLastKey;
+ lodash.findWhere = findWhere;
+ lodash.first = first;
+ lodash.floor = floor;
+ lodash.get = get;
+ lodash.gt = gt;
+ lodash.gte = gte;
+ lodash.has = has;
+ lodash.identity = identity;
+ lodash.includes = includes;
+ lodash.indexOf = indexOf;
+ lodash.inRange = inRange;
+ lodash.isArguments = isArguments;
+ lodash.isArray = isArray;
+ lodash.isBoolean = isBoolean;
+ lodash.isDate = isDate;
+ lodash.isElement = isElement;
+ lodash.isEmpty = isEmpty;
+ lodash.isEqual = isEqual;
+ lodash.isError = isError;
+ lodash.isFinite = isFinite;
+ lodash.isFunction = isFunction;
+ lodash.isMatch = isMatch;
+ lodash.isNaN = isNaN;
+ lodash.isNative = isNative;
+ lodash.isNull = isNull;
+ lodash.isNumber = isNumber;
+ lodash.isObject = isObject;
+ lodash.isPlainObject = isPlainObject;
+ lodash.isRegExp = isRegExp;
+ lodash.isString = isString;
+ lodash.isTypedArray = isTypedArray;
+ lodash.isUndefined = isUndefined;
+ lodash.kebabCase = kebabCase;
+ lodash.last = last;
+ lodash.lastIndexOf = lastIndexOf;
+ lodash.lt = lt;
+ lodash.lte = lte;
+ lodash.max = max;
+ lodash.min = min;
+ lodash.noConflict = noConflict;
+ lodash.noop = noop;
+ lodash.now = now;
+ lodash.pad = pad;
+ lodash.padLeft = padLeft;
+ lodash.padRight = padRight;
+ lodash.parseInt = parseInt;
+ lodash.random = random;
+ lodash.reduce = reduce;
+ lodash.reduceRight = reduceRight;
+ lodash.repeat = repeat;
+ lodash.result = result;
+ lodash.round = round;
+ lodash.runInContext = runInContext;
+ lodash.size = size;
+ lodash.snakeCase = snakeCase;
+ lodash.some = some;
+ lodash.sortedIndex = sortedIndex;
+ lodash.sortedLastIndex = sortedLastIndex;
+ lodash.startCase = startCase;
+ lodash.startsWith = startsWith;
+ lodash.sum = sum;
+ lodash.template = template;
+ lodash.trim = trim;
+ lodash.trimLeft = trimLeft;
+ lodash.trimRight = trimRight;
+ lodash.trunc = trunc;
+ lodash.unescape = unescape;
+ lodash.uniqueId = uniqueId;
+ lodash.words = words;
+
+ // Add aliases.
+ lodash.all = every;
+ lodash.any = some;
+ lodash.contains = includes;
+ lodash.eq = isEqual;
+ lodash.detect = find;
+ lodash.foldl = reduce;
+ lodash.foldr = reduceRight;
+ lodash.head = first;
+ lodash.include = includes;
+ lodash.inject = reduce;
+
+ mixin(lodash, (function() {
+ var source = {};
+ baseForOwn(lodash, function(func, methodName) {
+ if (!lodash.prototype[methodName]) {
+ source[methodName] = func;
+ }
+ });
+ return source;
+ }()), false);
+
+ /*------------------------------------------------------------------------*/
+
+ // Add functions capable of returning wrapped and unwrapped values when chaining.
+ lodash.sample = sample;
+
+ lodash.prototype.sample = function(n) {
+ if (!this.__chain__ && n == null) {
+ return sample(this.value());
+ }
+ return this.thru(function(value) {
+ return sample(value, n);
+ });
+ };
+
+ /*------------------------------------------------------------------------*/
+
+ /**
+ * The semantic version number.
+ *
+ * @static
+ * @memberOf _
+ * @type string
+ */
+ lodash.VERSION = VERSION;
+
+ // Assign default placeholders.
+ arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
+ lodash[methodName].placeholder = lodash;
+ });
+
+ // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
+ arrayEach(['drop', 'take'], function(methodName, index) {
+ LazyWrapper.prototype[methodName] = function(n) {
+ var filtered = this.__filtered__;
+ if (filtered && !index) {
+ return new LazyWrapper(this);
+ }
+ n = n == null ? 1 : nativeMax(nativeFloor(n) || 0, 0);
+
+ var result = this.clone();
+ if (filtered) {
+ result.__takeCount__ = nativeMin(result.__takeCount__, n);
+ } else {
+ result.__views__.push({ 'size': n, 'type': methodName + (result.__dir__ < 0 ? 'Right' : '') });
+ }
+ return result;
+ };
+
+ LazyWrapper.prototype[methodName + 'Right'] = function(n) {
+ return this.reverse()[methodName](n).reverse();
+ };
+ });
+
+ // Add `LazyWrapper` methods that accept an `iteratee` value.
+ arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
+ var type = index + 1,
+ isFilter = type != LAZY_MAP_FLAG;
+
+ LazyWrapper.prototype[methodName] = function(iteratee, thisArg) {
+ var result = this.clone();
+ result.__iteratees__.push({ 'iteratee': getCallback(iteratee, thisArg, 1), 'type': type });
+ result.__filtered__ = result.__filtered__ || isFilter;
+ return result;
+ };
+ });
+
+ // Add `LazyWrapper` methods for `_.first` and `_.last`.
+ arrayEach(['first', 'last'], function(methodName, index) {
+ var takeName = 'take' + (index ? 'Right' : '');
+
+ LazyWrapper.prototype[methodName] = function() {
+ return this[takeName](1).value()[0];
+ };
+ });
+
+ // Add `LazyWrapper` methods for `_.initial` and `_.rest`.
+ arrayEach(['initial', 'rest'], function(methodName, index) {
+ var dropName = 'drop' + (index ? '' : 'Right');
+
+ LazyWrapper.prototype[methodName] = function() {
+ return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
+ };
+ });
+
+ // Add `LazyWrapper` methods for `_.pluck` and `_.where`.
+ arrayEach(['pluck', 'where'], function(methodName, index) {
+ var operationName = index ? 'filter' : 'map',
+ createCallback = index ? baseMatches : property;
+
+ LazyWrapper.prototype[methodName] = function(value) {
+ return this[operationName](createCallback(value));
+ };
+ });
+
+ LazyWrapper.prototype.compact = function() {
+ return this.filter(identity);
+ };
+
+ LazyWrapper.prototype.reject = function(predicate, thisArg) {
+ predicate = getCallback(predicate, thisArg, 1);
+ return this.filter(function(value) {
+ return !predicate(value);
+ });
+ };
+
+ LazyWrapper.prototype.slice = function(start, end) {
+ start = start == null ? 0 : (+start || 0);
+
+ var result = this;
+ if (result.__filtered__ && (start > 0 || end < 0)) {
+ return new LazyWrapper(result);
+ }
+ if (start < 0) {
+ result = result.takeRight(-start);
+ } else if (start) {
+ result = result.drop(start);
+ }
+ if (end !== undefined) {
+ end = (+end || 0);
+ result = end < 0 ? result.dropRight(-end) : result.take(end - start);
+ }
+ return result;
+ };
+
+ LazyWrapper.prototype.takeRightWhile = function(predicate, thisArg) {
+ return this.reverse().takeWhile(predicate, thisArg).reverse();
+ };
+
+ LazyWrapper.prototype.toArray = function() {
+ return this.take(POSITIVE_INFINITY);
+ };
+
+ // Add `LazyWrapper` methods to `lodash.prototype`.
+ baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+ var checkIteratee = /^(?:filter|map|reject)|While$/.test(methodName),
+ retUnwrapped = /^(?:first|last)$/.test(methodName),
+ lodashFunc = lodash[retUnwrapped ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName];
+
+ if (!lodashFunc) {
+ return;
+ }
+ lodash.prototype[methodName] = function() {
+ var args = retUnwrapped ? [1] : arguments,
+ chainAll = this.__chain__,
+ value = this.__wrapped__,
+ isHybrid = !!this.__actions__.length,
+ isLazy = value instanceof LazyWrapper,
+ iteratee = args[0],
+ useLazy = isLazy || isArray(value);
+
+ if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
+ // Avoid lazy use if the iteratee has a "length" value other than `1`.
+ isLazy = useLazy = false;
+ }
+ var interceptor = function(value) {
+ return (retUnwrapped && chainAll)
+ ? lodashFunc(value, 1)[0]
+ : lodashFunc.apply(undefined, arrayPush([value], args));
+ };
+
+ var action = { 'func': thru, 'args': [interceptor], 'thisArg': undefined },
+ onlyLazy = isLazy && !isHybrid;
+
+ if (retUnwrapped && !chainAll) {
+ if (onlyLazy) {
+ value = value.clone();
+ value.__actions__.push(action);
+ return func.call(value);
+ }
+ return lodashFunc.call(undefined, this.value())[0];
+ }
+ if (!retUnwrapped && useLazy) {
+ value = onlyLazy ? value : new LazyWrapper(this);
+ var result = func.apply(value, args);
+ result.__actions__.push(action);
+ return new LodashWrapper(result, chainAll);
+ }
+ return this.thru(interceptor);
+ };
+ });
+
+ // Add `Array` and `String` methods to `lodash.prototype`.
+ arrayEach(['join', 'pop', 'push', 'replace', 'shift', 'sort', 'splice', 'split', 'unshift'], function(methodName) {
+ var func = (/^(?:replace|split)$/.test(methodName) ? stringProto : arrayProto)[methodName],
+ chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
+ retUnwrapped = /^(?:join|pop|replace|shift)$/.test(methodName);
+
+ lodash.prototype[methodName] = function() {
+ var args = arguments;
+ if (retUnwrapped && !this.__chain__) {
+ return func.apply(this.value(), args);
+ }
+ return this[chainName](function(value) {
+ return func.apply(value, args);
+ });
+ };
+ });
+
+ // Map minified function names to their real names.
+ baseForOwn(LazyWrapper.prototype, function(func, methodName) {
+ var lodashFunc = lodash[methodName];
+ if (lodashFunc) {
+ var key = lodashFunc.name,
+ names = realNames[key] || (realNames[key] = []);
+
+ names.push({ 'name': methodName, 'func': lodashFunc });
+ }
+ });
+
+ realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{ 'name': 'wrapper', 'func': undefined }];
+
+ // Add functions to the lazy wrapper.
+ LazyWrapper.prototype.clone = lazyClone;
+ LazyWrapper.prototype.reverse = lazyReverse;
+ LazyWrapper.prototype.value = lazyValue;
+
+ // Add chaining functions to the `lodash` wrapper.
+ lodash.prototype.chain = wrapperChain;
+ lodash.prototype.commit = wrapperCommit;
+ lodash.prototype.concat = wrapperConcat;
+ lodash.prototype.plant = wrapperPlant;
+ lodash.prototype.reverse = wrapperReverse;
+ lodash.prototype.toString = wrapperToString;
+ lodash.prototype.run = lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
+
+ // Add function aliases to the `lodash` wrapper.
+ lodash.prototype.collect = lodash.prototype.map;
+ lodash.prototype.head = lodash.prototype.first;
+ lodash.prototype.select = lodash.prototype.filter;
+ lodash.prototype.tail = lodash.prototype.rest;
+
+ return lodash;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ // Export lodash.
+ var _ = runInContext();
+
+ // Some AMD build optimizers like r.js check for condition patterns like the following:
+ if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
+ // Expose lodash to the global object when an AMD loader is present to avoid
+ // errors in cases where lodash is loaded by a script tag and not intended
+ // as an AMD module. See http://requirejs.org/docs/errors.html#mismatch for
+ // more details.
+ root._ = _;
+
+ // Define as an anonymous module so, through path mapping, it can be
+ // referenced as the "underscore" module.
+ define(function() {
+ return _;
+ });
+ }
+ // Check for `exports` after `define` in case a build optimizer adds an `exports` object.
+ else if (freeExports && freeModule) {
+ // Export for Node.js or RingoJS.
+ if (moduleExports) {
+ (freeModule.exports = _)._ = _;
+ }
+ // Export for Rhino with CommonJS support.
+ else {
+ freeExports._ = _;
+ }
+ }
+ else {
+ // Export for a browser or Rhino.
+ root._ = _;
+ }
+}.call(this));
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}]},{},[1])(1)
+}); \ No newline at end of file
diff --git a/docs/htmldoc/js/dagre.min.js b/docs/htmldoc/js/dagre.min.js
new file mode 100644
index 0000000..b7a9bbc
--- /dev/null
+++ b/docs/htmldoc/js/dagre.min.js
@@ -0,0 +1,6 @@
+!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){module.exports={graphlib:require("./lib/graphlib"),layout:require("./lib/layout"),debug:require("./lib/debug"),util:{time:require("./lib/util").time,notime:require("./lib/util").notime},version:require("./lib/version")}},{"./lib/debug":6,"./lib/graphlib":7,"./lib/layout":9,"./lib/util":29,"./lib/version":30}],2:[function(require,module,exports){"use strict";var _=require("./lodash"),greedyFAS=require("./greedy-fas");module.exports={run:run,undo:undo};function run(g){var fas=g.graph().acyclicer==="greedy"?greedyFAS(g,weightFn(g)):dfsFAS(g);_.each(fas,function(e){var label=g.edge(e);g.removeEdge(e);label.forwardName=e.name;label.reversed=true;g.setEdge(e.w,e.v,label,_.uniqueId("rev"))});function weightFn(g){return function(e){return g.edge(e).weight}}}function dfsFAS(g){var fas=[],stack={},visited={};function dfs(v){if(_.has(visited,v)){return}visited[v]=true;stack[v]=true;_.each(g.outEdges(v),function(e){if(_.has(stack,e.w)){fas.push(e)}else{dfs(e.w)}});delete stack[v]}_.each(g.nodes(),dfs);return fas}function undo(g){_.each(g.edges(),function(e){var label=g.edge(e);if(label.reversed){g.removeEdge(e);var forwardName=label.forwardName;delete label.reversed;delete label.forwardName;g.setEdge(e.w,e.v,label,forwardName)}})}},{"./greedy-fas":8,"./lodash":10}],3:[function(require,module,exports){var _=require("./lodash"),util=require("./util");module.exports=addBorderSegments;function addBorderSegments(g){function dfs(v){var children=g.children(v),node=g.node(v);if(children.length){_.each(children,dfs)}if(_.has(node,"minRank")){node.borderLeft=[];node.borderRight=[];for(var rank=node.minRank,maxRank=node.maxRank+1;rank<maxRank;++rank){addBorderNode(g,"borderLeft","_bl",v,node,rank);addBorderNode(g,"borderRight","_br",v,node,rank)}}}_.each(g.children(),dfs)}function addBorderNode(g,prop,prefix,sg,sgNode,rank){var label={width:0,height:0,rank:rank,borderType:prop},prev=sgNode[prop][rank-1],curr=util.addDummyNode(g,"border",label,prefix);sgNode[prop][rank]=curr;g.setParent(curr,sg);if(prev){g.setEdge(prev,curr,{weight:1})}}},{"./lodash":10,"./util":29}],4:[function(require,module,exports){"use strict";var _=require("./lodash");module.exports={adjust:adjust,undo:undo};function adjust(g){var rankDir=g.graph().rankdir.toLowerCase();if(rankDir==="lr"||rankDir==="rl"){swapWidthHeight(g)}}function undo(g){var rankDir=g.graph().rankdir.toLowerCase();if(rankDir==="bt"||rankDir==="rl"){reverseY(g)}if(rankDir==="lr"||rankDir==="rl"){swapXY(g);swapWidthHeight(g)}}function swapWidthHeight(g){_.each(g.nodes(),function(v){swapWidthHeightOne(g.node(v))});_.each(g.edges(),function(e){swapWidthHeightOne(g.edge(e))})}function swapWidthHeightOne(attrs){var w=attrs.width;attrs.width=attrs.height;attrs.height=w}function reverseY(g){_.each(g.nodes(),function(v){reverseYOne(g.node(v))});_.each(g.edges(),function(e){var edge=g.edge(e);_.each(edge.points,reverseYOne);if(_.has(edge,"y")){reverseYOne(edge)}})}function reverseYOne(attrs){attrs.y=-attrs.y}function swapXY(g){_.each(g.nodes(),function(v){swapXYOne(g.node(v))});_.each(g.edges(),function(e){var edge=g.edge(e);_.each(edge.points,swapXYOne);if(_.has(edge,"x")){swapXYOne(edge)}})}function swapXYOne(attrs){var x=attrs.x;attrs.x=attrs.y;attrs.y=x}},{"./lodash":10}],5:[function(require,module,exports){module.exports=List;function List(){var sentinel={};sentinel._next=sentinel._prev=sentinel;this._sentinel=sentinel}List.prototype.dequeue=function(){var sentinel=this._sentinel,entry=sentinel._prev;if(entry!==sentinel){unlink(entry);return entry}};List.prototype.enqueue=function(entry){var sentinel=this._sentinel;if(entry._prev&&entry._next){unlink(entry)}entry._next=sentinel._next;sentinel._next._prev=entry;sentinel._next=entry;entry._prev=sentinel};List.prototype.toString=function(){var strs=[],sentinel=this._sentinel,curr=sentinel._prev;while(curr!==sentinel){strs.push(JSON.stringify(curr,filterOutLinks));curr=curr._prev}return"["+strs.join(", ")+"]"};function unlink(entry){entry._prev._next=entry._next;entry._next._prev=entry._prev;delete entry._next;delete entry._prev}function filterOutLinks(k,v){if(k!=="_next"&&k!=="_prev"){return v}}},{}],6:[function(require,module,exports){var _=require("./lodash"),util=require("./util"),Graph=require("./graphlib").Graph;module.exports={debugOrdering:debugOrdering};function debugOrdering(g){var layerMatrix=util.buildLayerMatrix(g);var h=new Graph({compound:true,multigraph:true}).setGraph({});_.each(g.nodes(),function(v){h.setNode(v,{label:v});h.setParent(v,"layer"+g.node(v).rank)});_.each(g.edges(),function(e){h.setEdge(e.v,e.w,{},e.name)});_.each(layerMatrix,function(layer,i){var layerV="layer"+i;h.setNode(layerV,{rank:"same"});_.reduce(layer,function(u,v){h.setEdge(u,v,{style:"invis"});return v})});return h}},{"./graphlib":7,"./lodash":10,"./util":29}],7:[function(require,module,exports){var graphlib;if(typeof require==="function"){try{graphlib=require("graphlib")}catch(e){}}if(!graphlib){graphlib=window.graphlib}module.exports=graphlib},{graphlib:31}],8:[function(require,module,exports){var _=require("./lodash"),Graph=require("./graphlib").Graph,List=require("./data/list");module.exports=greedyFAS;var DEFAULT_WEIGHT_FN=_.constant(1);function greedyFAS(g,weightFn){if(g.nodeCount()<=1){return[]}var state=buildState(g,weightFn||DEFAULT_WEIGHT_FN);var results=doGreedyFAS(state.graph,state.buckets,state.zeroIdx);return _.flatten(_.map(results,function(e){return g.outEdges(e.v,e.w)}),true)}function doGreedyFAS(g,buckets,zeroIdx){var results=[],sources=buckets[buckets.length-1],sinks=buckets[0];var entry;while(g.nodeCount()){while(entry=sinks.dequeue()){removeNode(g,buckets,zeroIdx,entry)}while(entry=sources.dequeue()){removeNode(g,buckets,zeroIdx,entry)}if(g.nodeCount()){for(var i=buckets.length-2;i>0;--i){entry=buckets[i].dequeue();if(entry){results=results.concat(removeNode(g,buckets,zeroIdx,entry,true));break}}}}return results}function removeNode(g,buckets,zeroIdx,entry,collectPredecessors){var results=collectPredecessors?[]:undefined;_.each(g.inEdges(entry.v),function(edge){var weight=g.edge(edge),uEntry=g.node(edge.v);if(collectPredecessors){results.push({v:edge.v,w:edge.w})}uEntry.out-=weight;assignBucket(buckets,zeroIdx,uEntry)});_.each(g.outEdges(entry.v),function(edge){var weight=g.edge(edge),w=edge.w,wEntry=g.node(w);wEntry["in"]-=weight;assignBucket(buckets,zeroIdx,wEntry)});g.removeNode(entry.v);return results}function buildState(g,weightFn){var fasGraph=new Graph,maxIn=0,maxOut=0;_.each(g.nodes(),function(v){fasGraph.setNode(v,{v:v,"in":0,out:0})});_.each(g.edges(),function(e){var prevWeight=fasGraph.edge(e.v,e.w)||0,weight=weightFn(e),edgeWeight=prevWeight+weight;fasGraph.setEdge(e.v,e.w,edgeWeight);maxOut=Math.max(maxOut,fasGraph.node(e.v).out+=weight);maxIn=Math.max(maxIn,fasGraph.node(e.w)["in"]+=weight)});var buckets=_.range(maxOut+maxIn+3).map(function(){return new List});var zeroIdx=maxIn+1;_.each(fasGraph.nodes(),function(v){assignBucket(buckets,zeroIdx,fasGraph.node(v))});return{graph:fasGraph,buckets:buckets,zeroIdx:zeroIdx}}function assignBucket(buckets,zeroIdx,entry){if(!entry.out){buckets[0].enqueue(entry)}else if(!entry["in"]){buckets[buckets.length-1].enqueue(entry)}else{buckets[entry.out-entry["in"]+zeroIdx].enqueue(entry)}}},{"./data/list":5,"./graphlib":7,"./lodash":10}],9:[function(require,module,exports){"use strict";var _=require("./lodash"),acyclic=require("./acyclic"),normalize=require("./normalize"),rank=require("./rank"),normalizeRanks=require("./util").normalizeRanks,parentDummyChains=require("./parent-dummy-chains"),removeEmptyRanks=require("./util").removeEmptyRanks,nestingGraph=require("./nesting-graph"),addBorderSegments=require("./add-border-segments"),coordinateSystem=require("./coordinate-system"),order=require("./order"),position=require("./position"),util=require("./util"),Graph=require("./graphlib").Graph;module.exports=layout;function layout(g,opts){var time=opts&&opts.debugTiming?util.time:util.notime;time("layout",function(){var layoutGraph=time(" buildLayoutGraph",function(){return buildLayoutGraph(g)});time(" runLayout",function(){runLayout(layoutGraph,time)});time(" updateInputGraph",function(){updateInputGraph(g,layoutGraph)})})}function runLayout(g,time){time(" makeSpaceForEdgeLabels",function(){makeSpaceForEdgeLabels(g)});time(" removeSelfEdges",function(){removeSelfEdges(g)});time(" acyclic",function(){acyclic.run(g)});time(" nestingGraph.run",function(){nestingGraph.run(g)});time(" rank",function(){rank(util.asNonCompoundGraph(g))});time(" injectEdgeLabelProxies",function(){injectEdgeLabelProxies(g)});time(" removeEmptyRanks",function(){removeEmptyRanks(g)});time(" nestingGraph.cleanup",function(){nestingGraph.cleanup(g)});time(" normalizeRanks",function(){normalizeRanks(g)});time(" assignRankMinMax",function(){assignRankMinMax(g)});time(" removeEdgeLabelProxies",function(){removeEdgeLabelProxies(g)});time(" normalize.run",function(){normalize.run(g)});time(" parentDummyChains",function(){parentDummyChains(g)});time(" addBorderSegments",function(){addBorderSegments(g)});time(" order",function(){order(g)});time(" insertSelfEdges",function(){insertSelfEdges(g)});time(" adjustCoordinateSystem",function(){coordinateSystem.adjust(g)});time(" position",function(){position(g)});time(" positionSelfEdges",function(){positionSelfEdges(g)});time(" removeBorderNodes",function(){removeBorderNodes(g)});time(" normalize.undo",function(){normalize.undo(g)});time(" fixupEdgeLabelCoords",function(){fixupEdgeLabelCoords(g)});time(" undoCoordinateSystem",function(){coordinateSystem.undo(g)});time(" translateGraph",function(){translateGraph(g)});time(" assignNodeIntersects",function(){assignNodeIntersects(g)});time(" reversePoints",function(){reversePointsForReversedEdges(g)});time(" acyclic.undo",function(){acyclic.undo(g)})}function updateInputGraph(inputGraph,layoutGraph){_.each(inputGraph.nodes(),function(v){var inputLabel=inputGraph.node(v),layoutLabel=layoutGraph.node(v);if(inputLabel){inputLabel.x=layoutLabel.x;inputLabel.y=layoutLabel.y;if(layoutGraph.children(v).length){inputLabel.width=layoutLabel.width;inputLabel.height=layoutLabel.height}}});_.each(inputGraph.edges(),function(e){var inputLabel=inputGraph.edge(e),layoutLabel=layoutGraph.edge(e);inputLabel.points=layoutLabel.points;if(_.has(layoutLabel,"x")){inputLabel.x=layoutLabel.x;inputLabel.y=layoutLabel.y}});inputGraph.graph().width=layoutGraph.graph().width;inputGraph.graph().height=layoutGraph.graph().height}var graphNumAttrs=["nodesep","edgesep","ranksep","marginx","marginy"],graphDefaults={ranksep:50,edgesep:20,nodesep:50,rankdir:"tb"},graphAttrs=["acyclicer","ranker","rankdir","align"],nodeNumAttrs=["width","height"],nodeDefaults={width:0,height:0},edgeNumAttrs=["minlen","weight","width","height","labeloffset"],edgeDefaults={minlen:1,weight:1,width:0,height:0,labeloffset:10,labelpos:"r"},edgeAttrs=["labelpos"];function buildLayoutGraph(inputGraph){var g=new Graph({multigraph:true,compound:true}),graph=canonicalize(inputGraph.graph());g.setGraph(_.merge({},graphDefaults,selectNumberAttrs(graph,graphNumAttrs),_.pick(graph,graphAttrs)));_.each(inputGraph.nodes(),function(v){var node=canonicalize(inputGraph.node(v));g.setNode(v,_.defaults(selectNumberAttrs(node,nodeNumAttrs),nodeDefaults));g.setParent(v,inputGraph.parent(v))});_.each(inputGraph.edges(),function(e){var edge=canonicalize(inputGraph.edge(e));g.setEdge(e,_.merge({},edgeDefaults,selectNumberAttrs(edge,edgeNumAttrs),_.pick(edge,edgeAttrs)))});return g}function makeSpaceForEdgeLabels(g){var graph=g.graph();graph.ranksep/=2;_.each(g.edges(),function(e){var edge=g.edge(e);edge.minlen*=2;if(edge.labelpos.toLowerCase()!=="c"){if(graph.rankdir==="TB"||graph.rankdir==="BT"){edge.width+=edge.labeloffset}else{edge.height+=edge.labeloffset}}})}function injectEdgeLabelProxies(g){_.each(g.edges(),function(e){var edge=g.edge(e);if(edge.width&&edge.height){var v=g.node(e.v),w=g.node(e.w),label={rank:(w.rank-v.rank)/2+v.rank,e:e};util.addDummyNode(g,"edge-proxy",label,"_ep")}})}function assignRankMinMax(g){var maxRank=0;_.each(g.nodes(),function(v){var node=g.node(v);if(node.borderTop){node.minRank=g.node(node.borderTop).rank;node.maxRank=g.node(node.borderBottom).rank;maxRank=_.max(maxRank,node.maxRank)}});g.graph().maxRank=maxRank}function removeEdgeLabelProxies(g){_.each(g.nodes(),function(v){var node=g.node(v);if(node.dummy==="edge-proxy"){g.edge(node.e).labelRank=node.rank;g.removeNode(v)}})}function translateGraph(g){var minX=Number.POSITIVE_INFINITY,maxX=0,minY=Number.POSITIVE_INFINITY,maxY=0,graphLabel=g.graph(),marginX=graphLabel.marginx||0,marginY=graphLabel.marginy||0;function getExtremes(attrs){var x=attrs.x,y=attrs.y,w=attrs.width,h=attrs.height;minX=Math.min(minX,x-w/2);maxX=Math.max(maxX,x+w/2);minY=Math.min(minY,y-h/2);maxY=Math.max(maxY,y+h/2)}_.each(g.nodes(),function(v){getExtremes(g.node(v))});_.each(g.edges(),function(e){var edge=g.edge(e);if(_.has(edge,"x")){getExtremes(edge)}});minX-=marginX;minY-=marginY;_.each(g.nodes(),function(v){var node=g.node(v);node.x-=minX;node.y-=minY});_.each(g.edges(),function(e){var edge=g.edge(e);_.each(edge.points,function(p){p.x-=minX;p.y-=minY});if(_.has(edge,"x")){edge.x-=minX}if(_.has(edge,"y")){edge.y-=minY}});graphLabel.width=maxX-minX+marginX;graphLabel.height=maxY-minY+marginY}function assignNodeIntersects(g){_.each(g.edges(),function(e){var edge=g.edge(e),nodeV=g.node(e.v),nodeW=g.node(e.w),p1,p2;if(!edge.points){edge.points=[];p1=nodeW;p2=nodeV}else{p1=edge.points[0];p2=edge.points[edge.points.length-1]}edge.points.unshift(util.intersectRect(nodeV,p1));edge.points.push(util.intersectRect(nodeW,p2))})}function fixupEdgeLabelCoords(g){_.each(g.edges(),function(e){var edge=g.edge(e);if(_.has(edge,"x")){if(edge.labelpos==="l"||edge.labelpos==="r"){edge.width-=edge.labeloffset}switch(edge.labelpos){case"l":edge.x-=edge.width/2+edge.labeloffset;break;case"r":edge.x+=edge.width/2+edge.labeloffset;break}}})}function reversePointsForReversedEdges(g){_.each(g.edges(),function(e){var edge=g.edge(e);if(edge.reversed){edge.points.reverse()}})}function removeBorderNodes(g){_.each(g.nodes(),function(v){if(g.children(v).length){var node=g.node(v),t=g.node(node.borderTop),b=g.node(node.borderBottom),l=g.node(_.last(node.borderLeft)),r=g.node(_.last(node.borderRight));node.width=Math.abs(r.x-l.x);node.height=Math.abs(b.y-t.y);node.x=l.x+node.width/2;node.y=t.y+node.height/2}});_.each(g.nodes(),function(v){if(g.node(v).dummy==="border"){g.removeNode(v)}})}function removeSelfEdges(g){_.each(g.edges(),function(e){if(e.v===e.w){var node=g.node(e.v);if(!node.selfEdges){node.selfEdges=[]}node.selfEdges.push({e:e,label:g.edge(e)});g.removeEdge(e)}})}function insertSelfEdges(g){var layers=util.buildLayerMatrix(g);_.each(layers,function(layer){var orderShift=0;_.each(layer,function(v,i){var node=g.node(v);node.order=i+orderShift;_.each(node.selfEdges,function(selfEdge){util.addDummyNode(g,"selfedge",{width:selfEdge.label.width,height:selfEdge.label.height,rank:node.rank,order:i+ ++orderShift,e:selfEdge.e,label:selfEdge.label},"_se")});delete node.selfEdges})})}function positionSelfEdges(g){_.each(g.nodes(),function(v){var node=g.node(v);if(node.dummy==="selfedge"){var selfNode=g.node(node.e.v),x=selfNode.x+selfNode.width/2,y=selfNode.y,dx=node.x-x,dy=selfNode.height/2;g.setEdge(node.e,node.label);g.removeNode(v);node.label.points=[{x:x+2*dx/3,y:y-dy},{x:x+5*dx/6,y:y-dy},{x:x+dx,y:y},{x:x+5*dx/6,y:y+dy},{x:x+2*dx/3,y:y+dy}];node.label.x=node.x;node.label.y=node.y}})}function selectNumberAttrs(obj,attrs){return _.mapValues(_.pick(obj,attrs),Number)}function canonicalize(attrs){var newAttrs={};_.each(attrs,function(v,k){newAttrs[k.toLowerCase()]=v});return newAttrs}},{"./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){var lodash;if(typeof require==="function"){try{lodash=require("lodash")}catch(e){}}if(!lodash){lodash=window._}module.exports=lodash},{lodash:51}],11:[function(require,module,exports){var _=require("./lodash"),util=require("./util");module.exports={run:run,cleanup:cleanup};function run(g){var root=util.addDummyNode(g,"root",{},"_root"),depths=treeDepths(g),height=_.max(depths)-1,nodeSep=2*height+1;g.graph().nestingRoot=root;_.each(g.edges(),function(e){g.edge(e).minlen*=nodeSep});var weight=sumWeights(g)+1;_.each(g.children(),function(child){dfs(g,root,nodeSep,weight,height,depths,child)});g.graph().nodeRankFactor=nodeSep}function dfs(g,root,nodeSep,weight,height,depths,v){var children=g.children(v);if(!children.length){if(v!==root){g.setEdge(root,v,{weight:0,minlen:nodeSep})}return}var top=util.addBorderNode(g,"_bt"),bottom=util.addBorderNode(g,"_bb"),label=g.node(v);g.setParent(top,v);label.borderTop=top;g.setParent(bottom,v);label.borderBottom=bottom;_.each(children,function(child){dfs(g,root,nodeSep,weight,height,depths,child);var childNode=g.node(child),childTop=childNode.borderTop?childNode.borderTop:child,childBottom=childNode.borderBottom?childNode.borderBottom:child,thisWeight=childNode.borderTop?weight:2*weight,minlen=childTop!==childBottom?1:height-depths[v]+1;g.setEdge(top,childTop,{weight:thisWeight,minlen:minlen,nestingEdge:true});g.setEdge(childBottom,bottom,{weight:thisWeight,minlen:minlen,nestingEdge:true})});if(!g.parent(v)){g.setEdge(root,top,{weight:0,minlen:height+depths[v]})}}function treeDepths(g){var depths={};function dfs(v,depth){var children=g.children(v);if(children&&children.length){_.each(children,function(child){dfs(child,depth+1)})}depths[v]=depth}_.each(g.children(),function(v){dfs(v,1)});return depths}function sumWeights(g){return _.reduce(g.edges(),function(acc,e){return acc+g.edge(e).weight},0)}function cleanup(g){var graphLabel=g.graph();g.removeNode(graphLabel.nestingRoot);delete graphLabel.nestingRoot;_.each(g.edges(),function(e){var edge=g.edge(e);if(edge.nestingEdge){g.removeEdge(e)}})}},{"./lodash":10,"./util":29}],12:[function(require,module,exports){"use strict";var _=require("./lodash"),util=require("./util");module.exports={run:run,undo:undo};function run(g){g.graph().dummyChains=[];_.each(g.edges(),function(edge){normalizeEdge(g,edge)})}function normalizeEdge(g,e){var v=e.v,vRank=g.node(v).rank,w=e.w,wRank=g.node(w).rank,name=e.name,edgeLabel=g.edge(e),labelRank=edgeLabel.labelRank;if(wRank===vRank+1)return;g.removeEdge(e);var dummy,attrs,i;for(i=0,++vRank;vRank<wRank;++i,++vRank){edgeLabel.points=[];attrs={width:0,height:0,edgeLabel:edgeLabel,edgeObj:e,rank:vRank};dummy=util.addDummyNode(g,"edge",attrs,"_d");if(vRank===labelRank){attrs.width=edgeLabel.width;attrs.height=edgeLabel.height;attrs.dummy="edge-label";attrs.labelpos=edgeLabel.labelpos}g.setEdge(v,dummy,{weight:edgeLabel.weight},name);if(i===0){g.graph().dummyChains.push(dummy)}v=dummy}g.setEdge(v,w,{weight:edgeLabel.weight},name)}function undo(g){_.each(g.graph().dummyChains,function(v){var node=g.node(v),origLabel=node.edgeLabel,w;g.setEdge(node.edgeObj,origLabel);while(node.dummy){w=g.successors(v)[0];g.removeNode(v);origLabel.points.push({x:node.x,y:node.y});if(node.dummy==="edge-label"){origLabel.x=node.x;origLabel.y=node.y;origLabel.width=node.width;origLabel.height=node.height}v=w;node=g.node(v)}})}},{"./lodash":10,"./util":29}],13:[function(require,module,exports){var _=require("../lodash");module.exports=addSubgraphConstraints;function addSubgraphConstraints(g,cg,vs){var prev={},rootPrev;_.each(vs,function(v){var child=g.parent(v),parent,prevChild;while(child){parent=g.parent(child);if(parent){prevChild=prev[parent];prev[parent]=child}else{prevChild=rootPrev;rootPrev=child}if(prevChild&&prevChild!==child){cg.setEdge(prevChild,child);return}child=parent}})}},{"../lodash":10}],14:[function(require,module,exports){var _=require("../lodash");module.exports=barycenter;function barycenter(g,movable){return _.map(movable,function(v){var inV=g.inEdges(v);if(!inV.length){return{v:v}}else{var result=_.reduce(inV,function(acc,e){var edge=g.edge(e),nodeU=g.node(e.v);return{sum:acc.sum+edge.weight*nodeU.order,weight:acc.weight+edge.weight}},{sum:0,weight:0});return{v:v,barycenter:result.sum/result.weight,weight:result.weight}}})}},{"../lodash":10}],15:[function(require,module,exports){var _=require("../lodash"),Graph=require("../graphlib").Graph;module.exports=buildLayerGraph;function buildLayerGraph(g,rank,relationship){var root=createRootNode(g),result=new Graph({compound:true}).setGraph({root:root}).setDefaultNodeLabel(function(v){return g.node(v)});_.each(g.nodes(),function(v){var node=g.node(v),parent=g.parent(v);if(node.rank===rank||node.minRank<=rank&&rank<=node.maxRank){result.setNode(v);result.setParent(v,parent||root);_.each(g[relationship](v),function(e){var u=e.v===v?e.w:e.v,edge=result.edge(u,v),weight=!_.isUndefined(edge)?edge.weight:0;result.setEdge(u,v,{weight:g.edge(e).weight+weight})});if(_.has(node,"minRank")){result.setNode(v,{borderLeft:node.borderLeft[rank],borderRight:node.borderRight[rank]})}}});return result}function createRootNode(g){var v;while(g.hasNode(v=_.uniqueId("_root")));return v}},{"../graphlib":7,"../lodash":10}],16:[function(require,module,exports){"use strict";var _=require("../lodash");module.exports=crossCount;function crossCount(g,layering){var cc=0;for(var i=1;i<layering.length;++i){cc+=twoLayerCrossCount(g,layering[i-1],layering[i])}return cc}function twoLayerCrossCount(g,northLayer,southLayer){var southPos=_.zipObject(southLayer,_.map(southLayer,function(v,i){return i}));var southEntries=_.flatten(_.map(northLayer,function(v){return _.chain(g.outEdges(v)).map(function(e){return{pos:southPos[e.w],weight:g.edge(e).weight}}).sortBy("pos").value()}),true);var firstIndex=1;while(firstIndex<southLayer.length)firstIndex<<=1;var treeSize=2*firstIndex-1;firstIndex-=1;var tree=_.map(new Array(treeSize),function(){return 0});var cc=0;_.each(southEntries.forEach(function(entry){var index=entry.pos+firstIndex;tree[index]+=entry.weight;var weightSum=0;while(index>0){if(index%2){weightSum+=tree[index+1]}index=index-1>>1;tree[index]+=entry.weight}cc+=entry.weight*weightSum}));return cc}},{"../lodash":10}],17:[function(require,module,exports){"use strict";var _=require("../lodash"),initOrder=require("./init-order"),crossCount=require("./cross-count"),sortSubgraph=require("./sort-subgraph"),buildLayerGraph=require("./build-layer-graph"),addSubgraphConstraints=require("./add-subgraph-constraints"),Graph=require("../graphlib").Graph,util=require("../util");module.exports=order;function order(g){var maxRank=util.maxRank(g),downLayerGraphs=buildLayerGraphs(g,_.range(1,maxRank+1),"inEdges"),upLayerGraphs=buildLayerGraphs(g,_.range(maxRank-1,-1,-1),"outEdges");var layering=initOrder(g);assignOrder(g,layering);var bestCC=Number.POSITIVE_INFINITY,best;for(var i=0,lastBest=0;lastBest<4;++i,++lastBest){sweepLayerGraphs(i%2?downLayerGraphs:upLayerGraphs,i%4>=2);layering=util.buildLayerMatrix(g);var cc=crossCount(g,layering);if(cc<bestCC){lastBest=0;best=_.cloneDeep(layering);bestCC=cc}}assignOrder(g,best)}function buildLayerGraphs(g,ranks,relationship){return _.map(ranks,function(rank){return buildLayerGraph(g,rank,relationship)})}function sweepLayerGraphs(layerGraphs,biasRight){var cg=new Graph;_.each(layerGraphs,function(lg){var root=lg.graph().root;var sorted=sortSubgraph(lg,root,cg,biasRight);_.each(sorted.vs,function(v,i){lg.node(v).order=i});addSubgraphConstraints(lg,cg,sorted.vs)})}function assignOrder(g,layering){_.each(layering,function(layer){_.each(layer,function(v,i){g.node(v).order=i})})}},{"../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){"use strict";var _=require("../lodash");module.exports=initOrder;function initOrder(g){var visited={},simpleNodes=_.filter(g.nodes(),function(v){return!g.children(v).length}),maxRank=_.max(_.map(simpleNodes,function(v){return g.node(v).rank})),layers=_.map(_.range(maxRank+1),function(){return[]});function dfs(v){if(_.has(visited,v))return;visited[v]=true;var node=g.node(v);layers[node.rank].push(v);_.each(g.successors(v),dfs)}var orderedVs=_.sortBy(simpleNodes,function(v){return g.node(v).rank});_.each(orderedVs,dfs);return layers}},{"../lodash":10}],19:[function(require,module,exports){"use strict";var _=require("../lodash");module.exports=resolveConflicts;function resolveConflicts(entries,cg){var mappedEntries={};_.each(entries,function(entry,i){var tmp=mappedEntries[entry.v]={indegree:0,"in":[],out:[],vs:[entry.v],i:i};if(!_.isUndefined(entry.barycenter)){tmp.barycenter=entry.barycenter;tmp.weight=entry.weight}});_.each(cg.edges(),function(e){var entryV=mappedEntries[e.v],entryW=mappedEntries[e.w];if(!_.isUndefined(entryV)&&!_.isUndefined(entryW)){entryW.indegree++;entryV.out.push(mappedEntries[e.w])}});var sourceSet=_.filter(mappedEntries,function(entry){return!entry.indegree});return doResolveConflicts(sourceSet)}function doResolveConflicts(sourceSet){var entries=[];function handleIn(vEntry){return function(uEntry){if(uEntry.merged){return}if(_.isUndefined(uEntry.barycenter)||_.isUndefined(vEntry.barycenter)||uEntry.barycenter>=vEntry.barycenter){mergeEntries(vEntry,uEntry)}}}function handleOut(vEntry){return function(wEntry){wEntry["in"].push(vEntry);if(--wEntry.indegree===0){sourceSet.push(wEntry)}}}while(sourceSet.length){var entry=sourceSet.pop();entries.push(entry);_.each(entry["in"].reverse(),handleIn(entry));_.each(entry.out,handleOut(entry))}return _.chain(entries).filter(function(entry){return!entry.merged}).map(function(entry){return _.pick(entry,["vs","i","barycenter","weight"])}).value()}function mergeEntries(target,source){var sum=0,weight=0;if(target.weight){sum+=target.barycenter*target.weight;weight+=target.weight}if(source.weight){sum+=source.barycenter*source.weight;weight+=source.weight}target.vs=source.vs.concat(target.vs);target.barycenter=sum/weight;target.weight=weight;target.i=Math.min(source.i,target.i);source.merged=true}},{"../lodash":10}],20:[function(require,module,exports){var _=require("../lodash"),barycenter=require("./barycenter"),resolveConflicts=require("./resolve-conflicts"),sort=require("./sort");module.exports=sortSubgraph;function sortSubgraph(g,v,cg,biasRight){var movable=g.children(v),node=g.node(v),bl=node?node.borderLeft:undefined,br=node?node.borderRight:undefined,subgraphs={};if(bl){movable=_.filter(movable,function(w){return w!==bl&&w!==br})}var barycenters=barycenter(g,movable);_.each(barycenters,function(entry){if(g.children(entry.v).length){var subgraphResult=sortSubgraph(g,entry.v,cg,biasRight);subgraphs[entry.v]=subgraphResult;if(_.has(subgraphResult,"barycenter")){mergeBarycenters(entry,subgraphResult)}}});var entries=resolveConflicts(barycenters,cg);expandSubgraphs(entries,subgraphs);var result=sort(entries,biasRight);if(bl){result.vs=_.flatten([bl,result.vs,br],true);if(g.predecessors(bl).length){var blPred=g.node(g.predecessors(bl)[0]),brPred=g.node(g.predecessors(br)[0]);if(!_.has(result,"barycenter")){result.barycenter=0;result.weight=0}result.barycenter=(result.barycenter*result.weight+blPred.order+brPred.order)/(result.weight+2);result.weight+=2}}return result}function expandSubgraphs(entries,subgraphs){_.each(entries,function(entry){entry.vs=_.flatten(entry.vs.map(function(v){if(subgraphs[v]){return subgraphs[v].vs}return v}),true)})}function mergeBarycenters(target,other){if(!_.isUndefined(target.barycenter)){target.barycenter=(target.barycenter*target.weight+other.barycenter*other.weight)/(target.weight+other.weight);target.weight+=other.weight}else{target.barycenter=other.barycenter;target.weight=other.weight}}},{"../lodash":10,"./barycenter":14,"./resolve-conflicts":19,"./sort":21}],21:[function(require,module,exports){var _=require("../lodash"),util=require("../util");module.exports=sort;function sort(entries,biasRight){var parts=util.partition(entries,function(entry){return _.has(entry,"barycenter")});var sortable=parts.lhs,unsortable=_.sortBy(parts.rhs,function(entry){return-entry.i}),vs=[],sum=0,weight=0,vsIndex=0;sortable.sort(compareWithBias(!!biasRight));vsIndex=consumeUnsortable(vs,unsortable,vsIndex);_.each(sortable,function(entry){vsIndex+=entry.vs.length;vs.push(entry.vs);sum+=entry.barycenter*entry.weight;weight+=entry.weight;vsIndex=consumeUnsortable(vs,unsortable,vsIndex)});var result={vs:_.flatten(vs,true)};if(weight){result.barycenter=sum/weight;result.weight=weight}return result}function consumeUnsortable(vs,unsortable,index){var last;while(unsortable.length&&(last=_.last(unsortable)).i<=index){unsortable.pop();vs.push(last.vs);index++}return index}function compareWithBias(bias){return function(entryV,entryW){if(entryV.barycenter<entryW.barycenter){return-1}else if(entryV.barycenter>entryW.barycenter){return 1}return!bias?entryV.i-entryW.i:entryW.i-entryV.i}}},{"../lodash":10,"../util":29}],22:[function(require,module,exports){var _=require("./lodash");module.exports=parentDummyChains;function parentDummyChains(g){var postorderNums=postorder(g);_.each(g.graph().dummyChains,function(v){var node=g.node(v),edgeObj=node.edgeObj,pathData=findPath(g,postorderNums,edgeObj.v,edgeObj.w),path=pathData.path,lca=pathData.lca,pathIdx=0,pathV=path[pathIdx],ascending=true;while(v!==edgeObj.w){node=g.node(v);if(ascending){while((pathV=path[pathIdx])!==lca&&g.node(pathV).maxRank<node.rank){pathIdx++}if(pathV===lca){ascending=false}}if(!ascending){while(pathIdx<path.length-1&&g.node(pathV=path[pathIdx+1]).minRank<=node.rank){pathIdx++}pathV=path[pathIdx]}g.setParent(v,pathV);v=g.successors(v)[0]}})}function findPath(g,postorderNums,v,w){var vPath=[],wPath=[],low=Math.min(postorderNums[v].low,postorderNums[w].low),lim=Math.max(postorderNums[v].lim,postorderNums[w].lim),parent,lca;parent=v;do{parent=g.parent(parent);vPath.push(parent)}while(parent&&(postorderNums[parent].low>low||lim>postorderNums[parent].lim));lca=parent;parent=w;while((parent=g.parent(parent))!==lca){wPath.push(parent)}return{path:vPath.concat(wPath.reverse()),lca:lca}}function postorder(g){var result={},lim=0;function dfs(v){var low=lim;_.each(g.children(v),dfs);result[v]={low:low,lim:lim++}}_.each(g.children(),dfs);return result}},{"./lodash":10}],23:[function(require,module,exports){"use strict";var _=require("../lodash"),Graph=require("../graphlib").Graph,util=require("../util");module.exports={positionX:positionX,findType1Conflicts:findType1Conflicts,findType2Conflicts:findType2Conflicts,addConflict:addConflict,hasConflict:hasConflict,verticalAlignment:verticalAlignment,horizontalCompaction:horizontalCompaction,alignCoordinates:alignCoordinates,findSmallestWidthAlignment:findSmallestWidthAlignment,balance:balance};function findType1Conflicts(g,layering){var conflicts={};function visitLayer(prevLayer,layer){var k0=0,scanPos=0,prevLayerLength=prevLayer.length,lastNode=_.last(layer);_.each(layer,function(v,i){var w=findOtherInnerSegmentNode(g,v),k1=w?g.node(w).order:prevLayerLength;if(w||v===lastNode){_.each(layer.slice(scanPos,i+1),function(scanNode){_.each(g.predecessors(scanNode),function(u){var uLabel=g.node(u),uPos=uLabel.order;
+if((uPos<k0||k1<uPos)&&!(uLabel.dummy&&g.node(scanNode).dummy)){addConflict(conflicts,u,scanNode)}})});scanPos=i+1;k0=k1}});return layer}_.reduce(layering,visitLayer);return conflicts}function findType2Conflicts(g,layering){var conflicts={};function scan(south,southPos,southEnd,prevNorthBorder,nextNorthBorder){var v;_.each(_.range(southPos,southEnd),function(i){v=south[i];if(g.node(v).dummy){_.each(g.predecessors(v),function(u){var uNode=g.node(u);if(uNode.dummy&&(uNode.order<prevNorthBorder||uNode.order>nextNorthBorder)){addConflict(conflicts,u,v)}})}})}function visitLayer(north,south){var prevNorthPos=-1,nextNorthPos,southPos=0;_.each(south,function(v,southLookahead){if(g.node(v).dummy==="border"){var predecessors=g.predecessors(v);if(predecessors.length){nextNorthPos=g.node(predecessors[0]).order;scan(south,southPos,southLookahead,prevNorthPos,nextNorthPos);southPos=southLookahead;prevNorthPos=nextNorthPos}}scan(south,southPos,south.length,nextNorthPos,north.length)});return south}_.reduce(layering,visitLayer);return conflicts}function findOtherInnerSegmentNode(g,v){if(g.node(v).dummy){return _.find(g.predecessors(v),function(u){return g.node(u).dummy})}}function addConflict(conflicts,v,w){if(v>w){var tmp=v;v=w;w=tmp}var conflictsV=conflicts[v];if(!conflictsV){conflicts[v]=conflictsV={}}conflictsV[w]=true}function hasConflict(conflicts,v,w){if(v>w){var tmp=v;v=w;w=tmp}return _.has(conflicts[v],w)}function verticalAlignment(g,layering,conflicts,neighborFn){var root={},align={},pos={};_.each(layering,function(layer){_.each(layer,function(v,order){root[v]=v;align[v]=v;pos[v]=order})});_.each(layering,function(layer){var prevIdx=-1;_.each(layer,function(v){var ws=neighborFn(v);if(ws.length){ws=_.sortBy(ws,function(w){return pos[w]});var mp=(ws.length-1)/2;for(var i=Math.floor(mp),il=Math.ceil(mp);i<=il;++i){var w=ws[i];if(align[v]===v&&prevIdx<pos[w]&&!hasConflict(conflicts,v,w)){align[w]=v;align[v]=root[v]=root[w];prevIdx=pos[w]}}}})});return{root:root,align:align}}function horizontalCompaction(g,layering,root,align,reverseSep){var xs={},blockG=buildBlockGraph(g,layering,root,reverseSep);var visited={};function pass1(v){if(!_.has(visited,v)){visited[v]=true;xs[v]=_.reduce(blockG.inEdges(v),function(max,e){pass1(e.v);return Math.max(max,xs[e.v]+blockG.edge(e))},0)}}_.each(blockG.nodes(),pass1);var borderType=reverseSep?"borderLeft":"borderRight";function pass2(v){if(visited[v]!==2){visited[v]++;var node=g.node(v);var min=_.reduce(blockG.outEdges(v),function(min,e){pass2(e.w);return Math.min(min,xs[e.w]-blockG.edge(e))},Number.POSITIVE_INFINITY);if(min!==Number.POSITIVE_INFINITY&&node.borderType!==borderType){xs[v]=Math.max(xs[v],min)}}}_.each(blockG.nodes(),pass2);_.each(align,function(v){xs[v]=xs[root[v]]});return xs}function buildBlockGraph(g,layering,root,reverseSep){var blockGraph=new Graph,graphLabel=g.graph(),sepFn=sep(graphLabel.nodesep,graphLabel.edgesep,reverseSep);_.each(layering,function(layer){var u;_.each(layer,function(v){var vRoot=root[v];blockGraph.setNode(vRoot);if(u){var uRoot=root[u],prevMax=blockGraph.edge(uRoot,vRoot);blockGraph.setEdge(uRoot,vRoot,Math.max(sepFn(g,v,u),prevMax||0))}u=v})});return blockGraph}function findSmallestWidthAlignment(g,xss){return _.min(xss,function(xs){var min=_.min(xs,function(x,v){return x-width(g,v)/2}),max=_.max(xs,function(x,v){return x+width(g,v)/2});return max-min})}function alignCoordinates(xss,alignTo){var alignToMin=_.min(alignTo),alignToMax=_.max(alignTo);_.each(["u","d"],function(vert){_.each(["l","r"],function(horiz){var alignment=vert+horiz,xs=xss[alignment],delta;if(xs===alignTo)return;delta=horiz==="l"?alignToMin-_.min(xs):alignToMax-_.max(xs);if(delta){xss[alignment]=_.mapValues(xs,function(x){return x+delta})}})})}function balance(xss,align){return _.mapValues(xss.ul,function(ignore,v){if(align){return xss[align.toLowerCase()][v]}else{var xs=_.sortBy(_.pluck(xss,v));return(xs[1]+xs[2])/2}})}function positionX(g){var layering=util.buildLayerMatrix(g),conflicts=_.merge(findType1Conflicts(g,layering),findType2Conflicts(g,layering));var xss={},adjustedLayering;_.each(["u","d"],function(vert){adjustedLayering=vert==="u"?layering:_.values(layering).reverse();_.each(["l","r"],function(horiz){if(horiz==="r"){adjustedLayering=_.map(adjustedLayering,function(inner){return _.values(inner).reverse()})}var neighborFn=_.bind(vert==="u"?g.predecessors:g.successors,g);var align=verticalAlignment(g,adjustedLayering,conflicts,neighborFn);var xs=horizontalCompaction(g,adjustedLayering,align.root,align.align,horiz==="r");if(horiz==="r"){xs=_.mapValues(xs,function(x){return-x})}xss[vert+horiz]=xs})});var smallestWidth=findSmallestWidthAlignment(g,xss);alignCoordinates(xss,smallestWidth);return balance(xss,g.graph().align)}function sep(nodeSep,edgeSep,reverseSep){return function(g,v,w){var vLabel=g.node(v),wLabel=g.node(w),sum=0,delta;sum+=vLabel.width/2;if(_.has(vLabel,"labelpos")){switch(vLabel.labelpos.toLowerCase()){case"l":delta=-vLabel.width/2;break;case"r":delta=vLabel.width/2;break}}if(delta){sum+=reverseSep?delta:-delta}delta=0;sum+=(vLabel.dummy?edgeSep:nodeSep)/2;sum+=(wLabel.dummy?edgeSep:nodeSep)/2;sum+=wLabel.width/2;if(_.has(wLabel,"labelpos")){switch(wLabel.labelpos.toLowerCase()){case"l":delta=wLabel.width/2;break;case"r":delta=-wLabel.width/2;break}}if(delta){sum+=reverseSep?delta:-delta}delta=0;return sum}}function width(g,v){return g.node(v).width}},{"../graphlib":7,"../lodash":10,"../util":29}],24:[function(require,module,exports){"use strict";var _=require("../lodash"),util=require("../util"),positionX=require("./bk").positionX;module.exports=position;function position(g){g=util.asNonCompoundGraph(g);positionY(g);_.each(positionX(g),function(x,v){g.node(v).x=x})}function positionY(g){var layering=util.buildLayerMatrix(g),rankSep=g.graph().ranksep,prevY=0;_.each(layering,function(layer){var maxHeight=_.max(_.map(layer,function(v){return g.node(v).height}));_.each(layer,function(v){g.node(v).y=prevY+maxHeight/2});prevY+=maxHeight+rankSep})}},{"../lodash":10,"../util":29,"./bk":23}],25:[function(require,module,exports){"use strict";var _=require("../lodash"),Graph=require("../graphlib").Graph,slack=require("./util").slack;module.exports=feasibleTree;function feasibleTree(g){var t=new Graph({directed:false});var start=g.nodes()[0],size=g.nodeCount();t.setNode(start,{});var edge,delta;while(tightTree(t,g)<size){edge=findMinSlackEdge(t,g);delta=t.hasNode(edge.v)?slack(g,edge):-slack(g,edge);shiftRanks(t,g,delta)}return t}function tightTree(t,g){function dfs(v){_.each(g.nodeEdges(v),function(e){var edgeV=e.v,w=v===edgeV?e.w:edgeV;if(!t.hasNode(w)&&!slack(g,e)){t.setNode(w,{});t.setEdge(v,w,{});dfs(w)}})}_.each(t.nodes(),dfs);return t.nodeCount()}function findMinSlackEdge(t,g){return _.min(g.edges(),function(e){if(t.hasNode(e.v)!==t.hasNode(e.w)){return slack(g,e)}})}function shiftRanks(t,g,delta){_.each(t.nodes(),function(v){g.node(v).rank+=delta})}},{"../graphlib":7,"../lodash":10,"./util":28}],26:[function(require,module,exports){"use strict";var rankUtil=require("./util"),longestPath=rankUtil.longestPath,feasibleTree=require("./feasible-tree"),networkSimplex=require("./network-simplex");module.exports=rank;function rank(g){switch(g.graph().ranker){case"network-simplex":networkSimplexRanker(g);break;case"tight-tree":tightTreeRanker(g);break;case"longest-path":longestPathRanker(g);break;default:networkSimplexRanker(g)}}var longestPathRanker=longestPath;function tightTreeRanker(g){longestPath(g);feasibleTree(g)}function networkSimplexRanker(g){networkSimplex(g)}},{"./feasible-tree":25,"./network-simplex":27,"./util":28}],27:[function(require,module,exports){"use strict";var _=require("../lodash"),feasibleTree=require("./feasible-tree"),slack=require("./util").slack,initRank=require("./util").longestPath,preorder=require("../graphlib").alg.preorder,postorder=require("../graphlib").alg.postorder,simplify=require("../util").simplify;module.exports=networkSimplex;networkSimplex.initLowLimValues=initLowLimValues;networkSimplex.initCutValues=initCutValues;networkSimplex.calcCutValue=calcCutValue;networkSimplex.leaveEdge=leaveEdge;networkSimplex.enterEdge=enterEdge;networkSimplex.exchangeEdges=exchangeEdges;function networkSimplex(g){g=simplify(g);initRank(g);var t=feasibleTree(g);initLowLimValues(t);initCutValues(t,g);var e,f;while(e=leaveEdge(t)){f=enterEdge(t,g,e);exchangeEdges(t,g,e,f)}}function initCutValues(t,g){var vs=postorder(t,t.nodes());vs=vs.slice(0,vs.length-1);_.each(vs,function(v){assignCutValue(t,g,v)})}function assignCutValue(t,g,child){var childLab=t.node(child),parent=childLab.parent;t.edge(child,parent).cutvalue=calcCutValue(t,g,child)}function calcCutValue(t,g,child){var childLab=t.node(child),parent=childLab.parent,childIsTail=true,graphEdge=g.edge(child,parent),cutValue=0;if(!graphEdge){childIsTail=false;graphEdge=g.edge(parent,child)}cutValue=graphEdge.weight;_.each(g.nodeEdges(child),function(e){var isOutEdge=e.v===child,other=isOutEdge?e.w:e.v;if(other!==parent){var pointsToHead=isOutEdge===childIsTail,otherWeight=g.edge(e).weight;cutValue+=pointsToHead?otherWeight:-otherWeight;if(isTreeEdge(t,child,other)){var otherCutValue=t.edge(child,other).cutvalue;cutValue+=pointsToHead?-otherCutValue:otherCutValue}}});return cutValue}function initLowLimValues(tree,root){if(arguments.length<2){root=tree.nodes()[0]}dfsAssignLowLim(tree,{},1,root)}function dfsAssignLowLim(tree,visited,nextLim,v,parent){var low=nextLim,label=tree.node(v);visited[v]=true;_.each(tree.neighbors(v),function(w){if(!_.has(visited,w)){nextLim=dfsAssignLowLim(tree,visited,nextLim,w,v)}});label.low=low;label.lim=nextLim++;if(parent){label.parent=parent}else{delete label.parent}return nextLim}function leaveEdge(tree){return _.find(tree.edges(),function(e){return tree.edge(e).cutvalue<0})}function enterEdge(t,g,edge){var v=edge.v,w=edge.w;if(!g.hasEdge(v,w)){v=edge.w;w=edge.v}var vLabel=t.node(v),wLabel=t.node(w),tailLabel=vLabel,flip=false;if(vLabel.lim>wLabel.lim){tailLabel=wLabel;flip=true}var candidates=_.filter(g.edges(),function(edge){return flip===isDescendant(t,t.node(edge.v),tailLabel)&&flip!==isDescendant(t,t.node(edge.w),tailLabel)});return _.min(candidates,function(edge){return slack(g,edge)})}function exchangeEdges(t,g,e,f){var v=e.v,w=e.w;t.removeEdge(v,w);t.setEdge(f.v,f.w,{});initLowLimValues(t);initCutValues(t,g);updateRanks(t,g)}function updateRanks(t,g){var root=_.find(t.nodes(),function(v){return!g.node(v).parent}),vs=preorder(t,root);vs=vs.slice(1);_.each(vs,function(v){var parent=t.node(v).parent,edge=g.edge(v,parent),flipped=false;if(!edge){edge=g.edge(parent,v);flipped=true}g.node(v).rank=g.node(parent).rank+(flipped?edge.minlen:-edge.minlen)})}function isTreeEdge(tree,u,v){return tree.hasEdge(u,v)}function isDescendant(tree,vLabel,rootLabel){return rootLabel.low<=vLabel.lim&&vLabel.lim<=rootLabel.lim}},{"../graphlib":7,"../lodash":10,"../util":29,"./feasible-tree":25,"./util":28}],28:[function(require,module,exports){"use strict";var _=require("../lodash");module.exports={longestPath:longestPath,slack:slack};function longestPath(g){var visited={};function dfs(v){var label=g.node(v);if(_.has(visited,v)){return label.rank}visited[v]=true;var rank=_.min(_.map(g.outEdges(v),function(e){return dfs(e.w)-g.edge(e).minlen}));if(rank===Number.POSITIVE_INFINITY){rank=0}return label.rank=rank}_.each(g.sources(),dfs)}function slack(g,e){return g.node(e.w).rank-g.node(e.v).rank-g.edge(e).minlen}},{"../lodash":10}],29:[function(require,module,exports){"use strict";var _=require("./lodash"),Graph=require("./graphlib").Graph;module.exports={addDummyNode:addDummyNode,simplify:simplify,asNonCompoundGraph:asNonCompoundGraph,successorWeights:successorWeights,predecessorWeights:predecessorWeights,intersectRect:intersectRect,buildLayerMatrix:buildLayerMatrix,normalizeRanks:normalizeRanks,removeEmptyRanks:removeEmptyRanks,addBorderNode:addBorderNode,maxRank:maxRank,partition:partition,time:time,notime:notime};function addDummyNode(g,type,attrs,name){var v;do{v=_.uniqueId(name)}while(g.hasNode(v));attrs.dummy=type;g.setNode(v,attrs);return v}function simplify(g){var simplified=(new Graph).setGraph(g.graph());_.each(g.nodes(),function(v){simplified.setNode(v,g.node(v))});_.each(g.edges(),function(e){var simpleLabel=simplified.edge(e.v,e.w)||{weight:0,minlen:1},label=g.edge(e);simplified.setEdge(e.v,e.w,{weight:simpleLabel.weight+label.weight,minlen:Math.max(simpleLabel.minlen,label.minlen)})});return simplified}function asNonCompoundGraph(g){var simplified=new Graph({multigraph:g.isMultigraph()}).setGraph(g.graph());_.each(g.nodes(),function(v){if(!g.children(v).length){simplified.setNode(v,g.node(v))}});_.each(g.edges(),function(e){simplified.setEdge(e,g.edge(e))});return simplified}function successorWeights(g){var weightMap=_.map(g.nodes(),function(v){var sucs={};_.each(g.outEdges(v),function(e){sucs[e.w]=(sucs[e.w]||0)+g.edge(e).weight});return sucs});return _.zipObject(g.nodes(),weightMap)}function predecessorWeights(g){var weightMap=_.map(g.nodes(),function(v){var preds={};_.each(g.inEdges(v),function(e){preds[e.v]=(preds[e.v]||0)+g.edge(e).weight});return preds});return _.zipObject(g.nodes(),weightMap)}function intersectRect(rect,point){var x=rect.x;var y=rect.y;var dx=point.x-x;var dy=point.y-y;var w=rect.width/2;var h=rect.height/2;if(!dx&&!dy){throw new Error("Not possible to find intersection inside of the rectangle")}var sx,sy;if(Math.abs(dy)*w>Math.abs(dx)*h){if(dy<0){h=-h}sx=h*dx/dy;sy=h}else{if(dx<0){w=-w}sx=w;sy=w*dy/dx}return{x:x+sx,y:y+sy}}function buildLayerMatrix(g){var layering=_.map(_.range(maxRank(g)+1),function(){return[]});_.each(g.nodes(),function(v){var node=g.node(v),rank=node.rank;if(!_.isUndefined(rank)){layering[rank][node.order]=v}});return layering}function normalizeRanks(g){var min=_.min(_.map(g.nodes(),function(v){return g.node(v).rank}));_.each(g.nodes(),function(v){var node=g.node(v);if(_.has(node,"rank")){node.rank-=min}})}function removeEmptyRanks(g){var offset=_.min(_.map(g.nodes(),function(v){return g.node(v).rank}));var layers=[];_.each(g.nodes(),function(v){var rank=g.node(v).rank-offset;if(!layers[rank]){layers[rank]=[]}layers[rank].push(v)});var delta=0,nodeRankFactor=g.graph().nodeRankFactor;_.each(layers,function(vs,i){if(_.isUndefined(vs)&&i%nodeRankFactor!==0){--delta}else if(delta){_.each(vs,function(v){g.node(v).rank+=delta})}})}function addBorderNode(g,prefix,rank,order){var node={width:0,height:0};if(arguments.length>=4){node.rank=rank;node.order=order}return addDummyNode(g,"border",node,prefix)}function maxRank(g){return _.max(_.map(g.nodes(),function(v){var rank=g.node(v).rank;if(!_.isUndefined(rank)){return rank}}))}function partition(collection,fn){var result={lhs:[],rhs:[]};_.each(collection,function(value){if(fn(value)){result.lhs.push(value)}else{result.rhs.push(value)}});return result}function time(name,fn){var start=_.now();try{return fn()}finally{console.log(name+" time: "+(_.now()-start)+"ms")}}function notime(name,fn){return fn()}},{"./graphlib":7,"./lodash":10}],30:[function(require,module,exports){module.exports="0.7.4"},{}],31:[function(require,module,exports){var lib=require("./lib");module.exports={Graph:lib.Graph,json:require("./lib/json"),alg:require("./lib/alg"),version:lib.version}},{"./lib":47,"./lib/alg":38,"./lib/json":48}],32:[function(require,module,exports){var _=require("../lodash");module.exports=components;function components(g){var visited={},cmpts=[],cmpt;function dfs(v){if(_.has(visited,v))return;visited[v]=true;cmpt.push(v);_.each(g.successors(v),dfs);_.each(g.predecessors(v),dfs)}_.each(g.nodes(),function(v){cmpt=[];dfs(v);if(cmpt.length){cmpts.push(cmpt)}});return cmpts}},{"../lodash":49}],33:[function(require,module,exports){var _=require("../lodash");module.exports=dfs;function dfs(g,vs,order){if(!_.isArray(vs)){vs=[vs]}var acc=[],visited={};_.each(vs,function(v){if(!g.hasNode(v)){throw new Error("Graph does not have node: "+v)}doDfs(g,v,order==="post",visited,acc)});return acc}function doDfs(g,v,postorder,visited,acc){if(!_.has(visited,v)){visited[v]=true;if(!postorder){acc.push(v)}_.each(g.neighbors(v),function(w){doDfs(g,w,postorder,visited,acc)});if(postorder){acc.push(v)}}}},{"../lodash":49}],34:[function(require,module,exports){var dijkstra=require("./dijkstra"),_=require("../lodash");module.exports=dijkstraAll;function dijkstraAll(g,weightFunc,edgeFunc){return _.transform(g.nodes(),function(acc,v){acc[v]=dijkstra(g,v,weightFunc,edgeFunc)},{})}},{"../lodash":49,"./dijkstra":35}],35:[function(require,module,exports){var _=require("../lodash"),PriorityQueue=require("../data/priority-queue");module.exports=dijkstra;var DEFAULT_WEIGHT_FUNC=_.constant(1);function dijkstra(g,source,weightFn,edgeFn){return runDijkstra(g,String(source),weightFn||DEFAULT_WEIGHT_FUNC,edgeFn||function(v){return g.outEdges(v)})}function runDijkstra(g,source,weightFn,edgeFn){var results={},pq=new PriorityQueue,v,vEntry;var updateNeighbors=function(edge){var w=edge.v!==v?edge.v:edge.w,wEntry=results[w],weight=weightFn(edge),distance=vEntry.distance+weight;if(weight<0){throw new Error("dijkstra does not allow negative edge weights. "+"Bad edge: "+edge+" Weight: "+weight)}if(distance<wEntry.distance){wEntry.distance=distance;wEntry.predecessor=v;pq.decrease(w,distance)}};g.nodes().forEach(function(v){var distance=v===source?0:Number.POSITIVE_INFINITY;results[v]={distance:distance};pq.add(v,distance)});while(pq.size()>0){v=pq.removeMin();vEntry=results[v];if(vEntry.distance===Number.POSITIVE_INFINITY){break}edgeFn(v).forEach(updateNeighbors)}return results}},{"../data/priority-queue":45,"../lodash":49}],36:[function(require,module,exports){var _=require("../lodash"),tarjan=require("./tarjan");module.exports=findCycles;function findCycles(g){return _.filter(tarjan(g),function(cmpt){return cmpt.length>1||cmpt.length===1&&g.hasEdge(cmpt[0],cmpt[0])})}},{"../lodash":49,"./tarjan":43}],37:[function(require,module,exports){var _=require("../lodash");module.exports=floydWarshall;var DEFAULT_WEIGHT_FUNC=_.constant(1);function floydWarshall(g,weightFn,edgeFn){return runFloydWarshall(g,weightFn||DEFAULT_WEIGHT_FUNC,edgeFn||function(v){return g.outEdges(v)})}function runFloydWarshall(g,weightFn,edgeFn){var results={},nodes=g.nodes();nodes.forEach(function(v){results[v]={};results[v][v]={distance:0};nodes.forEach(function(w){if(v!==w){results[v][w]={distance:Number.POSITIVE_INFINITY}}});edgeFn(v).forEach(function(edge){var w=edge.v===v?edge.w:edge.v,d=weightFn(edge);results[v][w]={distance:d,predecessor:v}})});nodes.forEach(function(k){var rowK=results[k];nodes.forEach(function(i){var rowI=results[i];nodes.forEach(function(j){var ik=rowI[k];var kj=rowK[j];var ij=rowI[j];var altDistance=ik.distance+kj.distance;if(altDistance<ij.distance){ij.distance=altDistance;ij.predecessor=kj.predecessor}})})});return results}},{"../lodash":49}],38:[function(require,module,exports){module.exports={components:require("./components"),dijkstra:require("./dijkstra"),dijkstraAll:require("./dijkstra-all"),findCycles:require("./find-cycles"),floydWarshall:require("./floyd-warshall"),isAcyclic:require("./is-acyclic"),postorder:require("./postorder"),preorder:require("./preorder"),prim:require("./prim"),tarjan:require("./tarjan"),topsort:require("./topsort")}},{"./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){var topsort=require("./topsort");module.exports=isAcyclic;function isAcyclic(g){try{topsort(g)}catch(e){if(e instanceof topsort.CycleException){return false}throw e}return true}},{"./topsort":44}],40:[function(require,module,exports){var dfs=require("./dfs");module.exports=postorder;function postorder(g,vs){return dfs(g,vs,"post")}},{"./dfs":33}],41:[function(require,module,exports){var dfs=require("./dfs");module.exports=preorder;function preorder(g,vs){return dfs(g,vs,"pre")}},{"./dfs":33}],42:[function(require,module,exports){var _=require("../lodash"),Graph=require("../graph"),PriorityQueue=require("../data/priority-queue");module.exports=prim;function prim(g,weightFunc){var result=new Graph,parents={},pq=new PriorityQueue,v;function updateNeighbors(edge){var w=edge.v===v?edge.w:edge.v,pri=pq.priority(w);if(pri!==undefined){var edgeWeight=weightFunc(edge);if(edgeWeight<pri){parents[w]=v;pq.decrease(w,edgeWeight)}}}if(g.nodeCount()===0){return result}_.each(g.nodes(),function(v){pq.add(v,Number.POSITIVE_INFINITY);result.setNode(v)});pq.decrease(g.nodes()[0],0);var init=false;while(pq.size()>0){v=pq.removeMin();if(_.has(parents,v)){result.setEdge(v,parents[v])}else if(init){throw new Error("Input graph is not connected: "+g)}else{init=true}g.nodeEdges(v).forEach(updateNeighbors)}return result}},{"../data/priority-queue":45,"../graph":46,"../lodash":49}],43:[function(require,module,exports){var _=require("../lodash");module.exports=tarjan;function tarjan(g){var index=0,stack=[],visited={},results=[];function dfs(v){var entry=visited[v]={onStack:true,lowlink:index,index:index++};stack.push(v);g.successors(v).forEach(function(w){if(!_.has(visited,w)){dfs(w);entry.lowlink=Math.min(entry.lowlink,visited[w].lowlink)}else if(visited[w].onStack){entry.lowlink=Math.min(entry.lowlink,visited[w].index)}});if(entry.lowlink===entry.index){var cmpt=[],w;do{w=stack.pop();visited[w].onStack=false;cmpt.push(w)}while(v!==w);results.push(cmpt)}}g.nodes().forEach(function(v){if(!_.has(visited,v)){dfs(v)}});return results}},{"../lodash":49}],44:[function(require,module,exports){var _=require("../lodash");module.exports=topsort;topsort.CycleException=CycleException;function topsort(g){var visited={},stack={},results=[];function visit(node){if(_.has(stack,node)){throw new CycleException}if(!_.has(visited,node)){stack[node]=true;visited[node]=true;_.each(g.predecessors(node),visit);delete stack[node];results.push(node)}}_.each(g.sinks(),visit);if(_.size(visited)!==g.nodeCount()){throw new CycleException}return results}function CycleException(){}},{"../lodash":49}],45:[function(require,module,exports){var _=require("../lodash");module.exports=PriorityQueue;function PriorityQueue(){this._arr=[];this._keyIndices={}}PriorityQueue.prototype.size=function(){return this._arr.length};PriorityQueue.prototype.keys=function(){return this._arr.map(function(x){return x.key})};PriorityQueue.prototype.has=function(key){return _.has(this._keyIndices,key)};PriorityQueue.prototype.priority=function(key){var index=this._keyIndices[key];if(index!==undefined){return this._arr[index].priority}};PriorityQueue.prototype.min=function(){if(this.size()===0){throw new Error("Queue underflow")}return this._arr[0].key};PriorityQueue.prototype.add=function(key,priority){var keyIndices=this._keyIndices;key=String(key);if(!_.has(keyIndices,key)){var arr=this._arr;var index=arr.length;keyIndices[key]=index;arr.push({key:key,priority:priority});this._decrease(index);return true}return false};PriorityQueue.prototype.removeMin=function(){this._swap(0,this._arr.length-1);var min=this._arr.pop();delete this._keyIndices[min.key];this._heapify(0);return min.key};PriorityQueue.prototype.decrease=function(key,priority){var index=this._keyIndices[key];if(priority>this._arr[index].priority){throw new Error("New priority is greater than current priority. "+"Key: "+key+" Old: "+this._arr[index].priority+" New: "+priority)}this._arr[index].priority=priority;this._decrease(index)};PriorityQueue.prototype._heapify=function(i){var arr=this._arr;var l=2*i,r=l+1,largest=i;if(l<arr.length){largest=arr[l].priority<arr[largest].priority?l:largest;if(r<arr.length){largest=arr[r].priority<arr[largest].priority?r:largest}if(largest!==i){this._swap(i,largest);this._heapify(largest)}}};PriorityQueue.prototype._decrease=function(index){var arr=this._arr;var priority=arr[index].priority;var parent;while(index!==0){parent=index>>1;if(arr[parent].priority<priority){break}this._swap(index,parent);index=parent}};PriorityQueue.prototype._swap=function(i,j){var arr=this._arr;var keyIndices=this._keyIndices;var origArrI=arr[i];var origArrJ=arr[j];arr[i]=origArrJ;arr[j]=origArrI;keyIndices[origArrJ.key]=i;keyIndices[origArrI.key]=j}},{"../lodash":49}],46:[function(require,module,exports){"use strict";var _=require("./lodash");module.exports=Graph;var DEFAULT_EDGE_NAME="\x00",GRAPH_NODE="\x00",EDGE_KEY_DELIM="";function Graph(opts){this._isDirected=_.has(opts,"directed")?opts.directed:true;this._isMultigraph=_.has(opts,"multigraph")?opts.multigraph:false;this._isCompound=_.has(opts,"compound")?opts.compound:false;this._label=undefined;this._defaultNodeLabelFn=_.constant(undefined);this._defaultEdgeLabelFn=_.constant(undefined);this._nodes={};if(this._isCompound){this._parent={};this._children={};this._children[GRAPH_NODE]={}}this._in={};this._preds={};this._out={};this._sucs={};this._edgeObjs={};this._edgeLabels={}}Graph.prototype._nodeCount=0;Graph.prototype._edgeCount=0;Graph.prototype.isDirected=function(){return this._isDirected};Graph.prototype.isMultigraph=function(){return this._isMultigraph};Graph.prototype.isCompound=function(){return this._isCompound};Graph.prototype.setGraph=function(label){this._label=label;return this};Graph.prototype.graph=function(){return this._label};Graph.prototype.setDefaultNodeLabel=function(newDefault){if(!_.isFunction(newDefault)){newDefault=_.constant(newDefault)}this._defaultNodeLabelFn=newDefault;return this};Graph.prototype.nodeCount=function(){return this._nodeCount};Graph.prototype.nodes=function(){return _.keys(this._nodes)};Graph.prototype.sources=function(){return _.filter(this.nodes(),function(v){return _.isEmpty(this._in[v])},this)};Graph.prototype.sinks=function(){return _.filter(this.nodes(),function(v){return _.isEmpty(this._out[v])},this)};Graph.prototype.setNodes=function(vs,value){var args=arguments;_.each(vs,function(v){if(args.length>1){this.setNode(v,value)}else{this.setNode(v)}},this);return this};Graph.prototype.setNode=function(v,value){if(_.has(this._nodes,v)){if(arguments.length>1){this._nodes[v]=value}return this}this._nodes[v]=arguments.length>1?value:this._defaultNodeLabelFn(v);if(this._isCompound){this._parent[v]=GRAPH_NODE;this._children[v]={};this._children[GRAPH_NODE][v]=true}this._in[v]={};this._preds[v]={};this._out[v]={};this._sucs[v]={};++this._nodeCount;return this};Graph.prototype.node=function(v){return this._nodes[v]};Graph.prototype.hasNode=function(v){return _.has(this._nodes,v)};Graph.prototype.removeNode=function(v){var self=this;if(_.has(this._nodes,v)){var removeEdge=function(e){self.removeEdge(self._edgeObjs[e])};delete this._nodes[v];if(this._isCompound){this._removeFromParentsChildList(v);delete this._parent[v];_.each(this.children(v),function(child){this.setParent(child)},this);delete this._children[v]}_.each(_.keys(this._in[v]),removeEdge);delete this._in[v];delete this._preds[v];_.each(_.keys(this._out[v]),removeEdge);delete this._out[v];delete this._sucs[v];--this._nodeCount}return this};Graph.prototype.setParent=function(v,parent){if(!this._isCompound){throw new Error("Cannot set parent in a non-compound graph")}if(_.isUndefined(parent)){parent=GRAPH_NODE}else{parent+="";for(var ancestor=parent;!_.isUndefined(ancestor);ancestor=this.parent(ancestor)){if(ancestor===v){throw new Error("Setting "+parent+" as parent of "+v+" would create create a cycle")}}this.setNode(parent)}this.setNode(v);this._removeFromParentsChildList(v);this._parent[v]=parent;this._children[parent][v]=true;return this};Graph.prototype._removeFromParentsChildList=function(v){delete this._children[this._parent[v]][v]};Graph.prototype.parent=function(v){if(this._isCompound){var parent=this._parent[v];if(parent!==GRAPH_NODE){return parent}}};Graph.prototype.children=function(v){if(_.isUndefined(v)){v=GRAPH_NODE}if(this._isCompound){var children=this._children[v];if(children){return _.keys(children)}}else if(v===GRAPH_NODE){return this.nodes()}else if(this.hasNode(v)){return[]}};Graph.prototype.predecessors=function(v){var predsV=this._preds[v];if(predsV){return _.keys(predsV)}};Graph.prototype.successors=function(v){var sucsV=this._sucs[v];if(sucsV){return _.keys(sucsV)}};Graph.prototype.neighbors=function(v){var preds=this.predecessors(v);if(preds){return _.union(preds,this.successors(v))}};Graph.prototype.setDefaultEdgeLabel=function(newDefault){if(!_.isFunction(newDefault)){newDefault=_.constant(newDefault)}this._defaultEdgeLabelFn=newDefault;return this};Graph.prototype.edgeCount=function(){return this._edgeCount};Graph.prototype.edges=function(){return _.values(this._edgeObjs)};Graph.prototype.setPath=function(vs,value){var self=this,args=arguments;_.reduce(vs,function(v,w){if(args.length>1){self.setEdge(v,w,value)}else{self.setEdge(v,w)}return w});return this};Graph.prototype.setEdge=function(){var v,w,name,value,valueSpecified=false;if(_.isPlainObject(arguments[0])){v=arguments[0].v;w=arguments[0].w;name=arguments[0].name;if(arguments.length===2){value=arguments[1];valueSpecified=true}}else{v=arguments[0];w=arguments[1];name=arguments[3];if(arguments.length>2){value=arguments[2];valueSpecified=true}}v=""+v;w=""+w;if(!_.isUndefined(name)){name=""+name}var e=edgeArgsToId(this._isDirected,v,w,name);if(_.has(this._edgeLabels,e)){if(valueSpecified){this._edgeLabels[e]=value}return this}if(!_.isUndefined(name)&&!this._isMultigraph){throw new Error("Cannot set a named edge when isMultigraph = false")}this.setNode(v);this.setNode(w);this._edgeLabels[e]=valueSpecified?value:this._defaultEdgeLabelFn(v,w,name);var edgeObj=edgeArgsToObj(this._isDirected,v,w,name);v=edgeObj.v;w=edgeObj.w;Object.freeze(edgeObj);this._edgeObjs[e]=edgeObj;incrementOrInitEntry(this._preds[w],v);incrementOrInitEntry(this._sucs[v],w);this._in[w][e]=edgeObj;this._out[v][e]=edgeObj;this._edgeCount++;return this};Graph.prototype.edge=function(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);return this._edgeLabels[e]};Graph.prototype.hasEdge=function(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name);return _.has(this._edgeLabels,e)};Graph.prototype.removeEdge=function(v,w,name){var e=arguments.length===1?edgeObjToId(this._isDirected,arguments[0]):edgeArgsToId(this._isDirected,v,w,name),edge=this._edgeObjs[e];if(edge){v=edge.v;w=edge.w;delete this._edgeLabels[e];delete this._edgeObjs[e];decrementOrRemoveEntry(this._preds[w],v);decrementOrRemoveEntry(this._sucs[v],w);delete this._in[w][e];delete this._out[v][e];this._edgeCount--}return this};Graph.prototype.inEdges=function(v,u){var inV=this._in[v];if(inV){var edges=_.values(inV);if(!u){return edges}return _.filter(edges,function(edge){return edge.v===u})}};Graph.prototype.outEdges=function(v,w){var outV=this._out[v];if(outV){var edges=_.values(outV);if(!w){return edges}return _.filter(edges,function(edge){return edge.w===w})}};Graph.prototype.nodeEdges=function(v,w){var inEdges=this.inEdges(v,w);if(inEdges){return inEdges.concat(this.outEdges(v,w))}};function incrementOrInitEntry(map,k){if(_.has(map,k)){map[k]++}else{map[k]=1}}function decrementOrRemoveEntry(map,k){if(!--map[k]){delete map[k]}}function edgeArgsToId(isDirected,v,w,name){if(!isDirected&&v>w){var tmp=v;v=w;w=tmp}return v+EDGE_KEY_DELIM+w+EDGE_KEY_DELIM+(_.isUndefined(name)?DEFAULT_EDGE_NAME:name)}function edgeArgsToObj(isDirected,v,w,name){if(!isDirected&&v>w){var tmp=v;v=w;w=tmp}var edgeObj={v:v,w:w};if(name){edgeObj.name=name}return edgeObj}function edgeObjToId(isDirected,edgeObj){return edgeArgsToId(isDirected,edgeObj.v,edgeObj.w,edgeObj.name)}},{"./lodash":49}],47:[function(require,module,exports){module.exports={Graph:require("./graph"),version:require("./version")}},{"./graph":46,"./version":50}],48:[function(require,module,exports){var _=require("./lodash"),Graph=require("./graph");module.exports={write:write,read:read};function write(g){var json={options:{directed:g.isDirected(),multigraph:g.isMultigraph(),compound:g.isCompound()},nodes:writeNodes(g),edges:writeEdges(g)};
+if(!_.isUndefined(g.graph())){json.value=_.clone(g.graph())}return json}function writeNodes(g){return _.map(g.nodes(),function(v){var nodeValue=g.node(v),parent=g.parent(v),node={v:v};if(!_.isUndefined(nodeValue)){node.value=nodeValue}if(!_.isUndefined(parent)){node.parent=parent}return node})}function writeEdges(g){return _.map(g.edges(),function(e){var edgeValue=g.edge(e),edge={v:e.v,w:e.w};if(!_.isUndefined(e.name)){edge.name=e.name}if(!_.isUndefined(edgeValue)){edge.value=edgeValue}return edge})}function read(json){var g=new Graph(json.options).setGraph(json.value);_.each(json.nodes,function(entry){g.setNode(entry.v,entry.value);if(entry.parent){g.setParent(entry.v,entry.parent)}});_.each(json.edges,function(entry){g.setEdge({v:entry.v,w:entry.w,name:entry.name},entry.value)});return g}},{"./graph":46,"./lodash":49}],49:[function(require,module,exports){module.exports=require(10)},{"/Users/cpettitt/projects/dagre/lib/lodash.js":10,lodash:51}],50:[function(require,module,exports){module.exports="1.0.5"},{}],51:[function(require,module,exports){(function(global){(function(){var undefined;var VERSION="3.10.0";var BIND_FLAG=1,BIND_KEY_FLAG=2,CURRY_BOUND_FLAG=4,CURRY_FLAG=8,CURRY_RIGHT_FLAG=16,PARTIAL_FLAG=32,PARTIAL_RIGHT_FLAG=64,ARY_FLAG=128,REARG_FLAG=256;var DEFAULT_TRUNC_LENGTH=30,DEFAULT_TRUNC_OMISSION="...";var HOT_COUNT=150,HOT_SPAN=16;var LARGE_ARRAY_SIZE=200;var LAZY_FILTER_FLAG=1,LAZY_MAP_FLAG=2;var FUNC_ERROR_TEXT="Expected a function";var PLACEHOLDER="__lodash_placeholder__";var argsTag="[object Arguments]",arrayTag="[object Array]",boolTag="[object Boolean]",dateTag="[object Date]",errorTag="[object Error]",funcTag="[object Function]",mapTag="[object Map]",numberTag="[object Number]",objectTag="[object Object]",regexpTag="[object RegExp]",setTag="[object Set]",stringTag="[object String]",weakMapTag="[object WeakMap]";var arrayBufferTag="[object ArrayBuffer]",float32Tag="[object Float32Array]",float64Tag="[object Float64Array]",int8Tag="[object Int8Array]",int16Tag="[object Int16Array]",int32Tag="[object Int32Array]",uint8Tag="[object Uint8Array]",uint8ClampedTag="[object Uint8ClampedArray]",uint16Tag="[object Uint16Array]",uint32Tag="[object Uint32Array]";var reEmptyStringLeading=/\b__p \+= '';/g,reEmptyStringMiddle=/\b(__p \+=) '' \+/g,reEmptyStringTrailing=/(__e\(.*?\)|\b__t\)) \+\n'';/g;var reEscapedHtml=/&(?:amp|lt|gt|quot|#39|#96);/g,reUnescapedHtml=/[&<>"'`]/g,reHasEscapedHtml=RegExp(reEscapedHtml.source),reHasUnescapedHtml=RegExp(reUnescapedHtml.source);var reEscape=/<%-([\s\S]+?)%>/g,reEvaluate=/<%([\s\S]+?)%>/g,reInterpolate=/<%=([\s\S]+?)%>/g;var reIsDeepProp=/\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,reIsPlainProp=/^\w*$/,rePropName=/[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;var reRegExpChars=/^[:!,]|[\\^$.*+?()[\]{}|\/]|(^[0-9a-fA-Fnrtuvx])|([\n\r\u2028\u2029])/g,reHasRegExpChars=RegExp(reRegExpChars.source);var reComboMark=/[\u0300-\u036f\ufe20-\ufe23]/g;var reEscapeChar=/\\(\\)?/g;var reEsTemplate=/\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;var reFlags=/\w*$/;var reHasHexPrefix=/^0[xX]/;var reIsHostCtor=/^\[object .+?Constructor\]$/;var reIsUint=/^\d+$/;var reLatin1=/[\xc0-\xd6\xd8-\xde\xdf-\xf6\xf8-\xff]/g;var reNoMatch=/($^)/;var reUnescapedString=/['\n\r\u2028\u2029\\]/g;var reWords=function(){var upper="[A-Z\\xc0-\\xd6\\xd8-\\xde]",lower="[a-z\\xdf-\\xf6\\xf8-\\xff]+";return RegExp(upper+"+(?="+upper+lower+")|"+upper+"?"+lower+"|"+upper+"+|[0-9]+","g")}();var contextProps=["Array","ArrayBuffer","Date","Error","Float32Array","Float64Array","Function","Int8Array","Int16Array","Int32Array","Math","Number","Object","RegExp","Set","String","_","clearTimeout","isFinite","parseFloat","parseInt","setTimeout","TypeError","Uint8Array","Uint8ClampedArray","Uint16Array","Uint32Array","WeakMap"];var templateCounter=-1;var typedArrayTags={};typedArrayTags[float32Tag]=typedArrayTags[float64Tag]=typedArrayTags[int8Tag]=typedArrayTags[int16Tag]=typedArrayTags[int32Tag]=typedArrayTags[uint8Tag]=typedArrayTags[uint8ClampedTag]=typedArrayTags[uint16Tag]=typedArrayTags[uint32Tag]=true;typedArrayTags[argsTag]=typedArrayTags[arrayTag]=typedArrayTags[arrayBufferTag]=typedArrayTags[boolTag]=typedArrayTags[dateTag]=typedArrayTags[errorTag]=typedArrayTags[funcTag]=typedArrayTags[mapTag]=typedArrayTags[numberTag]=typedArrayTags[objectTag]=typedArrayTags[regexpTag]=typedArrayTags[setTag]=typedArrayTags[stringTag]=typedArrayTags[weakMapTag]=false;var cloneableTags={};cloneableTags[argsTag]=cloneableTags[arrayTag]=cloneableTags[arrayBufferTag]=cloneableTags[boolTag]=cloneableTags[dateTag]=cloneableTags[float32Tag]=cloneableTags[float64Tag]=cloneableTags[int8Tag]=cloneableTags[int16Tag]=cloneableTags[int32Tag]=cloneableTags[numberTag]=cloneableTags[objectTag]=cloneableTags[regexpTag]=cloneableTags[stringTag]=cloneableTags[uint8Tag]=cloneableTags[uint8ClampedTag]=cloneableTags[uint16Tag]=cloneableTags[uint32Tag]=true;cloneableTags[errorTag]=cloneableTags[funcTag]=cloneableTags[mapTag]=cloneableTags[setTag]=cloneableTags[weakMapTag]=false;var deburredLetters={"À":"A","Á":"A","Â":"A","Ã":"A","Ä":"A","Å":"A","à":"a","á":"a","â":"a","ã":"a","ä":"a","å":"a","Ç":"C","ç":"c","Ð":"D","ð":"d","È":"E","É":"E","Ê":"E","Ë":"E","è":"e","é":"e","ê":"e","ë":"e","Ì":"I","Í":"I","Î":"I","Ï":"I","ì":"i","í":"i","î":"i","ï":"i","Ñ":"N","ñ":"n","Ò":"O","Ó":"O","Ô":"O","Õ":"O","Ö":"O","Ø":"O","ò":"o","ó":"o","ô":"o","õ":"o","ö":"o","ø":"o","Ù":"U","Ú":"U","Û":"U","Ü":"U","ù":"u","ú":"u","û":"u","ü":"u","Ý":"Y","ý":"y","ÿ":"y","Æ":"Ae","æ":"ae","Þ":"Th","þ":"th","ß":"ss"};var htmlEscapes={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","`":"&#96;"};var htmlUnescapes={"&amp;":"&","&lt;":"<","&gt;":">","&quot;":'"',"&#39;":"'","&#96;":"`"};var objectTypes={"function":true,object:true};var regexpEscapes={0:"x30",1:"x31",2:"x32",3:"x33",4:"x34",5:"x35",6:"x36",7:"x37",8:"x38",9:"x39",A:"x41",B:"x42",C:"x43",D:"x44",E:"x45",F:"x46",a:"x61",b:"x62",c:"x63",d:"x64",e:"x65",f:"x66",n:"x6e",r:"x72",t:"x74",u:"x75",v:"x76",x:"x78"};var stringEscapes={"\\":"\\","'":"'","\n":"n","\r":"r","\u2028":"u2028","\u2029":"u2029"};var freeExports=objectTypes[typeof exports]&&exports&&!exports.nodeType&&exports;var freeModule=objectTypes[typeof module]&&module&&!module.nodeType&&module;var freeGlobal=freeExports&&freeModule&&typeof global=="object"&&global&&global.Object&&global;var freeSelf=objectTypes[typeof self]&&self&&self.Object&&self;var freeWindow=objectTypes[typeof window]&&window&&window.Object&&window;var moduleExports=freeModule&&freeModule.exports===freeExports&&freeExports;var root=freeGlobal||freeWindow!==(this&&this.window)&&freeWindow||freeSelf||this;function baseCompareAscending(value,other){if(value!==other){var valIsNull=value===null,valIsUndef=value===undefined,valIsReflexive=value===value;var othIsNull=other===null,othIsUndef=other===undefined,othIsReflexive=other===other;if(value>other&&!othIsNull||!valIsReflexive||valIsNull&&!othIsUndef&&othIsReflexive||valIsUndef&&othIsReflexive){return 1}if(value<other&&!valIsNull||!othIsReflexive||othIsNull&&!valIsUndef&&valIsReflexive||othIsUndef&&valIsReflexive){return-1}}return 0}function baseFindIndex(array,predicate,fromRight){var length=array.length,index=fromRight?length:-1;while(fromRight?index--:++index<length){if(predicate(array[index],index,array)){return index}}return-1}function baseIndexOf(array,value,fromIndex){if(value!==value){return indexOfNaN(array,fromIndex)}var index=fromIndex-1,length=array.length;while(++index<length){if(array[index]===value){return index}}return-1}function baseIsFunction(value){return typeof value=="function"||false}function baseToString(value){return value==null?"":value+""}function charsLeftIndex(string,chars){var index=-1,length=string.length;while(++index<length&&chars.indexOf(string.charAt(index))>-1){}return index}function charsRightIndex(string,chars){var index=string.length;while(index--&&chars.indexOf(string.charAt(index))>-1){}return index}function compareAscending(object,other){return baseCompareAscending(object.criteria,other.criteria)||object.index-other.index}function compareMultiple(object,other,orders){var index=-1,objCriteria=object.criteria,othCriteria=other.criteria,length=objCriteria.length,ordersLength=orders.length;while(++index<length){var result=baseCompareAscending(objCriteria[index],othCriteria[index]);if(result){if(index>=ordersLength){return result}var order=orders[index];return result*(order==="asc"||order===true?1:-1)}}return object.index-other.index}function deburrLetter(letter){return deburredLetters[letter]}function escapeHtmlChar(chr){return htmlEscapes[chr]}function escapeRegExpChar(chr,leadingChar,whitespaceChar){if(leadingChar){chr=regexpEscapes[chr]}else if(whitespaceChar){chr=stringEscapes[chr]}return"\\"+chr}function escapeStringChar(chr){return"\\"+stringEscapes[chr]}function indexOfNaN(array,fromIndex,fromRight){var length=array.length,index=fromIndex+(fromRight?0:-1);while(fromRight?index--:++index<length){var other=array[index];if(other!==other){return index}}return-1}function isObjectLike(value){return!!value&&typeof value=="object"}function isSpace(charCode){return charCode<=160&&(charCode>=9&&charCode<=13)||charCode==32||charCode==160||charCode==5760||charCode==6158||charCode>=8192&&(charCode<=8202||charCode==8232||charCode==8233||charCode==8239||charCode==8287||charCode==12288||charCode==65279)}function replaceHolders(array,placeholder){var index=-1,length=array.length,resIndex=-1,result=[];while(++index<length){if(array[index]===placeholder){array[index]=PLACEHOLDER;result[++resIndex]=index}}return result}function sortedUniq(array,iteratee){var seen,index=-1,length=array.length,resIndex=-1,result=[];while(++index<length){var value=array[index],computed=iteratee?iteratee(value,index,array):value;if(!index||seen!==computed){seen=computed;result[++resIndex]=value}}return result}function trimmedLeftIndex(string){var index=-1,length=string.length;while(++index<length&&isSpace(string.charCodeAt(index))){}return index}function trimmedRightIndex(string){var index=string.length;while(index--&&isSpace(string.charCodeAt(index))){}return index}function unescapeHtmlChar(chr){return htmlUnescapes[chr]}function runInContext(context){context=context?_.defaults(root.Object(),context,_.pick(root,contextProps)):root;var Array=context.Array,Date=context.Date,Error=context.Error,Function=context.Function,Math=context.Math,Number=context.Number,Object=context.Object,RegExp=context.RegExp,String=context.String,TypeError=context.TypeError;var arrayProto=Array.prototype,objectProto=Object.prototype,stringProto=String.prototype;var fnToString=Function.prototype.toString;var hasOwnProperty=objectProto.hasOwnProperty;var idCounter=0;var objToString=objectProto.toString;var oldDash=root._;var reIsNative=RegExp("^"+fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g,"\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g,"$1.*?")+"$");var ArrayBuffer=context.ArrayBuffer,clearTimeout=context.clearTimeout,parseFloat=context.parseFloat,pow=Math.pow,propertyIsEnumerable=objectProto.propertyIsEnumerable,Set=getNative(context,"Set"),setTimeout=context.setTimeout,splice=arrayProto.splice,Uint8Array=context.Uint8Array,WeakMap=getNative(context,"WeakMap");var nativeCeil=Math.ceil,nativeCreate=getNative(Object,"create"),nativeFloor=Math.floor,nativeIsArray=getNative(Array,"isArray"),nativeIsFinite=context.isFinite,nativeKeys=getNative(Object,"keys"),nativeMax=Math.max,nativeMin=Math.min,nativeNow=getNative(Date,"now"),nativeParseInt=context.parseInt,nativeRandom=Math.random;var NEGATIVE_INFINITY=Number.NEGATIVE_INFINITY,POSITIVE_INFINITY=Number.POSITIVE_INFINITY;var MAX_ARRAY_LENGTH=4294967295,MAX_ARRAY_INDEX=MAX_ARRAY_LENGTH-1,HALF_MAX_ARRAY_LENGTH=MAX_ARRAY_LENGTH>>>1;var MAX_SAFE_INTEGER=9007199254740991;var metaMap=WeakMap&&new WeakMap;var realNames={};function lodash(value){if(isObjectLike(value)&&!isArray(value)&&!(value instanceof LazyWrapper)){if(value instanceof LodashWrapper){return value}if(hasOwnProperty.call(value,"__chain__")&&hasOwnProperty.call(value,"__wrapped__")){return wrapperClone(value)}}return new LodashWrapper(value)}function baseLodash(){}function LodashWrapper(value,chainAll,actions){this.__wrapped__=value;this.__actions__=actions||[];this.__chain__=!!chainAll}var support=lodash.support={};lodash.templateSettings={escape:reEscape,evaluate:reEvaluate,interpolate:reInterpolate,variable:"",imports:{_:lodash}};function LazyWrapper(value){this.__wrapped__=value;this.__actions__=[];this.__dir__=1;this.__filtered__=false;this.__iteratees__=[];this.__takeCount__=POSITIVE_INFINITY;this.__views__=[]}function lazyClone(){var result=new LazyWrapper(this.__wrapped__);result.__actions__=arrayCopy(this.__actions__);result.__dir__=this.__dir__;result.__filtered__=this.__filtered__;result.__iteratees__=arrayCopy(this.__iteratees__);result.__takeCount__=this.__takeCount__;result.__views__=arrayCopy(this.__views__);return result}function lazyReverse(){if(this.__filtered__){var result=new LazyWrapper(this);result.__dir__=-1;result.__filtered__=true}else{result=this.clone();result.__dir__*=-1}return result}function lazyValue(){var array=this.__wrapped__.value(),dir=this.__dir__,isArr=isArray(array),isRight=dir<0,arrLength=isArr?array.length:0,view=getView(0,arrLength,this.__views__),start=view.start,end=view.end,length=end-start,index=isRight?end:start-1,iteratees=this.__iteratees__,iterLength=iteratees.length,resIndex=0,takeCount=nativeMin(length,this.__takeCount__);if(!isArr||arrLength<LARGE_ARRAY_SIZE||arrLength==length&&takeCount==length){return baseWrapperValue(isRight&&isArr?array.reverse():array,this.__actions__)}var result=[];outer:while(length--&&resIndex<takeCount){index+=dir;var iterIndex=-1,value=array[index];while(++iterIndex<iterLength){var data=iteratees[iterIndex],iteratee=data.iteratee,type=data.type,computed=iteratee(value);if(type==LAZY_MAP_FLAG){value=computed}else if(!computed){if(type==LAZY_FILTER_FLAG){continue outer}else{break outer}}}result[resIndex++]=value}return result}function MapCache(){this.__data__={}}function mapDelete(key){return this.has(key)&&delete this.__data__[key]}function mapGet(key){return key=="__proto__"?undefined:this.__data__[key]}function mapHas(key){return key!="__proto__"&&hasOwnProperty.call(this.__data__,key)}function mapSet(key,value){if(key!="__proto__"){this.__data__[key]=value}return this}function SetCache(values){var length=values?values.length:0;this.data={hash:nativeCreate(null),set:new Set};while(length--){this.push(values[length])}}function cacheIndexOf(cache,value){var data=cache.data,result=typeof value=="string"||isObject(value)?data.set.has(value):data.hash[value];return result?0:-1}function cachePush(value){var data=this.data;if(typeof value=="string"||isObject(value)){data.set.add(value)}else{data.hash[value]=true}}function arrayConcat(array,other){var index=-1,length=array.length,othIndex=-1,othLength=other.length,result=Array(length+othLength);while(++index<length){result[index]=array[index]}while(++othIndex<othLength){result[index++]=other[othIndex]}return result}function arrayCopy(source,array){var index=-1,length=source.length;array||(array=Array(length));while(++index<length){array[index]=source[index]}return array}function arrayEach(array,iteratee){var index=-1,length=array.length;while(++index<length){if(iteratee(array[index],index,array)===false){break}}return array}function arrayEachRight(array,iteratee){var length=array.length;while(length--){if(iteratee(array[length],length,array)===false){break}}return array}function arrayEvery(array,predicate){var index=-1,length=array.length;while(++index<length){if(!predicate(array[index],index,array)){return false}}return true}function arrayExtremum(array,iteratee,comparator,exValue){var index=-1,length=array.length,computed=exValue,result=computed;while(++index<length){var value=array[index],current=+iteratee(value);if(comparator(current,computed)){computed=current;result=value}}return result}function arrayFilter(array,predicate){var index=-1,length=array.length,resIndex=-1,result=[];while(++index<length){var value=array[index];if(predicate(value,index,array)){result[++resIndex]=value}}return result}function arrayMap(array,iteratee){var index=-1,length=array.length,result=Array(length);while(++index<length){result[index]=iteratee(array[index],index,array)}return result}function arrayPush(array,values){var index=-1,length=values.length,offset=array.length;while(++index<length){array[offset+index]=values[index]}return array}function arrayReduce(array,iteratee,accumulator,initFromArray){var index=-1,length=array.length;if(initFromArray&&length){accumulator=array[++index]}while(++index<length){accumulator=iteratee(accumulator,array[index],index,array)}return accumulator}function arrayReduceRight(array,iteratee,accumulator,initFromArray){var length=array.length;if(initFromArray&&length){accumulator=array[--length]}while(length--){accumulator=iteratee(accumulator,array[length],length,array)}return accumulator}function arraySome(array,predicate){var index=-1,length=array.length;while(++index<length){if(predicate(array[index],index,array)){return true}}return false}function arraySum(array,iteratee){var length=array.length,result=0;while(length--){result+=+iteratee(array[length])||0}return result}function assignDefaults(objectValue,sourceValue){return objectValue===undefined?sourceValue:objectValue}function assignOwnDefaults(objectValue,sourceValue,key,object){return objectValue===undefined||!hasOwnProperty.call(object,key)?sourceValue:objectValue}function assignWith(object,source,customizer){var index=-1,props=keys(source),length=props.length;while(++index<length){var key=props[index],value=object[key],result=customizer(value,source[key],key,object,source);if((result===result?result!==value:value===value)||value===undefined&&!(key in object)){object[key]=result}}return object}function baseAssign(object,source){return source==null?object:baseCopy(source,keys(source),object)}function baseAt(collection,props){var index=-1,isNil=collection==null,isArr=!isNil&&isArrayLike(collection),length=isArr?collection.length:0,propsLength=props.length,result=Array(propsLength);while(++index<propsLength){var key=props[index];if(isArr){result[index]=isIndex(key,length)?collection[key]:undefined}else{result[index]=isNil?undefined:collection[key]}}return result}function baseCopy(source,props,object){object||(object={});var index=-1,length=props.length;while(++index<length){var key=props[index];object[key]=source[key]}return object}function baseCallback(func,thisArg,argCount){var type=typeof func;if(type=="function"){return thisArg===undefined?func:bindCallback(func,thisArg,argCount)}if(func==null){return identity}if(type=="object"){return baseMatches(func)}return thisArg===undefined?property(func):baseMatchesProperty(func,thisArg)}function baseClone(value,isDeep,customizer,key,object,stackA,stackB){var result;if(customizer){result=object?customizer(value,key,object):customizer(value)}if(result!==undefined){return result}if(!isObject(value)){return value}var isArr=isArray(value);if(isArr){result=initCloneArray(value);if(!isDeep){return arrayCopy(value,result)}}else{var tag=objToString.call(value),isFunc=tag==funcTag;if(tag==objectTag||tag==argsTag||isFunc&&!object){result=initCloneObject(isFunc?{}:value);if(!isDeep){return baseAssign(result,value)}}else{return cloneableTags[tag]?initCloneByTag(value,tag,isDeep):object?value:{}}}stackA||(stackA=[]);stackB||(stackB=[]);var length=stackA.length;while(length--){if(stackA[length]==value){return stackB[length]}}stackA.push(value);stackB.push(result);(isArr?arrayEach:baseForOwn)(value,function(subValue,key){result[key]=baseClone(subValue,isDeep,customizer,key,value,stackA,stackB)});return result}var baseCreate=function(){function object(){}return function(prototype){if(isObject(prototype)){object.prototype=prototype;var result=new object;object.prototype=undefined}return result||{}}}();function baseDelay(func,wait,args){if(typeof func!="function"){throw new TypeError(FUNC_ERROR_TEXT)}return setTimeout(function(){func.apply(undefined,args)},wait)}function baseDifference(array,values){var length=array?array.length:0,result=[];if(!length){return result}var index=-1,indexOf=getIndexOf(),isCommon=indexOf==baseIndexOf,cache=isCommon&&values.length>=LARGE_ARRAY_SIZE?createCache(values):null,valuesLength=values.length;if(cache){indexOf=cacheIndexOf;isCommon=false;values=cache}outer:while(++index<length){var value=array[index];if(isCommon&&value===value){var valuesIndex=valuesLength;while(valuesIndex--){if(values[valuesIndex]===value){continue outer}}result.push(value)}else if(indexOf(values,value,0)<0){result.push(value)}}return result}var baseEach=createBaseEach(baseForOwn);var baseEachRight=createBaseEach(baseForOwnRight,true);function baseEvery(collection,predicate){var result=true;baseEach(collection,function(value,index,collection){result=!!predicate(value,index,collection);return result});return result}function baseExtremum(collection,iteratee,comparator,exValue){var computed=exValue,result=computed;baseEach(collection,function(value,index,collection){var current=+iteratee(value,index,collection);if(comparator(current,computed)||current===exValue&&current===result){computed=current;result=value}});return result}function baseFill(array,value,start,end){var length=array.length;start=start==null?0:+start||0;if(start<0){start=-start>length?0:length+start}end=end===undefined||end>length?length:+end||0;if(end<0){end+=length}length=start>end?0:end>>>0;start>>>=0;while(start<length){array[start++]=value}return array}function baseFilter(collection,predicate){var result=[];baseEach(collection,function(value,index,collection){if(predicate(value,index,collection)){result.push(value)}});return result}function baseFind(collection,predicate,eachFunc,retKey){var result;eachFunc(collection,function(value,key,collection){if(predicate(value,key,collection)){result=retKey?key:value;return false}});return result}function baseFlatten(array,isDeep,isStrict,result){result||(result=[]);var index=-1,length=array.length;while(++index<length){var value=array[index];if(isObjectLike(value)&&isArrayLike(value)&&(isStrict||isArray(value)||isArguments(value))){if(isDeep){baseFlatten(value,isDeep,isStrict,result)}else{arrayPush(result,value)}}else if(!isStrict){result[result.length]=value}}return result}var baseFor=createBaseFor();var baseForRight=createBaseFor(true);function baseForIn(object,iteratee){return baseFor(object,iteratee,keysIn)}function baseForOwn(object,iteratee){return baseFor(object,iteratee,keys)}function baseForOwnRight(object,iteratee){return baseForRight(object,iteratee,keys)}function baseFunctions(object,props){var index=-1,length=props.length,resIndex=-1,result=[];while(++index<length){var key=props[index];if(isFunction(object[key])){result[++resIndex]=key}}return result}function baseGet(object,path,pathKey){if(object==null){return}if(pathKey!==undefined&&pathKey in toObject(object)){path=[pathKey]}var index=0,length=path.length;while(object!=null&&index<length){object=object[path[index++]]}return index&&index==length?object:undefined}function baseIsEqual(value,other,customizer,isLoose,stackA,stackB){if(value===other){return true}if(value==null||other==null||!isObject(value)&&!isObjectLike(other)){return value!==value&&other!==other}return baseIsEqualDeep(value,other,baseIsEqual,customizer,isLoose,stackA,stackB)}function baseIsEqualDeep(object,other,equalFunc,customizer,isLoose,stackA,stackB){var objIsArr=isArray(object),othIsArr=isArray(other),objTag=arrayTag,othTag=arrayTag;if(!objIsArr){objTag=objToString.call(object);if(objTag==argsTag){objTag=objectTag}else if(objTag!=objectTag){objIsArr=isTypedArray(object)}}if(!othIsArr){othTag=objToString.call(other);if(othTag==argsTag){othTag=objectTag}else if(othTag!=objectTag){othIsArr=isTypedArray(other)}}var objIsObj=objTag==objectTag,othIsObj=othTag==objectTag,isSameTag=objTag==othTag;if(isSameTag&&!(objIsArr||objIsObj)){return equalByTag(object,other,objTag)}if(!isLoose){var objIsWrapped=objIsObj&&hasOwnProperty.call(object,"__wrapped__"),othIsWrapped=othIsObj&&hasOwnProperty.call(other,"__wrapped__");if(objIsWrapped||othIsWrapped){return equalFunc(objIsWrapped?object.value():object,othIsWrapped?other.value():other,customizer,isLoose,stackA,stackB)}}if(!isSameTag){return false}stackA||(stackA=[]);stackB||(stackB=[]);var length=stackA.length;while(length--){if(stackA[length]==object){return stackB[length]==other}}stackA.push(object);stackB.push(other);var result=(objIsArr?equalArrays:equalObjects)(object,other,equalFunc,customizer,isLoose,stackA,stackB);stackA.pop();stackB.pop();return result}function baseIsMatch(object,matchData,customizer){var index=matchData.length,length=index,noCustomizer=!customizer;if(object==null){return!length}object=toObject(object);while(index--){var data=matchData[index];if(noCustomizer&&data[2]?data[1]!==object[data[0]]:!(data[0]in object)){return false}}while(++index<length){data=matchData[index];var key=data[0],objValue=object[key],srcValue=data[1];if(noCustomizer&&data[2]){if(objValue===undefined&&!(key in object)){return false}}else{var result=customizer?customizer(objValue,srcValue,key):undefined;if(!(result===undefined?baseIsEqual(srcValue,objValue,customizer,true):result)){return false}}}return true}function baseMap(collection,iteratee){var index=-1,result=isArrayLike(collection)?Array(collection.length):[];baseEach(collection,function(value,key,collection){result[++index]=iteratee(value,key,collection)});return result}function baseMatches(source){var matchData=getMatchData(source);if(matchData.length==1&&matchData[0][2]){var key=matchData[0][0],value=matchData[0][1];return function(object){if(object==null){return false}return object[key]===value&&(value!==undefined||key in toObject(object))}}return function(object){return baseIsMatch(object,matchData)}}function baseMatchesProperty(path,srcValue){var isArr=isArray(path),isCommon=isKey(path)&&isStrictComparable(srcValue),pathKey=path+"";path=toPath(path);return function(object){if(object==null){return false}var key=pathKey;object=toObject(object);if((isArr||!isCommon)&&!(key in object)){object=path.length==1?object:baseGet(object,baseSlice(path,0,-1));if(object==null){return false}key=last(path);object=toObject(object)}return object[key]===srcValue?srcValue!==undefined||key in object:baseIsEqual(srcValue,object[key],undefined,true)}}function baseMerge(object,source,customizer,stackA,stackB){if(!isObject(object)){return object}var isSrcArr=isArrayLike(source)&&(isArray(source)||isTypedArray(source)),props=isSrcArr?undefined:keys(source);arrayEach(props||source,function(srcValue,key){if(props){key=srcValue;srcValue=source[key]}if(isObjectLike(srcValue)){stackA||(stackA=[]);stackB||(stackB=[]);baseMergeDeep(object,source,key,baseMerge,customizer,stackA,stackB)}else{var value=object[key],result=customizer?customizer(value,srcValue,key,object,source):undefined,isCommon=result===undefined;if(isCommon){result=srcValue}if((result!==undefined||isSrcArr&&!(key in object))&&(isCommon||(result===result?result!==value:value===value))){object[key]=result}}});return object}function baseMergeDeep(object,source,key,mergeFunc,customizer,stackA,stackB){var length=stackA.length,srcValue=source[key];while(length--){if(stackA[length]==srcValue){object[key]=stackB[length];return}}var value=object[key],result=customizer?customizer(value,srcValue,key,object,source):undefined,isCommon=result===undefined;if(isCommon){result=srcValue;if(isArrayLike(srcValue)&&(isArray(srcValue)||isTypedArray(srcValue))){result=isArray(value)?value:isArrayLike(value)?arrayCopy(value):[]}else if(isPlainObject(srcValue)||isArguments(srcValue)){result=isArguments(value)?toPlainObject(value):isPlainObject(value)?value:{}}else{isCommon=false}}stackA.push(srcValue);stackB.push(result);if(isCommon){object[key]=mergeFunc(result,srcValue,customizer,stackA,stackB)}else if(result===result?result!==value:value===value){object[key]=result}}function baseProperty(key){return function(object){return object==null?undefined:object[key]}}function basePropertyDeep(path){var pathKey=path+"";path=toPath(path);return function(object){return baseGet(object,path,pathKey)}}function basePullAt(array,indexes){var length=array?indexes.length:0;while(length--){var index=indexes[length];if(index!=previous&&isIndex(index)){var previous=index;splice.call(array,index,1)}}return array}function baseRandom(min,max){return min+nativeFloor(nativeRandom()*(max-min+1))}function baseReduce(collection,iteratee,accumulator,initFromCollection,eachFunc){eachFunc(collection,function(value,index,collection){accumulator=initFromCollection?(initFromCollection=false,value):iteratee(accumulator,value,index,collection)});return accumulator}var baseSetData=!metaMap?identity:function(func,data){metaMap.set(func,data);return func};function baseSlice(array,start,end){var index=-1,length=array.length;start=start==null?0:+start||0;if(start<0){start=-start>length?0:length+start}end=end===undefined||end>length?length:+end||0;if(end<0){end+=length}length=start>end?0:end-start>>>0;start>>>=0;var result=Array(length);while(++index<length){result[index]=array[index+start]}return result}function baseSome(collection,predicate){var result;baseEach(collection,function(value,index,collection){result=predicate(value,index,collection);return!result});return!!result}function baseSortBy(array,comparer){var length=array.length;array.sort(comparer);while(length--){array[length]=array[length].value}return array}function baseSortByOrder(collection,iteratees,orders){var callback=getCallback(),index=-1;iteratees=arrayMap(iteratees,function(iteratee){return callback(iteratee)});var result=baseMap(collection,function(value){var criteria=arrayMap(iteratees,function(iteratee){return iteratee(value)});return{criteria:criteria,index:++index,value:value}});return baseSortBy(result,function(object,other){return compareMultiple(object,other,orders)})}function baseSum(collection,iteratee){var result=0;baseEach(collection,function(value,index,collection){result+=+iteratee(value,index,collection)||0});return result}function baseUniq(array,iteratee){var index=-1,indexOf=getIndexOf(),length=array.length,isCommon=indexOf==baseIndexOf,isLarge=isCommon&&length>=LARGE_ARRAY_SIZE,seen=isLarge?createCache():null,result=[];if(seen){indexOf=cacheIndexOf;isCommon=false}else{isLarge=false;seen=iteratee?[]:result}outer:while(++index<length){var value=array[index],computed=iteratee?iteratee(value,index,array):value;if(isCommon&&value===value){var seenIndex=seen.length;while(seenIndex--){if(seen[seenIndex]===computed){continue outer}}if(iteratee){seen.push(computed)}result.push(value)}else if(indexOf(seen,computed,0)<0){if(iteratee||isLarge){seen.push(computed)}result.push(value)}}return result}function baseValues(object,props){var index=-1,length=props.length,result=Array(length);while(++index<length){result[index]=object[props[index]]}return result}function baseWhile(array,predicate,isDrop,fromRight){var length=array.length,index=fromRight?length:-1;while((fromRight?index--:++index<length)&&predicate(array[index],index,array)){}return isDrop?baseSlice(array,fromRight?0:index,fromRight?index+1:length):baseSlice(array,fromRight?index+1:0,fromRight?length:index)}function baseWrapperValue(value,actions){var result=value;if(result instanceof LazyWrapper){result=result.value()}var index=-1,length=actions.length;while(++index<length){var action=actions[index];result=action.func.apply(action.thisArg,arrayPush([result],action.args))}return result}function binaryIndex(array,value,retHighest){var low=0,high=array?array.length:low;if(typeof value=="number"&&value===value&&high<=HALF_MAX_ARRAY_LENGTH){while(low<high){var mid=low+high>>>1,computed=array[mid];if((retHighest?computed<=value:computed<value)&&computed!==null){low=mid+1}else{high=mid}}return high
+}return binaryIndexBy(array,value,identity,retHighest)}function binaryIndexBy(array,value,iteratee,retHighest){value=iteratee(value);var low=0,high=array?array.length:0,valIsNaN=value!==value,valIsNull=value===null,valIsUndef=value===undefined;while(low<high){var mid=nativeFloor((low+high)/2),computed=iteratee(array[mid]),isDef=computed!==undefined,isReflexive=computed===computed;if(valIsNaN){var setLow=isReflexive||retHighest}else if(valIsNull){setLow=isReflexive&&isDef&&(retHighest||computed!=null)}else if(valIsUndef){setLow=isReflexive&&(retHighest||isDef)}else if(computed==null){setLow=false}else{setLow=retHighest?computed<=value:computed<value}if(setLow){low=mid+1}else{high=mid}}return nativeMin(high,MAX_ARRAY_INDEX)}function bindCallback(func,thisArg,argCount){if(typeof func!="function"){return identity}if(thisArg===undefined){return func}switch(argCount){case 1:return function(value){return func.call(thisArg,value)};case 3:return function(value,index,collection){return func.call(thisArg,value,index,collection)};case 4:return function(accumulator,value,index,collection){return func.call(thisArg,accumulator,value,index,collection)};case 5:return function(value,other,key,object,source){return func.call(thisArg,value,other,key,object,source)}}return function(){return func.apply(thisArg,arguments)}}function bufferClone(buffer){var result=new ArrayBuffer(buffer.byteLength),view=new Uint8Array(result);view.set(new Uint8Array(buffer));return result}function composeArgs(args,partials,holders){var holdersLength=holders.length,argsIndex=-1,argsLength=nativeMax(args.length-holdersLength,0),leftIndex=-1,leftLength=partials.length,result=Array(leftLength+argsLength);while(++leftIndex<leftLength){result[leftIndex]=partials[leftIndex]}while(++argsIndex<holdersLength){result[holders[argsIndex]]=args[argsIndex]}while(argsLength--){result[leftIndex++]=args[argsIndex++]}return result}function composeArgsRight(args,partials,holders){var holdersIndex=-1,holdersLength=holders.length,argsIndex=-1,argsLength=nativeMax(args.length-holdersLength,0),rightIndex=-1,rightLength=partials.length,result=Array(argsLength+rightLength);while(++argsIndex<argsLength){result[argsIndex]=args[argsIndex]}var offset=argsIndex;while(++rightIndex<rightLength){result[offset+rightIndex]=partials[rightIndex]}while(++holdersIndex<holdersLength){result[offset+holders[holdersIndex]]=args[argsIndex++]}return result}function createAggregator(setter,initializer){return function(collection,iteratee,thisArg){var result=initializer?initializer():{};iteratee=getCallback(iteratee,thisArg,3);if(isArray(collection)){var index=-1,length=collection.length;while(++index<length){var value=collection[index];setter(result,value,iteratee(value,index,collection),collection)}}else{baseEach(collection,function(value,key,collection){setter(result,value,iteratee(value,key,collection),collection)})}return result}}function createAssigner(assigner){return restParam(function(object,sources){var index=-1,length=object==null?0:sources.length,customizer=length>2?sources[length-2]:undefined,guard=length>2?sources[2]:undefined,thisArg=length>1?sources[length-1]:undefined;if(typeof customizer=="function"){customizer=bindCallback(customizer,thisArg,5);length-=2}else{customizer=typeof thisArg=="function"?thisArg:undefined;length-=customizer?1:0}if(guard&&isIterateeCall(sources[0],sources[1],guard)){customizer=length<3?undefined:customizer;length=1}while(++index<length){var source=sources[index];if(source){assigner(object,source,customizer)}}return object})}function createBaseEach(eachFunc,fromRight){return function(collection,iteratee){var length=collection?getLength(collection):0;if(!isLength(length)){return eachFunc(collection,iteratee)}var index=fromRight?length:-1,iterable=toObject(collection);while(fromRight?index--:++index<length){if(iteratee(iterable[index],index,iterable)===false){break}}return collection}}function createBaseFor(fromRight){return function(object,iteratee,keysFunc){var iterable=toObject(object),props=keysFunc(object),length=props.length,index=fromRight?length:-1;while(fromRight?index--:++index<length){var key=props[index];if(iteratee(iterable[key],key,iterable)===false){break}}return object}}function createBindWrapper(func,thisArg){var Ctor=createCtorWrapper(func);function wrapper(){var fn=this&&this!==root&&this instanceof wrapper?Ctor:func;return fn.apply(thisArg,arguments)}return wrapper}function createCache(values){return nativeCreate&&Set?new SetCache(values):null}function createCompounder(callback){return function(string){var index=-1,array=words(deburr(string)),length=array.length,result="";while(++index<length){result=callback(result,array[index],index)}return result}}function createCtorWrapper(Ctor){return function(){var args=arguments;switch(args.length){case 0:return new Ctor;case 1:return new Ctor(args[0]);case 2:return new Ctor(args[0],args[1]);case 3:return new Ctor(args[0],args[1],args[2]);case 4:return new Ctor(args[0],args[1],args[2],args[3]);case 5:return new Ctor(args[0],args[1],args[2],args[3],args[4]);case 6:return new Ctor(args[0],args[1],args[2],args[3],args[4],args[5]);case 7:return new Ctor(args[0],args[1],args[2],args[3],args[4],args[5],args[6])}var thisBinding=baseCreate(Ctor.prototype),result=Ctor.apply(thisBinding,args);return isObject(result)?result:thisBinding}}function createCurry(flag){function curryFunc(func,arity,guard){if(guard&&isIterateeCall(func,arity,guard)){arity=undefined}var result=createWrapper(func,flag,undefined,undefined,undefined,undefined,undefined,arity);result.placeholder=curryFunc.placeholder;return result}return curryFunc}function createDefaults(assigner,customizer){return restParam(function(args){var object=args[0];if(object==null){return object}args.push(customizer);return assigner.apply(undefined,args)})}function createExtremum(comparator,exValue){return function(collection,iteratee,thisArg){if(thisArg&&isIterateeCall(collection,iteratee,thisArg)){iteratee=undefined}iteratee=getCallback(iteratee,thisArg,3);if(iteratee.length==1){collection=isArray(collection)?collection:toIterable(collection);var result=arrayExtremum(collection,iteratee,comparator,exValue);if(!(collection.length&&result===exValue)){return result}}return baseExtremum(collection,iteratee,comparator,exValue)}}function createFind(eachFunc,fromRight){return function(collection,predicate,thisArg){predicate=getCallback(predicate,thisArg,3);if(isArray(collection)){var index=baseFindIndex(collection,predicate,fromRight);return index>-1?collection[index]:undefined}return baseFind(collection,predicate,eachFunc)}}function createFindIndex(fromRight){return function(array,predicate,thisArg){if(!(array&&array.length)){return-1}predicate=getCallback(predicate,thisArg,3);return baseFindIndex(array,predicate,fromRight)}}function createFindKey(objectFunc){return function(object,predicate,thisArg){predicate=getCallback(predicate,thisArg,3);return baseFind(object,predicate,objectFunc,true)}}function createFlow(fromRight){return function(){var wrapper,length=arguments.length,index=fromRight?length:-1,leftIndex=0,funcs=Array(length);while(fromRight?index--:++index<length){var func=funcs[leftIndex++]=arguments[index];if(typeof func!="function"){throw new TypeError(FUNC_ERROR_TEXT)}if(!wrapper&&LodashWrapper.prototype.thru&&getFuncName(func)=="wrapper"){wrapper=new LodashWrapper([],true)}}index=wrapper?-1:length;while(++index<length){func=funcs[index];var funcName=getFuncName(func),data=funcName=="wrapper"?getData(func):undefined;if(data&&isLaziable(data[0])&&data[1]==(ARY_FLAG|CURRY_FLAG|PARTIAL_FLAG|REARG_FLAG)&&!data[4].length&&data[9]==1){wrapper=wrapper[getFuncName(data[0])].apply(wrapper,data[3])}else{wrapper=func.length==1&&isLaziable(func)?wrapper[funcName]():wrapper.thru(func)}}return function(){var args=arguments,value=args[0];if(wrapper&&args.length==1&&isArray(value)&&value.length>=LARGE_ARRAY_SIZE){return wrapper.plant(value).value()}var index=0,result=length?funcs[index].apply(this,args):value;while(++index<length){result=funcs[index].call(this,result)}return result}}}function createForEach(arrayFunc,eachFunc){return function(collection,iteratee,thisArg){return typeof iteratee=="function"&&thisArg===undefined&&isArray(collection)?arrayFunc(collection,iteratee):eachFunc(collection,bindCallback(iteratee,thisArg,3))}}function createForIn(objectFunc){return function(object,iteratee,thisArg){if(typeof iteratee!="function"||thisArg!==undefined){iteratee=bindCallback(iteratee,thisArg,3)}return objectFunc(object,iteratee,keysIn)}}function createForOwn(objectFunc){return function(object,iteratee,thisArg){if(typeof iteratee!="function"||thisArg!==undefined){iteratee=bindCallback(iteratee,thisArg,3)}return objectFunc(object,iteratee)}}function createObjectMapper(isMapKeys){return function(object,iteratee,thisArg){var result={};iteratee=getCallback(iteratee,thisArg,3);baseForOwn(object,function(value,key,object){var mapped=iteratee(value,key,object);key=isMapKeys?mapped:key;value=isMapKeys?value:mapped;result[key]=value});return result}}function createPadDir(fromRight){return function(string,length,chars){string=baseToString(string);return(fromRight?string:"")+createPadding(string,length,chars)+(fromRight?"":string)}}function createPartial(flag){var partialFunc=restParam(function(func,partials){var holders=replaceHolders(partials,partialFunc.placeholder);return createWrapper(func,flag,undefined,partials,holders)});return partialFunc}function createReduce(arrayFunc,eachFunc){return function(collection,iteratee,accumulator,thisArg){var initFromArray=arguments.length<3;return typeof iteratee=="function"&&thisArg===undefined&&isArray(collection)?arrayFunc(collection,iteratee,accumulator,initFromArray):baseReduce(collection,getCallback(iteratee,thisArg,4),accumulator,initFromArray,eachFunc)}}function createHybridWrapper(func,bitmask,thisArg,partials,holders,partialsRight,holdersRight,argPos,ary,arity){var isAry=bitmask&ARY_FLAG,isBind=bitmask&BIND_FLAG,isBindKey=bitmask&BIND_KEY_FLAG,isCurry=bitmask&CURRY_FLAG,isCurryBound=bitmask&CURRY_BOUND_FLAG,isCurryRight=bitmask&CURRY_RIGHT_FLAG,Ctor=isBindKey?undefined:createCtorWrapper(func);function wrapper(){var length=arguments.length,index=length,args=Array(length);while(index--){args[index]=arguments[index]}if(partials){args=composeArgs(args,partials,holders)}if(partialsRight){args=composeArgsRight(args,partialsRight,holdersRight)}if(isCurry||isCurryRight){var placeholder=wrapper.placeholder,argsHolders=replaceHolders(args,placeholder);length-=argsHolders.length;if(length<arity){var newArgPos=argPos?arrayCopy(argPos):undefined,newArity=nativeMax(arity-length,0),newsHolders=isCurry?argsHolders:undefined,newHoldersRight=isCurry?undefined:argsHolders,newPartials=isCurry?args:undefined,newPartialsRight=isCurry?undefined:args;bitmask|=isCurry?PARTIAL_FLAG:PARTIAL_RIGHT_FLAG;bitmask&=~(isCurry?PARTIAL_RIGHT_FLAG:PARTIAL_FLAG);if(!isCurryBound){bitmask&=~(BIND_FLAG|BIND_KEY_FLAG)}var newData=[func,bitmask,thisArg,newPartials,newsHolders,newPartialsRight,newHoldersRight,newArgPos,ary,newArity],result=createHybridWrapper.apply(undefined,newData);if(isLaziable(func)){setData(result,newData)}result.placeholder=placeholder;return result}}var thisBinding=isBind?thisArg:this,fn=isBindKey?thisBinding[func]:func;if(argPos){args=reorder(args,argPos)}if(isAry&&ary<args.length){args.length=ary}if(this&&this!==root&&this instanceof wrapper){fn=Ctor||createCtorWrapper(func)}return fn.apply(thisBinding,args)}return wrapper}function createPadding(string,length,chars){var strLength=string.length;length=+length;if(strLength>=length||!nativeIsFinite(length)){return""}var padLength=length-strLength;chars=chars==null?" ":chars+"";return repeat(chars,nativeCeil(padLength/chars.length)).slice(0,padLength)}function createPartialWrapper(func,bitmask,thisArg,partials){var isBind=bitmask&BIND_FLAG,Ctor=createCtorWrapper(func);function wrapper(){var argsIndex=-1,argsLength=arguments.length,leftIndex=-1,leftLength=partials.length,args=Array(leftLength+argsLength);while(++leftIndex<leftLength){args[leftIndex]=partials[leftIndex]}while(argsLength--){args[leftIndex++]=arguments[++argsIndex]}var fn=this&&this!==root&&this instanceof wrapper?Ctor:func;return fn.apply(isBind?thisArg:this,args)}return wrapper}function createRound(methodName){var func=Math[methodName];return function(number,precision){precision=precision===undefined?0:+precision||0;if(precision){precision=pow(10,precision);return func(number*precision)/precision}return func(number)}}function createSortedIndex(retHighest){return function(array,value,iteratee,thisArg){var callback=getCallback(iteratee);return iteratee==null&&callback===baseCallback?binaryIndex(array,value,retHighest):binaryIndexBy(array,value,callback(iteratee,thisArg,1),retHighest)}}function createWrapper(func,bitmask,thisArg,partials,holders,argPos,ary,arity){var isBindKey=bitmask&BIND_KEY_FLAG;if(!isBindKey&&typeof func!="function"){throw new TypeError(FUNC_ERROR_TEXT)}var length=partials?partials.length:0;if(!length){bitmask&=~(PARTIAL_FLAG|PARTIAL_RIGHT_FLAG);partials=holders=undefined}length-=holders?holders.length:0;if(bitmask&PARTIAL_RIGHT_FLAG){var partialsRight=partials,holdersRight=holders;partials=holders=undefined}var data=isBindKey?undefined:getData(func),newData=[func,bitmask,thisArg,partials,holders,partialsRight,holdersRight,argPos,ary,arity];if(data){mergeData(newData,data);bitmask=newData[1];arity=newData[9]}newData[9]=arity==null?isBindKey?0:func.length:nativeMax(arity-length,0)||0;if(bitmask==BIND_FLAG){var result=createBindWrapper(newData[0],newData[2])}else if((bitmask==PARTIAL_FLAG||bitmask==(BIND_FLAG|PARTIAL_FLAG))&&!newData[4].length){result=createPartialWrapper.apply(undefined,newData)}else{result=createHybridWrapper.apply(undefined,newData)}var setter=data?baseSetData:setData;return setter(result,newData)}function equalArrays(array,other,equalFunc,customizer,isLoose,stackA,stackB){var index=-1,arrLength=array.length,othLength=other.length;if(arrLength!=othLength&&!(isLoose&&othLength>arrLength)){return false}while(++index<arrLength){var arrValue=array[index],othValue=other[index],result=customizer?customizer(isLoose?othValue:arrValue,isLoose?arrValue:othValue,index):undefined;if(result!==undefined){if(result){continue}return false}if(isLoose){if(!arraySome(other,function(othValue){return arrValue===othValue||equalFunc(arrValue,othValue,customizer,isLoose,stackA,stackB)})){return false}}else if(!(arrValue===othValue||equalFunc(arrValue,othValue,customizer,isLoose,stackA,stackB))){return false}}return true}function equalByTag(object,other,tag){switch(tag){case boolTag:case dateTag:return+object==+other;case errorTag:return object.name==other.name&&object.message==other.message;case numberTag:return object!=+object?other!=+other:object==+other;case regexpTag:case stringTag:return object==other+""}return false}function equalObjects(object,other,equalFunc,customizer,isLoose,stackA,stackB){var objProps=keys(object),objLength=objProps.length,othProps=keys(other),othLength=othProps.length;if(objLength!=othLength&&!isLoose){return false}var index=objLength;while(index--){var key=objProps[index];if(!(isLoose?key in other:hasOwnProperty.call(other,key))){return false}}var skipCtor=isLoose;while(++index<objLength){key=objProps[index];var objValue=object[key],othValue=other[key],result=customizer?customizer(isLoose?othValue:objValue,isLoose?objValue:othValue,key):undefined;if(!(result===undefined?equalFunc(objValue,othValue,customizer,isLoose,stackA,stackB):result)){return false}skipCtor||(skipCtor=key=="constructor")}if(!skipCtor){var objCtor=object.constructor,othCtor=other.constructor;if(objCtor!=othCtor&&("constructor"in object&&"constructor"in other)&&!(typeof objCtor=="function"&&objCtor instanceof objCtor&&typeof othCtor=="function"&&othCtor instanceof othCtor)){return false}}return true}function getCallback(func,thisArg,argCount){var result=lodash.callback||callback;result=result===callback?baseCallback:result;return argCount?result(func,thisArg,argCount):result}var getData=!metaMap?noop:function(func){return metaMap.get(func)};function getFuncName(func){var result=func.name,array=realNames[result],length=array?array.length:0;while(length--){var data=array[length],otherFunc=data.func;if(otherFunc==null||otherFunc==func){return data.name}}return result}function getIndexOf(collection,target,fromIndex){var result=lodash.indexOf||indexOf;result=result===indexOf?baseIndexOf:result;return collection?result(collection,target,fromIndex):result}var getLength=baseProperty("length");function getMatchData(object){var result=pairs(object),length=result.length;while(length--){result[length][2]=isStrictComparable(result[length][1])}return result}function getNative(object,key){var value=object==null?undefined:object[key];return isNative(value)?value:undefined}function getView(start,end,transforms){var index=-1,length=transforms.length;while(++index<length){var data=transforms[index],size=data.size;switch(data.type){case"drop":start+=size;break;case"dropRight":end-=size;break;case"take":end=nativeMin(end,start+size);break;case"takeRight":start=nativeMax(start,end-size);break}}return{start:start,end:end}}function initCloneArray(array){var length=array.length,result=new array.constructor(length);if(length&&typeof array[0]=="string"&&hasOwnProperty.call(array,"index")){result.index=array.index;result.input=array.input}return result}function initCloneObject(object){var Ctor=object.constructor;if(!(typeof Ctor=="function"&&Ctor instanceof Ctor)){Ctor=Object}return new Ctor}function initCloneByTag(object,tag,isDeep){var Ctor=object.constructor;switch(tag){case arrayBufferTag:return bufferClone(object);case boolTag:case dateTag:return new Ctor(+object);case float32Tag:case float64Tag:case int8Tag:case int16Tag:case int32Tag:case uint8Tag:case uint8ClampedTag:case uint16Tag:case uint32Tag:var buffer=object.buffer;return new Ctor(isDeep?bufferClone(buffer):buffer,object.byteOffset,object.length);case numberTag:case stringTag:return new Ctor(object);case regexpTag:var result=new Ctor(object.source,reFlags.exec(object));result.lastIndex=object.lastIndex}return result}function invokePath(object,path,args){if(object!=null&&!isKey(path,object)){path=toPath(path);object=path.length==1?object:baseGet(object,baseSlice(path,0,-1));path=last(path)}var func=object==null?object:object[path];return func==null?undefined:func.apply(object,args)}function isArrayLike(value){return value!=null&&isLength(getLength(value))}function isIndex(value,length){value=typeof value=="number"||reIsUint.test(value)?+value:-1;length=length==null?MAX_SAFE_INTEGER:length;return value>-1&&value%1==0&&value<length}function isIterateeCall(value,index,object){if(!isObject(object)){return false}var type=typeof index;if(type=="number"?isArrayLike(object)&&isIndex(index,object.length):type=="string"&&index in object){var other=object[index];return value===value?value===other:other!==other}return false}function isKey(value,object){var type=typeof value;if(type=="string"&&reIsPlainProp.test(value)||type=="number"){return true}if(isArray(value)){return false}var result=!reIsDeepProp.test(value);return result||object!=null&&value in toObject(object)}function isLaziable(func){var funcName=getFuncName(func);if(!(funcName in LazyWrapper.prototype)){return false}var other=lodash[funcName];if(func===other){return true}var data=getData(other);return!!data&&func===data[0]}function isLength(value){return typeof value=="number"&&value>-1&&value%1==0&&value<=MAX_SAFE_INTEGER}function isStrictComparable(value){return value===value&&!isObject(value)}function mergeData(data,source){var bitmask=data[1],srcBitmask=source[1],newBitmask=bitmask|srcBitmask,isCommon=newBitmask<ARY_FLAG;var isCombo=srcBitmask==ARY_FLAG&&bitmask==CURRY_FLAG||srcBitmask==ARY_FLAG&&bitmask==REARG_FLAG&&data[7].length<=source[8]||srcBitmask==(ARY_FLAG|REARG_FLAG)&&bitmask==CURRY_FLAG;if(!(isCommon||isCombo)){return data}if(srcBitmask&BIND_FLAG){data[2]=source[2];newBitmask|=bitmask&BIND_FLAG?0:CURRY_BOUND_FLAG}var value=source[3];if(value){var partials=data[3];data[3]=partials?composeArgs(partials,value,source[4]):arrayCopy(value);data[4]=partials?replaceHolders(data[3],PLACEHOLDER):arrayCopy(source[4])}value=source[5];if(value){partials=data[5];data[5]=partials?composeArgsRight(partials,value,source[6]):arrayCopy(value);data[6]=partials?replaceHolders(data[5],PLACEHOLDER):arrayCopy(source[6])}value=source[7];if(value){data[7]=arrayCopy(value)}if(srcBitmask&ARY_FLAG){data[8]=data[8]==null?source[8]:nativeMin(data[8],source[8])}if(data[9]==null){data[9]=source[9]}data[0]=source[0];data[1]=newBitmask;return data}function mergeDefaults(objectValue,sourceValue){return objectValue===undefined?sourceValue:merge(objectValue,sourceValue,mergeDefaults)}function pickByArray(object,props){object=toObject(object);var index=-1,length=props.length,result={};while(++index<length){var key=props[index];if(key in object){result[key]=object[key]}}return result}function pickByCallback(object,predicate){var result={};baseForIn(object,function(value,key,object){if(predicate(value,key,object)){result[key]=value}});return result}function reorder(array,indexes){var arrLength=array.length,length=nativeMin(indexes.length,arrLength),oldArray=arrayCopy(array);while(length--){var index=indexes[length];array[length]=isIndex(index,arrLength)?oldArray[index]:undefined}return array}var setData=function(){var count=0,lastCalled=0;return function(key,value){var stamp=now(),remaining=HOT_SPAN-(stamp-lastCalled);lastCalled=stamp;if(remaining>0){if(++count>=HOT_COUNT){return key}}else{count=0}return baseSetData(key,value)}}();function shimKeys(object){var props=keysIn(object),propsLength=props.length,length=propsLength&&object.length;var allowIndexes=!!length&&isLength(length)&&(isArray(object)||isArguments(object));var index=-1,result=[];while(++index<propsLength){var key=props[index];if(allowIndexes&&isIndex(key,length)||hasOwnProperty.call(object,key)){result.push(key)}}return result}function toIterable(value){if(value==null){return[]}if(!isArrayLike(value)){return values(value)}return isObject(value)?value:Object(value)}function toObject(value){return isObject(value)?value:Object(value)}function toPath(value){if(isArray(value)){return value}var result=[];baseToString(value).replace(rePropName,function(match,number,quote,string){result.push(quote?string.replace(reEscapeChar,"$1"):number||match)});return result}function wrapperClone(wrapper){return wrapper instanceof LazyWrapper?wrapper.clone():new LodashWrapper(wrapper.__wrapped__,wrapper.__chain__,arrayCopy(wrapper.__actions__))}function chunk(array,size,guard){if(guard?isIterateeCall(array,size,guard):size==null){size=1}else{size=nativeMax(nativeFloor(size)||1,1)}var index=0,length=array?array.length:0,resIndex=-1,result=Array(nativeCeil(length/size));while(index<length){result[++resIndex]=baseSlice(array,index,index+=size)}return result}function compact(array){var index=-1,length=array?array.length:0,resIndex=-1,result=[];while(++index<length){var value=array[index];if(value){result[++resIndex]=value}}return result}var difference=restParam(function(array,values){return isObjectLike(array)&&isArrayLike(array)?baseDifference(array,baseFlatten(values,false,true)):[]});function drop(array,n,guard){var length=array?array.length:0;if(!length){return[]}if(guard?isIterateeCall(array,n,guard):n==null){n=1}return baseSlice(array,n<0?0:n)}function dropRight(array,n,guard){var length=array?array.length:0;if(!length){return[]}if(guard?isIterateeCall(array,n,guard):n==null){n=1}n=length-(+n||0);return baseSlice(array,0,n<0?0:n)}function dropRightWhile(array,predicate,thisArg){return array&&array.length?baseWhile(array,getCallback(predicate,thisArg,3),true,true):[]}function dropWhile(array,predicate,thisArg){return array&&array.length?baseWhile(array,getCallback(predicate,thisArg,3),true):[]}function fill(array,value,start,end){var length=array?array.length:0;if(!length){return[]}if(start&&typeof start!="number"&&isIterateeCall(array,value,start)){start=0;end=length}return baseFill(array,value,start,end)}var findIndex=createFindIndex();var findLastIndex=createFindIndex(true);function first(array){return array?array[0]:undefined}function flatten(array,isDeep,guard){var length=array?array.length:0;if(guard&&isIterateeCall(array,isDeep,guard)){isDeep=false}return length?baseFlatten(array,isDeep):[]}function flattenDeep(array){var length=array?array.length:0;return length?baseFlatten(array,true):[]}function indexOf(array,value,fromIndex){var length=array?array.length:0;if(!length){return-1}if(typeof fromIndex=="number"){fromIndex=fromIndex<0?nativeMax(length+fromIndex,0):fromIndex}else if(fromIndex){var index=binaryIndex(array,value);if(index<length&&(value===value?value===array[index]:array[index]!==array[index])){return index}return-1}return baseIndexOf(array,value,fromIndex||0)}function initial(array){return dropRight(array,1)}var intersection=restParam(function(arrays){var othLength=arrays.length,othIndex=othLength,caches=Array(length),indexOf=getIndexOf(),isCommon=indexOf==baseIndexOf,result=[];while(othIndex--){var value=arrays[othIndex]=isArrayLike(value=arrays[othIndex])?value:[];caches[othIndex]=isCommon&&value.length>=120?createCache(othIndex&&value):null}var array=arrays[0],index=-1,length=array?array.length:0,seen=caches[0];outer:while(++index<length){value=array[index];if((seen?cacheIndexOf(seen,value):indexOf(result,value,0))<0){var othIndex=othLength;while(--othIndex){var cache=caches[othIndex];if((cache?cacheIndexOf(cache,value):indexOf(arrays[othIndex],value,0))<0){continue outer}}if(seen){seen.push(value)}result.push(value)}}return result});function last(array){var length=array?array.length:0;return length?array[length-1]:undefined}function lastIndexOf(array,value,fromIndex){var length=array?array.length:0;if(!length){return-1}var index=length;if(typeof fromIndex=="number"){index=(fromIndex<0?nativeMax(length+fromIndex,0):nativeMin(fromIndex||0,length-1))+1}else if(fromIndex){index=binaryIndex(array,value,true)-1;var other=array[index];if(value===value?value===other:other!==other){return index}return-1}if(value!==value){return indexOfNaN(array,index,true)}while(index--){if(array[index]===value){return index}}return-1}function pull(){var args=arguments,array=args[0];if(!(array&&array.length)){return array}var index=0,indexOf=getIndexOf(),length=args.length;while(++index<length){var fromIndex=0,value=args[index];while((fromIndex=indexOf(array,value,fromIndex))>-1){splice.call(array,fromIndex,1)}}return array}var pullAt=restParam(function(array,indexes){indexes=baseFlatten(indexes);var result=baseAt(array,indexes);basePullAt(array,indexes.sort(baseCompareAscending));return result});function remove(array,predicate,thisArg){var result=[];if(!(array&&array.length)){return result}var index=-1,indexes=[],length=array.length;predicate=getCallback(predicate,thisArg,3);while(++index<length){var value=array[index];if(predicate(value,index,array)){result.push(value);indexes.push(index)}}basePullAt(array,indexes);return result}function rest(array){return drop(array,1)}function slice(array,start,end){var length=array?array.length:0;if(!length){return[]}if(end&&typeof end!="number"&&isIterateeCall(array,start,end)){start=0;end=length}return baseSlice(array,start,end)}var sortedIndex=createSortedIndex();var sortedLastIndex=createSortedIndex(true);function take(array,n,guard){var length=array?array.length:0;if(!length){return[]}if(guard?isIterateeCall(array,n,guard):n==null){n=1}return baseSlice(array,0,n<0?0:n)}function takeRight(array,n,guard){var length=array?array.length:0;if(!length){return[]}if(guard?isIterateeCall(array,n,guard):n==null){n=1}n=length-(+n||0);return baseSlice(array,n<0?0:n)}function takeRightWhile(array,predicate,thisArg){return array&&array.length?baseWhile(array,getCallback(predicate,thisArg,3),false,true):[]}function takeWhile(array,predicate,thisArg){return array&&array.length?baseWhile(array,getCallback(predicate,thisArg,3)):[]}var union=restParam(function(arrays){return baseUniq(baseFlatten(arrays,false,true))});function uniq(array,isSorted,iteratee,thisArg){var length=array?array.length:0;if(!length){return[]}if(isSorted!=null&&typeof isSorted!="boolean"){thisArg=iteratee;iteratee=isIterateeCall(array,isSorted,thisArg)?undefined:isSorted;isSorted=false}var callback=getCallback();if(!(iteratee==null&&callback===baseCallback)){iteratee=callback(iteratee,thisArg,3)}return isSorted&&getIndexOf()==baseIndexOf?sortedUniq(array,iteratee):baseUniq(array,iteratee)}function unzip(array){if(!(array&&array.length)){return[]}var index=-1,length=0;array=arrayFilter(array,function(group){if(isArrayLike(group)){length=nativeMax(group.length,length);return true}});var result=Array(length);while(++index<length){result[index]=arrayMap(array,baseProperty(index))}return result}function unzipWith(array,iteratee,thisArg){var length=array?array.length:0;if(!length){return[]}var result=unzip(array);if(iteratee==null){return result}iteratee=bindCallback(iteratee,thisArg,4);return arrayMap(result,function(group){return arrayReduce(group,iteratee,undefined,true)})}var without=restParam(function(array,values){return isArrayLike(array)?baseDifference(array,values):[]});function xor(){var index=-1,length=arguments.length;while(++index<length){var array=arguments[index];if(isArrayLike(array)){var result=result?arrayPush(baseDifference(result,array),baseDifference(array,result)):array}}return result?baseUniq(result):[]}var zip=restParam(unzip);function zipObject(props,values){var index=-1,length=props?props.length:0,result={};if(length&&!values&&!isArray(props[0])){values=[]}while(++index<length){var key=props[index];if(values){result[key]=values[index]}else if(key){result[key[0]]=key[1]}}return result}var zipWith=restParam(function(arrays){var length=arrays.length,iteratee=length>2?arrays[length-2]:undefined,thisArg=length>1?arrays[length-1]:undefined;if(length>2&&typeof iteratee=="function"){length-=2}else{iteratee=length>1&&typeof thisArg=="function"?(--length,thisArg):undefined;thisArg=undefined}arrays.length=length;return unzipWith(arrays,iteratee,thisArg)});function chain(value){var result=lodash(value);result.__chain__=true;return result}function tap(value,interceptor,thisArg){interceptor.call(thisArg,value);return value}function thru(value,interceptor,thisArg){return interceptor.call(thisArg,value)}function wrapperChain(){return chain(this)}function wrapperCommit(){return new LodashWrapper(this.value(),this.__chain__)}var wrapperConcat=restParam(function(values){values=baseFlatten(values);return this.thru(function(array){return arrayConcat(isArray(array)?array:[toObject(array)],values)})});function wrapperPlant(value){var result,parent=this;while(parent instanceof baseLodash){var clone=wrapperClone(parent);if(result){previous.__wrapped__=clone}else{result=clone}var previous=clone;parent=parent.__wrapped__}previous.__wrapped__=value;return result}function wrapperReverse(){var value=this.__wrapped__;var interceptor=function(value){return wrapped&&wrapped.__dir__<0?value:value.reverse()};if(value instanceof LazyWrapper){var wrapped=value;if(this.__actions__.length){wrapped=new LazyWrapper(this)}wrapped=wrapped.reverse();wrapped.__actions__.push({func:thru,args:[interceptor],thisArg:undefined});return new LodashWrapper(wrapped,this.__chain__)}return this.thru(interceptor)}function wrapperToString(){return this.value()+""}function wrapperValue(){return baseWrapperValue(this.__wrapped__,this.__actions__)}var at=restParam(function(collection,props){return baseAt(collection,baseFlatten(props))});var countBy=createAggregator(function(result,value,key){hasOwnProperty.call(result,key)?++result[key]:result[key]=1});function every(collection,predicate,thisArg){var func=isArray(collection)?arrayEvery:baseEvery;if(thisArg&&isIterateeCall(collection,predicate,thisArg)){predicate=undefined}if(typeof predicate!="function"||thisArg!==undefined){predicate=getCallback(predicate,thisArg,3)
+}return func(collection,predicate)}function filter(collection,predicate,thisArg){var func=isArray(collection)?arrayFilter:baseFilter;predicate=getCallback(predicate,thisArg,3);return func(collection,predicate)}var find=createFind(baseEach);var findLast=createFind(baseEachRight,true);function findWhere(collection,source){return find(collection,baseMatches(source))}var forEach=createForEach(arrayEach,baseEach);var forEachRight=createForEach(arrayEachRight,baseEachRight);var groupBy=createAggregator(function(result,value,key){if(hasOwnProperty.call(result,key)){result[key].push(value)}else{result[key]=[value]}});function includes(collection,target,fromIndex,guard){var length=collection?getLength(collection):0;if(!isLength(length)){collection=values(collection);length=collection.length}if(typeof fromIndex!="number"||guard&&isIterateeCall(target,fromIndex,guard)){fromIndex=0}else{fromIndex=fromIndex<0?nativeMax(length+fromIndex,0):fromIndex||0}return typeof collection=="string"||!isArray(collection)&&isString(collection)?fromIndex<=length&&collection.indexOf(target,fromIndex)>-1:!!length&&getIndexOf(collection,target,fromIndex)>-1}var indexBy=createAggregator(function(result,value,key){result[key]=value});var invoke=restParam(function(collection,path,args){var index=-1,isFunc=typeof path=="function",isProp=isKey(path),result=isArrayLike(collection)?Array(collection.length):[];baseEach(collection,function(value){var func=isFunc?path:isProp&&value!=null?value[path]:undefined;result[++index]=func?func.apply(value,args):invokePath(value,path,args)});return result});function map(collection,iteratee,thisArg){var func=isArray(collection)?arrayMap:baseMap;iteratee=getCallback(iteratee,thisArg,3);return func(collection,iteratee)}var partition=createAggregator(function(result,value,key){result[key?0:1].push(value)},function(){return[[],[]]});function pluck(collection,path){return map(collection,property(path))}var reduce=createReduce(arrayReduce,baseEach);var reduceRight=createReduce(arrayReduceRight,baseEachRight);function reject(collection,predicate,thisArg){var func=isArray(collection)?arrayFilter:baseFilter;predicate=getCallback(predicate,thisArg,3);return func(collection,function(value,index,collection){return!predicate(value,index,collection)})}function sample(collection,n,guard){if(guard?isIterateeCall(collection,n,guard):n==null){collection=toIterable(collection);var length=collection.length;return length>0?collection[baseRandom(0,length-1)]:undefined}var index=-1,result=toArray(collection),length=result.length,lastIndex=length-1;n=nativeMin(n<0?0:+n||0,length);while(++index<n){var rand=baseRandom(index,lastIndex),value=result[rand];result[rand]=result[index];result[index]=value}result.length=n;return result}function shuffle(collection){return sample(collection,POSITIVE_INFINITY)}function size(collection){var length=collection?getLength(collection):0;return isLength(length)?length:keys(collection).length}function some(collection,predicate,thisArg){var func=isArray(collection)?arraySome:baseSome;if(thisArg&&isIterateeCall(collection,predicate,thisArg)){predicate=undefined}if(typeof predicate!="function"||thisArg!==undefined){predicate=getCallback(predicate,thisArg,3)}return func(collection,predicate)}function sortBy(collection,iteratee,thisArg){if(collection==null){return[]}if(thisArg&&isIterateeCall(collection,iteratee,thisArg)){iteratee=undefined}var index=-1;iteratee=getCallback(iteratee,thisArg,3);var result=baseMap(collection,function(value,key,collection){return{criteria:iteratee(value,key,collection),index:++index,value:value}});return baseSortBy(result,compareAscending)}var sortByAll=restParam(function(collection,iteratees){if(collection==null){return[]}var guard=iteratees[2];if(guard&&isIterateeCall(iteratees[0],iteratees[1],guard)){iteratees.length=1}return baseSortByOrder(collection,baseFlatten(iteratees),[])});function sortByOrder(collection,iteratees,orders,guard){if(collection==null){return[]}if(guard&&isIterateeCall(iteratees,orders,guard)){orders=undefined}if(!isArray(iteratees)){iteratees=iteratees==null?[]:[iteratees]}if(!isArray(orders)){orders=orders==null?[]:[orders]}return baseSortByOrder(collection,iteratees,orders)}function where(collection,source){return filter(collection,baseMatches(source))}var now=nativeNow||function(){return(new Date).getTime()};function after(n,func){if(typeof func!="function"){if(typeof n=="function"){var temp=n;n=func;func=temp}else{throw new TypeError(FUNC_ERROR_TEXT)}}n=nativeIsFinite(n=+n)?n:0;return function(){if(--n<1){return func.apply(this,arguments)}}}function ary(func,n,guard){if(guard&&isIterateeCall(func,n,guard)){n=undefined}n=func&&n==null?func.length:nativeMax(+n||0,0);return createWrapper(func,ARY_FLAG,undefined,undefined,undefined,undefined,n)}function before(n,func){var result;if(typeof func!="function"){if(typeof n=="function"){var temp=n;n=func;func=temp}else{throw new TypeError(FUNC_ERROR_TEXT)}}return function(){if(--n>0){result=func.apply(this,arguments)}if(n<=1){func=undefined}return result}}var bind=restParam(function(func,thisArg,partials){var bitmask=BIND_FLAG;if(partials.length){var holders=replaceHolders(partials,bind.placeholder);bitmask|=PARTIAL_FLAG}return createWrapper(func,bitmask,thisArg,partials,holders)});var bindAll=restParam(function(object,methodNames){methodNames=methodNames.length?baseFlatten(methodNames):functions(object);var index=-1,length=methodNames.length;while(++index<length){var key=methodNames[index];object[key]=createWrapper(object[key],BIND_FLAG,object)}return object});var bindKey=restParam(function(object,key,partials){var bitmask=BIND_FLAG|BIND_KEY_FLAG;if(partials.length){var holders=replaceHolders(partials,bindKey.placeholder);bitmask|=PARTIAL_FLAG}return createWrapper(key,bitmask,object,partials,holders)});var curry=createCurry(CURRY_FLAG);var curryRight=createCurry(CURRY_RIGHT_FLAG);function debounce(func,wait,options){var args,maxTimeoutId,result,stamp,thisArg,timeoutId,trailingCall,lastCalled=0,maxWait=false,trailing=true;if(typeof func!="function"){throw new TypeError(FUNC_ERROR_TEXT)}wait=wait<0?0:+wait||0;if(options===true){var leading=true;trailing=false}else if(isObject(options)){leading=!!options.leading;maxWait="maxWait"in options&&nativeMax(+options.maxWait||0,wait);trailing="trailing"in options?!!options.trailing:trailing}function cancel(){if(timeoutId){clearTimeout(timeoutId)}if(maxTimeoutId){clearTimeout(maxTimeoutId)}lastCalled=0;maxTimeoutId=timeoutId=trailingCall=undefined}function complete(isCalled,id){if(id){clearTimeout(id)}maxTimeoutId=timeoutId=trailingCall=undefined;if(isCalled){lastCalled=now();result=func.apply(thisArg,args);if(!timeoutId&&!maxTimeoutId){args=thisArg=undefined}}}function delayed(){var remaining=wait-(now()-stamp);if(remaining<=0||remaining>wait){complete(trailingCall,maxTimeoutId)}else{timeoutId=setTimeout(delayed,remaining)}}function maxDelayed(){complete(trailing,timeoutId)}function debounced(){args=arguments;stamp=now();thisArg=this;trailingCall=trailing&&(timeoutId||!leading);if(maxWait===false){var leadingCall=leading&&!timeoutId}else{if(!maxTimeoutId&&!leading){lastCalled=stamp}var remaining=maxWait-(stamp-lastCalled),isCalled=remaining<=0||remaining>maxWait;if(isCalled){if(maxTimeoutId){maxTimeoutId=clearTimeout(maxTimeoutId)}lastCalled=stamp;result=func.apply(thisArg,args)}else if(!maxTimeoutId){maxTimeoutId=setTimeout(maxDelayed,remaining)}}if(isCalled&&timeoutId){timeoutId=clearTimeout(timeoutId)}else if(!timeoutId&&wait!==maxWait){timeoutId=setTimeout(delayed,wait)}if(leadingCall){isCalled=true;result=func.apply(thisArg,args)}if(isCalled&&!timeoutId&&!maxTimeoutId){args=thisArg=undefined}return result}debounced.cancel=cancel;return debounced}var defer=restParam(function(func,args){return baseDelay(func,1,args)});var delay=restParam(function(func,wait,args){return baseDelay(func,wait,args)});var flow=createFlow();var flowRight=createFlow(true);function memoize(func,resolver){if(typeof func!="function"||resolver&&typeof resolver!="function"){throw new TypeError(FUNC_ERROR_TEXT)}var memoized=function(){var args=arguments,key=resolver?resolver.apply(this,args):args[0],cache=memoized.cache;if(cache.has(key)){return cache.get(key)}var result=func.apply(this,args);memoized.cache=cache.set(key,result);return result};memoized.cache=new memoize.Cache;return memoized}var modArgs=restParam(function(func,transforms){transforms=baseFlatten(transforms);if(typeof func!="function"||!arrayEvery(transforms,baseIsFunction)){throw new TypeError(FUNC_ERROR_TEXT)}var length=transforms.length;return restParam(function(args){var index=nativeMin(args.length,length);while(index--){args[index]=transforms[index](args[index])}return func.apply(this,args)})});function negate(predicate){if(typeof predicate!="function"){throw new TypeError(FUNC_ERROR_TEXT)}return function(){return!predicate.apply(this,arguments)}}function once(func){return before(2,func)}var partial=createPartial(PARTIAL_FLAG);var partialRight=createPartial(PARTIAL_RIGHT_FLAG);var rearg=restParam(function(func,indexes){return createWrapper(func,REARG_FLAG,undefined,undefined,undefined,baseFlatten(indexes))});function restParam(func,start){if(typeof func!="function"){throw new TypeError(FUNC_ERROR_TEXT)}start=nativeMax(start===undefined?func.length-1:+start||0,0);return function(){var args=arguments,index=-1,length=nativeMax(args.length-start,0),rest=Array(length);while(++index<length){rest[index]=args[start+index]}switch(start){case 0:return func.call(this,rest);case 1:return func.call(this,args[0],rest);case 2:return func.call(this,args[0],args[1],rest)}var otherArgs=Array(start+1);index=-1;while(++index<start){otherArgs[index]=args[index]}otherArgs[start]=rest;return func.apply(this,otherArgs)}}function spread(func){if(typeof func!="function"){throw new TypeError(FUNC_ERROR_TEXT)}return function(array){return func.apply(this,array)}}function throttle(func,wait,options){var leading=true,trailing=true;if(typeof func!="function"){throw new TypeError(FUNC_ERROR_TEXT)}if(options===false){leading=false}else if(isObject(options)){leading="leading"in options?!!options.leading:leading;trailing="trailing"in options?!!options.trailing:trailing}return debounce(func,wait,{leading:leading,maxWait:+wait,trailing:trailing})}function wrap(value,wrapper){wrapper=wrapper==null?identity:wrapper;return createWrapper(wrapper,PARTIAL_FLAG,undefined,[value],[])}function clone(value,isDeep,customizer,thisArg){if(isDeep&&typeof isDeep!="boolean"&&isIterateeCall(value,isDeep,customizer)){isDeep=false}else if(typeof isDeep=="function"){thisArg=customizer;customizer=isDeep;isDeep=false}return typeof customizer=="function"?baseClone(value,isDeep,bindCallback(customizer,thisArg,1)):baseClone(value,isDeep)}function cloneDeep(value,customizer,thisArg){return typeof customizer=="function"?baseClone(value,true,bindCallback(customizer,thisArg,1)):baseClone(value,true)}function gt(value,other){return value>other}function gte(value,other){return value>=other}function isArguments(value){return isObjectLike(value)&&isArrayLike(value)&&hasOwnProperty.call(value,"callee")&&!propertyIsEnumerable.call(value,"callee")}var isArray=nativeIsArray||function(value){return isObjectLike(value)&&isLength(value.length)&&objToString.call(value)==arrayTag};function isBoolean(value){return value===true||value===false||isObjectLike(value)&&objToString.call(value)==boolTag}function isDate(value){return isObjectLike(value)&&objToString.call(value)==dateTag}function isElement(value){return!!value&&value.nodeType===1&&isObjectLike(value)&&!isPlainObject(value)}function isEmpty(value){if(value==null){return true}if(isArrayLike(value)&&(isArray(value)||isString(value)||isArguments(value)||isObjectLike(value)&&isFunction(value.splice))){return!value.length}return!keys(value).length}function isEqual(value,other,customizer,thisArg){customizer=typeof customizer=="function"?bindCallback(customizer,thisArg,3):undefined;var result=customizer?customizer(value,other):undefined;return result===undefined?baseIsEqual(value,other,customizer):!!result}function isError(value){return isObjectLike(value)&&typeof value.message=="string"&&objToString.call(value)==errorTag}function isFinite(value){return typeof value=="number"&&nativeIsFinite(value)}function isFunction(value){return isObject(value)&&objToString.call(value)==funcTag}function isObject(value){var type=typeof value;return!!value&&(type=="object"||type=="function")}function isMatch(object,source,customizer,thisArg){customizer=typeof customizer=="function"?bindCallback(customizer,thisArg,3):undefined;return baseIsMatch(object,getMatchData(source),customizer)}function isNaN(value){return isNumber(value)&&value!=+value}function isNative(value){if(value==null){return false}if(isFunction(value)){return reIsNative.test(fnToString.call(value))}return isObjectLike(value)&&reIsHostCtor.test(value)}function isNull(value){return value===null}function isNumber(value){return typeof value=="number"||isObjectLike(value)&&objToString.call(value)==numberTag}function isPlainObject(value){var Ctor;if(!(isObjectLike(value)&&objToString.call(value)==objectTag&&!isArguments(value))||!hasOwnProperty.call(value,"constructor")&&(Ctor=value.constructor,typeof Ctor=="function"&&!(Ctor instanceof Ctor))){return false}var result;baseForIn(value,function(subValue,key){result=key});return result===undefined||hasOwnProperty.call(value,result)}function isRegExp(value){return isObject(value)&&objToString.call(value)==regexpTag}function isString(value){return typeof value=="string"||isObjectLike(value)&&objToString.call(value)==stringTag}function isTypedArray(value){return isObjectLike(value)&&isLength(value.length)&&!!typedArrayTags[objToString.call(value)]}function isUndefined(value){return value===undefined}function lt(value,other){return value<other}function lte(value,other){return value<=other}function toArray(value){var length=value?getLength(value):0;if(!isLength(length)){return values(value)}if(!length){return[]}return arrayCopy(value)}function toPlainObject(value){return baseCopy(value,keysIn(value))}var merge=createAssigner(baseMerge);var assign=createAssigner(function(object,source,customizer){return customizer?assignWith(object,source,customizer):baseAssign(object,source)});function create(prototype,properties,guard){var result=baseCreate(prototype);if(guard&&isIterateeCall(prototype,properties,guard)){properties=undefined}return properties?baseAssign(result,properties):result}var defaults=createDefaults(assign,assignDefaults);var defaultsDeep=createDefaults(merge,mergeDefaults);var findKey=createFindKey(baseForOwn);var findLastKey=createFindKey(baseForOwnRight);var forIn=createForIn(baseFor);var forInRight=createForIn(baseForRight);var forOwn=createForOwn(baseForOwn);var forOwnRight=createForOwn(baseForOwnRight);function functions(object){return baseFunctions(object,keysIn(object))}function get(object,path,defaultValue){var result=object==null?undefined:baseGet(object,toPath(path),path+"");return result===undefined?defaultValue:result}function has(object,path){if(object==null){return false}var result=hasOwnProperty.call(object,path);if(!result&&!isKey(path)){path=toPath(path);object=path.length==1?object:baseGet(object,baseSlice(path,0,-1));if(object==null){return false}path=last(path);result=hasOwnProperty.call(object,path)}return result||isLength(object.length)&&isIndex(path,object.length)&&(isArray(object)||isArguments(object))}function invert(object,multiValue,guard){if(guard&&isIterateeCall(object,multiValue,guard)){multiValue=undefined}var index=-1,props=keys(object),length=props.length,result={};while(++index<length){var key=props[index],value=object[key];if(multiValue){if(hasOwnProperty.call(result,value)){result[value].push(key)}else{result[value]=[key]}}else{result[value]=key}}return result}var keys=!nativeKeys?shimKeys:function(object){var Ctor=object==null?undefined:object.constructor;if(typeof Ctor=="function"&&Ctor.prototype===object||typeof object!="function"&&isArrayLike(object)){return shimKeys(object)}return isObject(object)?nativeKeys(object):[]};function keysIn(object){if(object==null){return[]}if(!isObject(object)){object=Object(object)}var length=object.length;length=length&&isLength(length)&&(isArray(object)||isArguments(object))&&length||0;var Ctor=object.constructor,index=-1,isProto=typeof Ctor=="function"&&Ctor.prototype===object,result=Array(length),skipIndexes=length>0;while(++index<length){result[index]=index+""}for(var key in object){if(!(skipIndexes&&isIndex(key,length))&&!(key=="constructor"&&(isProto||!hasOwnProperty.call(object,key)))){result.push(key)}}return result}var mapKeys=createObjectMapper(true);var mapValues=createObjectMapper();var omit=restParam(function(object,props){if(object==null){return{}}if(typeof props[0]!="function"){var props=arrayMap(baseFlatten(props),String);return pickByArray(object,baseDifference(keysIn(object),props))}var predicate=bindCallback(props[0],props[1],3);return pickByCallback(object,function(value,key,object){return!predicate(value,key,object)})});function pairs(object){object=toObject(object);var index=-1,props=keys(object),length=props.length,result=Array(length);while(++index<length){var key=props[index];result[index]=[key,object[key]]}return result}var pick=restParam(function(object,props){if(object==null){return{}}return typeof props[0]=="function"?pickByCallback(object,bindCallback(props[0],props[1],3)):pickByArray(object,baseFlatten(props))});function result(object,path,defaultValue){var result=object==null?undefined:object[path];if(result===undefined){if(object!=null&&!isKey(path,object)){path=toPath(path);object=path.length==1?object:baseGet(object,baseSlice(path,0,-1));result=object==null?undefined:object[last(path)]}result=result===undefined?defaultValue:result}return isFunction(result)?result.call(object):result}function set(object,path,value){if(object==null){return object}var pathKey=path+"";path=object[pathKey]!=null||isKey(path,object)?[pathKey]:toPath(path);var index=-1,length=path.length,lastIndex=length-1,nested=object;while(nested!=null&&++index<length){var key=path[index];if(isObject(nested)){if(index==lastIndex){nested[key]=value}else if(nested[key]==null){nested[key]=isIndex(path[index+1])?[]:{}}}nested=nested[key]}return object}function transform(object,iteratee,accumulator,thisArg){var isArr=isArray(object)||isTypedArray(object);iteratee=getCallback(iteratee,thisArg,4);if(accumulator==null){if(isArr||isObject(object)){var Ctor=object.constructor;if(isArr){accumulator=isArray(object)?new Ctor:[]}else{accumulator=baseCreate(isFunction(Ctor)?Ctor.prototype:undefined)}}else{accumulator={}}}(isArr?arrayEach:baseForOwn)(object,function(value,index,object){return iteratee(accumulator,value,index,object)});return accumulator}function values(object){return baseValues(object,keys(object))}function valuesIn(object){return baseValues(object,keysIn(object))}function inRange(value,start,end){start=+start||0;if(end===undefined){end=start;start=0}else{end=+end||0}return value>=nativeMin(start,end)&&value<nativeMax(start,end)}function random(min,max,floating){if(floating&&isIterateeCall(min,max,floating)){max=floating=undefined}var noMin=min==null,noMax=max==null;if(floating==null){if(noMax&&typeof min=="boolean"){floating=min;min=1}else if(typeof max=="boolean"){floating=max;noMax=true}}if(noMin&&noMax){max=1;noMax=false}min=+min||0;if(noMax){max=min;min=0}else{max=+max||0}if(floating||min%1||max%1){var rand=nativeRandom();return nativeMin(min+rand*(max-min+parseFloat("1e-"+((rand+"").length-1))),max)}return baseRandom(min,max)}var camelCase=createCompounder(function(result,word,index){word=word.toLowerCase();return result+(index?word.charAt(0).toUpperCase()+word.slice(1):word)});function capitalize(string){string=baseToString(string);return string&&string.charAt(0).toUpperCase()+string.slice(1)}function deburr(string){string=baseToString(string);return string&&string.replace(reLatin1,deburrLetter).replace(reComboMark,"")}function endsWith(string,target,position){string=baseToString(string);target=target+"";var length=string.length;position=position===undefined?length:nativeMin(position<0?0:+position||0,length);position-=target.length;return position>=0&&string.indexOf(target,position)==position}function escape(string){string=baseToString(string);return string&&reHasUnescapedHtml.test(string)?string.replace(reUnescapedHtml,escapeHtmlChar):string}function escapeRegExp(string){string=baseToString(string);return string&&reHasRegExpChars.test(string)?string.replace(reRegExpChars,escapeRegExpChar):string||"(?:)"}var kebabCase=createCompounder(function(result,word,index){return result+(index?"-":"")+word.toLowerCase()});function pad(string,length,chars){string=baseToString(string);length=+length;var strLength=string.length;if(strLength>=length||!nativeIsFinite(length)){return string}var mid=(length-strLength)/2,leftLength=nativeFloor(mid),rightLength=nativeCeil(mid);chars=createPadding("",rightLength,chars);return chars.slice(0,leftLength)+string+chars}var padLeft=createPadDir();var padRight=createPadDir(true);function parseInt(string,radix,guard){if(guard?isIterateeCall(string,radix,guard):radix==null){radix=0}else if(radix){radix=+radix}string=trim(string);return nativeParseInt(string,radix||(reHasHexPrefix.test(string)?16:10))}function repeat(string,n){var result="";string=baseToString(string);n=+n;if(n<1||!string||!nativeIsFinite(n)){return result}do{if(n%2){result+=string}n=nativeFloor(n/2);string+=string}while(n);return result}var snakeCase=createCompounder(function(result,word,index){return result+(index?"_":"")+word.toLowerCase()});var startCase=createCompounder(function(result,word,index){return result+(index?" ":"")+(word.charAt(0).toUpperCase()+word.slice(1))});function startsWith(string,target,position){string=baseToString(string);position=position==null?0:nativeMin(position<0?0:+position||0,string.length);return string.lastIndexOf(target,position)==position}function template(string,options,otherOptions){var settings=lodash.templateSettings;if(otherOptions&&isIterateeCall(string,options,otherOptions)){options=otherOptions=undefined}string=baseToString(string);options=assignWith(baseAssign({},otherOptions||options),settings,assignOwnDefaults);var imports=assignWith(baseAssign({},options.imports),settings.imports,assignOwnDefaults),importsKeys=keys(imports),importsValues=baseValues(imports,importsKeys);var isEscaping,isEvaluating,index=0,interpolate=options.interpolate||reNoMatch,source="__p += '";var reDelimiters=RegExp((options.escape||reNoMatch).source+"|"+interpolate.source+"|"+(interpolate===reInterpolate?reEsTemplate:reNoMatch).source+"|"+(options.evaluate||reNoMatch).source+"|$","g");var sourceURL="//# sourceURL="+("sourceURL"in options?options.sourceURL:"lodash.templateSources["+ ++templateCounter+"]")+"\n";string.replace(reDelimiters,function(match,escapeValue,interpolateValue,esTemplateValue,evaluateValue,offset){interpolateValue||(interpolateValue=esTemplateValue);source+=string.slice(index,offset).replace(reUnescapedString,escapeStringChar);if(escapeValue){isEscaping=true;source+="' +\n__e("+escapeValue+") +\n'"}if(evaluateValue){isEvaluating=true;source+="';\n"+evaluateValue+";\n__p += '"}if(interpolateValue){source+="' +\n((__t = ("+interpolateValue+")) == null ? '' : __t) +\n'"}index=offset+match.length;return match});source+="';\n";var variable=options.variable;if(!variable){source="with (obj) {\n"+source+"\n}\n"}source=(isEvaluating?source.replace(reEmptyStringLeading,""):source).replace(reEmptyStringMiddle,"$1").replace(reEmptyStringTrailing,"$1;");source="function("+(variable||"obj")+") {\n"+(variable?"":"obj || (obj = {});\n")+"var __t, __p = ''"+(isEscaping?", __e = _.escape":"")+(isEvaluating?", __j = Array.prototype.join;\n"+"function print() { __p += __j.call(arguments, '') }\n":";\n")+source+"return __p\n}";var result=attempt(function(){return Function(importsKeys,sourceURL+"return "+source).apply(undefined,importsValues)});result.source=source;if(isError(result)){throw result}return result}function trim(string,chars,guard){var value=string;string=baseToString(string);if(!string){return string}if(guard?isIterateeCall(value,chars,guard):chars==null){return string.slice(trimmedLeftIndex(string),trimmedRightIndex(string)+1)}chars=chars+"";return string.slice(charsLeftIndex(string,chars),charsRightIndex(string,chars)+1)}function trimLeft(string,chars,guard){var value=string;string=baseToString(string);if(!string){return string}if(guard?isIterateeCall(value,chars,guard):chars==null){return string.slice(trimmedLeftIndex(string))}return string.slice(charsLeftIndex(string,chars+""))}function trimRight(string,chars,guard){var value=string;string=baseToString(string);if(!string){return string}if(guard?isIterateeCall(value,chars,guard):chars==null){return string.slice(0,trimmedRightIndex(string)+1)}return string.slice(0,charsRightIndex(string,chars+"")+1)}function trunc(string,options,guard){if(guard&&isIterateeCall(string,options,guard)){options=undefined}var length=DEFAULT_TRUNC_LENGTH,omission=DEFAULT_TRUNC_OMISSION;if(options!=null){if(isObject(options)){var separator="separator"in options?options.separator:separator;length="length"in options?+options.length||0:length;omission="omission"in options?baseToString(options.omission):omission}else{length=+options||0}}string=baseToString(string);if(length>=string.length){return string}var end=length-omission.length;if(end<1){return omission}var result=string.slice(0,end);if(separator==null){return result+omission}if(isRegExp(separator)){if(string.slice(end).search(separator)){var match,newEnd,substring=string.slice(0,end);if(!separator.global){separator=RegExp(separator.source,(reFlags.exec(separator)||"")+"g")}separator.lastIndex=0;while(match=separator.exec(substring)){newEnd=match.index}result=result.slice(0,newEnd==null?end:newEnd)}}else if(string.indexOf(separator,end)!=end){var index=result.lastIndexOf(separator);if(index>-1){result=result.slice(0,index)}}return result+omission}function unescape(string){string=baseToString(string);return string&&reHasEscapedHtml.test(string)?string.replace(reEscapedHtml,unescapeHtmlChar):string}function words(string,pattern,guard){if(guard&&isIterateeCall(string,pattern,guard)){pattern=undefined}string=baseToString(string);return string.match(pattern||reWords)||[]}var attempt=restParam(function(func,args){try{return func.apply(undefined,args)}catch(e){return isError(e)?e:new Error(e)}});function callback(func,thisArg,guard){if(guard&&isIterateeCall(func,thisArg,guard)){thisArg=undefined}return isObjectLike(func)?matches(func):baseCallback(func,thisArg)}function constant(value){return function(){return value}}function identity(value){return value}function matches(source){return baseMatches(baseClone(source,true))}function matchesProperty(path,srcValue){return baseMatchesProperty(path,baseClone(srcValue,true))}var method=restParam(function(path,args){return function(object){return invokePath(object,path,args)}});var methodOf=restParam(function(object,args){return function(path){return invokePath(object,path,args)}});function mixin(object,source,options){if(options==null){var isObj=isObject(source),props=isObj?keys(source):undefined,methodNames=props&&props.length?baseFunctions(source,props):undefined;if(!(methodNames?methodNames.length:isObj)){methodNames=false;options=source;source=object;object=this}}if(!methodNames){methodNames=baseFunctions(source,keys(source))}var chain=true,index=-1,isFunc=isFunction(object),length=methodNames.length;if(options===false){chain=false}else if(isObject(options)&&"chain"in options){chain=options.chain}while(++index<length){var methodName=methodNames[index],func=source[methodName];object[methodName]=func;if(isFunc){object.prototype[methodName]=function(func){return function(){var chainAll=this.__chain__;if(chain||chainAll){var result=object(this.__wrapped__),actions=result.__actions__=arrayCopy(this.__actions__);actions.push({func:func,args:arguments,thisArg:object});result.__chain__=chainAll;return result}return func.apply(object,arrayPush([this.value()],arguments))}}(func)}}return object}function noConflict(){root._=oldDash;return this}function noop(){}function property(path){return isKey(path)?baseProperty(path):basePropertyDeep(path)}function propertyOf(object){return function(path){return baseGet(object,toPath(path),path+"")}}function range(start,end,step){if(step&&isIterateeCall(start,end,step)){end=step=undefined}start=+start||0;step=step==null?1:+step||0;if(end==null){end=start;start=0}else{end=+end||0}var index=-1,length=nativeMax(nativeCeil((end-start)/(step||1)),0),result=Array(length);while(++index<length){result[index]=start;start+=step}return result}function times(n,iteratee,thisArg){n=nativeFloor(n);if(n<1||!nativeIsFinite(n)){return[]}var index=-1,result=Array(nativeMin(n,MAX_ARRAY_LENGTH));iteratee=bindCallback(iteratee,thisArg,1);while(++index<n){if(index<MAX_ARRAY_LENGTH){result[index]=iteratee(index)}else{iteratee(index)}}return result}function uniqueId(prefix){var id=++idCounter;return baseToString(prefix)+id}function add(augend,addend){return(+augend||0)+(+addend||0)}var ceil=createRound("ceil");var floor=createRound("floor");var max=createExtremum(gt,NEGATIVE_INFINITY);var min=createExtremum(lt,POSITIVE_INFINITY);var round=createRound("round");function sum(collection,iteratee,thisArg){if(thisArg&&isIterateeCall(collection,iteratee,thisArg)){iteratee=undefined}iteratee=getCallback(iteratee,thisArg,3);return iteratee.length==1?arraySum(isArray(collection)?collection:toIterable(collection),iteratee):baseSum(collection,iteratee)}lodash.prototype=baseLodash.prototype;LodashWrapper.prototype=baseCreate(baseLodash.prototype);LodashWrapper.prototype.constructor=LodashWrapper;LazyWrapper.prototype=baseCreate(baseLodash.prototype);LazyWrapper.prototype.constructor=LazyWrapper;MapCache.prototype["delete"]=mapDelete;MapCache.prototype.get=mapGet;MapCache.prototype.has=mapHas;MapCache.prototype.set=mapSet;SetCache.prototype.push=cachePush;memoize.Cache=MapCache;lodash.after=after;lodash.ary=ary;lodash.assign=assign;lodash.at=at;lodash.before=before;lodash.bind=bind;lodash.bindAll=bindAll;lodash.bindKey=bindKey;lodash.callback=callback;lodash.chain=chain;lodash.chunk=chunk;lodash.compact=compact;lodash.constant=constant;lodash.countBy=countBy;lodash.create=create;lodash.curry=curry;lodash.curryRight=curryRight;lodash.debounce=debounce;lodash.defaults=defaults;lodash.defaultsDeep=defaultsDeep;lodash.defer=defer;lodash.delay=delay;lodash.difference=difference;lodash.drop=drop;lodash.dropRight=dropRight;lodash.dropRightWhile=dropRightWhile;lodash.dropWhile=dropWhile;lodash.fill=fill;lodash.filter=filter;lodash.flatten=flatten;lodash.flattenDeep=flattenDeep;lodash.flow=flow;lodash.flowRight=flowRight;lodash.forEach=forEach;lodash.forEachRight=forEachRight;lodash.forIn=forIn;lodash.forInRight=forInRight;lodash.forOwn=forOwn;lodash.forOwnRight=forOwnRight;lodash.functions=functions;lodash.groupBy=groupBy;lodash.indexBy=indexBy;lodash.initial=initial;lodash.intersection=intersection;lodash.invert=invert;lodash.invoke=invoke;lodash.keys=keys;lodash.keysIn=keysIn;lodash.map=map;lodash.mapKeys=mapKeys;lodash.mapValues=mapValues;lodash.matches=matches;lodash.matchesProperty=matchesProperty;lodash.memoize=memoize;lodash.merge=merge;lodash.method=method;lodash.methodOf=methodOf;lodash.mixin=mixin;lodash.modArgs=modArgs;lodash.negate=negate;lodash.omit=omit;lodash.once=once;lodash.pairs=pairs;lodash.partial=partial;lodash.partialRight=partialRight;lodash.partition=partition;lodash.pick=pick;lodash.pluck=pluck;lodash.property=property;lodash.propertyOf=propertyOf;lodash.pull=pull;lodash.pullAt=pullAt;lodash.range=range;lodash.rearg=rearg;lodash.reject=reject;lodash.remove=remove;lodash.rest=rest;lodash.restParam=restParam;lodash.set=set;lodash.shuffle=shuffle;lodash.slice=slice;lodash.sortBy=sortBy;lodash.sortByAll=sortByAll;lodash.sortByOrder=sortByOrder;
+lodash.spread=spread;lodash.take=take;lodash.takeRight=takeRight;lodash.takeRightWhile=takeRightWhile;lodash.takeWhile=takeWhile;lodash.tap=tap;lodash.throttle=throttle;lodash.thru=thru;lodash.times=times;lodash.toArray=toArray;lodash.toPlainObject=toPlainObject;lodash.transform=transform;lodash.union=union;lodash.uniq=uniq;lodash.unzip=unzip;lodash.unzipWith=unzipWith;lodash.values=values;lodash.valuesIn=valuesIn;lodash.where=where;lodash.without=without;lodash.wrap=wrap;lodash.xor=xor;lodash.zip=zip;lodash.zipObject=zipObject;lodash.zipWith=zipWith;lodash.backflow=flowRight;lodash.collect=map;lodash.compose=flowRight;lodash.each=forEach;lodash.eachRight=forEachRight;lodash.extend=assign;lodash.iteratee=callback;lodash.methods=functions;lodash.object=zipObject;lodash.select=filter;lodash.tail=rest;lodash.unique=uniq;mixin(lodash,lodash);lodash.add=add;lodash.attempt=attempt;lodash.camelCase=camelCase;lodash.capitalize=capitalize;lodash.ceil=ceil;lodash.clone=clone;lodash.cloneDeep=cloneDeep;lodash.deburr=deburr;lodash.endsWith=endsWith;lodash.escape=escape;lodash.escapeRegExp=escapeRegExp;lodash.every=every;lodash.find=find;lodash.findIndex=findIndex;lodash.findKey=findKey;lodash.findLast=findLast;lodash.findLastIndex=findLastIndex;lodash.findLastKey=findLastKey;lodash.findWhere=findWhere;lodash.first=first;lodash.floor=floor;lodash.get=get;lodash.gt=gt;lodash.gte=gte;lodash.has=has;lodash.identity=identity;lodash.includes=includes;lodash.indexOf=indexOf;lodash.inRange=inRange;lodash.isArguments=isArguments;lodash.isArray=isArray;lodash.isBoolean=isBoolean;lodash.isDate=isDate;lodash.isElement=isElement;lodash.isEmpty=isEmpty;lodash.isEqual=isEqual;lodash.isError=isError;lodash.isFinite=isFinite;lodash.isFunction=isFunction;lodash.isMatch=isMatch;lodash.isNaN=isNaN;lodash.isNative=isNative;lodash.isNull=isNull;lodash.isNumber=isNumber;lodash.isObject=isObject;lodash.isPlainObject=isPlainObject;lodash.isRegExp=isRegExp;lodash.isString=isString;lodash.isTypedArray=isTypedArray;lodash.isUndefined=isUndefined;lodash.kebabCase=kebabCase;lodash.last=last;lodash.lastIndexOf=lastIndexOf;lodash.lt=lt;lodash.lte=lte;lodash.max=max;lodash.min=min;lodash.noConflict=noConflict;lodash.noop=noop;lodash.now=now;lodash.pad=pad;lodash.padLeft=padLeft;lodash.padRight=padRight;lodash.parseInt=parseInt;lodash.random=random;lodash.reduce=reduce;lodash.reduceRight=reduceRight;lodash.repeat=repeat;lodash.result=result;lodash.round=round;lodash.runInContext=runInContext;lodash.size=size;lodash.snakeCase=snakeCase;lodash.some=some;lodash.sortedIndex=sortedIndex;lodash.sortedLastIndex=sortedLastIndex;lodash.startCase=startCase;lodash.startsWith=startsWith;lodash.sum=sum;lodash.template=template;lodash.trim=trim;lodash.trimLeft=trimLeft;lodash.trimRight=trimRight;lodash.trunc=trunc;lodash.unescape=unescape;lodash.uniqueId=uniqueId;lodash.words=words;lodash.all=every;lodash.any=some;lodash.contains=includes;lodash.eq=isEqual;lodash.detect=find;lodash.foldl=reduce;lodash.foldr=reduceRight;lodash.head=first;lodash.include=includes;lodash.inject=reduce;mixin(lodash,function(){var source={};baseForOwn(lodash,function(func,methodName){if(!lodash.prototype[methodName]){source[methodName]=func}});return source}(),false);lodash.sample=sample;lodash.prototype.sample=function(n){if(!this.__chain__&&n==null){return sample(this.value())}return this.thru(function(value){return sample(value,n)})};lodash.VERSION=VERSION;arrayEach(["bind","bindKey","curry","curryRight","partial","partialRight"],function(methodName){lodash[methodName].placeholder=lodash});arrayEach(["drop","take"],function(methodName,index){LazyWrapper.prototype[methodName]=function(n){var filtered=this.__filtered__;if(filtered&&!index){return new LazyWrapper(this)}n=n==null?1:nativeMax(nativeFloor(n)||0,0);var result=this.clone();if(filtered){result.__takeCount__=nativeMin(result.__takeCount__,n)}else{result.__views__.push({size:n,type:methodName+(result.__dir__<0?"Right":"")})}return result};LazyWrapper.prototype[methodName+"Right"]=function(n){return this.reverse()[methodName](n).reverse()}});arrayEach(["filter","map","takeWhile"],function(methodName,index){var type=index+1,isFilter=type!=LAZY_MAP_FLAG;LazyWrapper.prototype[methodName]=function(iteratee,thisArg){var result=this.clone();result.__iteratees__.push({iteratee:getCallback(iteratee,thisArg,1),type:type});result.__filtered__=result.__filtered__||isFilter;return result}});arrayEach(["first","last"],function(methodName,index){var takeName="take"+(index?"Right":"");LazyWrapper.prototype[methodName]=function(){return this[takeName](1).value()[0]}});arrayEach(["initial","rest"],function(methodName,index){var dropName="drop"+(index?"":"Right");LazyWrapper.prototype[methodName]=function(){return this.__filtered__?new LazyWrapper(this):this[dropName](1)}});arrayEach(["pluck","where"],function(methodName,index){var operationName=index?"filter":"map",createCallback=index?baseMatches:property;LazyWrapper.prototype[methodName]=function(value){return this[operationName](createCallback(value))}});LazyWrapper.prototype.compact=function(){return this.filter(identity)};LazyWrapper.prototype.reject=function(predicate,thisArg){predicate=getCallback(predicate,thisArg,1);return this.filter(function(value){return!predicate(value)})};LazyWrapper.prototype.slice=function(start,end){start=start==null?0:+start||0;var result=this;if(result.__filtered__&&(start>0||end<0)){return new LazyWrapper(result)}if(start<0){result=result.takeRight(-start)}else if(start){result=result.drop(start)}if(end!==undefined){end=+end||0;result=end<0?result.dropRight(-end):result.take(end-start)}return result};LazyWrapper.prototype.takeRightWhile=function(predicate,thisArg){return this.reverse().takeWhile(predicate,thisArg).reverse()};LazyWrapper.prototype.toArray=function(){return this.take(POSITIVE_INFINITY)};baseForOwn(LazyWrapper.prototype,function(func,methodName){var checkIteratee=/^(?:filter|map|reject)|While$/.test(methodName),retUnwrapped=/^(?:first|last)$/.test(methodName),lodashFunc=lodash[retUnwrapped?"take"+(methodName=="last"?"Right":""):methodName];if(!lodashFunc){return}lodash.prototype[methodName]=function(){var args=retUnwrapped?[1]:arguments,chainAll=this.__chain__,value=this.__wrapped__,isHybrid=!!this.__actions__.length,isLazy=value instanceof LazyWrapper,iteratee=args[0],useLazy=isLazy||isArray(value);if(useLazy&&checkIteratee&&typeof iteratee=="function"&&iteratee.length!=1){isLazy=useLazy=false}var interceptor=function(value){return retUnwrapped&&chainAll?lodashFunc(value,1)[0]:lodashFunc.apply(undefined,arrayPush([value],args))};var action={func:thru,args:[interceptor],thisArg:undefined},onlyLazy=isLazy&&!isHybrid;if(retUnwrapped&&!chainAll){if(onlyLazy){value=value.clone();value.__actions__.push(action);return func.call(value)}return lodashFunc.call(undefined,this.value())[0]}if(!retUnwrapped&&useLazy){value=onlyLazy?value:new LazyWrapper(this);var result=func.apply(value,args);result.__actions__.push(action);return new LodashWrapper(result,chainAll)}return this.thru(interceptor)}});arrayEach(["join","pop","push","replace","shift","sort","splice","split","unshift"],function(methodName){var func=(/^(?:replace|split)$/.test(methodName)?stringProto:arrayProto)[methodName],chainName=/^(?:push|sort|unshift)$/.test(methodName)?"tap":"thru",retUnwrapped=/^(?:join|pop|replace|shift)$/.test(methodName);lodash.prototype[methodName]=function(){var args=arguments;if(retUnwrapped&&!this.__chain__){return func.apply(this.value(),args)}return this[chainName](function(value){return func.apply(value,args)})}});baseForOwn(LazyWrapper.prototype,function(func,methodName){var lodashFunc=lodash[methodName];if(lodashFunc){var key=lodashFunc.name,names=realNames[key]||(realNames[key]=[]);names.push({name:methodName,func:lodashFunc})}});realNames[createHybridWrapper(undefined,BIND_KEY_FLAG).name]=[{name:"wrapper",func:undefined}];LazyWrapper.prototype.clone=lazyClone;LazyWrapper.prototype.reverse=lazyReverse;LazyWrapper.prototype.value=lazyValue;lodash.prototype.chain=wrapperChain;lodash.prototype.commit=wrapperCommit;lodash.prototype.concat=wrapperConcat;lodash.prototype.plant=wrapperPlant;lodash.prototype.reverse=wrapperReverse;lodash.prototype.toString=wrapperToString;lodash.prototype.run=lodash.prototype.toJSON=lodash.prototype.valueOf=lodash.prototype.value=wrapperValue;lodash.prototype.collect=lodash.prototype.map;lodash.prototype.head=lodash.prototype.first;lodash.prototype.select=lodash.prototype.filter;lodash.prototype.tail=lodash.prototype.rest;return lodash}var _=runInContext();if(typeof define=="function"&&typeof define.amd=="object"&&define.amd){root._=_;define(function(){return _})}else if(freeExports&&freeModule){if(moduleExports){(freeModule.exports=_)._=_}else{freeExports._=_}}else{root._=_}}).call(this)}).call(this,typeof global!=="undefined"?global:typeof self!=="undefined"?self:typeof window!=="undefined"?window:{})},{}]},{},[1])(1)}); \ No newline at end of file
diff --git a/docs/htmldoc/js/jquery-2.0.3.js b/docs/htmldoc/js/jquery-2.0.3.js
new file mode 100644
index 0000000..ebc6c18
--- /dev/null
+++ b/docs/htmldoc/js/jquery-2.0.3.js
@@ -0,0 +1,8829 @@
+/*!
+ * jQuery JavaScript Library v2.0.3
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2013-07-03T13:30Z
+ */
+(function( window, undefined ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//"use strict";
+var
+ // A central reference to the root jQuery(document)
+ rootjQuery,
+
+ // The deferred used on DOM ready
+ readyList,
+
+ // Support: IE9
+ // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined`
+ core_strundefined = typeof undefined,
+
+ // Use the correct document accordingly with window argument (sandbox)
+ location = window.location,
+ document = window.document,
+ docElem = document.documentElement,
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$,
+
+ // [[Class]] -> type pairs
+ class2type = {},
+
+ // List of deleted data cache ids, so we can reuse them
+ core_deletedIds = [],
+
+ core_version = "2.0.3",
+
+ // Save a reference to some core methods
+ core_concat = core_deletedIds.concat,
+ core_push = core_deletedIds.push,
+ core_slice = core_deletedIds.slice,
+ core_indexOf = core_deletedIds.indexOf,
+ core_toString = class2type.toString,
+ core_hasOwn = class2type.hasOwnProperty,
+ core_trim = core_version.trim,
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ return new jQuery.fn.init( selector, context, rootjQuery );
+ },
+
+ // Used for matching numbers
+ core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,
+
+ // Used for splitting on whitespace
+ core_rnotwhite = /\S+/g,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+ // Match a standalone tag
+ rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ },
+
+ // The ready event handler and self cleanup method
+ completed = function() {
+ document.removeEventListener( "DOMContentLoaded", completed, false );
+ window.removeEventListener( "load", completed, false );
+ jQuery.ready();
+ };
+
+jQuery.fn = jQuery.prototype = {
+ // The current version of jQuery being used
+ jquery: core_version,
+
+ constructor: jQuery,
+ init: function( selector, context, rootjQuery ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+
+ // scripts is true for back-compat
+ jQuery.merge( this, jQuery.parseHTML(
+ match[1],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return rootjQuery.ready( selector );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ },
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ toArray: function() {
+ return core_slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num == null ?
+
+ // Return a 'clean' array
+ this.toArray() :
+
+ // Return just the object
+ ( num < 0 ? this[ this.length + num ] : this[ num ] );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+ ret.context = this.context;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ ready: function( fn ) {
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+ },
+
+ slice: function() {
+ return this.pushStack( core_slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: core_push,
+ sort: [].sort,
+ splice: [].splice
+};
+
+// Give the init function the jQuery prototype for later instantiation
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+ target = arguments[1] || {};
+ // skip the boolean and the target
+ i = 2;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( length === i ) {
+ target = this;
+ --i;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ // Unique for each copy of jQuery on the page
+ expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ),
+
+ noConflict: function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+ },
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.trigger ) {
+ jQuery( document ).trigger("ready").off("ready");
+ }
+ },
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray,
+
+ isWindow: function( obj ) {
+ return obj != null && obj === obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ return !isNaN( parseFloat(obj) ) && isFinite( obj );
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return String( obj );
+ }
+ // Support: Safari <= 5.1 (functionish RegExp)
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ core_toString.call(obj) ] || "object" :
+ typeof obj;
+ },
+
+ isPlainObject: function( obj ) {
+ // Not plain objects:
+ // - Any object or value whose internal [[Class]] property is not "[object Object]"
+ // - DOM nodes
+ // - window
+ if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ // Support: Firefox <20
+ // The try/catch suppresses exceptions thrown when attempting to access
+ // the "constructor" property of certain host objects, ie. |window.location|
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=814622
+ try {
+ if ( obj.constructor &&
+ !core_hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {
+ return false;
+ }
+ } catch ( e ) {
+ return false;
+ }
+
+ // If the function hasn't returned already, we're confident that
+ // |obj| is a plain object, created by {} or constructed with new Object
+ return true;
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ // data: string of html
+ // context (optional): If specified, the fragment will be created in this context, defaults to document
+ // keepScripts (optional): If true, will include scripts passed in the html string
+ parseHTML: function( data, context, keepScripts ) {
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+ context = context || document;
+
+ var parsed = rsingleTag.exec( data ),
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[1] ) ];
+ }
+
+ parsed = jQuery.buildFragment( [ data ], context, scripts );
+
+ if ( scripts ) {
+ jQuery( scripts ).remove();
+ }
+
+ return jQuery.merge( [], parsed.childNodes );
+ },
+
+ parseJSON: JSON.parse,
+
+ // Cross-browser xml parsing
+ parseXML: function( data ) {
+ var xml, tmp;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+
+ // Support: IE9
+ try {
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data , "text/xml" );
+ } catch ( e ) {
+ xml = undefined;
+ }
+
+ if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+ },
+
+ noop: function() {},
+
+ // Evaluates a script in a global context
+ globalEval: function( code ) {
+ var script,
+ indirect = eval;
+
+ code = jQuery.trim( code );
+
+ if ( code ) {
+ // If the code includes a valid, prologue position
+ // strict mode pragma, execute code by injecting a
+ // script tag into the document.
+ if ( code.indexOf("use strict") === 1 ) {
+ script = document.createElement("script");
+ script.text = code;
+ document.head.appendChild( script ).parentNode.removeChild( script );
+ } else {
+ // Otherwise, avoid the DOM node creation, insertion
+ // and removal by using an indirect global eval
+ indirect( code );
+ }
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ // args is for internal usage only
+ each: function( obj, callback, args ) {
+ var value,
+ i = 0,
+ length = obj.length,
+ isArray = isArraylike( obj );
+
+ if ( args ) {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ trim: function( text ) {
+ return text == null ? "" : core_trim.call( text );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArraylike( Object(arr) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ core_push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ return arr == null ? -1 : core_indexOf.call( arr, elem, i );
+ },
+
+ merge: function( first, second ) {
+ var l = second.length,
+ i = first.length,
+ j = 0;
+
+ if ( typeof l === "number" ) {
+ for ( ; j < l; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+ } else {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, inv ) {
+ var retVal,
+ ret = [],
+ i = 0,
+ length = elems.length;
+ inv = !!inv;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ retVal = !!callback( elems[ i ], i );
+ if ( inv !== retVal ) {
+ ret.push( elems[ i ] );
+ }
+ }
+
+ return ret;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value,
+ i = 0,
+ length = elems.length,
+ isArray = isArraylike( elems ),
+ ret = [];
+
+ // Go through the array, translating each of the items to their
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret[ ret.length ] = value;
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return core_concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var tmp, args, proxy;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = core_slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ // Multifunctional method to get and set values of a collection
+ // The value/s can optionally be executed if it's a function
+ access: function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ length = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < length; i++ ) {
+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+ },
+
+ now: Date.now,
+
+ // A method for quickly swapping in/out CSS properties to get correct calculations.
+ // Note: this method belongs to the css module but it's needed here for the support module.
+ // If support gets modularized, this method should be moved back to the css module.
+ swap: function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+ }
+});
+
+jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ setTimeout( jQuery.ready );
+
+ } else {
+
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed, false );
+ }
+ }
+ return readyList.promise( obj );
+};
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+ var length = obj.length,
+ type = jQuery.type( obj );
+
+ if ( jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ if ( obj.nodeType === 1 && length ) {
+ return true;
+ }
+
+ return type === "array" || type !== "function" &&
+ ( length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj );
+}
+
+// All jQuery objects should point back to these
+rootjQuery = jQuery(document);
+/*!
+ * Sizzle CSS Selector Engine v1.9.4-pre
+ * http://sizzlejs.com/
+ *
+ * Copyright 2013 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2013-06-03
+ */
+(function( window, undefined ) {
+
+var i,
+ support,
+ cachedruns,
+ Expr,
+ getText,
+ isXML,
+ compile,
+ outermostContext,
+ sortInput,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+
+ // Instance-specific data
+ expando = "sizzle" + -(new Date()),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ hasDuplicate = false,
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+ return 0;
+ },
+
+ // General-purpose constants
+ strundefined = typeof undefined,
+ MAX_NEGATIVE = 1 << 31,
+
+ // Instance methods
+ hasOwn = ({}).hasOwnProperty,
+ arr = [],
+ pop = arr.pop,
+ push_native = arr.push,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf if we can't use a native one
+ indexOf = arr.indexOf || function( elem ) {
+ var i = 0,
+ len = this.length;
+ for ( ; i < len; i++ ) {
+ if ( this[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+ // Regular expressions
+
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+ // http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace( "w", "w#" ),
+
+ // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +
+ "*(?:([*^$|!~]?=)" + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]",
+
+ // Prefer arguments quoted,
+ // then not containing pseudos/brackets,
+ // then attribute selectors/non-parenthetical expressions,
+ // then anything else
+ // These preferences are here to reduce the number of selectors
+ // needing tokenize in the PSEUDO preFilter
+ pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+ rsibling = new RegExp( whitespace + "*[+~]" ),
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*)" + whitespace + "*\\]", "g" ),
+
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rnative = /^[^{]+\{\s*\[native \w/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rescape = /'|\\/g,
+
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+ funescape = function( _, escaped, escapedWhitespace ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ // Support: Firefox
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ // BMP codepoint
+ high < 0 ?
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ };
+
+// Optimize for push.apply( _, NodeList )
+try {
+ push.apply(
+ (arr = slice.call( preferredDoc.childNodes )),
+ preferredDoc.childNodes
+ );
+ // Support: Android<4.0
+ // Detect silently failing push.apply
+ arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+ push = { apply: arr.length ?
+
+ // Leverage slice if possible
+ function( target, els ) {
+ push_native.apply( target, slice.call(els) );
+ } :
+
+ // Support: IE<9
+ // Otherwise append directly
+ function( target, els ) {
+ var j = target.length,
+ i = 0;
+ // Can't trust NodeList.length
+ while ( (target[j++] = els[i++]) ) {}
+ target.length = j - 1;
+ }
+ };
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var match, elem, m, nodeType,
+ // QSA vars
+ i, groups, old, nid, newContext, newSelector;
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+
+ context = context || document;
+ results = results || [];
+
+ if ( !selector || typeof selector !== "string" ) {
+ return results;
+ }
+
+ if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {
+ return [];
+ }
+
+ if ( documentIsHTML && !seed ) {
+
+ // Shortcuts
+ if ( (match = rquickExpr.exec( selector )) ) {
+ // Speed-up: Sizzle("#ID")
+ if ( (m = match[1]) ) {
+ if ( nodeType === 9 ) {
+ elem = context.getElementById( m );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+ contains( context, elem ) && elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Speed-up: Sizzle("TAG")
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
+ }
+
+ // QSA path
+ if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+ nid = old = expando;
+ newContext = context;
+ newSelector = nodeType === 9 && selector;
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ groups = tokenize( selector );
+
+ if ( (old = context.getAttribute("id")) ) {
+ nid = old.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", nid );
+ }
+ nid = "[id='" + nid + "'] ";
+
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = nid + toSelector( groups[i] );
+ }
+ newContext = rsibling.test( selector ) && context.parentNode || context;
+ newSelector = groups.join(",");
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch(qsaError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var keys = [];
+
+ function cache( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key += " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key ] = value);
+ }
+ return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return !!fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // Remove from its parent by default
+ if ( div.parentNode ) {
+ div.parentNode.removeChild( div );
+ }
+ // release memory in IE
+ div = null;
+ }
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+ var arr = attrs.split("|"),
+ i = attrs.length;
+
+ while ( i-- ) {
+ Expr.attrHandle[ arr[i] ] = handler;
+ }
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+ ( ~b.sourceIndex || MAX_NEGATIVE ) -
+ ( ~a.sourceIndex || MAX_NEGATIVE );
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Detect xml
+ * @param {Element|Object} elem An element or a document
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var doc = node ? node.ownerDocument || node : preferredDoc,
+ parent = doc.defaultView;
+
+ // If no document and documentElement is available, return
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Set our document
+ document = doc;
+ docElem = doc.documentElement;
+
+ // Support tests
+ documentIsHTML = !isXML( doc );
+
+ // Support: IE>8
+ // If iframe document is assigned to "document" variable and if iframe has been reloaded,
+ // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+ // IE6-8 do not support the defaultView property so parent will be undefined
+ if ( parent && parent.attachEvent && parent !== parent.top ) {
+ parent.attachEvent( "onbeforeunload", function() {
+ setDocument();
+ });
+ }
+
+ /* Attributes
+ ---------------------------------------------------------------------- */
+
+ // Support: IE<8
+ // Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)
+ support.attributes = assert(function( div ) {
+ div.className = "i";
+ return !div.getAttribute("className");
+ });
+
+ /* getElement(s)By*
+ ---------------------------------------------------------------------- */
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.getElementsByTagName = assert(function( div ) {
+ div.appendChild( doc.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Check if getElementsByClassName can be trusted
+ support.getElementsByClassName = assert(function( div ) {
+ div.innerHTML = "<div class='a'></div><div class='a i'></div>";
+
+ // Support: Safari<4
+ // Catch class over-caching
+ div.firstChild.className = "i";
+ // Support: Opera<10
+ // Catch gEBCN failure to find non-leading classes
+ return div.getElementsByClassName("i").length === 2;
+ });
+
+ // Support: IE<10
+ // Check if getElementById returns elements by name
+ // The broken getElementById methods don't pick up programatically-set names,
+ // so use a roundabout getElementsByName test
+ support.getById = assert(function( div ) {
+ docElem.appendChild( div ).id = expando;
+ return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+ });
+
+ // ID find and filter
+ if ( support.getById ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== strundefined && documentIsHTML ) {
+ var m = context.getElementById( id );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [m] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ // Support: IE6/7
+ // getElementById is not reliable as a find shortcut
+ delete Expr.find["ID"];
+
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== strundefined ) {
+ return context.getElementsByTagName( tag );
+ }
+ } :
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+ if ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ /* QSA/matchesSelector
+ ---------------------------------------------------------------------- */
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21)
+ // We allow this because of a bug in IE8/9 that throws an error
+ // whenever `document.activeElement` is accessed on an iframe
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
+ // See http://bugs.jquery.com/ticket/13378
+ rbuggyQSA = [];
+
+ if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explicitly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ div.innerHTML = "<select><option selected=''></option></select>";
+
+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+ });
+
+ assert(function( div ) {
+
+ // Support: Opera 10-12/IE8
+ // ^= $= *= and empty values
+ // Should not select anything
+ // Support: Windows 8 Native Apps
+ // The type attribute is restricted during .innerHTML assignment
+ var input = doc.createElement("input");
+ input.setAttribute( "type", "hidden" );
+ div.appendChild( input ).setAttribute( "t", "" );
+
+ if ( div.querySelectorAll("[t^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( div, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+ /* Contains
+ ---------------------------------------------------------------------- */
+
+ // Element contains another
+ // Purposefully does not implement inclusive descendent
+ // As in, an element does not contain itself
+ contains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ /* Sorting
+ ---------------------------------------------------------------------- */
+
+ // Document order sorting
+ sortOrder = docElem.compareDocumentPosition ?
+ function( a, b ) {
+
+ // Flag for duplicate removal
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b );
+
+ if ( compare ) {
+ // Disconnected nodes
+ if ( compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+ // Choose the first element that is related to our preferred document
+ if ( a === doc || contains(preferredDoc, a) ) {
+ return -1;
+ }
+ if ( b === doc || contains(preferredDoc, b) ) {
+ return 1;
+ }
+
+ // Maintain original order
+ return sortInput ?
+ ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+ 0;
+ }
+
+ return compare & 4 ? -1 : 1;
+ }
+
+ // Not directly comparable, sort on existence of method
+ return a.compareDocumentPosition ? -1 : 1;
+ } :
+ function( a, b ) {
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+
+ // Parentless nodes are either documents or disconnected
+ } else if ( !aup || !bup ) {
+ return a === doc ? -1 :
+ b === doc ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ if ( support.matchesSelector && documentIsHTML &&
+ ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+ ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
+
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch(e) {}
+ }
+
+ return Sizzle( expr, document, null, [elem] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ var fn = Expr.attrHandle[ name.toLowerCase() ],
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
+ val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+ fn( elem, name, !documentIsHTML ) :
+ undefined;
+
+ return val === undefined ?
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute( name ) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null :
+ val;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ j = 0,
+ i = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ sortInput = !support.sortStable && results.slice( 0 );
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem === results[ i ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ for ( ; (node = elem[i]); i++ ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (see #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ attrHandle: {},
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[5] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[3] && match[4] !== undefined ) {
+ match[2] = match[4];
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeNameSelector ) {
+ var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+ return nodeNameSelector === "*" ?
+ function() { return true; } :
+ function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, outerCache, node, diff, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+ // Seek `elem` from a previously-cached index
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
+ cache = outerCache[ type ] || [];
+ nodeIndex = cache[0] === dirruns && cache[1];
+ diff = cache[0] === dirruns && cache[2];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ // Use previously-cached element index if available
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+ diff = cache[1];
+
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ } else {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf.call( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifier
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsHTML ?
+ elem.lang :
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),
+ // not comment, processing instructions, or others
+ // Thanks to Diego Perini for the nodeName shortcut
+ // Greater than "@" means alpha characters (specifically not starting with "#" or "?")
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
+ // use getAttribute instead to test this case
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+function tokenize( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( tokens = [] );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ });
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ type: type,
+ matches: match
+ });
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+}
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var data, cache, outerCache,
+ dirkey = dirruns + " " + doneName;
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+ if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {
+ if ( (data = cache[1]) === true || data === cachedruns ) {
+ return data === true;
+ }
+ } else {
+ cache = outerCache[ dir ] = [ dirkey ];
+ cache[1] = matcher( elem, context, xml ) || cachedruns;
+ if ( cache[1] === true ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf.call( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ return ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector(
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+ tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+ ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ // A counter to specify which element is currently being matched
+ var matcherCachedRuns = 0,
+ bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, expandContext ) {
+ var elem, j, matcher,
+ setMatched = [],
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ outermost = expandContext != null,
+ contextBackup = outermostContext,
+ // We must always have either seed elements or context
+ elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);
+
+ if ( outermost ) {
+ outermostContext = context !== document && context;
+ cachedruns = matcherCachedRuns;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context, xml ) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ cachedruns = ++matcherCachedRuns;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !group ) {
+ group = tokenize( selector );
+ }
+ i = group.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( group[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+ }
+ return cached;
+};
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function select( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ match = tokenize( selector );
+
+ if ( !seed ) {
+ // Try to minimize operations if there is only one group
+ if ( match.length === 1 ) {
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ support.getById && context.nodeType === 9 && documentIsHTML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+ if ( !context ) {
+ return results;
+ }
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && context.parentNode || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, seed );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function
+ // Provide `match` to avoid retokenization if we modified the selector above
+ compile( selector, match )(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ rsibling.test( selector )
+ );
+ return results;
+}
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome<14
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+ // Should return 1, but returns 4 (following)
+ return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+ div.innerHTML = "<a href='#'></a>";
+ return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+ addHandle( "type|href|height|width", function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+ }
+ });
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+ div.innerHTML = "<input/>";
+ div.firstChild.setAttribute( "value", "" );
+ return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+ addHandle( "value", function( elem, name, isXML ) {
+ if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+ return elem.defaultValue;
+ }
+ });
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+ return div.getAttribute("disabled") == null;
+}) ) {
+ addHandle( booleans, function( elem, name, isXML ) {
+ var val;
+ if ( !isXML ) {
+ return (val = elem.getAttributeNode( name )) && val.specified ?
+ val.value :
+ elem[ name ] === true ? name.toLowerCase() : null;
+ }
+ });
+}
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+})( window );
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+ var object = optionsCache[ options ] = {};
+ jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ });
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ ( optionsCache[ options ] || createOptions( options ) ) :
+ jQuery.extend( {}, options );
+
+ var // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // Flag to know if list is currently firing
+ firing,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = !options.once && [],
+ // Fire callbacks
+ fire = function( data ) {
+ memory = options.memory && data;
+ fired = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ firing = true;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+ memory = false; // To prevent further calls using add
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( stack ) {
+ if ( stack.length ) {
+ fire( stack.shift() );
+ }
+ } else if ( memory ) {
+ list = [];
+ } else {
+ self.disable();
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ // First, we save the current length
+ var start = list.length;
+ (function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ var type = jQuery.type( arg );
+ if ( type === "function" ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && type !== "string" ) {
+ // Inspect recursively
+ add( arg );
+ }
+ });
+ })( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away
+ } else if ( memory ) {
+ firingStart = start;
+ fire( memory );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+ // Handle firing indexes
+ if ( firing ) {
+ if ( index <= firingLength ) {
+ firingLength--;
+ }
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ });
+ }
+ return this;
+ },
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ firingLength = 0;
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( list && ( !fired || stack ) ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ if ( firing ) {
+ stack.push( args );
+ } else {
+ fire( args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var tuples = [
+ // action, add listener, listener list, final state
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var action = tuple[ 0 ],
+ fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
+ deferred[ tuple[1] ](function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+ }
+ });
+ });
+ fns = null;
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Keep pipe for back-compat
+ promise.pipe = promise.then;
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 3 ];
+
+ // promise[ done | fail | progress ] = list.add
+ promise[ tuple[1] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(function() {
+ // state = [ resolved | rejected ]
+ state = stateString;
+
+ // [ reject_list | resolve_list ].disable; progress_list.lock
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ }
+
+ // deferred[ resolve | reject | notify ]
+ deferred[ tuple[0] ] = function() {
+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+ return this;
+ };
+ deferred[ tuple[0] + "With" ] = list.fireWith;
+ });
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( subordinate /* , ..., subordinateN */ ) {
+ var i = 0,
+ resolveValues = core_slice.call( arguments ),
+ length = resolveValues.length,
+
+ // the count of uncompleted subordinates
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+ // Update function for both resolve and progress values
+ updateFunc = function( i, contexts, values ) {
+ return function( value ) {
+ contexts[ i ] = this;
+ values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;
+ if( values === progressValues ) {
+ deferred.notifyWith( contexts, values );
+ } else if ( !( --remaining ) ) {
+ deferred.resolveWith( contexts, values );
+ }
+ };
+ },
+
+ progressValues, progressContexts, resolveContexts;
+
+ // add listeners to Deferred subordinates; treat others as resolved
+ if ( length > 1 ) {
+ progressValues = new Array( length );
+ progressContexts = new Array( length );
+ resolveContexts = new Array( length );
+ for ( ; i < length; i++ ) {
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+ resolveValues[ i ].promise()
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject )
+ .progress( updateFunc( i, progressContexts, progressValues ) );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // if we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+});
+jQuery.support = (function( support ) {
+ var input = document.createElement("input"),
+ fragment = document.createDocumentFragment(),
+ div = document.createElement("div"),
+ select = document.createElement("select"),
+ opt = select.appendChild( document.createElement("option") );
+
+ // Finish early in limited environments
+ if ( !input.type ) {
+ return support;
+ }
+
+ input.type = "checkbox";
+
+ // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
+ // Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere)
+ support.checkOn = input.value !== "";
+
+ // Must access the parent to make an option select properly
+ // Support: IE9, IE10
+ support.optSelected = opt.selected;
+
+ // Will be defined later
+ support.reliableMarginRight = true;
+ support.boxSizingReliable = true;
+ support.pixelPosition = false;
+
+ // Make sure checked status is properly cloned
+ // Support: IE9, IE10
+ input.checked = true;
+ support.noCloneChecked = input.cloneNode( true ).checked;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Check if an input maintains its value after becoming a radio
+ // Support: IE9, IE10
+ input = document.createElement("input");
+ input.value = "t";
+ input.type = "radio";
+ support.radioValue = input.value === "t";
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ input.setAttribute( "checked", "t" );
+ input.setAttribute( "name", "t" );
+
+ fragment.appendChild( input );
+
+ // Support: Safari 5.1, Android 4.x, Android 2.3
+ // old WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: Firefox, Chrome, Safari
+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
+ support.focusinBubbles = "onfocusin" in window;
+
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ // Run tests that need a body at doc ready
+ jQuery(function() {
+ var container, marginDiv,
+ // Support: Firefox, Android 2.3 (Prefixed box-sizing versions).
+ divReset = "padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",
+ body = document.getElementsByTagName("body")[ 0 ];
+
+ if ( !body ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ container = document.createElement("div");
+ container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";
+
+ // Check box-sizing and margin behavior.
+ body.appendChild( container ).appendChild( div );
+ div.innerHTML = "";
+ // Support: Firefox, Android 2.3 (Prefixed box-sizing versions).
+ div.style.cssText = "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%";
+
+ // Workaround failing boxSizing test due to offsetWidth returning wrong value
+ // with some non-1 values of body zoom, ticket #13543
+ jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() {
+ support.boxSizing = div.offsetWidth === 4;
+ });
+
+ // Use window.getComputedStyle because jsdom on node.js will break without it.
+ if ( window.getComputedStyle ) {
+ support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+ support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+ // Support: Android 2.3
+ // Check if div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container. (#3333)
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ marginDiv = div.appendChild( document.createElement("div") );
+ marginDiv.style.cssText = div.style.cssText = divReset;
+ marginDiv.style.marginRight = marginDiv.style.width = "0";
+ div.style.width = "1px";
+
+ support.reliableMarginRight =
+ !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );
+ }
+
+ body.removeChild( container );
+ });
+
+ return support;
+})( {} );
+
+/*
+ Implementation Summary
+
+ 1. Enforce API surface and semantic compatibility with 1.9.x branch
+ 2. Improve the module's maintainability by reducing the storage
+ paths to a single mechanism.
+ 3. Use the same single mechanism to support "private" and "user" data.
+ 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
+ 5. Avoid exposing implementation details on user objects (eg. expando properties)
+ 6. Provide a clear path for implementation upgrade to WeakMap in 2014
+*/
+var data_user, data_priv,
+ rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+function Data() {
+ // Support: Android < 4,
+ // Old WebKit does not have Object.preventExtensions/freeze method,
+ // return new empty object instead with no [[set]] accessor
+ Object.defineProperty( this.cache = {}, 0, {
+ get: function() {
+ return {};
+ }
+ });
+
+ this.expando = jQuery.expando + Math.random();
+}
+
+Data.uid = 1;
+
+Data.accepts = function( owner ) {
+ // Accepts only:
+ // - Node
+ // - Node.ELEMENT_NODE
+ // - Node.DOCUMENT_NODE
+ // - Object
+ // - Any
+ return owner.nodeType ?
+ owner.nodeType === 1 || owner.nodeType === 9 : true;
+};
+
+Data.prototype = {
+ key: function( owner ) {
+ // We can accept data for non-element nodes in modern browsers,
+ // but we should not, see #8335.
+ // Always return the key for a frozen object.
+ if ( !Data.accepts( owner ) ) {
+ return 0;
+ }
+
+ var descriptor = {},
+ // Check if the owner object already has a cache key
+ unlock = owner[ this.expando ];
+
+ // If not, create one
+ if ( !unlock ) {
+ unlock = Data.uid++;
+
+ // Secure it in a non-enumerable, non-writable property
+ try {
+ descriptor[ this.expando ] = { value: unlock };
+ Object.defineProperties( owner, descriptor );
+
+ // Support: Android < 4
+ // Fallback to a less secure definition
+ } catch ( e ) {
+ descriptor[ this.expando ] = unlock;
+ jQuery.extend( owner, descriptor );
+ }
+ }
+
+ // Ensure the cache object
+ if ( !this.cache[ unlock ] ) {
+ this.cache[ unlock ] = {};
+ }
+
+ return unlock;
+ },
+ set: function( owner, data, value ) {
+ var prop,
+ // There may be an unlock assigned to this node,
+ // if there is no entry for this "owner", create one inline
+ // and set the unlock as though an owner entry had always existed
+ unlock = this.key( owner ),
+ cache = this.cache[ unlock ];
+
+ // Handle: [ owner, key, value ] args
+ if ( typeof data === "string" ) {
+ cache[ data ] = value;
+
+ // Handle: [ owner, { properties } ] args
+ } else {
+ // Fresh assignments by object are shallow copied
+ if ( jQuery.isEmptyObject( cache ) ) {
+ jQuery.extend( this.cache[ unlock ], data );
+ // Otherwise, copy the properties one-by-one to the cache object
+ } else {
+ for ( prop in data ) {
+ cache[ prop ] = data[ prop ];
+ }
+ }
+ }
+ return cache;
+ },
+ get: function( owner, key ) {
+ // Either a valid cache is found, or will be created.
+ // New caches will be created and the unlock returned,
+ // allowing direct access to the newly created
+ // empty data object. A valid owner object must be provided.
+ var cache = this.cache[ this.key( owner ) ];
+
+ return key === undefined ?
+ cache : cache[ key ];
+ },
+ access: function( owner, key, value ) {
+ var stored;
+ // In cases where either:
+ //
+ // 1. No key was specified
+ // 2. A string key was specified, but no value provided
+ //
+ // Take the "read" path and allow the get method to determine
+ // which value to return, respectively either:
+ //
+ // 1. The entire cache object
+ // 2. The data stored at the key
+ //
+ if ( key === undefined ||
+ ((key && typeof key === "string") && value === undefined) ) {
+
+ stored = this.get( owner, key );
+
+ return stored !== undefined ?
+ stored : this.get( owner, jQuery.camelCase(key) );
+ }
+
+ // [*]When the key is not a string, or both a key and value
+ // are specified, set or extend (existing objects) with either:
+ //
+ // 1. An object of properties
+ // 2. A key and value
+ //
+ this.set( owner, key, value );
+
+ // Since the "set" path can have two possible entry points
+ // return the expected data based on which path was taken[*]
+ return value !== undefined ? value : key;
+ },
+ remove: function( owner, key ) {
+ var i, name, camel,
+ unlock = this.key( owner ),
+ cache = this.cache[ unlock ];
+
+ if ( key === undefined ) {
+ this.cache[ unlock ] = {};
+
+ } else {
+ // Support array or space separated string of keys
+ if ( jQuery.isArray( key ) ) {
+ // If "name" is an array of keys...
+ // When data is initially created, via ("key", "val") signature,
+ // keys will be converted to camelCase.
+ // Since there is no way to tell _how_ a key was added, remove
+ // both plain key and camelCase key. #12786
+ // This will only penalize the array argument path.
+ name = key.concat( key.map( jQuery.camelCase ) );
+ } else {
+ camel = jQuery.camelCase( key );
+ // Try the string as a key before any manipulation
+ if ( key in cache ) {
+ name = [ key, camel ];
+ } else {
+ // If a key with the spaces exists, use it.
+ // Otherwise, create an array by matching non-whitespace
+ name = camel;
+ name = name in cache ?
+ [ name ] : ( name.match( core_rnotwhite ) || [] );
+ }
+ }
+
+ i = name.length;
+ while ( i-- ) {
+ delete cache[ name[ i ] ];
+ }
+ }
+ },
+ hasData: function( owner ) {
+ return !jQuery.isEmptyObject(
+ this.cache[ owner[ this.expando ] ] || {}
+ );
+ },
+ discard: function( owner ) {
+ if ( owner[ this.expando ] ) {
+ delete this.cache[ owner[ this.expando ] ];
+ }
+ }
+};
+
+// These may be used throughout the jQuery core codebase
+data_user = new Data();
+data_priv = new Data();
+
+
+jQuery.extend({
+ acceptData: Data.accepts,
+
+ hasData: function( elem ) {
+ return data_user.hasData( elem ) || data_priv.hasData( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return data_user.access( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ data_user.remove( elem, name );
+ },
+
+ // TODO: Now that all calls to _data and _removeData have been replaced
+ // with direct calls to data_priv methods, these can be deprecated.
+ _data: function( elem, name, data ) {
+ return data_priv.access( elem, name, data );
+ },
+
+ _removeData: function( elem, name ) {
+ data_priv.remove( elem, name );
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var attrs, name,
+ elem = this[ 0 ],
+ i = 0,
+ data = null;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = data_user.get( elem );
+
+ if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {
+ attrs = elem.attributes;
+ for ( ; i < attrs.length; i++ ) {
+ name = attrs[ i ].name;
+
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.slice(5) );
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ data_priv.set( elem, "hasDataAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ data_user.set( this, key );
+ });
+ }
+
+ return jQuery.access( this, function( value ) {
+ var data,
+ camelKey = jQuery.camelCase( key );
+
+ // The calling jQuery object (element matches) is not empty
+ // (and therefore has an element appears at this[ 0 ]) and the
+ // `value` parameter was not undefined. An empty jQuery object
+ // will result in `undefined` for elem = this[ 0 ] which will
+ // throw an exception if an attempt to read a data cache is made.
+ if ( elem && value === undefined ) {
+ // Attempt to get data from the cache
+ // with the key as-is
+ data = data_user.get( elem, key );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // Attempt to get data from the cache
+ // with the key camelized
+ data = data_user.get( elem, camelKey );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // Attempt to "discover" the data in
+ // HTML5 custom data-* attrs
+ data = dataAttr( elem, camelKey, undefined );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // We tried really hard, but the data doesn't exist.
+ return;
+ }
+
+ // Set the data...
+ this.each(function() {
+ // First, attempt to store a copy or reference of any
+ // data that might've been store with a camelCased key.
+ var data = data_user.get( this, camelKey );
+
+ // For HTML5 data-* attribute interop, we have to
+ // store property names with dashes in a camelCase form.
+ // This might not apply to all properties...*
+ data_user.set( this, camelKey, value );
+
+ // *... In the case of properties that might _actually_
+ // have dashes, we need to also store a copy of that
+ // unchanged property.
+ if ( key.indexOf("-") !== -1 && data !== undefined ) {
+ data_user.set( this, key, value );
+ }
+ });
+ }, null, value, arguments.length > 1, null, true );
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ data_user.remove( this, key );
+ });
+ }
+});
+
+function dataAttr( elem, key, data ) {
+ var name;
+
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+ name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? JSON.parse( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ data_user.set( elem, key, data );
+ } else {
+ data = undefined;
+ }
+ }
+ return data;
+}
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = data_priv.get( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray( data ) ) {
+ queue = data_priv.access( elem, type, jQuery.makeArray(data) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return data_priv.get( elem, key ) || data_priv.access( elem, key, {
+ empty: jQuery.Callbacks("once memory").add(function() {
+ data_priv.remove( elem, [ type + "queue", key ] );
+ })
+ });
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ // Based off of the plugin by Clint Helfers, with permission.
+ // http://blindsignals.com/index.php/2009/07/jquery-delay/
+ delay: function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while( i-- ) {
+ tmp = data_priv.get( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+});
+var nodeHook, boolHook,
+ rclass = /[\t\r\n\f]/g,
+ rreturn = /\r/g,
+ rfocusable = /^(?:input|select|textarea|button)$/i;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ },
+
+ prop: function( name, value ) {
+ return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ return this.each(function() {
+ delete this[ jQuery.propFix[ name ] || name ];
+ });
+ },
+
+ addClass: function( value ) {
+ var classes, elem, cur, clazz, j,
+ i = 0,
+ len = this.length,
+ proceed = typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call( this, j, this.className ) );
+ });
+ }
+
+ if ( proceed ) {
+ // The disjunction here is for better compressibility (see removeClass)
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ " "
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+ elem.className = jQuery.trim( cur );
+
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, clazz, j,
+ i = 0,
+ len = this.length,
+ proceed = arguments.length === 0 || typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, this.className ) );
+ });
+ }
+ if ( proceed ) {
+ classes = ( value || "" ).match( core_rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ ""
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+ elem.className = value ? jQuery.trim( cur ) : "";
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value;
+
+ if ( typeof stateVal === "boolean" && type === "string" ) {
+ return stateVal ? this.addClass( value ) : this.removeClass( value );
+ }
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ classNames = value.match( core_rnotwhite ) || [];
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space separated list
+ if ( self.hasClass( className ) ) {
+ self.removeClass( className );
+ } else {
+ self.addClass( className );
+ }
+ }
+
+ // Toggle whole class name
+ } else if ( type === core_strundefined || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ data_priv.set( this, "__className__", this.className );
+ }
+
+ // If the element has a class name or if we're passed "false",
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+ return true;
+ }
+ }
+
+ return false;
+ },
+
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, jQuery( this ).val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map(val, function ( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ // attributes.value is undefined in Blackberry 4.7 but
+ // uses .value. See #6932
+ var val = elem.attributes.value;
+ return !val || val.specified ? elem.value : elem.text;
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one" || index < 0,
+ values = one ? null : [],
+ max = one ? index + 1 : options.length,
+ i = index < 0 ?
+ max :
+ one ? index : 0;
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // IE6-9 doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+ // Don't return options that are disabled or in a disabled optgroup
+ ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+ ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var optionSet, option,
+ options = elem.options,
+ values = jQuery.makeArray( value ),
+ i = options.length;
+
+ while ( i-- ) {
+ option = options[ i ];
+ if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) {
+ optionSet = true;
+ }
+ }
+
+ // force browsers to behave consistently when non-matching value is set
+ if ( !optionSet ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ },
+
+ attr: function( elem, name, value ) {
+ var hooks, ret,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === core_strundefined ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] ||
+ ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+
+ } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ ret = jQuery.find.attr( elem, name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name, propName,
+ i = 0,
+ attrNames = value && value.match( core_rnotwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( (name = attrNames[i++]) ) {
+ propName = jQuery.propFix[ name ] || name;
+
+ // Boolean attributes get special treatment (#10870)
+ if ( jQuery.expr.match.bool.test( name ) ) {
+ // Set corresponding property to false
+ elem[ propName ] = false;
+ }
+
+ elem.removeAttribute( name );
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to default in case type is set after value during creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ },
+
+ propFix: {
+ "for": "htmlFor",
+ "class": "className"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
+ ret :
+ ( elem[ name ] = value );
+
+ } else {
+ return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
+ ret :
+ elem[ name ];
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?
+ elem.tabIndex :
+ -1;
+ }
+ }
+ }
+});
+
+// Hooks for boolean attributes
+boolHook = {
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ elem.setAttribute( name, name );
+ }
+ return name;
+ }
+};
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+ var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr;
+
+ jQuery.expr.attrHandle[ name ] = function( elem, name, isXML ) {
+ var fn = jQuery.expr.attrHandle[ name ],
+ ret = isXML ?
+ undefined :
+ /* jshint eqeqeq: false */
+ // Temporarily disable this handler to check existence
+ (jQuery.expr.attrHandle[ name ] = undefined) !=
+ getter( elem, name, isXML ) ?
+
+ name.toLowerCase() :
+ null;
+
+ // Restore handler
+ jQuery.expr.attrHandle[ name ] = fn;
+
+ return ret;
+ };
+});
+
+// Support: IE9+
+// Selectedness for an option in an optgroup can be inaccurate
+if ( !jQuery.support.optSelected ) {
+ jQuery.propHooks.selected = {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+ if ( parent && parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ return null;
+ }
+ };
+}
+
+jQuery.each([
+ "tabIndex",
+ "readOnly",
+ "maxLength",
+ "cellSpacing",
+ "cellPadding",
+ "rowSpan",
+ "colSpan",
+ "useMap",
+ "frameBorder",
+ "contentEditable"
+], function() {
+ jQuery.propFix[ this.toLowerCase() ] = this;
+});
+
+// Radios and checkboxes getter/setter
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ };
+ if ( !jQuery.support.checkOn ) {
+ jQuery.valHooks[ this ].get = function( elem ) {
+ // Support: Webkit
+ // "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ };
+ }
+});
+var rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+function safeActiveElement() {
+ try {
+ return document.activeElement;
+ } catch ( err ) { }
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var handleObjIn, eventHandle, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = data_priv.get( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !(events = elemData.events) ) {
+ events = elemData.events = {};
+ }
+ if ( !(eventHandle = elemData.handle) ) {
+ eventHandle = elemData.handle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // There *must* be a type, no attaching namespace-only handlers
+ if ( !type ) {
+ continue;
+ }
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !(handlers = events[ type ]) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+
+ var j, origCount, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = data_priv.hasData( elem ) && data_priv.get( elem );
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( core_rnotwhite ) || [""];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ delete elemData.handle;
+ data_priv.remove( elem, "events" );
+ }
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+
+ var i, cur, tmp, bubbleType, ontype, handle, special,
+ eventPath = [ elem || document ],
+ type = core_hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf(".") >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf(":") < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+ event.isTrigger = onlyHandlers ? 2 : 3;
+ event.namespace = namespaces.join(".");
+ event.namespace_re = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === (elem.ownerDocument || document) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {
+ event.preventDefault();
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
+ jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event );
+
+ var i, j, ret, matched, handleObj,
+ handlerQueue = [],
+ args = core_slice.call( arguments ),
+ handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( (event.result = ret) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var i, matches, sel, handleObj,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Find delegate handlers
+ // Black-hole SVG <use> instance trees (#13180)
+ // Avoid non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+ for ( ; cur !== this; cur = cur.parentNode || this ) {
+
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.disabled !== true || event.type !== "click" ) {
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matches[ sel ] === undefined ) {
+ matches[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) >= 0 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matches[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, handlers: matches });
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+ }
+
+ return handlerQueue;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var eventDoc, doc, body,
+ button = original.button;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop, copy,
+ type = event.type,
+ originalEvent = event,
+ fixHook = this.fixHooks[ type ];
+
+ if ( !fixHook ) {
+ this.fixHooks[ type ] = fixHook =
+ rmouseEvent.test( type ) ? this.mouseHooks :
+ rkeyEvent.test( type ) ? this.keyHooks :
+ {};
+ }
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = new jQuery.Event( originalEvent );
+
+ i = copy.length;
+ while ( i-- ) {
+ prop = copy[ i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Support: Cordova 2.5 (WebKit) (#13255)
+ // All events should have a target; Cordova deviceready doesn't
+ if ( !event.target ) {
+ event.target = document;
+ }
+
+ // Support: Safari 6.0+, Chrome < 28
+ // Target should not be a text node (#504, #13143)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ special: {
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ focus: {
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== safeActiveElement() && this.focus ) {
+ this.focus();
+ return false;
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === safeActiveElement() && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+ click: {
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
+ this.click();
+ return false;
+ }
+ },
+
+ // For cross-browser consistency, don't fire native .click() on links
+ _default: function( event ) {
+ return jQuery.nodeName( event.target, "a" );
+ }
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Support: Firefox 20+
+ // Firefox doesn't alert if the returnValue field is not set.
+ if ( event.result !== undefined ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ {
+ type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+jQuery.removeEvent = function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+};
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = ( src.defaultPrevented ||
+ src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+
+ if ( e && e.preventDefault ) {
+ e.preventDefault();
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+
+ if ( e && e.stopPropagation ) {
+ e.stopPropagation();
+ }
+ },
+ stopImmediatePropagation: function() {
+ this.isImmediatePropagationStopped = returnTrue;
+ this.stopPropagation();
+ }
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+// Support: Chrome 15+
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+});
+
+// Create "bubbling" focus and blur events
+// Support: Firefox, Chrome, Safari
+if ( !jQuery.support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler while someone wants focusin/focusout
+ var attaches = 0,
+ handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ if ( attaches++ === 0 ) {
+ document.addEventListener( orig, handler, true );
+ }
+ },
+ teardown: function() {
+ if ( --attaches === 0 ) {
+ document.removeEventListener( orig, handler, true );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on( types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[0];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+});
+var isSimple = /^.[^:#\[\.,]*$/,
+ rparentsprev = /^(?:parents|prev(?:Until|All))/,
+ rneedsContext = jQuery.expr.match.needsContext,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var i,
+ ret = [],
+ self = this,
+ len = self.length;
+
+ if ( typeof selector !== "string" ) {
+ return this.pushStack( jQuery( selector ).filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ }) );
+ }
+
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, self[ i ], ret );
+ }
+
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+ ret.selector = this.selector ? this.selector + " " + selector : selector;
+ return ret;
+ },
+
+ has: function( target ) {
+ var targets = jQuery( target, this ),
+ l = targets.length;
+
+ return this.filter(function() {
+ var i = 0;
+ for ( ; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector || [], true) );
+ },
+
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector || [], false) );
+ },
+
+ is: function( selector ) {
+ return !!winnow(
+ this,
+
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ typeof selector === "string" && rneedsContext.test( selector ) ?
+ jQuery( selector ) :
+ selector || [],
+ false
+ ).length;
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ matched = [],
+ pos = ( rneedsContext.test( selectors ) || typeof selectors !== "string" ) ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+ // Always skip document fragments
+ if ( cur.nodeType < 11 && (pos ?
+ pos.index(cur) > -1 :
+
+ // Don't pass non-elements to Sizzle
+ cur.nodeType === 1 &&
+ jQuery.find.matchesSelector(cur, selectors)) ) {
+
+ cur = matched.push( cur );
+ break;
+ }
+ }
+ }
+
+ return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return core_indexOf.call( jQuery( elem ), this[ 0 ] );
+ }
+
+ // Locate the position of the desired element
+ return core_indexOf.call( this,
+
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[ 0 ] : elem
+ );
+ },
+
+ add: function( selector, context ) {
+ var set = typeof selector === "string" ?
+ jQuery( selector, context ) :
+ jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
+ all = jQuery.merge( this.get(), set );
+
+ return this.pushStack( jQuery.unique(all) );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter(selector)
+ );
+ }
+});
+
+function sibling( cur, dir ) {
+ while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}
+
+ return cur;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return elem.contentDocument || jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var matched = jQuery.map( this, fn, until );
+
+ if ( name.slice( -5 ) !== "Until" ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ matched = jQuery.filter( selector, matched );
+ }
+
+ if ( this.length > 1 ) {
+ // Remove duplicates
+ if ( !guaranteedUnique[ name ] ) {
+ jQuery.unique( matched );
+ }
+
+ // Reverse order for parents* and prev-derivatives
+ if ( rparentsprev.test( name ) ) {
+ matched.reverse();
+ }
+ }
+
+ return this.pushStack( matched );
+ };
+});
+
+jQuery.extend({
+ filter: function( expr, elems, not ) {
+ var elem = elems[ 0 ];
+
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 && elem.nodeType === 1 ?
+ jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+ jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+ return elem.nodeType === 1;
+ }));
+ },
+
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ truncate = until !== undefined;
+
+ while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {
+ if ( elem.nodeType === 1 ) {
+ if ( truncate && jQuery( elem ).is( until ) ) {
+ break;
+ }
+ matched.push( elem );
+ }
+ }
+ return matched;
+ },
+
+ sibling: function( n, elem ) {
+ var matched = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ matched.push( n );
+ }
+ }
+
+ return matched;
+ }
+});
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep( elements, function( elem, i ) {
+ /* jshint -W018 */
+ return !!qualifier.call( elem, i, elem ) !== not;
+ });
+
+ }
+
+ if ( qualifier.nodeType ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( elem === qualifier ) !== not;
+ });
+
+ }
+
+ if ( typeof qualifier === "string" ) {
+ if ( isSimple.test( qualifier ) ) {
+ return jQuery.filter( qualifier, elements, not );
+ }
+
+ qualifier = jQuery.filter( qualifier, elements );
+ }
+
+ return jQuery.grep( elements, function( elem ) {
+ return ( core_indexOf.call( qualifier, elem ) >= 0 ) !== not;
+ });
+}
+var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+ rtagName = /<([\w:]+)/,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style|link)/i,
+ manipulation_rcheckableType = /^(?:checkbox|radio)$/i,
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /^$|\/(?:java|ecma)script/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+ // We have to close these tags to support XHTML (#13200)
+ wrapMap = {
+
+ // Support: IE 9
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+
+ thead: [ 1, "<table>", "</table>" ],
+ col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+ _default: [ 0, "", "" ]
+ };
+
+// Support: IE 9
+wrapMap.optgroup = wrapMap.option;
+
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+jQuery.fn.extend({
+ text: function( value ) {
+ return jQuery.access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().append( ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) );
+ }, null, value, arguments.length );
+ },
+
+ append: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.insertBefore( elem, target.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ });
+ },
+
+ after: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ });
+ },
+
+ // keepData is for internal use only--do not document
+ remove: function( selector, keepData ) {
+ var elem,
+ elems = selector ? jQuery.filter( selector, this ) : this,
+ i = 0;
+
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem ) );
+ }
+
+ if ( elem.parentNode ) {
+ if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+ setGlobalEval( getAll( elem, "script" ) );
+ }
+ elem.parentNode.removeChild( elem );
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ if ( elem.nodeType === 1 ) {
+
+ // Prevent memory leaks
+ jQuery.cleanData( getAll( elem, false ) );
+
+ // Remove any remaining nodes
+ elem.textContent = "";
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function () {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ return jQuery.access( this, function( value ) {
+ var elem = this[ 0 ] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined && elem.nodeType === 1 ) {
+ return elem.innerHTML;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
+
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+ try {
+ for ( ; i < l; i++ ) {
+ elem = this[ i ] || {};
+
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch( e ) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function() {
+ var
+ // Snapshot the DOM in case .domManip sweeps something relevant into its fragment
+ args = jQuery.map( this, function( elem ) {
+ return [ elem.nextSibling, elem.parentNode ];
+ }),
+ i = 0;
+
+ // Make the changes, replacing each context element with the new content
+ this.domManip( arguments, function( elem ) {
+ var next = args[ i++ ],
+ parent = args[ i++ ];
+
+ if ( parent ) {
+ // Don't use the snapshot next if it has moved (#13810)
+ if ( next && next.parentNode !== parent ) {
+ next = this.nextSibling;
+ }
+ jQuery( this ).remove();
+ parent.insertBefore( elem, next );
+ }
+ // Allow new content to include elements from the context set
+ }, true );
+
+ // Force removal if there was no new content (e.g., from empty arguments)
+ return i ? this : this.remove();
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, callback, allowIntersection ) {
+
+ // Flatten any nested arrays
+ args = core_concat.apply( [], args );
+
+ var fragment, first, scripts, hasScripts, node, doc,
+ i = 0,
+ l = this.length,
+ set = this,
+ iNoClone = l - 1,
+ value = args[ 0 ],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {
+ return this.each(function( index ) {
+ var self = set.eq( index );
+ if ( isFunction ) {
+ args[ 0 ] = value.call( this, index, self.html() );
+ }
+ self.domManip( args, callback, allowIntersection );
+ });
+ }
+
+ if ( l ) {
+ fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ if ( first ) {
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+ // Support: QtWebKit
+ // jQuery.merge because core_push.apply(_, arraylike) throws
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call( this[ i ], node, i );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+ // Hope ajax is available...
+ jQuery._evalUrl( node.src );
+ } else {
+ jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return this;
+ }
+});
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1,
+ i = 0;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone( true );
+ jQuery( insert[ i ] )[ original ]( elems );
+
+ // Support: QtWebKit
+ // .get() because core_push.apply(_, arraylike) throws
+ core_push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+});
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var i, l, srcElements, destElements,
+ clone = elem.cloneNode( true ),
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ // Support: IE >= 9
+ // Fix Cloning issues
+ if ( !jQuery.support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) {
+
+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ fixInput( srcElements[ i ], destElements[ i ] );
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ cloneCopyEvent( srcElements[ i ], destElements[ i ] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ // Return the cloned set
+ return clone;
+ },
+
+ buildFragment: function( elems, context, scripts, selection ) {
+ var elem, tmp, tag, wrap, contains, j,
+ i = 0,
+ l = elems.length,
+ fragment = context.createDocumentFragment(),
+ nodes = [];
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+ // Support: QtWebKit
+ // jQuery.merge because core_push.apply(_, arraylike) throws
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || fragment.appendChild( context.createElement("div") );
+
+ // Deserialize a standard representation
+ tag = ( rtagName.exec( elem ) || ["", ""] )[ 1 ].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+ tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];
+
+ // Descend through wrappers to the right content
+ j = wrap[ 0 ];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Support: QtWebKit
+ // jQuery.merge because core_push.apply(_, arraylike) throws
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Remember the top-level container
+ tmp = fragment.firstChild;
+
+ // Fixes #12346
+ // Support: Webkit, IE
+ tmp.textContent = "";
+ }
+ }
+ }
+
+ // Remove wrapper from fragment
+ fragment.textContent = "";
+
+ i = 0;
+ while ( (elem = nodes[ i++ ]) ) {
+
+ // #4087 - If origin and destination elements are the same, and this is
+ // that element, do not do anything
+ if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( fragment.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( (elem = tmp[ j++ ]) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ return fragment;
+ },
+
+ cleanData: function( elems ) {
+ var data, elem, events, type, key, j,
+ special = jQuery.event.special,
+ i = 0;
+
+ for ( ; (elem = elems[ i ]) !== undefined; i++ ) {
+ if ( Data.accepts( elem ) ) {
+ key = elem[ data_priv.expando ];
+
+ if ( key && (data = data_priv.cache[ key ]) ) {
+ events = Object.keys( data.events || {} );
+ if ( events.length ) {
+ for ( j = 0; (type = events[j]) !== undefined; j++ ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+ if ( data_priv.cache[ key ] ) {
+ // Discard any remaining `private` data
+ delete data_priv.cache[ key ];
+ }
+ }
+ }
+ // Discard any remaining `user` data
+ delete data_user.cache[ elem[ data_user.expando ] ];
+ }
+ },
+
+ _evalUrl: function( url ) {
+ return jQuery.ajax({
+ url: url,
+ type: "GET",
+ dataType: "script",
+ async: false,
+ global: false,
+ "throws": true
+ });
+ }
+});
+
+// Support: 1.x compatibility
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+ return jQuery.nodeName( elem, "table" ) &&
+ jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ?
+
+ elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
+ elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+ elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
+ return elem;
+}
+function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+
+ if ( match ) {
+ elem.type = match[ 1 ];
+ } else {
+ elem.removeAttribute("type");
+ }
+
+ return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var l = elems.length,
+ i = 0;
+
+ for ( ; i < l; i++ ) {
+ data_priv.set(
+ elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )
+ );
+ }
+}
+
+function cloneCopyEvent( src, dest ) {
+ var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
+
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ // 1. Copy private data: events, handlers, etc.
+ if ( data_priv.hasData( src ) ) {
+ pdataOld = data_priv.access( src );
+ pdataCur = data_priv.set( dest, pdataOld );
+ events = pdataOld.events;
+
+ if ( events ) {
+ delete pdataCur.handle;
+ pdataCur.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+ }
+
+ // 2. Copy user data
+ if ( data_user.hasData( src ) ) {
+ udataOld = data_user.access( src );
+ udataCur = jQuery.extend( {}, udataOld );
+
+ data_user.set( dest, udataCur );
+ }
+}
+
+
+function getAll( context, tag ) {
+ var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :
+ context.querySelectorAll ? context.querySelectorAll( tag || "*" ) :
+ [];
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], ret ) :
+ ret;
+}
+
+// Support: IE >= 9
+function fixInput( src, dest ) {
+ var nodeName = dest.nodeName.toLowerCase();
+
+ // Fails to persist the checked state of a cloned checkbox or radio button.
+ if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {
+ dest.checked = src.checked;
+
+ // Fails to return the selected option to the default selected state when cloning options
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+}
+jQuery.fn.extend({
+ wrapAll: function( html ) {
+ var wrap;
+
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[ 0 ] ) {
+
+ // The elements to wrap the target around
+ wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
+
+ if ( this[ 0 ].parentNode ) {
+ wrap.insertBefore( this[ 0 ] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstElementChild ) {
+ elem = elem.firstElementChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function( i ) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ }
+});
+var curCSS, iframe,
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ rmargin = /^margin/,
+ rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),
+ rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),
+ rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),
+ elemdisplay = { BODY: "block" },
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: 0,
+ fontWeight: 400
+ },
+
+ cssExpand = [ "Top", "Right", "Bottom", "Left" ],
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+ // shortcut for names that are not vendor prefixed
+ if ( name in style ) {
+ return name;
+ }
+
+ // check for vendor prefixed names
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
+ origName = name,
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in style ) {
+ return name;
+ }
+ }
+
+ return origName;
+}
+
+function isHidden( elem, el ) {
+ // isHidden might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+}
+
+// NOTE: we've included the "window" in window.getComputedStyle
+// because jsdom on node.js will break without it.
+function getStyles( elem ) {
+ return window.getComputedStyle( elem, null );
+}
+
+function showHide( elements, show ) {
+ var display, elem, hidden,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ values[ index ] = data_priv.get( elem, "olddisplay" );
+ display = elem.style.display;
+ if ( show ) {
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !values[ index ] && display === "none" ) {
+ elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( elem.style.display === "" && isHidden( elem ) ) {
+ values[ index ] = data_priv.access( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );
+ }
+ } else {
+
+ if ( !values[ index ] ) {
+ hidden = isHidden( elem );
+
+ if ( display && display !== "none" || !hidden ) {
+ data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css(elem, "display") );
+ }
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( index = 0; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+ elem.style.display = show ? values[ index ] || "" : "none";
+ }
+ }
+
+ return elements;
+}
+
+jQuery.fn.extend({
+ css: function( name, value ) {
+ return jQuery.access( this, function( elem, name, value ) {
+ var styles, len,
+ map = {},
+ i = 0;
+
+ if ( jQuery.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ },
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ if ( typeof state === "boolean" ) {
+ return state ? this.show() : this.hide();
+ }
+
+ return this.each(function() {
+ if ( isHidden( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Don't automatically add "px" to these possibly-unitless properties
+ cssNumber: {
+ "columnCount": true,
+ "fillOpacity": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "order": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": "cssFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ style = elem.style;
+
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that NaN and null values aren't set. See: #7116
+ if ( value == null || type === "number" && isNaN( value ) ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // Fixes #8908, it can be done more correctly by specifying setters in cssHooks,
+ // but it would mean to define eight (for every problematic property) identical functions
+ if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+ style[ name ] = value;
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var val, num, hooks,
+ origName = jQuery.camelCase( name );
+
+ // Make sure that we're working with the right name
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ //convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+ }
+ return val;
+ }
+});
+
+curCSS = function( elem, name, _computed ) {
+ var width, minWidth, maxWidth,
+ computed = _computed || getStyles( elem ),
+
+ // Support: IE9
+ // getPropertyValue is only needed for .css('filter') in IE9, see #12537
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,
+ style = elem.style;
+
+ if ( computed ) {
+
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // Support: Safari 5.1
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ return ret;
+};
+
+
+function setPositiveNumber( elem, value, subtract ) {
+ var matches = rnumsplit.exec( value );
+ return matches ?
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+ value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+ // Otherwise initialize for horizontal or vertical properties
+ name === "width" ? 1 : 0,
+
+ val = 0;
+
+ for ( ; i < 4; i += 2 ) {
+ // both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // at this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+ // at this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // at this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property, which is equivalent to the border-box value
+ var valueIsBorderBox = true,
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ styles = getStyles( elem ),
+ isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, styles );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // we need the check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+}
+
+// Try to determine the default display value of an element
+function css_defaultDisplay( nodeName ) {
+ var doc = document,
+ display = elemdisplay[ nodeName ];
+
+ if ( !display ) {
+ display = actualDisplay( nodeName, doc );
+
+ // If the simple way fails, read from inside an iframe
+ if ( display === "none" || !display ) {
+ // Use the already-created iframe if possible
+ iframe = ( iframe ||
+ jQuery("<iframe frameborder='0' width='0' height='0'/>")
+ .css( "cssText", "display:block !important" )
+ ).appendTo( doc.documentElement );
+
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+ doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
+ doc.write("<!doctype html><html><body>");
+ doc.close();
+
+ display = actualDisplay( nodeName, doc );
+ iframe.detach();
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return display;
+}
+
+// Called ONLY from within css_defaultDisplay
+function actualDisplay( name, doc ) {
+ var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+ display = jQuery.css( elem[0], "display" );
+ elem.remove();
+ return display;
+}
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+ // certain elements can have dimension info if we invisibly show them
+ // however, it must have a current display style that would benefit from this
+ return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?
+ jQuery.swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ }) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var styles = extra && getStyles( elem );
+ return setPositiveNumber( elem, value, extra ?
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ ) : 0
+ );
+ }
+ };
+});
+
+// These hooks cannot be added until DOM ready because the support test
+// for it is not run until after DOM ready
+jQuery(function() {
+ // Support: Android 2.3
+ if ( !jQuery.support.reliableMarginRight ) {
+ jQuery.cssHooks.marginRight = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // Support: Android 2.3
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ return jQuery.swap( elem, { "display": "inline-block" },
+ curCSS, [ elem, "marginRight" ] );
+ }
+ }
+ };
+ }
+
+ // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+ // getComputedStyle returns percent when specified for top/left/bottom/right
+ // rather than make the css module depend on the offset module, we just check for it here
+ if ( !jQuery.support.pixelPosition && jQuery.fn.position ) {
+ jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+ // if curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ };
+ });
+ }
+
+});
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.hidden = function( elem ) {
+ // Support: Opera <= 12.12
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
+ return elem.offsetWidth <= 0 && elem.offsetHeight <= 0;
+ };
+
+ jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+ };
+}
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+});
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+jQuery.fn.extend({
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map(function(){
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ })
+ .filter(function(){
+ var type = this.type;
+ // Use .is(":disabled") so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !manipulation_rcheckableType.test( type ) );
+ })
+ .map(function( i, elem ){
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val ){
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+//Serialize an array of form elements or a set of
+//key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+};
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+});
+
+jQuery.fn.extend({
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+ }
+});
+var
+ // Document location
+ ajaxLocParts,
+ ajaxLocation,
+
+ ajax_nonce = jQuery.now(),
+
+ ajax_rquery = /\?/,
+ rhash = /#.*$/,
+ rts = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,
+
+ // Keep a copy of the old load method
+ _load = jQuery.fn.load,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+ ajaxLocation = location.href;
+} catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+ // For each dataType in the dataTypeExpression
+ while ( (dataType = dataTypes[i++]) ) {
+ // Prepend if requested
+ if ( dataType[0] === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+ // Otherwise append
+ } else {
+ (structure[ dataType ] = structure[ dataType ] || []).push( func );
+ }
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ });
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var key, deep,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+}
+
+jQuery.fn.load = function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+ }
+
+ var selector, type, response,
+ self = this,
+ off = url.indexOf(" ");
+
+ if ( off >= 0 ) {
+ selector = url.slice( off );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax({
+ url: url,
+
+ // if "type" variable is undefined, then "GET" method will be used
+ type: type,
+ dataType: "html",
+ data: params
+ }).done(function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ }).complete( callback && function( jqXHR, status ) {
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ });
+ }
+
+ return this;
+};
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){
+ jQuery.fn[ type ] = function( fn ){
+ return this.on( type, fn );
+ };
+});
+
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ type: "GET",
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText",
+ json: "responseJSON"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var transport,
+ // URL without anti-cache param
+ cacheURL,
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+ // timeout handle
+ timeoutTimer,
+ // Cross-domain detection vars
+ parts,
+ // To know if global events are to be dispatched
+ fireGlobals,
+ // Loop variable
+ i,
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks("once memory"),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // The jqXHR state
+ state = 0,
+ // Default abort message
+ strAbort = "canceled",
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( (match = rheaders.exec( responseHeadersString )) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ var lname = name.toLowerCase();
+ if ( !state ) {
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( state < 2 ) {
+ for ( code in map ) {
+ // Lazy-add the new callback in a way that preserves old ones
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ } else {
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (prefilters might expect it)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )
+ .replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];
+
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ fireGlobals = s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger("ajaxStart");
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ cacheURL = s.url;
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+ s.url = rts.test( cacheURL ) ?
+
+ // If there is already a '_' parameter, set its value
+ cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :
+
+ // Otherwise add one to the end
+ cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;
+ }
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout(function() {
+ jqXHR.abort("timeout");
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Determine if successful
+ isSuccess = status >= 200 && status < 300 || status === 304;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // Convert no matter what (that way responseXXX fields are always set)
+ response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+ // If successful, handle type chaining
+ if ( isSuccess ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader("Last-Modified");
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader("etag");
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 || s.type === "HEAD" ) {
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ statusText = response.state;
+ success = response.data;
+ error = response.error;
+ isSuccess = !error;
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger("ajaxStop");
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ }
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ });
+ };
+});
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+ var ct, type, finalDataType, firstDataType,
+ contents = s.contents,
+ dataTypes = s.dataTypes;
+
+ // Remove auto dataType and get content-type in the process
+ while( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+ var conv2, current, conv, tmp, prev,
+ converters = {},
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice();
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ current = dataTypes.shift();
+
+ // Convert to each sequential dataType
+ while ( current ) {
+
+ if ( s.responseFields[ current ] ) {
+ jqXHR[ s.responseFields[ current ] ] = response;
+ }
+
+ // Apply the dataFilter if provided
+ if ( !prev && isSuccess && s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ prev = current;
+ current = dataTypes.shift();
+
+ if ( current ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current === "*" ) {
+
+ current = prev;
+
+ // Convert response if prev dataType is non-auto and differs from current
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split( " " );
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.unshift( tmp[ 1 ] );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s[ "throws" ] ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return { state: "success", data: response };
+}
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /(?:java|ecma)script/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and crossDomain
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function( s ) {
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+ var script, callback;
+ return {
+ send: function( _, complete ) {
+ script = jQuery("<script>").prop({
+ async: true,
+ charset: s.scriptCharset,
+ src: s.url
+ }).on(
+ "load error",
+ callback = function( evt ) {
+ script.remove();
+ callback = null;
+ if ( evt ) {
+ complete( evt.type === "error" ? 404 : 200, evt.type );
+ }
+ }
+ );
+ document.head.appendChild( script[ 0 ] );
+ },
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+});
+var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always(function() {
+ // Restore preexisting value
+ window[ callbackName ] = overwritten;
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+ // make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ });
+
+ // Delegate to script
+ return "script";
+ }
+});
+jQuery.ajaxSettings.xhr = function() {
+ try {
+ return new XMLHttpRequest();
+ } catch( e ) {}
+};
+
+var xhrSupported = jQuery.ajaxSettings.xhr(),
+ xhrSuccessStatus = {
+ // file protocol always yields status code 0, assume 200
+ 0: 200,
+ // Support: IE9
+ // #1450: sometimes IE returns 1223 when it should be 204
+ 1223: 204
+ },
+ // Support: IE9
+ // We need to keep track of outbound xhr and abort them manually
+ // because IE is not smart enough to do it all by itself
+ xhrId = 0,
+ xhrCallbacks = {};
+
+if ( window.ActiveXObject ) {
+ jQuery( window ).on( "unload", function() {
+ for( var key in xhrCallbacks ) {
+ xhrCallbacks[ key ]();
+ }
+ xhrCallbacks = undefined;
+ });
+}
+
+jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+jQuery.support.ajax = xhrSupported = !!xhrSupported;
+
+jQuery.ajaxTransport(function( options ) {
+ var callback;
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( jQuery.support.cors || xhrSupported && !options.crossDomain ) {
+ return {
+ send: function( headers, complete ) {
+ var i, id,
+ xhr = options.xhr();
+ xhr.open( options.type, options.url, options.async, options.username, options.password );
+ // Apply custom fields if provided
+ if ( options.xhrFields ) {
+ for ( i in options.xhrFields ) {
+ xhr[ i ] = options.xhrFields[ i ];
+ }
+ }
+ // Override mime type if needed
+ if ( options.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( options.mimeType );
+ }
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !options.crossDomain && !headers["X-Requested-With"] ) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+ // Set headers
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+ // Callback
+ callback = function( type ) {
+ return function() {
+ if ( callback ) {
+ delete xhrCallbacks[ id ];
+ callback = xhr.onload = xhr.onerror = null;
+ if ( type === "abort" ) {
+ xhr.abort();
+ } else if ( type === "error" ) {
+ complete(
+ // file protocol always yields status 0, assume 404
+ xhr.status || 404,
+ xhr.statusText
+ );
+ } else {
+ complete(
+ xhrSuccessStatus[ xhr.status ] || xhr.status,
+ xhr.statusText,
+ // Support: IE9
+ // #11426: When requesting binary data, IE9 will throw an exception
+ // on any attempt to access responseText
+ typeof xhr.responseText === "string" ? {
+ text: xhr.responseText
+ } : undefined,
+ xhr.getAllResponseHeaders()
+ );
+ }
+ }
+ };
+ };
+ // Listen to events
+ xhr.onload = callback();
+ xhr.onerror = callback("error");
+ // Create the abort callback
+ callback = xhrCallbacks[( id = xhrId++ )] = callback("abort");
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( options.hasContent && options.data || null );
+ },
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+});
+var fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),
+ rrun = /queueHooks$/,
+ animationPrefilters = [ defaultPrefilter ],
+ tweeners = {
+ "*": [function( prop, value ) {
+ var tween = this.createTween( prop, value ),
+ target = tween.cur(),
+ parts = rfxnum.exec( value ),
+ unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+ // Starting value computation is required for potential unit mismatches
+ start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
+ rfxnum.exec( jQuery.css( tween.elem, prop ) ),
+ scale = 1,
+ maxIterations = 20;
+
+ if ( start && start[ 3 ] !== unit ) {
+ // Trust units reported by jQuery.css
+ unit = unit || start[ 3 ];
+
+ // Make sure we update the tween properties later on
+ parts = parts || [];
+
+ // Iteratively approximate from a nonzero starting point
+ start = +target || 1;
+
+ do {
+ // If previous iteration zeroed out, double until we get *something*
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ start = start / scale;
+ jQuery.style( tween.elem, prop, start + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+ }
+
+ // Update tween properties
+ if ( parts ) {
+ start = tween.start = +start || +target || 0;
+ tween.unit = unit;
+ // If a +=/-= token was provided, we're doing a relative animation
+ tween.end = parts[ 1 ] ?
+ start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+ +parts[ 2 ];
+ }
+
+ return tween;
+ }]
+ };
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout(function() {
+ fxNow = undefined;
+ });
+ return ( fxNow = jQuery.now() );
+}
+
+function createTween( value, prop, animation ) {
+ var tween,
+ collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( (tween = collection[ index ].call( animation, prop, value )) ) {
+
+ // we're done with this property
+ return tween;
+ }
+ }
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = animationPrefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+ // don't match elem in the :animated selector
+ delete tick.elem;
+ }),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+ if ( percent < 1 && length ) {
+ return remaining;
+ } else {
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ }
+ },
+ animation = deferred.promise({
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+ // if we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // resolve when we played the last frame
+ // otherwise, reject
+ if ( gotoEnd ) {
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ }),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length ; index++ ) {
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ return result;
+ }
+ }
+
+ jQuery.map( props, createTween, animation );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ })
+ );
+
+ // attach callbacks from options
+ return animation.progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+}
+
+function propFilter( props, specialEasing ) {
+ var index, name, easing, value, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'index' from above because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.split(" ");
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length ; index++ ) {
+ prop = props[ index ];
+ tweeners[ prop ] = tweeners[ prop ] || [];
+ tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ animationPrefilters.unshift( callback );
+ } else {
+ animationPrefilters.push( callback );
+ }
+ }
+});
+
+function defaultPrefilter( elem, props, opts ) {
+ /* jshint validthis: true */
+ var prop, value, toggle, tween, hooks, oldfire,
+ anim = this,
+ orig = {},
+ style = elem.style,
+ hidden = elem.nodeType && isHidden( elem ),
+ dataShow = data_priv.get( elem, "fxshow" );
+
+ // handle queue: false promises
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always(function() {
+ // doing this makes sure that the complete handler will be called
+ // before this completes
+ anim.always(function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ });
+ });
+ }
+
+ // height/width overflow pass
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE9-10 do not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ if ( jQuery.css( elem, "display" ) === "inline" &&
+ jQuery.css( elem, "float" ) === "none" ) {
+
+ style.display = "inline-block";
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ anim.always(function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ });
+ }
+
+
+ // show/hide pass
+ for ( prop in props ) {
+ value = props[ prop ];
+ if ( rfxtypes.exec( value ) ) {
+ delete props[ prop ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+
+ // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
+ if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+ hidden = true;
+ } else {
+ continue;
+ }
+ }
+ orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+ }
+ }
+
+ if ( !jQuery.isEmptyObject( orig ) ) {
+ if ( dataShow ) {
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+ } else {
+ dataShow = data_priv.access( elem, "fxshow", {} );
+ }
+
+ // store state if its toggle - enables .stop().toggle() to "reverse"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+ if ( hidden ) {
+ jQuery( elem ).show();
+ } else {
+ anim.done(function() {
+ jQuery( elem ).hide();
+ });
+ }
+ anim.done(function() {
+ var prop;
+
+ data_priv.remove( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ });
+ for ( prop in orig ) {
+ tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = tween.start;
+ if ( hidden ) {
+ tween.end = tween.start;
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ }
+ }
+ }
+ }
+}
+
+function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || "swing";
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ if ( tween.elem[ tween.prop ] != null &&
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails
+ // so, simple values such as "10px" are parsed to Float.
+ // complex values such as "rotate(1rad)" are returned as is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+ // use step hook for back compat - use cssHook if its there - use .style if its
+ // available and use plain properties where available
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+};
+
+// Support: IE9
+// Panic based approach to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+};
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+});
+
+jQuery.fn.extend({
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // show any hidden elements after setting opacity to 0
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+ // animate to the value specified
+ .end().animate({ opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+ // Empty animations, or finishing resolves immediately
+ if ( empty || data_priv.get( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = data_priv.get( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each(function() {
+ var index,
+ data = data_priv.get( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // enable finishing flag on private data
+ data.finish = true;
+
+ // empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.stop ) {
+ hooks.stop.call( this, true );
+ }
+
+ // look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // turn off finishing flag
+ delete data.finish;
+ });
+ }
+});
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ attrs = { height: type },
+ i = 0;
+
+ // if we include width, step value is 1 to do all cssExpand values,
+ // if we don't include width, step value is 2 to skip over Left and Right
+ includeWidth = includeWidth? 1 : 0;
+ for( ; i < 4 ; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+}
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show"),
+ slideUp: genFx("hide"),
+ slideToggle: genFx("toggle"),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+};
+
+jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p*Math.PI ) / 2;
+ }
+};
+
+jQuery.timers = [];
+jQuery.fx = Tween.prototype.init;
+jQuery.fx.tick = function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+ if ( timer() && jQuery.timers.push( timer ) ) {
+ jQuery.fx.start();
+ }
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+};
+
+jQuery.fx.stop = function() {
+ clearInterval( timerId );
+ timerId = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+};
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+if ( jQuery.expr && jQuery.expr.filters ) {
+ jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+ };
+}
+jQuery.fn.offset = function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ elem = this[ 0 ],
+ box = { top: 0, left: 0 },
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ // If we don't have gBCR, just use 0,0 rather than error
+ // BlackBerry 5, iOS 3 (original iPhone)
+ if ( typeof elem.getBoundingClientRect !== core_strundefined ) {
+ box = elem.getBoundingClientRect();
+ }
+ win = getWindow( doc );
+ return {
+ top: box.top + win.pageYOffset - docElem.clientTop,
+ left: box.left + win.pageXOffset - docElem.clientLeft
+ };
+};
+
+jQuery.offset = {
+
+ setOffset: function( elem, options, i ) {
+ var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+ position = jQuery.css( elem, "position" ),
+ curElem = jQuery( elem ),
+ props = {};
+
+ // Set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ curOffset = curElem.offset();
+ curCSSTop = jQuery.css( elem, "top" );
+ curCSSLeft = jQuery.css( elem, "left" );
+ calculatePosition = ( position === "absolute" || position === "fixed" ) && ( curCSSTop + curCSSLeft ).indexOf("auto") > -1;
+
+ // Need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+
+jQuery.fn.extend({
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ elem = this[ 0 ],
+ parentOffset = { top: 0, left: 0 };
+
+ // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+ // We assume that getBoundingClientRect is available when computed position is fixed
+ offset = elem.getBoundingClientRect();
+
+ } else {
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || docElem;
+
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ return offsetParent || docElem;
+ });
+ }
+});
+
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {
+ var top = "pageYOffset" === prop;
+
+ jQuery.fn[ method ] = function( val ) {
+ return jQuery.access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? win[ prop ] : elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : window.pageXOffset,
+ top ? val : window.pageYOffset
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+});
+
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
+}
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+ // margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return jQuery.access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
+ // whichever is greatest
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ });
+});
+// Limit scope pollution from any deprecated API
+// (function() {
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+ return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+// })();
+if ( typeof module === "object" && module && typeof module.exports === "object" ) {
+ // Expose jQuery as module.exports in loaders that implement the Node
+ // module pattern (including browserify). Do not create the global, since
+ // the user will be storing it themselves locally, and globals are frowned
+ // upon in the Node module world.
+ module.exports = jQuery;
+} else {
+ // Register as a named AMD module, since jQuery can be concatenated with other
+ // files that may use define, but not via a proper concatenation script that
+ // understands anonymous AMD modules. A named AMD is safest and most robust
+ // way to register. Lowercase jquery is used because AMD module names are
+ // derived from file names, and jQuery is normally delivered in a lowercase
+ // file name. Do this after creating the global so that if an AMD module wants
+ // to call noConflict to hide this version of jQuery, it will work.
+ if ( typeof define === "function" && define.amd ) {
+ define( "jquery", [], function () { return jQuery; } );
+ }
+}
+
+// If there is a window object, that at least has a document property,
+// define jQuery and $ identifiers
+if ( typeof window === "object" && typeof window.document === "object" ) {
+ window.jQuery = window.$ = jQuery;
+}
+
+})( window );
diff --git a/docs/htmldoc/js/jquery-2.0.3.min.js b/docs/htmldoc/js/jquery-2.0.3.min.js
new file mode 100644
index 0000000..2be209d
--- /dev/null
+++ b/docs/htmldoc/js/jquery-2.0.3.min.js
@@ -0,0 +1,6 @@
+/*! jQuery v2.0.3 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license
+//@ sourceMappingURL=jquery-2.0.3.min.map
+*/
+(function(e,undefined){var t,n,r=typeof undefined,i=e.location,o=e.document,s=o.documentElement,a=e.jQuery,u=e.$,l={},c=[],p="2.0.3",f=c.concat,h=c.push,d=c.slice,g=c.indexOf,m=l.toString,y=l.hasOwnProperty,v=p.trim,x=function(e,n){return new x.fn.init(e,n,t)},b=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,w=/\S+/g,T=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,C=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,k=/^-ms-/,N=/-([\da-z])/gi,E=function(e,t){return t.toUpperCase()},S=function(){o.removeEventListener("DOMContentLoaded",S,!1),e.removeEventListener("load",S,!1),x.ready()};x.fn=x.prototype={jquery:p,constructor:x,init:function(e,t,n){var r,i;if(!e)return this;if("string"==typeof e){if(r="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:T.exec(e),!r||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof x?t[0]:t,x.merge(this,x.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:o,!0)),C.test(r[1])&&x.isPlainObject(t))for(r in t)x.isFunction(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return i=o.getElementById(r[2]),i&&i.parentNode&&(this.length=1,this[0]=i),this.context=o,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?n.ready(e):(e.selector!==undefined&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return d.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,t,n,r,i,o,s=arguments[0]||{},a=1,u=arguments.length,l=!1;for("boolean"==typeof s&&(l=s,s=arguments[1]||{},a=2),"object"==typeof s||x.isFunction(s)||(s={}),u===a&&(s=this,--a);u>a;a++)if(null!=(e=arguments[a]))for(t in e)n=s[t],r=e[t],s!==r&&(l&&r&&(x.isPlainObject(r)||(i=x.isArray(r)))?(i?(i=!1,o=n&&x.isArray(n)?n:[]):o=n&&x.isPlainObject(n)?n:{},s[t]=x.extend(l,o,r)):r!==undefined&&(s[t]=r));return s},x.extend({expando:"jQuery"+(p+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=a),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){(e===!0?--x.readyWait:x.isReady)||(x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(o,[x]),x.fn.trigger&&x(o).trigger("ready").off("ready")))},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray,isWindow:function(e){return null!=e&&e===e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?l[m.call(e)]||"object":typeof e},isPlainObject:function(e){if("object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!y.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(t){return!1}return!0},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||o;var r=C.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:JSON.parse,parseXML:function(e){var t,n;if(!e||"string"!=typeof e)return null;try{n=new DOMParser,t=n.parseFromString(e,"text/xml")}catch(r){t=undefined}return(!t||t.getElementsByTagName("parsererror").length)&&x.error("Invalid XML: "+e),t},noop:function(){},globalEval:function(e){var t,n=eval;e=x.trim(e),e&&(1===e.indexOf("use strict")?(t=o.createElement("script"),t.text=e,o.head.appendChild(t).parentNode.removeChild(t)):n(e))},camelCase:function(e){return e.replace(k,"ms-").replace(N,E)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,s=j(e);if(n){if(s){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(s){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:function(e){return null==e?"":v.call(e)},makeArray:function(e,t){var n=t||[];return null!=e&&(j(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:g.call(t,e,n)},merge:function(e,t){var n=t.length,r=e.length,i=0;if("number"==typeof n)for(;n>i;i++)e[r++]=t[i];else while(t[i]!==undefined)e[r++]=t[i++];return e.length=r,e},grep:function(e,t,n){var r,i=[],o=0,s=e.length;for(n=!!n;s>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,s=j(e),a=[];if(s)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(a[a.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(a[a.length]=r);return f.apply([],a)},guid:1,proxy:function(e,t){var n,r,i;return"string"==typeof t&&(n=e[t],t=e,e=n),x.isFunction(e)?(r=d.call(arguments,2),i=function(){return e.apply(t||this,r.concat(d.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):undefined},access:function(e,t,n,r,i,o,s){var a=0,u=e.length,l=null==n;if("object"===x.type(n)){i=!0;for(a in n)x.access(e,t,a,n[a],!0,o,s)}else if(r!==undefined&&(i=!0,x.isFunction(r)||(s=!0),l&&(s?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(x(e),n)})),t))for(;u>a;a++)t(e[a],n,s?r:r.call(e[a],a,t(e[a],n)));return i?e:l?t.call(e):u?t(e[0],n):o},now:Date.now,swap:function(e,t,n,r){var i,o,s={};for(o in t)s[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=s[o];return i}}),x.ready.promise=function(t){return n||(n=x.Deferred(),"complete"===o.readyState?setTimeout(x.ready):(o.addEventListener("DOMContentLoaded",S,!1),e.addEventListener("load",S,!1))),n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){l["[object "+t+"]"]=t.toLowerCase()});function j(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}t=x(o),function(e,undefined){var t,n,r,i,o,s,a,u,l,c,p,f,h,d,g,m,y,v="sizzle"+-new Date,b=e.document,w=0,T=0,C=st(),k=st(),N=st(),E=!1,S=function(e,t){return e===t?(E=!0,0):0},j=typeof undefined,D=1<<31,A={}.hasOwnProperty,L=[],q=L.pop,H=L.push,O=L.push,F=L.slice,P=L.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",W="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",$=W.replace("w","w#"),B="\\["+M+"*("+W+")"+M+"*(?:([*^$|!~]?=)"+M+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+$+")|)|)"+M+"*\\]",I=":("+W+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+B.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=RegExp("^"+M+"*,"+M+"*"),X=RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=RegExp(M+"*[+~]"),Y=RegExp("="+M+"*([^\\]'\"]*)"+M+"*\\]","g"),V=RegExp(I),G=RegExp("^"+$+"$"),J={ID:RegExp("^#("+W+")"),CLASS:RegExp("^\\.("+W+")"),TAG:RegExp("^("+W.replace("w","w*")+")"),ATTR:RegExp("^"+B),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:RegExp("^(?:"+R+")$","i"),needsContext:RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/^[^{]+\{\s*\[native \w/,K=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,Z=/^(?:input|select|textarea|button)$/i,et=/^h\d$/i,tt=/'|\\/g,nt=RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),rt=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{O.apply(L=F.call(b.childNodes),b.childNodes),L[b.childNodes.length].nodeType}catch(it){O={apply:L.length?function(e,t){H.apply(e,F.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function ot(e,t,r,i){var o,s,a,u,l,f,g,m,x,w;if((t?t.ownerDocument||t:b)!==p&&c(t),t=t||p,r=r||[],!e||"string"!=typeof e)return r;if(1!==(u=t.nodeType)&&9!==u)return[];if(h&&!i){if(o=K.exec(e))if(a=o[1]){if(9===u){if(s=t.getElementById(a),!s||!s.parentNode)return r;if(s.id===a)return r.push(s),r}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(a))&&y(t,s)&&s.id===a)return r.push(s),r}else{if(o[2])return O.apply(r,t.getElementsByTagName(e)),r;if((a=o[3])&&n.getElementsByClassName&&t.getElementsByClassName)return O.apply(r,t.getElementsByClassName(a)),r}if(n.qsa&&(!d||!d.test(e))){if(m=g=v,x=t,w=9===u&&e,1===u&&"object"!==t.nodeName.toLowerCase()){f=gt(e),(g=t.getAttribute("id"))?m=g.replace(tt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",l=f.length;while(l--)f[l]=m+mt(f[l]);x=U.test(e)&&t.parentNode||t,w=f.join(",")}if(w)try{return O.apply(r,x.querySelectorAll(w)),r}catch(T){}finally{g||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,r,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>i.cacheLength&&delete t[e.shift()],t[n]=r}return t}function at(e){return e[v]=!0,e}function ut(e){var t=p.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function lt(e,t){var n=e.split("|"),r=e.length;while(r--)i.attrHandle[n[r]]=t}function ct(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function pt(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return at(function(t){return t=+t,at(function(n,r){var i,o=e([],n.length,t),s=o.length;while(s--)n[i=o[s]]&&(n[i]=!(r[i]=n[i]))})})}s=ot.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},n=ot.support={},c=ot.setDocument=function(e){var t=e?e.ownerDocument||e:b,r=t.defaultView;return t!==p&&9===t.nodeType&&t.documentElement?(p=t,f=t.documentElement,h=!s(t),r&&r.attachEvent&&r!==r.top&&r.attachEvent("onbeforeunload",function(){c()}),n.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),n.getElementsByTagName=ut(function(e){return e.appendChild(t.createComment("")),!e.getElementsByTagName("*").length}),n.getElementsByClassName=ut(function(e){return e.innerHTML="<div class='a'></div><div class='a i'></div>",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),n.getById=ut(function(e){return f.appendChild(e).id=v,!t.getElementsByName||!t.getElementsByName(v).length}),n.getById?(i.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){return e.getAttribute("id")===t}}):(delete i.find.ID,i.filter.ID=function(e){var t=e.replace(nt,rt);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),i.find.TAG=n.getElementsByTagName?function(e,t){return typeof t.getElementsByTagName!==j?t.getElementsByTagName(e):undefined}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},i.find.CLASS=n.getElementsByClassName&&function(e,t){return typeof t.getElementsByClassName!==j&&h?t.getElementsByClassName(e):undefined},g=[],d=[],(n.qsa=Q.test(t.querySelectorAll))&&(ut(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||d.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll(":checked").length||d.push(":checked")}),ut(function(e){var n=t.createElement("input");n.setAttribute("type","hidden"),e.appendChild(n).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&d.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||d.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),d.push(",.*:")})),(n.matchesSelector=Q.test(m=f.webkitMatchesSelector||f.mozMatchesSelector||f.oMatchesSelector||f.msMatchesSelector))&&ut(function(e){n.disconnectedMatch=m.call(e,"div"),m.call(e,"[s!='']:x"),g.push("!=",I)}),d=d.length&&RegExp(d.join("|")),g=g.length&&RegExp(g.join("|")),y=Q.test(f.contains)||f.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},S=f.compareDocumentPosition?function(e,r){if(e===r)return E=!0,0;var i=r.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(r);return i?1&i||!n.sortDetached&&r.compareDocumentPosition(e)===i?e===t||y(b,e)?-1:r===t||y(b,r)?1:l?P.call(l,e)-P.call(l,r):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,n){var r,i=0,o=e.parentNode,s=n.parentNode,a=[e],u=[n];if(e===n)return E=!0,0;if(!o||!s)return e===t?-1:n===t?1:o?-1:s?1:l?P.call(l,e)-P.call(l,n):0;if(o===s)return ct(e,n);r=e;while(r=r.parentNode)a.unshift(r);r=n;while(r=r.parentNode)u.unshift(r);while(a[i]===u[i])i++;return i?ct(a[i],u[i]):a[i]===b?-1:u[i]===b?1:0},t):p},ot.matches=function(e,t){return ot(e,null,null,t)},ot.matchesSelector=function(e,t){if((e.ownerDocument||e)!==p&&c(e),t=t.replace(Y,"='$1']"),!(!n.matchesSelector||!h||g&&g.test(t)||d&&d.test(t)))try{var r=m.call(e,t);if(r||n.disconnectedMatch||e.document&&11!==e.document.nodeType)return r}catch(i){}return ot(t,p,null,[e]).length>0},ot.contains=function(e,t){return(e.ownerDocument||e)!==p&&c(e),y(e,t)},ot.attr=function(e,t){(e.ownerDocument||e)!==p&&c(e);var r=i.attrHandle[t.toLowerCase()],o=r&&A.call(i.attrHandle,t.toLowerCase())?r(e,t,!h):undefined;return o===undefined?n.attributes||!h?e.getAttribute(t):(o=e.getAttributeNode(t))&&o.specified?o.value:null:o},ot.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},ot.uniqueSort=function(e){var t,r=[],i=0,o=0;if(E=!n.detectDuplicates,l=!n.sortStable&&e.slice(0),e.sort(S),E){while(t=e[o++])t===e[o]&&(i=r.push(o));while(i--)e.splice(r[i],1)}return e},o=ot.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=o(t);return n},i=ot.selectors={cacheLength:50,createPseudo:at,match:J,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(nt,rt),e[3]=(e[4]||e[5]||"").replace(nt,rt),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||ot.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&ot.error(e[0]),e},PSEUDO:function(e){var t,n=!e[5]&&e[2];return J.CHILD.test(e[0])?null:(e[3]&&e[4]!==undefined?e[2]=e[4]:n&&V.test(n)&&(t=gt(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(nt,rt).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=C[e+" "];return t||(t=RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&C(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=ot.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),s="last"!==e.slice(-4),a="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,u){var l,c,p,f,h,d,g=o!==s?"nextSibling":"previousSibling",m=t.parentNode,y=a&&t.nodeName.toLowerCase(),x=!u&&!a;if(m){if(o){while(g){p=t;while(p=p[g])if(a?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;d=g="only"===e&&!d&&"nextSibling"}return!0}if(d=[s?m.firstChild:m.lastChild],s&&x){c=m[v]||(m[v]={}),l=c[e]||[],h=l[0]===w&&l[1],f=l[0]===w&&l[2],p=h&&m.childNodes[h];while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[w,h,f];break}}else if(x&&(l=(t[v]||(t[v]={}))[e])&&l[0]===w)f=l[1];else while(p=++h&&p&&p[g]||(f=h=0)||d.pop())if((a?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(x&&((p[v]||(p[v]={}))[e]=[w,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||ot.error("unsupported pseudo: "+e);return r[v]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?at(function(e,n){var i,o=r(e,t),s=o.length;while(s--)i=P.call(e,o[s]),e[i]=!(n[i]=o[s])}):function(e){return r(e,0,n)}):r}},pseudos:{not:at(function(e){var t=[],n=[],r=a(e.replace(z,"$1"));return r[v]?at(function(e,t,n,i){var o,s=r(e,null,i,[]),a=e.length;while(a--)(o=s[a])&&(e[a]=!(t[a]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:at(function(e){return function(t){return ot(e,t).length>0}}),contains:at(function(e){return function(t){return(t.textContent||t.innerText||o(t)).indexOf(e)>-1}}),lang:at(function(e){return G.test(e||"")||ot.error("unsupported lang: "+e),e=e.replace(nt,rt).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===f},focus:function(e){return e===p.activeElement&&(!p.hasFocus||p.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!i.pseudos.empty(e)},header:function(e){return et.test(e.nodeName)},input:function(e){return Z.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},i.pseudos.nth=i.pseudos.eq;for(t in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})i.pseudos[t]=pt(t);for(t in{submit:!0,reset:!0})i.pseudos[t]=ft(t);function dt(){}dt.prototype=i.filters=i.pseudos,i.setFilters=new dt;function gt(e,t){var n,r,o,s,a,u,l,c=k[e+" "];if(c)return t?0:c.slice(0);a=e,u=[],l=i.preFilter;while(a){(!n||(r=_.exec(a)))&&(r&&(a=a.slice(r[0].length)||a),u.push(o=[])),n=!1,(r=X.exec(a))&&(n=r.shift(),o.push({value:n,type:r[0].replace(z," ")}),a=a.slice(n.length));for(s in i.filter)!(r=J[s].exec(a))||l[s]&&!(r=l[s](r))||(n=r.shift(),o.push({value:n,type:s,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?ot.error(e):k(e,u).slice(0)}function mt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function yt(e,t,n){var i=t.dir,o=n&&"parentNode"===i,s=T++;return t.first?function(t,n,r){while(t=t[i])if(1===t.nodeType||o)return e(t,n,r)}:function(t,n,a){var u,l,c,p=w+" "+s;if(a){while(t=t[i])if((1===t.nodeType||o)&&e(t,n,a))return!0}else while(t=t[i])if(1===t.nodeType||o)if(c=t[v]||(t[v]={}),(l=c[i])&&l[0]===p){if((u=l[1])===!0||u===r)return u===!0}else if(l=c[i]=[p],l[1]=e(t,n,a)||r,l[1]===!0)return!0}}function vt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,s=[],a=0,u=e.length,l=null!=t;for(;u>a;a++)(o=e[a])&&(!n||n(o,r,i))&&(s.push(o),l&&t.push(a));return s}function bt(e,t,n,r,i,o){return r&&!r[v]&&(r=bt(r)),i&&!i[v]&&(i=bt(i,o)),at(function(o,s,a,u){var l,c,p,f=[],h=[],d=s.length,g=o||Ct(t||"*",a.nodeType?[a]:a,[]),m=!e||!o&&t?g:xt(g,f,e,a,u),y=n?i||(o?e:d||r)?[]:s:m;if(n&&n(m,y,a,u),r){l=xt(y,h),r(l,[],a,u),c=l.length;while(c--)(p=l[c])&&(y[h[c]]=!(m[h[c]]=p))}if(o){if(i||e){if(i){l=[],c=y.length;while(c--)(p=y[c])&&l.push(m[c]=p);i(null,y=[],l,u)}c=y.length;while(c--)(p=y[c])&&(l=i?P.call(o,p):f[c])>-1&&(o[l]=!(s[l]=p))}}else y=xt(y===s?y.splice(d,y.length):y),i?i(null,s,y,u):O.apply(s,y)})}function wt(e){var t,n,r,o=e.length,s=i.relative[e[0].type],a=s||i.relative[" "],l=s?1:0,c=yt(function(e){return e===t},a,!0),p=yt(function(e){return P.call(t,e)>-1},a,!0),f=[function(e,n,r){return!s&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;o>l;l++)if(n=i.relative[e[l].type])f=[yt(vt(f),n)];else{if(n=i.filter[e[l].type].apply(null,e[l].matches),n[v]){for(r=++l;o>r;r++)if(i.relative[e[r].type])break;return bt(l>1&&vt(f),l>1&&mt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&wt(e.slice(l,r)),o>r&&wt(e=e.slice(r)),o>r&&mt(e))}f.push(n)}return vt(f)}function Tt(e,t){var n=0,o=t.length>0,s=e.length>0,a=function(a,l,c,f,h){var d,g,m,y=[],v=0,x="0",b=a&&[],T=null!=h,C=u,k=a||s&&i.find.TAG("*",h&&l.parentNode||l),N=w+=null==C?1:Math.random()||.1;for(T&&(u=l!==p&&l,r=n);null!=(d=k[x]);x++){if(s&&d){g=0;while(m=e[g++])if(m(d,l,c)){f.push(d);break}T&&(w=N,r=++n)}o&&((d=!m&&d)&&v--,a&&b.push(d))}if(v+=x,o&&x!==v){g=0;while(m=t[g++])m(b,y,l,c);if(a){if(v>0)while(x--)b[x]||y[x]||(y[x]=q.call(f));y=xt(y)}O.apply(f,y),T&&!a&&y.length>0&&v+t.length>1&&ot.uniqueSort(f)}return T&&(w=N,u=C),b};return o?at(a):a}a=ot.compile=function(e,t){var n,r=[],i=[],o=N[e+" "];if(!o){t||(t=gt(e)),n=t.length;while(n--)o=wt(t[n]),o[v]?r.push(o):i.push(o);o=N(e,Tt(i,r))}return o};function Ct(e,t,n){var r=0,i=t.length;for(;i>r;r++)ot(e,t[r],n);return n}function kt(e,t,r,o){var s,u,l,c,p,f=gt(e);if(!o&&1===f.length){if(u=f[0]=f[0].slice(0),u.length>2&&"ID"===(l=u[0]).type&&n.getById&&9===t.nodeType&&h&&i.relative[u[1].type]){if(t=(i.find.ID(l.matches[0].replace(nt,rt),t)||[])[0],!t)return r;e=e.slice(u.shift().value.length)}s=J.needsContext.test(e)?0:u.length;while(s--){if(l=u[s],i.relative[c=l.type])break;if((p=i.find[c])&&(o=p(l.matches[0].replace(nt,rt),U.test(u[0].type)&&t.parentNode||t))){if(u.splice(s,1),e=o.length&&mt(u),!e)return O.apply(r,o),r;break}}}return a(e,f)(o,t,!h,r,U.test(e)),r}n.sortStable=v.split("").sort(S).join("")===v,n.detectDuplicates=E,c(),n.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(p.createElement("div"))}),ut(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||lt("type|href|height|width",function(e,t,n){return n?undefined:e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),n.attributes&&ut(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||lt("value",function(e,t,n){return n||"input"!==e.nodeName.toLowerCase()?undefined:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||lt(R,function(e,t,n){var r;return n?undefined:(r=e.getAttributeNode(t))&&r.specified?r.value:e[t]===!0?t.toLowerCase():null}),x.find=ot,x.expr=ot.selectors,x.expr[":"]=x.expr.pseudos,x.unique=ot.uniqueSort,x.text=ot.getText,x.isXMLDoc=ot.isXML,x.contains=ot.contains}(e);var D={};function A(e){var t=D[e]={};return x.each(e.match(w)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?D[e]||A(e):x.extend({},e);var t,n,r,i,o,s,a=[],u=!e.once&&[],l=function(p){for(t=e.memory&&p,n=!0,s=i||0,i=0,o=a.length,r=!0;a&&o>s;s++)if(a[s].apply(p[0],p[1])===!1&&e.stopOnFalse){t=!1;break}r=!1,a&&(u?u.length&&l(u.shift()):t?a=[]:c.disable())},c={add:function(){if(a){var n=a.length;(function s(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&c.has(n)||a.push(n):n&&n.length&&"string"!==r&&s(n)})})(arguments),r?o=a.length:t&&(i=n,l(t))}return this},remove:function(){return a&&x.each(arguments,function(e,t){var n;while((n=x.inArray(t,a,n))>-1)a.splice(n,1),r&&(o>=n&&o--,s>=n&&s--)}),this},has:function(e){return e?x.inArray(e,a)>-1:!(!a||!a.length)},empty:function(){return a=[],o=0,this},disable:function(){return a=u=t=undefined,this},disabled:function(){return!a},lock:function(){return u=undefined,t||c.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!a||n&&!u||(t=t||[],t=[e,t.slice?t.slice():t],r?u.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!n}};return c},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var s=o[0],a=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=a&&a.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===r?n.promise():this,a?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var s=o[2],a=o[3];r[o[1]]=s.add,a&&s.add(function(){n=a},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=s.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=d.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),s=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?d.call(arguments):r,n===a?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},a,u,l;if(r>1)for(a=Array(r),u=Array(r),l=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(s(t,l,n)).fail(o.reject).progress(s(t,u,a)):--i;return i||o.resolveWith(l,n),o.promise()}}),x.support=function(t){var n=o.createElement("input"),r=o.createDocumentFragment(),i=o.createElement("div"),s=o.createElement("select"),a=s.appendChild(o.createElement("option"));return n.type?(n.type="checkbox",t.checkOn=""!==n.value,t.optSelected=a.selected,t.reliableMarginRight=!0,t.boxSizingReliable=!0,t.pixelPosition=!1,n.checked=!0,t.noCloneChecked=n.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!a.disabled,n=o.createElement("input"),n.value="t",n.type="radio",t.radioValue="t"===n.value,n.setAttribute("checked","t"),n.setAttribute("name","t"),r.appendChild(n),t.checkClone=r.cloneNode(!0).cloneNode(!0).lastChild.checked,t.focusinBubbles="onfocusin"in e,i.style.backgroundClip="content-box",i.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===i.style.backgroundClip,x(function(){var n,r,s="padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",a=o.getElementsByTagName("body")[0];a&&(n=o.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",a.appendChild(n).appendChild(i),i.innerHTML="",i.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%",x.swap(a,null!=a.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===i.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(i,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(i,null)||{width:"4px"}).width,r=i.appendChild(o.createElement("div")),r.style.cssText=i.style.cssText=s,r.style.marginRight=r.style.width="0",i.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),a.removeChild(n))}),t):t}({});var L,q,H=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,O=/([A-Z])/g;function F(){Object.defineProperty(this.cache={},0,{get:function(){return{}}}),this.expando=x.expando+Math.random()}F.uid=1,F.accepts=function(e){return e.nodeType?1===e.nodeType||9===e.nodeType:!0},F.prototype={key:function(e){if(!F.accepts(e))return 0;var t={},n=e[this.expando];if(!n){n=F.uid++;try{t[this.expando]={value:n},Object.defineProperties(e,t)}catch(r){t[this.expando]=n,x.extend(e,t)}}return this.cache[n]||(this.cache[n]={}),n},set:function(e,t,n){var r,i=this.key(e),o=this.cache[i];if("string"==typeof t)o[t]=n;else if(x.isEmptyObject(o))x.extend(this.cache[i],t);else for(r in t)o[r]=t[r];return o},get:function(e,t){var n=this.cache[this.key(e)];return t===undefined?n:n[t]},access:function(e,t,n){var r;return t===undefined||t&&"string"==typeof t&&n===undefined?(r=this.get(e,t),r!==undefined?r:this.get(e,x.camelCase(t))):(this.set(e,t,n),n!==undefined?n:t)},remove:function(e,t){var n,r,i,o=this.key(e),s=this.cache[o];if(t===undefined)this.cache[o]={};else{x.isArray(t)?r=t.concat(t.map(x.camelCase)):(i=x.camelCase(t),t in s?r=[t,i]:(r=i,r=r in s?[r]:r.match(w)||[])),n=r.length;while(n--)delete s[r[n]]}},hasData:function(e){return!x.isEmptyObject(this.cache[e[this.expando]]||{})},discard:function(e){e[this.expando]&&delete this.cache[e[this.expando]]}},L=new F,q=new F,x.extend({acceptData:F.accepts,hasData:function(e){return L.hasData(e)||q.hasData(e)},data:function(e,t,n){return L.access(e,t,n)},removeData:function(e,t){L.remove(e,t)},_data:function(e,t,n){return q.access(e,t,n)},_removeData:function(e,t){q.remove(e,t)}}),x.fn.extend({data:function(e,t){var n,r,i=this[0],o=0,s=null;if(e===undefined){if(this.length&&(s=L.get(i),1===i.nodeType&&!q.get(i,"hasDataAttrs"))){for(n=i.attributes;n.length>o;o++)r=n[o].name,0===r.indexOf("data-")&&(r=x.camelCase(r.slice(5)),P(i,r,s[r]));q.set(i,"hasDataAttrs",!0)}return s}return"object"==typeof e?this.each(function(){L.set(this,e)}):x.access(this,function(t){var n,r=x.camelCase(e);if(i&&t===undefined){if(n=L.get(i,e),n!==undefined)return n;if(n=L.get(i,r),n!==undefined)return n;if(n=P(i,r,undefined),n!==undefined)return n}else this.each(function(){var n=L.get(this,r);L.set(this,r,t),-1!==e.indexOf("-")&&n!==undefined&&L.set(this,e,t)})},null,t,arguments.length>1,null,!0)},removeData:function(e){return this.each(function(){L.remove(this,e)})}});function P(e,t,n){var r;if(n===undefined&&1===e.nodeType)if(r="data-"+t.replace(O,"-$1").toLowerCase(),n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:H.test(n)?JSON.parse(n):n}catch(i){}L.set(e,t,n)}else n=undefined;return n}x.extend({queue:function(e,t,n){var r;return e?(t=(t||"fx")+"queue",r=q.get(e,t),n&&(!r||x.isArray(n)?r=q.access(e,t,x.makeArray(n)):r.push(n)),r||[]):undefined},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),s=function(){x.dequeue(e,t)
+};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,s,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return q.get(e,n)||q.access(e,n,{empty:x.Callbacks("once memory").add(function(){q.remove(e,[t+"queue",n])})})}}),x.fn.extend({queue:function(e,t){var n=2;return"string"!=typeof e&&(t=e,e="fx",n--),n>arguments.length?x.queue(this[0],e):t===undefined?this:this.each(function(){var n=x.queue(this,e,t);x._queueHooks(this,e),"fx"===e&&"inprogress"!==n[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=x.Deferred(),o=this,s=this.length,a=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=undefined),e=e||"fx";while(s--)n=q.get(o[s],e+"queueHooks"),n&&n.empty&&(r++,n.empty.add(a));return a(),i.promise(t)}});var R,M,W=/[\t\r\n\f]/g,$=/\r/g,B=/^(?:input|select|textarea|button)$/i;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return this.each(function(){delete this[x.propFix[e]||e]})},addClass:function(e){var t,n,r,i,o,s=0,a=this.length,u="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,s=0,a=this.length,u=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(u)for(t=(e||"").match(w)||[];a>s;s++)if(n=this[s],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(W," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,i=0,o=x(this),s=e.match(w)||[];while(t=s[i++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===r||"boolean"===n)&&(this.className&&q.set(this,"__className__",this.className),this.className=this.className||e===!1?"":q.get(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(W," ").indexOf(t)>=0)return!0;return!1},val:function(e){var t,n,r,i=this[0];{if(arguments.length)return r=x.isFunction(e),this.each(function(n){var i;1===this.nodeType&&(i=r?e.call(this,n,x(this).val()):e,null==i?i="":"number"==typeof i?i+="":x.isArray(i)&&(i=x.map(i,function(e){return null==e?"":e+""})),t=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],t&&"set"in t&&t.set(this,i,"value")!==undefined||(this.value=i))});if(i)return t=x.valHooks[i.type]||x.valHooks[i.nodeName.toLowerCase()],t&&"get"in t&&(n=t.get(i,"value"))!==undefined?n:(n=i.value,"string"==typeof n?n.replace($,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,s=o?null:[],a=o?i+1:r.length,u=0>i?a:o?i:0;for(;a>u;u++)if(n=r[u],!(!n.selected&&u!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),s=i.length;while(s--)r=i[s],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,t,n){var i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===r?x.prop(e,t,n):(1===s&&x.isXMLDoc(e)||(t=t.toLowerCase(),i=x.attrHooks[t]||(x.expr.match.bool.test(t)?M:R)),n===undefined?i&&"get"in i&&null!==(o=i.get(e,t))?o:(o=x.find.attr(e,t),null==o?undefined:o):null!==n?i&&"set"in i&&(o=i.set(e,n,t))!==undefined?o:(e.setAttribute(t,n+""),n):(x.removeAttr(e,t),undefined))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(w);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)&&(e[r]=!1),e.removeAttribute(n)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,t,n){var r,i,o,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return o=1!==s||!x.isXMLDoc(e),o&&(t=x.propFix[t]||t,i=x.propHooks[t]),n!==undefined?i&&"set"in i&&(r=i.set(e,n,t))!==undefined?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){return e.hasAttribute("tabindex")||B.test(e.nodeName)||e.href?e.tabIndex:-1}}}}),M={set:function(e,t,n){return t===!1?x.removeAttr(e,n):e.setAttribute(n,n),n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,t){var n=x.expr.attrHandle[t]||x.find.attr;x.expr.attrHandle[t]=function(e,t,r){var i=x.expr.attrHandle[t],o=r?undefined:(x.expr.attrHandle[t]=undefined)!=n(e,t,r)?t.toLowerCase():null;return x.expr.attrHandle[t]=i,o}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,t){return x.isArray(t)?e.checked=x.inArray(x(e).val(),t)>=0:undefined}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var I=/^key/,z=/^(?:mouse|contextmenu)|click/,_=/^(?:focusinfocus|focusoutblur)$/,X=/^([^.]*)(?:\.(.+)|)$/;function U(){return!0}function Y(){return!1}function V(){try{return o.activeElement}catch(e){}}x.event={global:{},add:function(e,t,n,i,o){var s,a,u,l,c,p,f,h,d,g,m,y=q.get(e);if(y){n.handler&&(s=n,n=s.handler,o=s.selector),n.guid||(n.guid=x.guid++),(l=y.events)||(l=y.events={}),(a=y.handle)||(a=y.handle=function(e){return typeof x===r||e&&x.event.triggered===e.type?undefined:x.event.dispatch.apply(a.elem,arguments)},a.elem=e),t=(t||"").match(w)||[""],c=t.length;while(c--)u=X.exec(t[c])||[],d=m=u[1],g=(u[2]||"").split(".").sort(),d&&(f=x.event.special[d]||{},d=(o?f.delegateType:f.bindType)||d,f=x.event.special[d]||{},p=x.extend({type:d,origType:m,data:i,handler:n,guid:n.guid,selector:o,needsContext:o&&x.expr.match.needsContext.test(o),namespace:g.join(".")},s),(h=l[d])||(h=l[d]=[],h.delegateCount=0,f.setup&&f.setup.call(e,i,g,a)!==!1||e.addEventListener&&e.addEventListener(d,a,!1)),f.add&&(f.add.call(e,p),p.handler.guid||(p.handler.guid=n.guid)),o?h.splice(h.delegateCount++,0,p):h.push(p),x.event.global[d]=!0);e=null}},remove:function(e,t,n,r,i){var o,s,a,u,l,c,p,f,h,d,g,m=q.hasData(e)&&q.get(e);if(m&&(u=m.events)){t=(t||"").match(w)||[""],l=t.length;while(l--)if(a=X.exec(t[l])||[],h=g=a[1],d=(a[2]||"").split(".").sort(),h){p=x.event.special[h]||{},h=(r?p.delegateType:p.bindType)||h,f=u[h]||[],a=a[2]&&RegExp("(^|\\.)"+d.join("\\.(?:.*\\.|)")+"(\\.|$)"),s=o=f.length;while(o--)c=f[o],!i&&g!==c.origType||n&&n.guid!==c.guid||a&&!a.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(f.splice(o,1),c.selector&&f.delegateCount--,p.remove&&p.remove.call(e,c));s&&!f.length&&(p.teardown&&p.teardown.call(e,d,m.handle)!==!1||x.removeEvent(e,h,m.handle),delete u[h])}else for(h in u)x.event.remove(e,h+t[l],n,r,!0);x.isEmptyObject(u)&&(delete m.handle,q.remove(e,"events"))}},trigger:function(t,n,r,i){var s,a,u,l,c,p,f,h=[r||o],d=y.call(t,"type")?t.type:t,g=y.call(t,"namespace")?t.namespace.split("."):[];if(a=u=r=r||o,3!==r.nodeType&&8!==r.nodeType&&!_.test(d+x.event.triggered)&&(d.indexOf(".")>=0&&(g=d.split("."),d=g.shift(),g.sort()),c=0>d.indexOf(":")&&"on"+d,t=t[x.expando]?t:new x.Event(d,"object"==typeof t&&t),t.isTrigger=i?2:3,t.namespace=g.join("."),t.namespace_re=t.namespace?RegExp("(^|\\.)"+g.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,t.result=undefined,t.target||(t.target=r),n=null==n?[t]:x.makeArray(n,[t]),f=x.event.special[d]||{},i||!f.trigger||f.trigger.apply(r,n)!==!1)){if(!i&&!f.noBubble&&!x.isWindow(r)){for(l=f.delegateType||d,_.test(l+d)||(a=a.parentNode);a;a=a.parentNode)h.push(a),u=a;u===(r.ownerDocument||o)&&h.push(u.defaultView||u.parentWindow||e)}s=0;while((a=h[s++])&&!t.isPropagationStopped())t.type=s>1?l:f.bindType||d,p=(q.get(a,"events")||{})[t.type]&&q.get(a,"handle"),p&&p.apply(a,n),p=c&&a[c],p&&x.acceptData(a)&&p.apply&&p.apply(a,n)===!1&&t.preventDefault();return t.type=d,i||t.isDefaultPrevented()||f._default&&f._default.apply(h.pop(),n)!==!1||!x.acceptData(r)||c&&x.isFunction(r[d])&&!x.isWindow(r)&&(u=r[c],u&&(r[c]=null),x.event.triggered=d,r[d](),x.event.triggered=undefined,u&&(r[c]=u)),t.result}},dispatch:function(e){e=x.event.fix(e);var t,n,r,i,o,s=[],a=d.call(arguments),u=(q.get(this,"events")||{})[e.type]||[],l=x.event.special[e.type]||{};if(a[0]=e,e.delegateTarget=this,!l.preDispatch||l.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),t=0;while((i=s[t++])&&!e.isPropagationStopped()){e.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(o.namespace))&&(e.handleObj=o,e.data=o.data,r=((x.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,a),r!==undefined&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return l.postDispatch&&l.postDispatch.call(this,e),e.result}},handlers:function(e,t){var n,r,i,o,s=[],a=t.delegateCount,u=e.target;if(a&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!==this;u=u.parentNode||this)if(u.disabled!==!0||"click"!==e.type){for(r=[],n=0;a>n;n++)o=t[n],i=o.selector+" ",r[i]===undefined&&(r[i]=o.needsContext?x(i,this).index(u)>=0:x.find(i,this,null,[u]).length),r[i]&&r.push(o);r.length&&s.push({elem:u,handlers:r})}return t.length>a&&s.push({elem:this,handlers:t.slice(a)}),s},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,t){var n,r,i,s=t.button;return null==e.pageX&&null!=t.clientX&&(n=e.target.ownerDocument||o,r=n.documentElement,i=n.body,e.pageX=t.clientX+(r&&r.scrollLeft||i&&i.scrollLeft||0)-(r&&r.clientLeft||i&&i.clientLeft||0),e.pageY=t.clientY+(r&&r.scrollTop||i&&i.scrollTop||0)-(r&&r.clientTop||i&&i.clientTop||0)),e.which||s===undefined||(e.which=1&s?1:2&s?3:4&s?2:0),e}},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,s=e,a=this.fixHooks[i];a||(this.fixHooks[i]=a=z.test(i)?this.mouseHooks:I.test(i)?this.keyHooks:{}),r=a.props?this.props.concat(a.props):this.props,e=new x.Event(s),t=r.length;while(t--)n=r[t],e[n]=s[n];return e.target||(e.target=o),3===e.target.nodeType&&(e.target=e.target.parentNode),a.filter?a.filter(e,s):e},special:{load:{noBubble:!0},focus:{trigger:function(){return this!==V()&&this.focus?(this.focus(),!1):undefined},delegateType:"focusin"},blur:{trigger:function(){return this===V()&&this.blur?(this.blur(),!1):undefined},delegateType:"focusout"},click:{trigger:function(){return"checkbox"===this.type&&this.click&&x.nodeName(this,"input")?(this.click(),!1):undefined},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==undefined&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)},x.Event=function(e,t){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.getPreventDefault&&e.getPreventDefault()?U:Y):this.type=e,t&&x.extend(this,t),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,undefined):new x.Event(e,t)},x.Event.prototype={isDefaultPrevented:Y,isPropagationStopped:Y,isImmediatePropagationStopped:Y,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=U,e&&e.preventDefault&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=U,e&&e.stopPropagation&&e.stopPropagation()},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=U,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&o.addEventListener(e,r,!0)},teardown:function(){0===--n&&o.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,t,n,r,i){var o,s;if("object"==typeof e){"string"!=typeof t&&(n=n||t,t=undefined);for(s in e)this.on(s,t,n,e[s],i);return this}if(null==n&&null==r?(r=t,n=t=undefined):null==r&&("string"==typeof t?(r=n,n=undefined):(r=n,n=t,t=undefined)),r===!1)r=Y;else if(!r)return this;return 1===i&&(o=r,r=function(e){return x().off(e),o.apply(this,arguments)},r.guid=o.guid||(o.guid=x.guid++)),this.each(function(){x.event.add(this,e,r,n,t)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,x(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return(t===!1||"function"==typeof t)&&(n=t,t=undefined),n===!1&&(n=Y),this.each(function(){x.event.remove(this,e,n,t)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];return n?x.event.trigger(e,t,n,!0):undefined}});var G=/^.[^:#\[\.,]*$/,J=/^(?:parents|prev(?:Until|All))/,Q=x.expr.match.needsContext,K={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t=x(e,this),n=t.length;return this.filter(function(){var e=0;for(;n>e;e++)if(x.contains(this,t[e]))return!0})},not:function(e){return this.pushStack(et(this,e||[],!0))},filter:function(e){return this.pushStack(et(this,e||[],!1))},is:function(e){return!!et(this,"string"==typeof e&&Q.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],s=Q.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(s?s.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?g.call(x(e),this[0]):g.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function Z(e,t){while((e=e[t])&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return Z(e,"nextSibling")},prev:function(e){return Z(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return e.contentDocument||x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(K[e]||x.unique(i),J.test(e)&&i.reverse()),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,t,n){var r=[],i=n!==undefined;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&x(e).is(n))break;r.push(e)}return r},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function et(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(G.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return g.call(t,e)>=0!==n})}var tt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,nt=/<([\w:]+)/,rt=/<|&#?\w+;/,it=/<(?:script|style|link)/i,ot=/^(?:checkbox|radio)$/i,st=/checked\s*(?:[^=]|=\s*.checked.)/i,at=/^$|\/(?:java|ecma)script/i,ut=/^true\/(.*)/,lt=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,ct={option:[1,"<select multiple='multiple'>","</select>"],thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};ct.optgroup=ct.option,ct.tbody=ct.tfoot=ct.colgroup=ct.caption=ct.thead,ct.th=ct.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===undefined?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||o).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=pt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(mt(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&dt(mt(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++)1===e.nodeType&&(x.cleanData(mt(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var t=this[0]||{},n=0,r=this.length;if(e===undefined&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!it.test(e)&&!ct[(nt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(tt,"<$1></$2>");try{for(;r>n;n++)t=this[n]||{},1===t.nodeType&&(x.cleanData(mt(t,!1)),t.innerHTML=e);t=0}catch(i){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=f.apply([],e);var r,i,o,s,a,u,l=0,c=this.length,p=this,h=c-1,d=e[0],g=x.isFunction(d);if(g||!(1>=c||"string"!=typeof d||x.support.checkClone)&&st.test(d))return this.each(function(r){var i=p.eq(r);g&&(e[0]=d.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(r=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),i=r.firstChild,1===r.childNodes.length&&(r=i),i)){for(o=x.map(mt(r,"script"),ft),s=o.length;c>l;l++)a=r,l!==h&&(a=x.clone(a,!0,!0),s&&x.merge(o,mt(a,"script"))),t.call(this[l],a,l);if(s)for(u=o[o.length-1].ownerDocument,x.map(o,ht),l=0;s>l;l++)a=o[l],at.test(a.type||"")&&!q.access(a,"globalEval")&&x.contains(u,a)&&(a.src?x._evalUrl(a.src):x.globalEval(a.textContent.replace(lt,"")))}return this}}),x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=[],i=x(e),o=i.length-1,s=0;for(;o>=s;s++)n=s===o?this:this.clone(!0),x(i[s])[t](n),h.apply(r,n.get());return this.pushStack(r)}}),x.extend({clone:function(e,t,n){var r,i,o,s,a=e.cloneNode(!0),u=x.contains(e.ownerDocument,e);if(!(x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(s=mt(a),o=mt(e),r=0,i=o.length;i>r;r++)yt(o[r],s[r]);if(t)if(n)for(o=o||mt(e),s=s||mt(a),r=0,i=o.length;i>r;r++)gt(o[r],s[r]);else gt(e,a);return s=mt(a,"script"),s.length>0&&dt(s,!u&&mt(e,"script")),a},buildFragment:function(e,t,n,r){var i,o,s,a,u,l,c=0,p=e.length,f=t.createDocumentFragment(),h=[];for(;p>c;c++)if(i=e[c],i||0===i)if("object"===x.type(i))x.merge(h,i.nodeType?[i]:i);else if(rt.test(i)){o=o||f.appendChild(t.createElement("div")),s=(nt.exec(i)||["",""])[1].toLowerCase(),a=ct[s]||ct._default,o.innerHTML=a[1]+i.replace(tt,"<$1></$2>")+a[2],l=a[0];while(l--)o=o.lastChild;x.merge(h,o.childNodes),o=f.firstChild,o.textContent=""}else h.push(t.createTextNode(i));f.textContent="",c=0;while(i=h[c++])if((!r||-1===x.inArray(i,r))&&(u=x.contains(i.ownerDocument,i),o=mt(f.appendChild(i),"script"),u&&dt(o),n)){l=0;while(i=o[l++])at.test(i.type||"")&&n.push(i)}return f},cleanData:function(e){var t,n,r,i,o,s,a=x.event.special,u=0;for(;(n=e[u])!==undefined;u++){if(F.accepts(n)&&(o=n[q.expando],o&&(t=q.cache[o]))){if(r=Object.keys(t.events||{}),r.length)for(s=0;(i=r[s])!==undefined;s++)a[i]?x.event.remove(n,i):x.removeEvent(n,i,t.handle);q.cache[o]&&delete q.cache[o]}delete L.cache[n[L.expando]]}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}});function pt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function ft(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function ht(e){var t=ut.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function dt(e,t){var n=e.length,r=0;for(;n>r;r++)q.set(e[r],"globalEval",!t||q.get(t[r],"globalEval"))}function gt(e,t){var n,r,i,o,s,a,u,l;if(1===t.nodeType){if(q.hasData(e)&&(o=q.access(e),s=q.set(t,o),l=o.events)){delete s.handle,s.events={};for(i in l)for(n=0,r=l[i].length;r>n;n++)x.event.add(t,i,l[i][n])}L.hasData(e)&&(a=L.access(e),u=x.extend({},a),L.set(t,u))}}function mt(e,t){var n=e.getElementsByTagName?e.getElementsByTagName(t||"*"):e.querySelectorAll?e.querySelectorAll(t||"*"):[];return t===undefined||t&&x.nodeName(e,t)?x.merge([e],n):n}function yt(e,t){var n=t.nodeName.toLowerCase();"input"===n&&ot.test(e.type)?t.checked=e.checked:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}x.fn.extend({wrapAll:function(e){var t;return x.isFunction(e)?this.each(function(t){x(this).wrapAll(e.call(this,t))}):(this[0]&&(t=x(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this)},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var vt,xt,bt=/^(none|table(?!-c[ea]).+)/,wt=/^margin/,Tt=RegExp("^("+b+")(.*)$","i"),Ct=RegExp("^("+b+")(?!px)[a-z%]+$","i"),kt=RegExp("^([+-])=("+b+")","i"),Nt={BODY:"block"},Et={position:"absolute",visibility:"hidden",display:"block"},St={letterSpacing:0,fontWeight:400},jt=["Top","Right","Bottom","Left"],Dt=["Webkit","O","Moz","ms"];function At(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Dt.length;while(i--)if(t=Dt[i]+n,t in e)return t;return r}function Lt(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function qt(t){return e.getComputedStyle(t,null)}function Ht(e,t){var n,r,i,o=[],s=0,a=e.length;for(;a>s;s++)r=e[s],r.style&&(o[s]=q.get(r,"olddisplay"),n=r.style.display,t?(o[s]||"none"!==n||(r.style.display=""),""===r.style.display&&Lt(r)&&(o[s]=q.access(r,"olddisplay",Rt(r.nodeName)))):o[s]||(i=Lt(r),(n&&"none"!==n||!i)&&q.set(r,"olddisplay",i?n:x.css(r,"display"))));for(s=0;a>s;s++)r=e[s],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[s]||"":"none"));return e}x.fn.extend({css:function(e,t){return x.access(this,function(e,t,n){var r,i,o={},s=0;if(x.isArray(t)){for(r=qt(e),i=t.length;i>s;s++)o[t[s]]=x.css(e,t[s],!1,r);return o}return n!==undefined?x.style(e,t,n):x.css(e,t)},e,t,arguments.length>1)},show:function(){return Ht(this,!0)},hide:function(){return Ht(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){Lt(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=vt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":"cssFloat"},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,s,a=x.camelCase(t),u=e.style;return t=x.cssProps[a]||(x.cssProps[a]=At(u,a)),s=x.cssHooks[t]||x.cssHooks[a],n===undefined?s&&"get"in s&&(i=s.get(e,!1,r))!==undefined?i:u[t]:(o=typeof n,"string"===o&&(i=kt.exec(n))&&(n=(i[1]+1)*i[2]+parseFloat(x.css(e,t)),o="number"),null==n||"number"===o&&isNaN(n)||("number"!==o||x.cssNumber[a]||(n+="px"),x.support.clearCloneStyle||""!==n||0!==t.indexOf("background")||(u[t]="inherit"),s&&"set"in s&&(n=s.set(e,n,r))===undefined||(u[t]=n)),undefined)}},css:function(e,t,n,r){var i,o,s,a=x.camelCase(t);return t=x.cssProps[a]||(x.cssProps[a]=At(e.style,a)),s=x.cssHooks[t]||x.cssHooks[a],s&&"get"in s&&(i=s.get(e,!0,n)),i===undefined&&(i=vt(e,t,r)),"normal"===i&&t in St&&(i=St[t]),""===n||n?(o=parseFloat(i),n===!0||x.isNumeric(o)?o||0:i):i}}),vt=function(e,t,n){var r,i,o,s=n||qt(e),a=s?s.getPropertyValue(t)||s[t]:undefined,u=e.style;return s&&(""!==a||x.contains(e.ownerDocument,e)||(a=x.style(e,t)),Ct.test(a)&&wt.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=s.width,u.width=r,u.minWidth=i,u.maxWidth=o)),a};function Ot(e,t,n){var r=Tt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function Ft(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,s=0;for(;4>o;o+=2)"margin"===n&&(s+=x.css(e,n+jt[o],!0,i)),r?("content"===n&&(s-=x.css(e,"padding"+jt[o],!0,i)),"margin"!==n&&(s-=x.css(e,"border"+jt[o]+"Width",!0,i))):(s+=x.css(e,"padding"+jt[o],!0,i),"padding"!==n&&(s+=x.css(e,"border"+jt[o]+"Width",!0,i)));return s}function Pt(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=qt(e),s=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=vt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Ct.test(i))return i;r=s&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+Ft(e,t,n||(s?"border":"content"),r,o)+"px"}function Rt(e){var t=o,n=Nt[e];return n||(n=Mt(e,t),"none"!==n&&n||(xt=(xt||x("<iframe frameborder='0' width='0' height='0'/>").css("cssText","display:block !important")).appendTo(t.documentElement),t=(xt[0].contentWindow||xt[0].contentDocument).document,t.write("<!doctype html><html><body>"),t.close(),n=Mt(e,t),xt.detach()),Nt[e]=n),n}function Mt(e,t){var n=x(t.createElement(e)).appendTo(t.body),r=x.css(n[0],"display");return n.remove(),r}x.each(["height","width"],function(e,t){x.cssHooks[t]={get:function(e,n,r){return n?0===e.offsetWidth&&bt.test(x.css(e,"display"))?x.swap(e,Et,function(){return Pt(e,t,r)}):Pt(e,t,r):undefined},set:function(e,n,r){var i=r&&qt(e);return Ot(e,n,r?Ft(e,t,r,x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,i),i):0)}}}),x(function(){x.support.reliableMarginRight||(x.cssHooks.marginRight={get:function(e,t){return t?x.swap(e,{display:"inline-block"},vt,[e,"marginRight"]):undefined}}),!x.support.pixelPosition&&x.fn.position&&x.each(["top","left"],function(e,t){x.cssHooks[t]={get:function(e,n){return n?(n=vt(e,t),Ct.test(n)?x(e).position()[t]+"px":n):undefined}}})}),x.expr&&x.expr.filters&&(x.expr.filters.hidden=function(e){return 0>=e.offsetWidth&&0>=e.offsetHeight},x.expr.filters.visible=function(e){return!x.expr.filters.hidden(e)}),x.each({margin:"",padding:"",border:"Width"},function(e,t){x.cssHooks[e+t]={expand:function(n){var r=0,i={},o="string"==typeof n?n.split(" "):[n];for(;4>r;r++)i[e+jt[r]+t]=o[r]||o[r-2]||o[0];return i}},wt.test(e)||(x.cssHooks[e+t].set=Ot)});var Wt=/%20/g,$t=/\[\]$/,Bt=/\r?\n/g,It=/^(?:submit|button|image|reset|file)$/i,zt=/^(?:input|select|textarea|keygen)/i;x.fn.extend({serialize:function(){return x.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=x.prop(this,"elements");return e?x.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!x(this).is(":disabled")&&zt.test(this.nodeName)&&!It.test(e)&&(this.checked||!ot.test(e))}).map(function(e,t){var n=x(this).val();return null==n?null:x.isArray(n)?x.map(n,function(e){return{name:t.name,value:e.replace(Bt,"\r\n")}}):{name:t.name,value:n.replace(Bt,"\r\n")}}).get()}}),x.param=function(e,t){var n,r=[],i=function(e,t){t=x.isFunction(t)?t():null==t?"":t,r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};if(t===undefined&&(t=x.ajaxSettings&&x.ajaxSettings.traditional),x.isArray(e)||e.jquery&&!x.isPlainObject(e))x.each(e,function(){i(this.name,this.value)});else for(n in e)_t(n,e[n],t,i);return r.join("&").replace(Wt,"+")};function _t(e,t,n,r){var i;if(x.isArray(t))x.each(t,function(t,i){n||$t.test(e)?r(e,i):_t(e+"["+("object"==typeof i?t:"")+"]",i,n,r)});else if(n||"object"!==x.type(t))r(e,t);else for(i in t)_t(e+"["+i+"]",t[i],n,r)}x.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){x.fn[t]=function(e,n){return arguments.length>0?this.on(t,null,e,n):this.trigger(t)}}),x.fn.extend({hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)
+},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)}});var Xt,Ut,Yt=x.now(),Vt=/\?/,Gt=/#.*$/,Jt=/([?&])_=[^&]*/,Qt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Kt=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Zt=/^(?:GET|HEAD)$/,en=/^\/\//,tn=/^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,nn=x.fn.load,rn={},on={},sn="*/".concat("*");try{Ut=i.href}catch(an){Ut=o.createElement("a"),Ut.href="",Ut=Ut.href}Xt=tn.exec(Ut.toLowerCase())||[];function un(e){return function(t,n){"string"!=typeof t&&(n=t,t="*");var r,i=0,o=t.toLowerCase().match(w)||[];if(x.isFunction(n))while(r=o[i++])"+"===r[0]?(r=r.slice(1)||"*",(e[r]=e[r]||[]).unshift(n)):(e[r]=e[r]||[]).push(n)}}function ln(e,t,n,r){var i={},o=e===on;function s(a){var u;return i[a]=!0,x.each(e[a]||[],function(e,a){var l=a(t,n,r);return"string"!=typeof l||o||i[l]?o?!(u=l):undefined:(t.dataTypes.unshift(l),s(l),!1)}),u}return s(t.dataTypes[0])||!i["*"]&&s("*")}function cn(e,t){var n,r,i=x.ajaxSettings.flatOptions||{};for(n in t)t[n]!==undefined&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&x.extend(!0,e,r),e}x.fn.load=function(e,t,n){if("string"!=typeof e&&nn)return nn.apply(this,arguments);var r,i,o,s=this,a=e.indexOf(" ");return a>=0&&(r=e.slice(a),e=e.slice(0,a)),x.isFunction(t)?(n=t,t=undefined):t&&"object"==typeof t&&(i="POST"),s.length>0&&x.ajax({url:e,type:i,dataType:"html",data:t}).done(function(e){o=arguments,s.html(r?x("<div>").append(x.parseHTML(e)).find(r):e)}).complete(n&&function(e,t){s.each(n,o||[e.responseText,t,e])}),this},x.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){x.fn[t]=function(e){return this.on(t,e)}}),x.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Ut,type:"GET",isLocal:Kt.test(Xt[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":sn,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":x.parseJSON,"text xml":x.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?cn(cn(e,x.ajaxSettings),t):cn(x.ajaxSettings,e)},ajaxPrefilter:un(rn),ajaxTransport:un(on),ajax:function(e,t){"object"==typeof e&&(t=e,e=undefined),t=t||{};var n,r,i,o,s,a,u,l,c=x.ajaxSetup({},t),p=c.context||c,f=c.context&&(p.nodeType||p.jquery)?x(p):x.event,h=x.Deferred(),d=x.Callbacks("once memory"),g=c.statusCode||{},m={},y={},v=0,b="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(2===v){if(!o){o={};while(t=Qt.exec(i))o[t[1].toLowerCase()]=t[2]}t=o[e.toLowerCase()]}return null==t?null:t},getAllResponseHeaders:function(){return 2===v?i:null},setRequestHeader:function(e,t){var n=e.toLowerCase();return v||(e=y[n]=y[n]||e,m[e]=t),this},overrideMimeType:function(e){return v||(c.mimeType=e),this},statusCode:function(e){var t;if(e)if(2>v)for(t in e)g[t]=[g[t],e[t]];else T.always(e[T.status]);return this},abort:function(e){var t=e||b;return n&&n.abort(t),k(0,t),this}};if(h.promise(T).complete=d.add,T.success=T.done,T.error=T.fail,c.url=((e||c.url||Ut)+"").replace(Gt,"").replace(en,Xt[1]+"//"),c.type=t.method||t.type||c.method||c.type,c.dataTypes=x.trim(c.dataType||"*").toLowerCase().match(w)||[""],null==c.crossDomain&&(a=tn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===Xt[1]&&a[2]===Xt[2]&&(a[3]||("http:"===a[1]?"80":"443"))===(Xt[3]||("http:"===Xt[1]?"80":"443")))),c.data&&c.processData&&"string"!=typeof c.data&&(c.data=x.param(c.data,c.traditional)),ln(rn,c,t,T),2===v)return T;u=c.global,u&&0===x.active++&&x.event.trigger("ajaxStart"),c.type=c.type.toUpperCase(),c.hasContent=!Zt.test(c.type),r=c.url,c.hasContent||(c.data&&(r=c.url+=(Vt.test(r)?"&":"?")+c.data,delete c.data),c.cache===!1&&(c.url=Jt.test(r)?r.replace(Jt,"$1_="+Yt++):r+(Vt.test(r)?"&":"?")+"_="+Yt++)),c.ifModified&&(x.lastModified[r]&&T.setRequestHeader("If-Modified-Since",x.lastModified[r]),x.etag[r]&&T.setRequestHeader("If-None-Match",x.etag[r])),(c.data&&c.hasContent&&c.contentType!==!1||t.contentType)&&T.setRequestHeader("Content-Type",c.contentType),T.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+("*"!==c.dataTypes[0]?", "+sn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)T.setRequestHeader(l,c.headers[l]);if(c.beforeSend&&(c.beforeSend.call(p,T,c)===!1||2===v))return T.abort();b="abort";for(l in{success:1,error:1,complete:1})T[l](c[l]);if(n=ln(on,c,t,T)){T.readyState=1,u&&f.trigger("ajaxSend",[T,c]),c.async&&c.timeout>0&&(s=setTimeout(function(){T.abort("timeout")},c.timeout));try{v=1,n.send(m,k)}catch(C){if(!(2>v))throw C;k(-1,C)}}else k(-1,"No Transport");function k(e,t,o,a){var l,m,y,b,w,C=t;2!==v&&(v=2,s&&clearTimeout(s),n=undefined,i=a||"",T.readyState=e>0?4:0,l=e>=200&&300>e||304===e,o&&(b=pn(c,T,o)),b=fn(c,b,T,l),l?(c.ifModified&&(w=T.getResponseHeader("Last-Modified"),w&&(x.lastModified[r]=w),w=T.getResponseHeader("etag"),w&&(x.etag[r]=w)),204===e||"HEAD"===c.type?C="nocontent":304===e?C="notmodified":(C=b.state,m=b.data,y=b.error,l=!y)):(y=C,(e||!C)&&(C="error",0>e&&(e=0))),T.status=e,T.statusText=(t||C)+"",l?h.resolveWith(p,[m,C,T]):h.rejectWith(p,[T,C,y]),T.statusCode(g),g=undefined,u&&f.trigger(l?"ajaxSuccess":"ajaxError",[T,c,l?m:y]),d.fireWith(p,[T,C]),u&&(f.trigger("ajaxComplete",[T,c]),--x.active||x.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return x.get(e,t,n,"json")},getScript:function(e,t){return x.get(e,undefined,t,"script")}}),x.each(["get","post"],function(e,t){x[t]=function(e,n,r,i){return x.isFunction(n)&&(i=i||r,r=n,n=undefined),x.ajax({url:e,type:t,dataType:i,data:n,success:r})}});function pn(e,t,n){var r,i,o,s,a=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),r===undefined&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in a)if(a[i]&&a[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}s||(s=i)}o=o||s}return o?(o!==u[0]&&u.unshift(o),n[o]):undefined}function fn(e,t,n,r){var i,o,s,a,u,l={},c=e.dataTypes.slice();if(c[1])for(s in e.converters)l[s.toLowerCase()]=e.converters[s];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(s=l[u+" "+o]||l["* "+o],!s)for(i in l)if(a=i.split(" "),a[1]===o&&(s=l[u+" "+a[0]]||l["* "+a[0]])){s===!0?s=l[i]:l[i]!==!0&&(o=a[0],c.unshift(a[1]));break}if(s!==!0)if(s&&e["throws"])t=s(t);else try{t=s(t)}catch(p){return{state:"parsererror",error:s?p:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}x.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(e){return x.globalEval(e),e}}}),x.ajaxPrefilter("script",function(e){e.cache===undefined&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),x.ajaxTransport("script",function(e){if(e.crossDomain){var t,n;return{send:function(r,i){t=x("<script>").prop({async:!0,charset:e.scriptCharset,src:e.url}).on("load error",n=function(e){t.remove(),n=null,e&&i("error"===e.type?404:200,e.type)}),o.head.appendChild(t[0])},abort:function(){n&&n()}}}});var hn=[],dn=/(=)\?(?=&|$)|\?\?/;x.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=hn.pop()||x.expando+"_"+Yt++;return this[e]=!0,e}}),x.ajaxPrefilter("json jsonp",function(t,n,r){var i,o,s,a=t.jsonp!==!1&&(dn.test(t.url)?"url":"string"==typeof t.data&&!(t.contentType||"").indexOf("application/x-www-form-urlencoded")&&dn.test(t.data)&&"data");return a||"jsonp"===t.dataTypes[0]?(i=t.jsonpCallback=x.isFunction(t.jsonpCallback)?t.jsonpCallback():t.jsonpCallback,a?t[a]=t[a].replace(dn,"$1"+i):t.jsonp!==!1&&(t.url+=(Vt.test(t.url)?"&":"?")+t.jsonp+"="+i),t.converters["script json"]=function(){return s||x.error(i+" was not called"),s[0]},t.dataTypes[0]="json",o=e[i],e[i]=function(){s=arguments},r.always(function(){e[i]=o,t[i]&&(t.jsonpCallback=n.jsonpCallback,hn.push(i)),s&&x.isFunction(o)&&o(s[0]),s=o=undefined}),"script"):undefined}),x.ajaxSettings.xhr=function(){try{return new XMLHttpRequest}catch(e){}};var gn=x.ajaxSettings.xhr(),mn={0:200,1223:204},yn=0,vn={};e.ActiveXObject&&x(e).on("unload",function(){for(var e in vn)vn[e]();vn=undefined}),x.support.cors=!!gn&&"withCredentials"in gn,x.support.ajax=gn=!!gn,x.ajaxTransport(function(e){var t;return x.support.cors||gn&&!e.crossDomain?{send:function(n,r){var i,o,s=e.xhr();if(s.open(e.type,e.url,e.async,e.username,e.password),e.xhrFields)for(i in e.xhrFields)s[i]=e.xhrFields[i];e.mimeType&&s.overrideMimeType&&s.overrideMimeType(e.mimeType),e.crossDomain||n["X-Requested-With"]||(n["X-Requested-With"]="XMLHttpRequest");for(i in n)s.setRequestHeader(i,n[i]);t=function(e){return function(){t&&(delete vn[o],t=s.onload=s.onerror=null,"abort"===e?s.abort():"error"===e?r(s.status||404,s.statusText):r(mn[s.status]||s.status,s.statusText,"string"==typeof s.responseText?{text:s.responseText}:undefined,s.getAllResponseHeaders()))}},s.onload=t(),s.onerror=t("error"),t=vn[o=yn++]=t("abort"),s.send(e.hasContent&&e.data||null)},abort:function(){t&&t()}}:undefined});var xn,bn,wn=/^(?:toggle|show|hide)$/,Tn=RegExp("^(?:([+-])=|)("+b+")([a-z%]*)$","i"),Cn=/queueHooks$/,kn=[An],Nn={"*":[function(e,t){var n=this.createTween(e,t),r=n.cur(),i=Tn.exec(t),o=i&&i[3]||(x.cssNumber[e]?"":"px"),s=(x.cssNumber[e]||"px"!==o&&+r)&&Tn.exec(x.css(n.elem,e)),a=1,u=20;if(s&&s[3]!==o){o=o||s[3],i=i||[],s=+r||1;do a=a||".5",s/=a,x.style(n.elem,e,s+o);while(a!==(a=n.cur()/r)&&1!==a&&--u)}return i&&(s=n.start=+s||+r||0,n.unit=o,n.end=i[1]?s+(i[1]+1)*i[2]:+i[2]),n}]};function En(){return setTimeout(function(){xn=undefined}),xn=x.now()}function Sn(e,t,n){var r,i=(Nn[t]||[]).concat(Nn["*"]),o=0,s=i.length;for(;s>o;o++)if(r=i[o].call(n,t,e))return r}function jn(e,t,n){var r,i,o=0,s=kn.length,a=x.Deferred().always(function(){delete u.elem}),u=function(){if(i)return!1;var t=xn||En(),n=Math.max(0,l.startTime+l.duration-t),r=n/l.duration||0,o=1-r,s=0,u=l.tweens.length;for(;u>s;s++)l.tweens[s].run(o);return a.notifyWith(e,[l,o,n]),1>o&&u?n:(a.resolveWith(e,[l]),!1)},l=a.promise({elem:e,props:x.extend({},t),opts:x.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:xn||En(),duration:n.duration,tweens:[],createTween:function(t,n){var r=x.Tween(e,l.opts,t,n,l.opts.specialEasing[t]||l.opts.easing);return l.tweens.push(r),r},stop:function(t){var n=0,r=t?l.tweens.length:0;if(i)return this;for(i=!0;r>n;n++)l.tweens[n].run(1);return t?a.resolveWith(e,[l,t]):a.rejectWith(e,[l,t]),this}}),c=l.props;for(Dn(c,l.opts.specialEasing);s>o;o++)if(r=kn[o].call(l,e,c,l.opts))return r;return x.map(c,Sn,l),x.isFunction(l.opts.start)&&l.opts.start.call(e,l),x.fx.timer(x.extend(u,{elem:e,anim:l,queue:l.opts.queue})),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always)}function Dn(e,t){var n,r,i,o,s;for(n in e)if(r=x.camelCase(n),i=t[r],o=e[n],x.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),s=x.cssHooks[r],s&&"expand"in s){o=s.expand(o),delete e[r];for(n in o)n in e||(e[n]=o[n],t[n]=i)}else t[r]=i}x.Animation=x.extend(jn,{tweener:function(e,t){x.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;i>r;r++)n=e[r],Nn[n]=Nn[n]||[],Nn[n].unshift(t)},prefilter:function(e,t){t?kn.unshift(e):kn.push(e)}});function An(e,t,n){var r,i,o,s,a,u,l=this,c={},p=e.style,f=e.nodeType&&Lt(e),h=q.get(e,"fxshow");n.queue||(a=x._queueHooks(e,"fx"),null==a.unqueued&&(a.unqueued=0,u=a.empty.fire,a.empty.fire=function(){a.unqueued||u()}),a.unqueued++,l.always(function(){l.always(function(){a.unqueued--,x.queue(e,"fx").length||a.empty.fire()})})),1===e.nodeType&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],"inline"===x.css(e,"display")&&"none"===x.css(e,"float")&&(p.display="inline-block")),n.overflow&&(p.overflow="hidden",l.always(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t)if(i=t[r],wn.exec(i)){if(delete t[r],o=o||"toggle"===i,i===(f?"hide":"show")){if("show"!==i||!h||h[r]===undefined)continue;f=!0}c[r]=h&&h[r]||x.style(e,r)}if(!x.isEmptyObject(c)){h?"hidden"in h&&(f=h.hidden):h=q.access(e,"fxshow",{}),o&&(h.hidden=!f),f?x(e).show():l.done(function(){x(e).hide()}),l.done(function(){var t;q.remove(e,"fxshow");for(t in c)x.style(e,t,c[t])});for(r in c)s=Sn(f?h[r]:0,r,l),r in h||(h[r]=s.start,f&&(s.end=s.start,s.start="width"===r||"height"===r?1:0))}}function Ln(e,t,n,r,i){return new Ln.prototype.init(e,t,n,r,i)}x.Tween=Ln,Ln.prototype={constructor:Ln,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(x.cssNumber[n]?"":"px")},cur:function(){var e=Ln.propHooks[this.prop];return e&&e.get?e.get(this):Ln.propHooks._default.get(this)},run:function(e){var t,n=Ln.propHooks[this.prop];return this.pos=t=this.options.duration?x.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):Ln.propHooks._default.set(this),this}},Ln.prototype.init.prototype=Ln.prototype,Ln.propHooks={_default:{get:function(e){var t;return null==e.elem[e.prop]||e.elem.style&&null!=e.elem.style[e.prop]?(t=x.css(e.elem,e.prop,""),t&&"auto"!==t?t:0):e.elem[e.prop]},set:function(e){x.fx.step[e.prop]?x.fx.step[e.prop](e):e.elem.style&&(null!=e.elem.style[x.cssProps[e.prop]]||x.cssHooks[e.prop])?x.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},Ln.propHooks.scrollTop=Ln.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},x.each(["toggle","show","hide"],function(e,t){var n=x.fn[t];x.fn[t]=function(e,r,i){return null==e||"boolean"==typeof e?n.apply(this,arguments):this.animate(qn(t,!0),e,r,i)}}),x.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Lt).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=x.isEmptyObject(e),o=x.speed(t,n,r),s=function(){var t=jn(this,x.extend({},e),o);(i||q.get(this,"finish"))&&t.stop(!0)};return s.finish=s,i||o.queue===!1?this.each(s):this.queue(o.queue,s)},stop:function(e,t,n){var r=function(e){var t=e.stop;delete e.stop,t(n)};return"string"!=typeof e&&(n=t,t=e,e=undefined),t&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,i=null!=e&&e+"queueHooks",o=x.timers,s=q.get(this);if(i)s[i]&&s[i].stop&&r(s[i]);else for(i in s)s[i]&&s[i].stop&&Cn.test(i)&&r(s[i]);for(i=o.length;i--;)o[i].elem!==this||null!=e&&o[i].queue!==e||(o[i].anim.stop(n),t=!1,o.splice(i,1));(t||!n)&&x.dequeue(this,e)})},finish:function(e){return e!==!1&&(e=e||"fx"),this.each(function(){var t,n=q.get(this),r=n[e+"queue"],i=n[e+"queueHooks"],o=x.timers,s=r?r.length:0;for(n.finish=!0,x.queue(this,e,[]),i&&i.stop&&i.stop.call(this,!0),t=o.length;t--;)o[t].elem===this&&o[t].queue===e&&(o[t].anim.stop(!0),o.splice(t,1));for(t=0;s>t;t++)r[t]&&r[t].finish&&r[t].finish.call(this);delete n.finish})}});function qn(e,t){var n,r={height:e},i=0;for(t=t?1:0;4>i;i+=2-t)n=jt[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}x.each({slideDown:qn("show"),slideUp:qn("hide"),slideToggle:qn("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){x.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),x.speed=function(e,t,n){var r=e&&"object"==typeof e?x.extend({},e):{complete:n||!n&&t||x.isFunction(e)&&e,duration:e,easing:n&&t||t&&!x.isFunction(t)&&t};return r.duration=x.fx.off?0:"number"==typeof r.duration?r.duration:r.duration in x.fx.speeds?x.fx.speeds[r.duration]:x.fx.speeds._default,(null==r.queue||r.queue===!0)&&(r.queue="fx"),r.old=r.complete,r.complete=function(){x.isFunction(r.old)&&r.old.call(this),r.queue&&x.dequeue(this,r.queue)},r},x.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},x.timers=[],x.fx=Ln.prototype.init,x.fx.tick=function(){var e,t=x.timers,n=0;for(xn=x.now();t.length>n;n++)e=t[n],e()||t[n]!==e||t.splice(n--,1);t.length||x.fx.stop(),xn=undefined},x.fx.timer=function(e){e()&&x.timers.push(e)&&x.fx.start()},x.fx.interval=13,x.fx.start=function(){bn||(bn=setInterval(x.fx.tick,x.fx.interval))},x.fx.stop=function(){clearInterval(bn),bn=null},x.fx.speeds={slow:600,fast:200,_default:400},x.fx.step={},x.expr&&x.expr.filters&&(x.expr.filters.animated=function(e){return x.grep(x.timers,function(t){return e===t.elem}).length}),x.fn.offset=function(e){if(arguments.length)return e===undefined?this:this.each(function(t){x.offset.setOffset(this,e,t)});var t,n,i=this[0],o={top:0,left:0},s=i&&i.ownerDocument;if(s)return t=s.documentElement,x.contains(t,i)?(typeof i.getBoundingClientRect!==r&&(o=i.getBoundingClientRect()),n=Hn(s),{top:o.top+n.pageYOffset-t.clientTop,left:o.left+n.pageXOffset-t.clientLeft}):o},x.offset={setOffset:function(e,t,n){var r,i,o,s,a,u,l,c=x.css(e,"position"),p=x(e),f={};"static"===c&&(e.style.position="relative"),a=p.offset(),o=x.css(e,"top"),u=x.css(e,"left"),l=("absolute"===c||"fixed"===c)&&(o+u).indexOf("auto")>-1,l?(r=p.position(),s=r.top,i=r.left):(s=parseFloat(o)||0,i=parseFloat(u)||0),x.isFunction(t)&&(t=t.call(e,n,a)),null!=t.top&&(f.top=t.top-a.top+s),null!=t.left&&(f.left=t.left-a.left+i),"using"in t?t.using.call(e,f):p.css(f)}},x.fn.extend({position:function(){if(this[0]){var e,t,n=this[0],r={top:0,left:0};return"fixed"===x.css(n,"position")?t=n.getBoundingClientRect():(e=this.offsetParent(),t=this.offset(),x.nodeName(e[0],"html")||(r=e.offset()),r.top+=x.css(e[0],"borderTopWidth",!0),r.left+=x.css(e[0],"borderLeftWidth",!0)),{top:t.top-r.top-x.css(n,"marginTop",!0),left:t.left-r.left-x.css(n,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||s;while(e&&!x.nodeName(e,"html")&&"static"===x.css(e,"position"))e=e.offsetParent;return e||s})}}),x.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,n){var r="pageYOffset"===n;x.fn[t]=function(i){return x.access(this,function(t,i,o){var s=Hn(t);return o===undefined?s?s[n]:t[i]:(s?s.scrollTo(r?e.pageXOffset:o,r?o:e.pageYOffset):t[i]=o,undefined)},t,i,arguments.length,null)}});function Hn(e){return x.isWindow(e)?e:9===e.nodeType&&e.defaultView}x.each({Height:"height",Width:"width"},function(e,t){x.each({padding:"inner"+e,content:t,"":"outer"+e},function(n,r){x.fn[r]=function(r,i){var o=arguments.length&&(n||"boolean"!=typeof r),s=n||(r===!0||i===!0?"margin":"border");return x.access(this,function(t,n,r){var i;return x.isWindow(t)?t.document.documentElement["client"+e]:9===t.nodeType?(i=t.documentElement,Math.max(t.body["scroll"+e],i["scroll"+e],t.body["offset"+e],i["offset"+e],i["client"+e])):r===undefined?x.css(t,n,s):x.style(t,n,r,s)},t,o?r:undefined,o,null)}})}),x.fn.size=function(){return this.length},x.fn.andSelf=x.fn.addBack,"object"==typeof module&&module&&"object"==typeof module.exports?module.exports=x:"function"==typeof define&&define.amd&&define("jquery",[],function(){return x}),"object"==typeof e&&"object"==typeof e.document&&(e.jQuery=e.$=x)})(window);
diff --git a/docs/htmldoc/js/jquery.qtip.css b/docs/htmldoc/js/jquery.qtip.css
new file mode 100644
index 0000000..c2dcb30
--- /dev/null
+++ b/docs/htmldoc/js/jquery.qtip.css
@@ -0,0 +1,623 @@
+/*
+ * qTip2 - Pretty powerful tooltips - v2.2.0
+ * http://qtip2.com
+ *
+ * Copyright (c) 2013 Craig Michael Thompson
+ * Released under the MIT, GPL licenses
+ * http://jquery.org/license
+ *
+ * Date: Thu Nov 21 2013 08:34 GMT+0000
+ * Plugins: tips modal viewport svg imagemap ie6
+ * Styles: basic css3
+ */
+.qtip{
+ position: absolute;
+ left: -28000px;
+ top: -28000px;
+ display: none;
+
+ max-width: 280px;
+ min-width: 50px;
+
+ font-size: 10.5px;
+ line-height: 12px;
+
+ direction: ltr;
+
+ box-shadow: none;
+ padding: 0;
+}
+
+ .qtip-content{
+ position: relative;
+ padding: 5px 9px;
+ overflow: hidden;
+
+ text-align: left;
+ word-wrap: break-word;
+ }
+
+ .qtip-titlebar{
+ position: relative;
+ padding: 5px 35px 5px 10px;
+ overflow: hidden;
+
+ border-width: 0 0 1px;
+ font-weight: bold;
+ }
+
+ .qtip-titlebar + .qtip-content{ border-top-width: 0 !important; }
+
+ /* Default close button class */
+ .qtip-close{
+ position: absolute;
+ right: -9px; top: -9px;
+
+ cursor: pointer;
+ outline: medium none;
+
+ border-width: 1px;
+ border-style: solid;
+ border-color: transparent;
+ }
+
+ .qtip-titlebar .qtip-close{
+ right: 4px; top: 50%;
+ margin-top: -9px;
+ }
+
+ * html .qtip-titlebar .qtip-close{ top: 16px; } /* IE fix */
+
+ .qtip-titlebar .ui-icon,
+ .qtip-icon .ui-icon{
+ display: block;
+ text-indent: -1000em;
+ direction: ltr;
+ }
+
+ .qtip-icon, .qtip-icon .ui-icon{
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+ text-decoration: none;
+ }
+
+ .qtip-icon .ui-icon{
+ width: 18px;
+ height: 14px;
+
+ line-height: 14px;
+ text-align: center;
+ text-indent: 0;
+ font: normal bold 10px/13px Tahoma,sans-serif;
+
+ color: inherit;
+ background: transparent none no-repeat -100em -100em;
+ }
+
+/* Applied to 'focused' tooltips e.g. most recently displayed/interacted with */
+.qtip-focus{}
+
+/* Applied on hover of tooltips i.e. added/removed on mouseenter/mouseleave respectively */
+.qtip-hover{}
+
+/* Default tooltip style */
+.qtip-default{
+ border-width: 1px;
+ border-style: solid;
+ border-color: #F1D031;
+
+ background-color: #FFFFA3;
+ color: #555;
+}
+
+ .qtip-default .qtip-titlebar{
+ background-color: #FFEF93;
+ }
+
+ .qtip-default .qtip-icon{
+ border-color: #CCC;
+ background: #F1F1F1;
+ color: #777;
+ }
+
+ .qtip-default .qtip-titlebar .qtip-close{
+ border-color: #AAA;
+ color: #111;
+ }
+
+
+
+/*! Light tooltip style */
+.qtip-light{
+ background-color: white;
+ border-color: #E2E2E2;
+ color: #454545;
+}
+
+ .qtip-light .qtip-titlebar{
+ background-color: #f1f1f1;
+ }
+
+
+/*! Dark tooltip style */
+.qtip-dark{
+ background-color: #505050;
+ border-color: #303030;
+ color: #f3f3f3;
+}
+
+ .qtip-dark .qtip-titlebar{
+ background-color: #404040;
+ }
+
+ .qtip-dark .qtip-icon{
+ border-color: #444;
+ }
+
+ .qtip-dark .qtip-titlebar .ui-state-hover{
+ border-color: #303030;
+ }
+
+
+/*! Cream tooltip style */
+.qtip-cream{
+ background-color: #FBF7AA;
+ border-color: #F9E98E;
+ color: #A27D35;
+}
+
+ .qtip-cream .qtip-titlebar{
+ background-color: #F0DE7D;
+ }
+
+ .qtip-cream .qtip-close .qtip-icon{
+ background-position: -82px 0;
+ }
+
+
+/*! Red tooltip style */
+.qtip-red{
+ background-color: #F78B83;
+ border-color: #D95252;
+ color: #912323;
+}
+
+ .qtip-red .qtip-titlebar{
+ background-color: #F06D65;
+ }
+
+ .qtip-red .qtip-close .qtip-icon{
+ background-position: -102px 0;
+ }
+
+ .qtip-red .qtip-icon{
+ border-color: #D95252;
+ }
+
+ .qtip-red .qtip-titlebar .ui-state-hover{
+ border-color: #D95252;
+ }
+
+
+/*! Green tooltip style */
+.qtip-green{
+ background-color: #CAED9E;
+ border-color: #90D93F;
+ color: #3F6219;
+}
+
+ .qtip-green .qtip-titlebar{
+ background-color: #B0DE78;
+ }
+
+ .qtip-green .qtip-close .qtip-icon{
+ background-position: -42px 0;
+ }
+
+
+/*! Blue tooltip style */
+.qtip-blue{
+ background-color: #E5F6FE;
+ border-color: #ADD9ED;
+ color: #5E99BD;
+}
+
+ .qtip-blue .qtip-titlebar{
+ background-color: #D0E9F5;
+ }
+
+ .qtip-blue .qtip-close .qtip-icon{
+ background-position: -2px 0;
+ }
+
+
+
+.qtip-shadow{
+ -webkit-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
+ -moz-box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
+ box-shadow: 1px 1px 3px 1px rgba(0, 0, 0, 0.15);
+}
+
+/* Add rounded corners to your tooltips in: FF3+, Chrome 2+, Opera 10.6+, IE9+, Safari 2+ */
+.qtip-rounded,
+.qtip-tipsy,
+.qtip-bootstrap{
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ border-radius: 5px;
+}
+
+.qtip-rounded .qtip-titlebar{
+ -moz-border-radius: 4px 4px 0 0;
+ -webkit-border-radius: 4px 4px 0 0;
+ border-radius: 4px 4px 0 0;
+}
+
+/* Youtube tooltip style */
+.qtip-youtube{
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+
+ -webkit-box-shadow: 0 0 3px #333;
+ -moz-box-shadow: 0 0 3px #333;
+ box-shadow: 0 0 3px #333;
+
+ color: white;
+ border-width: 0;
+
+ background: #4A4A4A;
+ background-image: -webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,black));
+ background-image: -webkit-linear-gradient(top,#4A4A4A 0,black 100%);
+ background-image: -moz-linear-gradient(top,#4A4A4A 0,black 100%);
+ background-image: -ms-linear-gradient(top,#4A4A4A 0,black 100%);
+ background-image: -o-linear-gradient(top,#4A4A4A 0,black 100%);
+}
+
+ .qtip-youtube .qtip-titlebar{
+ background-color: #4A4A4A;
+ background-color: rgba(0,0,0,0);
+ }
+
+ .qtip-youtube .qtip-content{
+ padding: .75em;
+ font: 12px arial,sans-serif;
+
+ filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);
+ -ms-filter: "progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr=#4a4a4a,EndColorStr=#000000);";
+ }
+
+ .qtip-youtube .qtip-icon{
+ border-color: #222;
+ }
+
+ .qtip-youtube .qtip-titlebar .ui-state-hover{
+ border-color: #303030;
+ }
+
+
+/* jQuery TOOLS Tooltip style */
+.qtip-jtools{
+ background: #232323;
+ background: rgba(0, 0, 0, 0.7);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#717171), to(#232323));
+ background-image: -moz-linear-gradient(top, #717171, #232323);
+ background-image: -webkit-linear-gradient(top, #717171, #232323);
+ background-image: -ms-linear-gradient(top, #717171, #232323);
+ background-image: -o-linear-gradient(top, #717171, #232323);
+
+ border: 2px solid #ddd;
+ border: 2px solid rgba(241,241,241,1);
+
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+
+ -webkit-box-shadow: 0 0 12px #333;
+ -moz-box-shadow: 0 0 12px #333;
+ box-shadow: 0 0 12px #333;
+}
+
+ /* IE Specific */
+ .qtip-jtools .qtip-titlebar{
+ background-color: transparent;
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171,endColorstr=#4A4A4A)";
+ }
+ .qtip-jtools .qtip-content{
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A,endColorstr=#232323)";
+ }
+
+ .qtip-jtools .qtip-titlebar,
+ .qtip-jtools .qtip-content{
+ background: transparent;
+ color: white;
+ border: 0 dashed transparent;
+ }
+
+ .qtip-jtools .qtip-icon{
+ border-color: #555;
+ }
+
+ .qtip-jtools .qtip-titlebar .ui-state-hover{
+ border-color: #333;
+ }
+
+
+/* Cluetip style */
+.qtip-cluetip{
+ -webkit-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
+ -moz-box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
+ box-shadow: 4px 4px 5px rgba(0, 0, 0, 0.4);
+
+ background-color: #D9D9C2;
+ color: #111;
+ border: 0 dashed transparent;
+}
+
+ .qtip-cluetip .qtip-titlebar{
+ background-color: #87876A;
+ color: white;
+ border: 0 dashed transparent;
+ }
+
+ .qtip-cluetip .qtip-icon{
+ border-color: #808064;
+ }
+
+ .qtip-cluetip .qtip-titlebar .ui-state-hover{
+ border-color: #696952;
+ color: #696952;
+ }
+
+
+/* Tipsy style */
+.qtip-tipsy{
+ background: black;
+ background: rgba(0, 0, 0, .87);
+
+ color: white;
+ border: 0 solid transparent;
+
+ font-size: 11px;
+ font-family: 'Lucida Grande', sans-serif;
+ font-weight: bold;
+ line-height: 16px;
+ text-shadow: 0 1px black;
+}
+
+ .qtip-tipsy .qtip-titlebar{
+ padding: 6px 35px 0 10px;
+ background-color: transparent;
+ }
+
+ .qtip-tipsy .qtip-content{
+ padding: 6px 10px;
+ }
+
+ .qtip-tipsy .qtip-icon{
+ border-color: #222;
+ text-shadow: none;
+ }
+
+ .qtip-tipsy .qtip-titlebar .ui-state-hover{
+ border-color: #303030;
+ }
+
+
+/* Tipped style */
+.qtip-tipped{
+ border: 3px solid #959FA9;
+
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
+
+ background-color: #F9F9F9;
+ color: #454545;
+
+ font-weight: normal;
+ font-family: serif;
+}
+
+ .qtip-tipped .qtip-titlebar{
+ border-bottom-width: 0;
+
+ color: white;
+ background: #3A79B8;
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#3A79B8), to(#2E629D));
+ background-image: -webkit-linear-gradient(top, #3A79B8, #2E629D);
+ background-image: -moz-linear-gradient(top, #3A79B8, #2E629D);
+ background-image: -ms-linear-gradient(top, #3A79B8, #2E629D);
+ background-image: -o-linear-gradient(top, #3A79B8, #2E629D);
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8,endColorstr=#2E629D)";
+ }
+
+ .qtip-tipped .qtip-icon{
+ border: 2px solid #285589;
+ background: #285589;
+ }
+
+ .qtip-tipped .qtip-icon .ui-icon{
+ background-color: #FBFBFB;
+ color: #555;
+ }
+
+
+/**
+ * Twitter Bootstrap style.
+ *
+ * Tested with IE 8, IE 9, Chrome 18, Firefox 9, Opera 11.
+ * Does not work with IE 7.
+ */
+.qtip-bootstrap{
+ /** Taken from Bootstrap body */
+ font-size: 14px;
+ line-height: 20px;
+ color: #333333;
+
+ /** Taken from Bootstrap .popover */
+ padding: 1px;
+ background-color: #ffffff;
+ border: 1px solid #ccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -moz-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ -webkit-background-clip: padding-box;
+ -moz-background-clip: padding;
+ background-clip: padding-box;
+}
+
+ .qtip-bootstrap .qtip-titlebar{
+ /** Taken from Bootstrap .popover-title */
+ padding: 8px 14px;
+ margin: 0;
+ font-size: 14px;
+ font-weight: normal;
+ line-height: 18px;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ -webkit-border-radius: 5px 5px 0 0;
+ -moz-border-radius: 5px 5px 0 0;
+ border-radius: 5px 5px 0 0;
+ }
+
+ .qtip-bootstrap .qtip-titlebar .qtip-close{
+ /**
+ * Overrides qTip2:
+ * .qtip-titlebar .qtip-close{
+ * [...]
+ * right: 4px;
+ * top: 50%;
+ * [...]
+ * border-style: solid;
+ * }
+ */
+ right: 11px;
+ top: 45%;
+ border-style: none;
+ }
+
+ .qtip-bootstrap .qtip-content{
+ /** Taken from Bootstrap .popover-content */
+ padding: 9px 14px;
+ }
+
+ .qtip-bootstrap .qtip-icon{
+ /**
+ * Overrides qTip2:
+ * .qtip-default .qtip-icon {
+ * border-color: #CCC;
+ * background: #F1F1F1;
+ * color: #777;
+ * }
+ */
+ background: transparent;
+ }
+
+ .qtip-bootstrap .qtip-icon .ui-icon{
+ /**
+ * Overrides qTip2:
+ * .qtip-icon .ui-icon{
+ * width: 18px;
+ * height: 14px;
+ * }
+ */
+ width: auto;
+ height: auto;
+
+ /* Taken from Bootstrap .close */
+ float: right;
+ font-size: 20px;
+ font-weight: bold;
+ line-height: 18px;
+ color: #000000;
+ text-shadow: 0 1px 0 #ffffff;
+ opacity: 0.2;
+ filter: alpha(opacity=20);
+ }
+
+ .qtip-bootstrap .qtip-icon .ui-icon:hover{
+ /* Taken from Bootstrap .close:hover */
+ color: #000000;
+ text-decoration: none;
+ cursor: pointer;
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+ }
+
+
+/* IE9 fix - removes all filters */
+.qtip:not(.ie9haxors) div.qtip-content,
+.qtip:not(.ie9haxors) div.qtip-titlebar{
+ filter: none;
+ -ms-filter: none;
+}
+
+
+
+.qtip .qtip-tip{
+ margin: 0 auto;
+ overflow: hidden;
+ z-index: 10;
+
+}
+
+ /* Opera bug #357 - Incorrect tip position
+ https://github.com/Craga89/qTip2/issues/367 */
+ x:-o-prefocus, .qtip .qtip-tip{
+ visibility: hidden;
+ }
+
+ .qtip .qtip-tip,
+ .qtip .qtip-tip .qtip-vml,
+ .qtip .qtip-tip canvas{
+ position: absolute;
+
+ color: #123456;
+ background: transparent;
+ border: 0 dashed transparent;
+ }
+
+ .qtip .qtip-tip canvas{ top: 0; left: 0; }
+
+ .qtip .qtip-tip .qtip-vml{
+ behavior: url(#default#VML);
+ display: inline-block;
+ visibility: visible;
+ }
+
+#qtip-overlay{
+ position: fixed;
+ left: 0; top: 0;
+ width: 100%; height: 100%;
+}
+
+ /* Applied to modals with show.modal.blur set to true */
+ #qtip-overlay.blurs{ cursor: pointer; }
+
+ /* Change opacity of overlay here */
+ #qtip-overlay div{
+ position: absolute;
+ left: 0; top: 0;
+ width: 100%; height: 100%;
+
+ background-color: black;
+
+ opacity: 0.7;
+ filter:alpha(opacity=70);
+ -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=70)";
+ }
+
+
+
+.qtipmodal-ie6fix{
+ position: absolute !important;
+} \ No newline at end of file
diff --git a/docs/htmldoc/js/jquery.qtip.js b/docs/htmldoc/js/jquery.qtip.js
new file mode 100644
index 0000000..52443c0
--- /dev/null
+++ b/docs/htmldoc/js/jquery.qtip.js
@@ -0,0 +1,3440 @@
+/*
+ * qTip2 - Pretty powerful tooltips - v2.2.0
+ * http://qtip2.com
+ *
+ * Copyright (c) 2013 Craig Michael Thompson
+ * Released under the MIT, GPL licenses
+ * http://jquery.org/license
+ *
+ * Date: Thu Nov 21 2013 08:34 GMT+0000
+ * Plugins: tips modal viewport svg imagemap ie6
+ * Styles: basic css3
+ */
+/*global window: false, jQuery: false, console: false, define: false */
+
+/* Cache window, document, undefined */
+(function( window, document, undefined ) {
+
+// Uses AMD or browser globals to create a jQuery plugin.
+(function( factory ) {
+ "use strict";
+ if(typeof define === 'function' && define.amd) {
+ define(['jquery'], factory);
+ }
+ else if(jQuery && !jQuery.fn.qtip) {
+ factory(jQuery);
+ }
+}
+(function($) {
+ "use strict"; // Enable ECMAScript "strict" operation for this function. See more: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/
+
+;// Munge the primitives - Paul Irish tip
+var TRUE = true,
+FALSE = false,
+NULL = null,
+
+// Common variables
+X = 'x', Y = 'y',
+WIDTH = 'width',
+HEIGHT = 'height',
+
+// Positioning sides
+TOP = 'top',
+LEFT = 'left',
+BOTTOM = 'bottom',
+RIGHT = 'right',
+CENTER = 'center',
+
+// Position adjustment types
+FLIP = 'flip',
+FLIPINVERT = 'flipinvert',
+SHIFT = 'shift',
+
+// Shortcut vars
+QTIP, PROTOTYPE, CORNER, CHECKS,
+PLUGINS = {},
+NAMESPACE = 'qtip',
+ATTR_HAS = 'data-hasqtip',
+ATTR_ID = 'data-qtip-id',
+WIDGET = ['ui-widget', 'ui-tooltip'],
+SELECTOR = '.'+NAMESPACE,
+INACTIVE_EVENTS = 'click dblclick mousedown mouseup mousemove mouseleave mouseenter'.split(' '),
+
+CLASS_FIXED = NAMESPACE+'-fixed',
+CLASS_DEFAULT = NAMESPACE + '-default',
+CLASS_FOCUS = NAMESPACE + '-focus',
+CLASS_HOVER = NAMESPACE + '-hover',
+CLASS_DISABLED = NAMESPACE+'-disabled',
+
+replaceSuffix = '_replacedByqTip',
+oldtitle = 'oldtitle',
+trackingBound,
+
+// Browser detection
+BROWSER = {
+ /*
+ * IE version detection
+ *
+ * Adapted from: http://ajaxian.com/archives/attack-of-the-ie-conditional-comment
+ * Credit to James Padolsey for the original implemntation!
+ */
+ ie: (function(){
+ var v = 3, div = document.createElement('div');
+ while ((div.innerHTML = '<!--[if gt IE '+(++v)+']><i></i><![endif]-->')) {
+ if(!div.getElementsByTagName('i')[0]) { break; }
+ }
+ return v > 4 ? v : NaN;
+ }()),
+
+ /*
+ * iOS version detection
+ */
+ iOS: parseFloat(
+ ('' + (/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0,''])[1])
+ .replace('undefined', '3_2').replace('_', '.').replace('_', '')
+ ) || FALSE
+};
+
+;function QTip(target, options, id, attr) {
+ // Elements and ID
+ this.id = id;
+ this.target = target;
+ this.tooltip = NULL;
+ this.elements = { target: target };
+
+ // Internal constructs
+ this._id = NAMESPACE + '-' + id;
+ this.timers = { img: {} };
+ this.options = options;
+ this.plugins = {};
+
+ // Cache object
+ this.cache = {
+ event: {},
+ target: $(),
+ disabled: FALSE,
+ attr: attr,
+ onTooltip: FALSE,
+ lastClass: ''
+ };
+
+ // Set the initial flags
+ this.rendered = this.destroyed = this.disabled = this.waiting =
+ this.hiddenDuringWait = this.positioning = this.triggering = FALSE;
+}
+PROTOTYPE = QTip.prototype;
+
+PROTOTYPE._when = function(deferreds) {
+ return $.when.apply($, deferreds);
+};
+
+PROTOTYPE.render = function(show) {
+ if(this.rendered || this.destroyed) { return this; } // If tooltip has already been rendered, exit
+
+ var self = this,
+ options = this.options,
+ cache = this.cache,
+ elements = this.elements,
+ text = options.content.text,
+ title = options.content.title,
+ button = options.content.button,
+ posOptions = options.position,
+ namespace = '.'+this._id+' ',
+ deferreds = [],
+ tooltip;
+
+ // Add ARIA attributes to target
+ $.attr(this.target[0], 'aria-describedby', this._id);
+
+ // Create tooltip element
+ this.tooltip = elements.tooltip = tooltip = $('<div/>', {
+ 'id': this._id,
+ 'class': [ NAMESPACE, CLASS_DEFAULT, options.style.classes, NAMESPACE + '-pos-' + options.position.my.abbrev() ].join(' '),
+ 'width': options.style.width || '',
+ 'height': options.style.height || '',
+ 'tracking': posOptions.target === 'mouse' && posOptions.adjust.mouse,
+
+ /* ARIA specific attributes */
+ 'role': 'alert',
+ 'aria-live': 'polite',
+ 'aria-atomic': FALSE,
+ 'aria-describedby': this._id + '-content',
+ 'aria-hidden': TRUE
+ })
+ .toggleClass(CLASS_DISABLED, this.disabled)
+ .attr(ATTR_ID, this.id)
+ .data(NAMESPACE, this)
+ .appendTo(posOptions.container)
+ .append(
+ // Create content element
+ elements.content = $('<div />', {
+ 'class': NAMESPACE + '-content',
+ 'id': this._id + '-content',
+ 'aria-atomic': TRUE
+ })
+ );
+
+ // Set rendered flag and prevent redundant reposition calls for now
+ this.rendered = -1;
+ this.positioning = TRUE;
+
+ // Create title...
+ if(title) {
+ this._createTitle();
+
+ // Update title only if its not a callback (called in toggle if so)
+ if(!$.isFunction(title)) {
+ deferreds.push( this._updateTitle(title, FALSE) );
+ }
+ }
+
+ // Create button
+ if(button) { this._createButton(); }
+
+ // Set proper rendered flag and update content if not a callback function (called in toggle)
+ if(!$.isFunction(text)) {
+ deferreds.push( this._updateContent(text, FALSE) );
+ }
+ this.rendered = TRUE;
+
+ // Setup widget classes
+ this._setWidget();
+
+ // Initialize 'render' plugins
+ $.each(PLUGINS, function(name) {
+ var instance;
+ if(this.initialize === 'render' && (instance = this(self))) {
+ self.plugins[name] = instance;
+ }
+ });
+
+ // Unassign initial events and assign proper events
+ this._unassignEvents();
+ this._assignEvents();
+
+ // When deferreds have completed
+ this._when(deferreds).then(function() {
+ // tooltiprender event
+ self._trigger('render');
+
+ // Reset flags
+ self.positioning = FALSE;
+
+ // Show tooltip if not hidden during wait period
+ if(!self.hiddenDuringWait && (options.show.ready || show)) {
+ self.toggle(TRUE, cache.event, FALSE);
+ }
+ self.hiddenDuringWait = FALSE;
+ });
+
+ // Expose API
+ QTIP.api[this.id] = this;
+
+ return this;
+};
+
+PROTOTYPE.destroy = function(immediate) {
+ // Set flag the signify destroy is taking place to plugins
+ // and ensure it only gets destroyed once!
+ if(this.destroyed) { return this.target; }
+
+ function process() {
+ if(this.destroyed) { return; }
+ this.destroyed = TRUE;
+
+ var target = this.target,
+ title = target.attr(oldtitle);
+
+ // Destroy tooltip if rendered
+ if(this.rendered) {
+ this.tooltip.stop(1,0).find('*').remove().end().remove();
+ }
+
+ // Destroy all plugins
+ $.each(this.plugins, function(name) {
+ this.destroy && this.destroy();
+ });
+
+ // Clear timers and remove bound events
+ clearTimeout(this.timers.show);
+ clearTimeout(this.timers.hide);
+ this._unassignEvents();
+
+ // Remove api object and ARIA attributes
+ target.removeData(NAMESPACE)
+ .removeAttr(ATTR_ID)
+ .removeAttr(ATTR_HAS)
+ .removeAttr('aria-describedby');
+
+ // Reset old title attribute if removed
+ if(this.options.suppress && title) {
+ target.attr('title', title).removeAttr(oldtitle);
+ }
+
+ // Remove qTip events associated with this API
+ this._unbind(target);
+
+ // Remove ID from used id objects, and delete object references
+ // for better garbage collection and leak protection
+ this.options = this.elements = this.cache = this.timers =
+ this.plugins = this.mouse = NULL;
+
+ // Delete epoxsed API object
+ delete QTIP.api[this.id];
+ }
+
+ // If an immediate destory is needed
+ if((immediate !== TRUE || this.triggering === 'hide') && this.rendered) {
+ this.tooltip.one('tooltiphidden', $.proxy(process, this));
+ !this.triggering && this.hide();
+ }
+
+ // If we're not in the process of hiding... process
+ else { process.call(this); }
+
+ return this.target;
+};
+
+;function invalidOpt(a) {
+ return a === NULL || $.type(a) !== 'object';
+}
+
+function invalidContent(c) {
+ return !( $.isFunction(c) || (c && c.attr) || c.length || ($.type(c) === 'object' && (c.jquery || c.then) ));
+}
+
+// Option object sanitizer
+function sanitizeOptions(opts) {
+ var content, text, ajax, once;
+
+ if(invalidOpt(opts)) { return FALSE; }
+
+ if(invalidOpt(opts.metadata)) {
+ opts.metadata = { type: opts.metadata };
+ }
+
+ if('content' in opts) {
+ content = opts.content;
+
+ if(invalidOpt(content) || content.jquery || content.done) {
+ content = opts.content = {
+ text: (text = invalidContent(content) ? FALSE : content)
+ };
+ }
+ else { text = content.text; }
+
+ // DEPRECATED - Old content.ajax plugin functionality
+ // Converts it into the proper Deferred syntax
+ if('ajax' in content) {
+ ajax = content.ajax;
+ once = ajax && ajax.once !== FALSE;
+ delete content.ajax;
+
+ content.text = function(event, api) {
+ var loading = text || $(this).attr(api.options.content.attr) || 'Loading...',
+
+ deferred = $.ajax(
+ $.extend({}, ajax, { context: api })
+ )
+ .then(ajax.success, NULL, ajax.error)
+ .then(function(content) {
+ if(content && once) { api.set('content.text', content); }
+ return content;
+ },
+ function(xhr, status, error) {
+ if(api.destroyed || xhr.status === 0) { return; }
+ api.set('content.text', status + ': ' + error);
+ });
+
+ return !once ? (api.set('content.text', loading), deferred) : loading;
+ };
+ }
+
+ if('title' in content) {
+ if(!invalidOpt(content.title)) {
+ content.button = content.title.button;
+ content.title = content.title.text;
+ }
+
+ if(invalidContent(content.title || FALSE)) {
+ content.title = FALSE;
+ }
+ }
+ }
+
+ if('position' in opts && invalidOpt(opts.position)) {
+ opts.position = { my: opts.position, at: opts.position };
+ }
+
+ if('show' in opts && invalidOpt(opts.show)) {
+ opts.show = opts.show.jquery ? { target: opts.show } :
+ opts.show === TRUE ? { ready: TRUE } : { event: opts.show };
+ }
+
+ if('hide' in opts && invalidOpt(opts.hide)) {
+ opts.hide = opts.hide.jquery ? { target: opts.hide } : { event: opts.hide };
+ }
+
+ if('style' in opts && invalidOpt(opts.style)) {
+ opts.style = { classes: opts.style };
+ }
+
+ // Sanitize plugin options
+ $.each(PLUGINS, function() {
+ this.sanitize && this.sanitize(opts);
+ });
+
+ return opts;
+}
+
+// Setup builtin .set() option checks
+CHECKS = PROTOTYPE.checks = {
+ builtin: {
+ // Core checks
+ '^id$': function(obj, o, v, prev) {
+ var id = v === TRUE ? QTIP.nextid : v,
+ new_id = NAMESPACE + '-' + id;
+
+ if(id !== FALSE && id.length > 0 && !$('#'+new_id).length) {
+ this._id = new_id;
+
+ if(this.rendered) {
+ this.tooltip[0].id = this._id;
+ this.elements.content[0].id = this._id + '-content';
+ this.elements.title[0].id = this._id + '-title';
+ }
+ }
+ else { obj[o] = prev; }
+ },
+ '^prerender': function(obj, o, v) {
+ v && !this.rendered && this.render(this.options.show.ready);
+ },
+
+ // Content checks
+ '^content.text$': function(obj, o, v) {
+ this._updateContent(v);
+ },
+ '^content.attr$': function(obj, o, v, prev) {
+ if(this.options.content.text === this.target.attr(prev)) {
+ this._updateContent( this.target.attr(v) );
+ }
+ },
+ '^content.title$': function(obj, o, v) {
+ // Remove title if content is null
+ if(!v) { return this._removeTitle(); }
+
+ // If title isn't already created, create it now and update
+ v && !this.elements.title && this._createTitle();
+ this._updateTitle(v);
+ },
+ '^content.button$': function(obj, o, v) {
+ this._updateButton(v);
+ },
+ '^content.title.(text|button)$': function(obj, o, v) {
+ this.set('content.'+o, v); // Backwards title.text/button compat
+ },
+
+ // Position checks
+ '^position.(my|at)$': function(obj, o, v){
+ 'string' === typeof v && (obj[o] = new CORNER(v, o === 'at'));
+ },
+ '^position.container$': function(obj, o, v){
+ this.rendered && this.tooltip.appendTo(v);
+ },
+
+ // Show checks
+ '^show.ready$': function(obj, o, v) {
+ v && (!this.rendered && this.render(TRUE) || this.toggle(TRUE));
+ },
+
+ // Style checks
+ '^style.classes$': function(obj, o, v, p) {
+ this.rendered && this.tooltip.removeClass(p).addClass(v);
+ },
+ '^style.(width|height)': function(obj, o, v) {
+ this.rendered && this.tooltip.css(o, v);
+ },
+ '^style.widget|content.title': function() {
+ this.rendered && this._setWidget();
+ },
+ '^style.def': function(obj, o, v) {
+ this.rendered && this.tooltip.toggleClass(CLASS_DEFAULT, !!v);
+ },
+
+ // Events check
+ '^events.(render|show|move|hide|focus|blur)$': function(obj, o, v) {
+ this.rendered && this.tooltip[($.isFunction(v) ? '' : 'un') + 'bind']('tooltip'+o, v);
+ },
+
+ // Properties which require event reassignment
+ '^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)': function() {
+ if(!this.rendered) { return; }
+
+ // Set tracking flag
+ var posOptions = this.options.position;
+ this.tooltip.attr('tracking', posOptions.target === 'mouse' && posOptions.adjust.mouse);
+
+ // Reassign events
+ this._unassignEvents();
+ this._assignEvents();
+ }
+ }
+};
+
+// Dot notation converter
+function convertNotation(options, notation) {
+ var i = 0, obj, option = options,
+
+ // Split notation into array
+ levels = notation.split('.');
+
+ // Loop through
+ while( option = option[ levels[i++] ] ) {
+ if(i < levels.length) { obj = option; }
+ }
+
+ return [obj || options, levels.pop()];
+}
+
+PROTOTYPE.get = function(notation) {
+ if(this.destroyed) { return this; }
+
+ var o = convertNotation(this.options, notation.toLowerCase()),
+ result = o[0][ o[1] ];
+
+ return result.precedance ? result.string() : result;
+};
+
+function setCallback(notation, args) {
+ var category, rule, match;
+
+ for(category in this.checks) {
+ for(rule in this.checks[category]) {
+ if(match = (new RegExp(rule, 'i')).exec(notation)) {
+ args.push(match);
+
+ if(category === 'builtin' || this.plugins[category]) {
+ this.checks[category][rule].apply(
+ this.plugins[category] || this, args
+ );
+ }
+ }
+ }
+ }
+}
+
+var rmove = /^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,
+ rrender = /^prerender|show\.ready/i;
+
+PROTOTYPE.set = function(option, value) {
+ if(this.destroyed) { return this; }
+
+ var rendered = this.rendered,
+ reposition = FALSE,
+ options = this.options,
+ checks = this.checks,
+ name;
+
+ // Convert singular option/value pair into object form
+ if('string' === typeof option) {
+ name = option; option = {}; option[name] = value;
+ }
+ else { option = $.extend({}, option); }
+
+ // Set all of the defined options to their new values
+ $.each(option, function(notation, value) {
+ if(rendered && rrender.test(notation)) {
+ delete option[notation]; return;
+ }
+
+ // Set new obj value
+ var obj = convertNotation(options, notation.toLowerCase()), previous;
+ previous = obj[0][ obj[1] ];
+ obj[0][ obj[1] ] = value && value.nodeType ? $(value) : value;
+
+ // Also check if we need to reposition
+ reposition = rmove.test(notation) || reposition;
+
+ // Set the new params for the callback
+ option[notation] = [obj[0], obj[1], value, previous];
+ });
+
+ // Re-sanitize options
+ sanitizeOptions(options);
+
+ /*
+ * Execute any valid callbacks for the set options
+ * Also set positioning flag so we don't get loads of redundant repositioning calls.
+ */
+ this.positioning = TRUE;
+ $.each(option, $.proxy(setCallback, this));
+ this.positioning = FALSE;
+
+ // Update position if needed
+ if(this.rendered && this.tooltip[0].offsetWidth > 0 && reposition) {
+ this.reposition( options.position.target === 'mouse' ? NULL : this.cache.event );
+ }
+
+ return this;
+};
+
+;PROTOTYPE._update = function(content, element, reposition) {
+ var self = this,
+ cache = this.cache;
+
+ // Make sure tooltip is rendered and content is defined. If not return
+ if(!this.rendered || !content) { return FALSE; }
+
+ // Use function to parse content
+ if($.isFunction(content)) {
+ content = content.call(this.elements.target, cache.event, this) || '';
+ }
+
+ // Handle deferred content
+ if($.isFunction(content.then)) {
+ cache.waiting = TRUE;
+ return content.then(function(c) {
+ cache.waiting = FALSE;
+ return self._update(c, element);
+ }, NULL, function(e) {
+ return self._update(e, element);
+ });
+ }
+
+ // If content is null... return false
+ if(content === FALSE || (!content && content !== '')) { return FALSE; }
+
+ // Append new content if its a DOM array and show it if hidden
+ if(content.jquery && content.length > 0) {
+ element.empty().append(
+ content.css({ display: 'block', visibility: 'visible' })
+ );
+ }
+
+ // Content is a regular string, insert the new content
+ else { element.html(content); }
+
+ // Wait for content to be loaded, and reposition
+ return this._waitForContent(element).then(function(images) {
+ if(images.images && images.images.length && self.rendered && self.tooltip[0].offsetWidth > 0) {
+ self.reposition(cache.event, !images.length);
+ }
+ });
+};
+
+PROTOTYPE._waitForContent = function(element) {
+ var cache = this.cache;
+
+ // Set flag
+ cache.waiting = TRUE;
+
+ // If imagesLoaded is included, ensure images have loaded and return promise
+ return ( $.fn.imagesLoaded ? element.imagesLoaded() : $.Deferred().resolve([]) )
+ .done(function() { cache.waiting = FALSE; })
+ .promise();
+};
+
+PROTOTYPE._updateContent = function(content, reposition) {
+ this._update(content, this.elements.content, reposition);
+};
+
+PROTOTYPE._updateTitle = function(content, reposition) {
+ if(this._update(content, this.elements.title, reposition) === FALSE) {
+ this._removeTitle(FALSE);
+ }
+};
+
+PROTOTYPE._createTitle = function()
+{
+ var elements = this.elements,
+ id = this._id+'-title';
+
+ // Destroy previous title element, if present
+ if(elements.titlebar) { this._removeTitle(); }
+
+ // Create title bar and title elements
+ elements.titlebar = $('<div />', {
+ 'class': NAMESPACE + '-titlebar ' + (this.options.style.widget ? createWidgetClass('header') : '')
+ })
+ .append(
+ elements.title = $('<div />', {
+ 'id': id,
+ 'class': NAMESPACE + '-title',
+ 'aria-atomic': TRUE
+ })
+ )
+ .insertBefore(elements.content)
+
+ // Button-specific events
+ .delegate('.qtip-close', 'mousedown keydown mouseup keyup mouseout', function(event) {
+ $(this).toggleClass('ui-state-active ui-state-focus', event.type.substr(-4) === 'down');
+ })
+ .delegate('.qtip-close', 'mouseover mouseout', function(event){
+ $(this).toggleClass('ui-state-hover', event.type === 'mouseover');
+ });
+
+ // Create button if enabled
+ if(this.options.content.button) { this._createButton(); }
+};
+
+PROTOTYPE._removeTitle = function(reposition)
+{
+ var elements = this.elements;
+
+ if(elements.title) {
+ elements.titlebar.remove();
+ elements.titlebar = elements.title = elements.button = NULL;
+
+ // Reposition if enabled
+ if(reposition !== FALSE) { this.reposition(); }
+ }
+};
+
+;PROTOTYPE.reposition = function(event, effect) {
+ if(!this.rendered || this.positioning || this.destroyed) { return this; }
+
+ // Set positioning flag
+ this.positioning = TRUE;
+
+ var cache = this.cache,
+ tooltip = this.tooltip,
+ posOptions = this.options.position,
+ target = posOptions.target,
+ my = posOptions.my,
+ at = posOptions.at,
+ viewport = posOptions.viewport,
+ container = posOptions.container,
+ adjust = posOptions.adjust,
+ method = adjust.method.split(' '),
+ tooltipWidth = tooltip.outerWidth(FALSE),
+ tooltipHeight = tooltip.outerHeight(FALSE),
+ targetWidth = 0,
+ targetHeight = 0,
+ type = tooltip.css('position'),
+ position = { left: 0, top: 0 },
+ visible = tooltip[0].offsetWidth > 0,
+ isScroll = event && event.type === 'scroll',
+ win = $(window),
+ doc = container[0].ownerDocument,
+ mouse = this.mouse,
+ pluginCalculations, offset;
+
+ // Check if absolute position was passed
+ if($.isArray(target) && target.length === 2) {
+ // Force left top and set position
+ at = { x: LEFT, y: TOP };
+ position = { left: target[0], top: target[1] };
+ }
+
+ // Check if mouse was the target
+ else if(target === 'mouse') {
+ // Force left top to allow flipping
+ at = { x: LEFT, y: TOP };
+
+ // Use the cached mouse coordinates if available, or passed event has no coordinates
+ if(mouse && mouse.pageX && (adjust.mouse || !event || !event.pageX) ) {
+ event = mouse;
+ }
+
+ // If the passed event has no coordinates (such as a scroll event)
+ else if(!event || !event.pageX) {
+ // Use the mouse origin that caused the show event, if distance hiding is enabled
+ if((!adjust.mouse || this.options.show.distance) && cache.origin && cache.origin.pageX) {
+ event = cache.origin;
+ }
+
+ // Use cached event for resize/scroll events
+ else if(!event || (event && (event.type === 'resize' || event.type === 'scroll'))) {
+ event = cache.event;
+ }
+ }
+
+ // Calculate body and container offset and take them into account below
+ if(type !== 'static') { position = container.offset(); }
+ if(doc.body.offsetWidth !== (window.innerWidth || doc.documentElement.clientWidth)) {
+ offset = $(document.body).offset();
+ }
+
+ // Use event coordinates for position
+ position = {
+ left: event.pageX - position.left + (offset && offset.left || 0),
+ top: event.pageY - position.top + (offset && offset.top || 0)
+ };
+
+ // Scroll events are a pain, some browsers
+ if(adjust.mouse && isScroll && mouse) {
+ position.left -= (mouse.scrollX || 0) - win.scrollLeft();
+ position.top -= (mouse.scrollY || 0) - win.scrollTop();
+ }
+ }
+
+ // Target wasn't mouse or absolute...
+ else {
+ // Check if event targetting is being used
+ if(target === 'event') {
+ if(event && event.target && event.type !== 'scroll' && event.type !== 'resize') {
+ cache.target = $(event.target);
+ }
+ else if(!event.target) {
+ cache.target = this.elements.target;
+ }
+ }
+ else if(target !== 'event'){
+ cache.target = $(target.jquery ? target : this.elements.target);
+ }
+ target = cache.target;
+
+ // Parse the target into a jQuery object and make sure there's an element present
+ target = $(target).eq(0);
+ if(target.length === 0) { return this; }
+
+ // Check if window or document is the target
+ else if(target[0] === document || target[0] === window) {
+ targetWidth = BROWSER.iOS ? window.innerWidth : target.width();
+ targetHeight = BROWSER.iOS ? window.innerHeight : target.height();
+
+ if(target[0] === window) {
+ position = {
+ top: (viewport || target).scrollTop(),
+ left: (viewport || target).scrollLeft()
+ };
+ }
+ }
+
+ // Check if the target is an <AREA> element
+ else if(PLUGINS.imagemap && target.is('area')) {
+ pluginCalculations = PLUGINS.imagemap(this, target, at, PLUGINS.viewport ? method : FALSE);
+ }
+
+ // Check if the target is an SVG element
+ else if(PLUGINS.svg && target && target[0].ownerSVGElement) {
+ pluginCalculations = PLUGINS.svg(this, target, at, PLUGINS.viewport ? method : FALSE);
+ }
+
+ // Otherwise use regular jQuery methods
+ else {
+ targetWidth = target.outerWidth(FALSE);
+ targetHeight = target.outerHeight(FALSE);
+ position = target.offset();
+ }
+
+ // Parse returned plugin values into proper variables
+ if(pluginCalculations) {
+ targetWidth = pluginCalculations.width;
+ targetHeight = pluginCalculations.height;
+ offset = pluginCalculations.offset;
+ position = pluginCalculations.position;
+ }
+
+ // Adjust position to take into account offset parents
+ position = this.reposition.offset(target, position, container);
+
+ // Adjust for position.fixed tooltips (and also iOS scroll bug in v3.2-4.0 & v4.3-4.3.2)
+ if((BROWSER.iOS > 3.1 && BROWSER.iOS < 4.1) ||
+ (BROWSER.iOS >= 4.3 && BROWSER.iOS < 4.33) ||
+ (!BROWSER.iOS && type === 'fixed')
+ ){
+ position.left -= win.scrollLeft();
+ position.top -= win.scrollTop();
+ }
+
+ // Adjust position relative to target
+ if(!pluginCalculations || (pluginCalculations && pluginCalculations.adjustable !== FALSE)) {
+ position.left += at.x === RIGHT ? targetWidth : at.x === CENTER ? targetWidth / 2 : 0;
+ position.top += at.y === BOTTOM ? targetHeight : at.y === CENTER ? targetHeight / 2 : 0;
+ }
+ }
+
+ // Adjust position relative to tooltip
+ position.left += adjust.x + (my.x === RIGHT ? -tooltipWidth : my.x === CENTER ? -tooltipWidth / 2 : 0);
+ position.top += adjust.y + (my.y === BOTTOM ? -tooltipHeight : my.y === CENTER ? -tooltipHeight / 2 : 0);
+
+ // Use viewport adjustment plugin if enabled
+ if(PLUGINS.viewport) {
+ position.adjusted = PLUGINS.viewport(
+ this, position, posOptions, targetWidth, targetHeight, tooltipWidth, tooltipHeight
+ );
+
+ // Apply offsets supplied by positioning plugin (if used)
+ if(offset && position.adjusted.left) { position.left += offset.left; }
+ if(offset && position.adjusted.top) { position.top += offset.top; }
+ }
+
+ // Viewport adjustment is disabled, set values to zero
+ else { position.adjusted = { left: 0, top: 0 }; }
+
+ // tooltipmove event
+ if(!this._trigger('move', [position, viewport.elem || viewport], event)) { return this; }
+ delete position.adjusted;
+
+ // If effect is disabled, target it mouse, no animation is defined or positioning gives NaN out, set CSS directly
+ if(effect === FALSE || !visible || isNaN(position.left) || isNaN(position.top) || target === 'mouse' || !$.isFunction(posOptions.effect)) {
+ tooltip.css(position);
+ }
+
+ // Use custom function if provided
+ else if($.isFunction(posOptions.effect)) {
+ posOptions.effect.call(tooltip, this, $.extend({}, position));
+ tooltip.queue(function(next) {
+ // Reset attributes to avoid cross-browser rendering bugs
+ $(this).css({ opacity: '', height: '' });
+ if(BROWSER.ie) { this.style.removeAttribute('filter'); }
+
+ next();
+ });
+ }
+
+ // Set positioning flag
+ this.positioning = FALSE;
+
+ return this;
+};
+
+// Custom (more correct for qTip!) offset calculator
+PROTOTYPE.reposition.offset = function(elem, pos, container) {
+ if(!container[0]) { return pos; }
+
+ var ownerDocument = $(elem[0].ownerDocument),
+ quirks = !!BROWSER.ie && document.compatMode !== 'CSS1Compat',
+ parent = container[0],
+ scrolled, position, parentOffset, overflow;
+
+ function scroll(e, i) {
+ pos.left += i * e.scrollLeft();
+ pos.top += i * e.scrollTop();
+ }
+
+ // Compensate for non-static containers offset
+ do {
+ if((position = $.css(parent, 'position')) !== 'static') {
+ if(position === 'fixed') {
+ parentOffset = parent.getBoundingClientRect();
+ scroll(ownerDocument, -1);
+ }
+ else {
+ parentOffset = $(parent).position();
+ parentOffset.left += (parseFloat($.css(parent, 'borderLeftWidth')) || 0);
+ parentOffset.top += (parseFloat($.css(parent, 'borderTopWidth')) || 0);
+ }
+
+ pos.left -= parentOffset.left + (parseFloat($.css(parent, 'marginLeft')) || 0);
+ pos.top -= parentOffset.top + (parseFloat($.css(parent, 'marginTop')) || 0);
+
+ // If this is the first parent element with an overflow of "scroll" or "auto", store it
+ if(!scrolled && (overflow = $.css(parent, 'overflow')) !== 'hidden' && overflow !== 'visible') { scrolled = $(parent); }
+ }
+ }
+ while((parent = parent.offsetParent));
+
+ // Compensate for containers scroll if it also has an offsetParent (or in IE quirks mode)
+ if(scrolled && (scrolled[0] !== ownerDocument[0] || quirks)) {
+ scroll(scrolled, 1);
+ }
+
+ return pos;
+};
+
+// Corner class
+var C = (CORNER = PROTOTYPE.reposition.Corner = function(corner, forceY) {
+ corner = ('' + corner).replace(/([A-Z])/, ' $1').replace(/middle/gi, CENTER).toLowerCase();
+ this.x = (corner.match(/left|right/i) || corner.match(/center/) || ['inherit'])[0].toLowerCase();
+ this.y = (corner.match(/top|bottom|center/i) || ['inherit'])[0].toLowerCase();
+ this.forceY = !!forceY;
+
+ var f = corner.charAt(0);
+ this.precedance = (f === 't' || f === 'b' ? Y : X);
+}).prototype;
+
+C.invert = function(z, center) {
+ this[z] = this[z] === LEFT ? RIGHT : this[z] === RIGHT ? LEFT : center || this[z];
+};
+
+C.string = function() {
+ var x = this.x, y = this.y;
+ return x === y ? x : this.precedance === Y || (this.forceY && y !== 'center') ? y+' '+x : x+' '+y;
+};
+
+C.abbrev = function() {
+ var result = this.string().split(' ');
+ return result[0].charAt(0) + (result[1] && result[1].charAt(0) || '');
+};
+
+C.clone = function() {
+ return new CORNER( this.string(), this.forceY );
+};;
+PROTOTYPE.toggle = function(state, event) {
+ var cache = this.cache,
+ options = this.options,
+ tooltip = this.tooltip;
+
+ // Try to prevent flickering when tooltip overlaps show element
+ if(event) {
+ if((/over|enter/).test(event.type) && (/out|leave/).test(cache.event.type) &&
+ options.show.target.add(event.target).length === options.show.target.length &&
+ tooltip.has(event.relatedTarget).length) {
+ return this;
+ }
+
+ // Cache event
+ cache.event = cloneEvent(event);
+ }
+
+ // If we're currently waiting and we've just hidden... stop it
+ this.waiting && !state && (this.hiddenDuringWait = TRUE);
+
+ // Render the tooltip if showing and it isn't already
+ if(!this.rendered) { return state ? this.render(1) : this; }
+ else if(this.destroyed || this.disabled) { return this; }
+
+ var type = state ? 'show' : 'hide',
+ opts = this.options[type],
+ otherOpts = this.options[ !state ? 'show' : 'hide' ],
+ posOptions = this.options.position,
+ contentOptions = this.options.content,
+ width = this.tooltip.css('width'),
+ visible = this.tooltip.is(':visible'),
+ animate = state || opts.target.length === 1,
+ sameTarget = !event || opts.target.length < 2 || cache.target[0] === event.target,
+ identicalState, allow, showEvent, delay, after;
+
+ // Detect state if valid one isn't provided
+ if((typeof state).search('boolean|number')) { state = !visible; }
+
+ // Check if the tooltip is in an identical state to the new would-be state
+ identicalState = !tooltip.is(':animated') && visible === state && sameTarget;
+
+ // Fire tooltip(show/hide) event and check if destroyed
+ allow = !identicalState ? !!this._trigger(type, [90]) : NULL;
+
+ // Check to make sure the tooltip wasn't destroyed in the callback
+ if(this.destroyed) { return this; }
+
+ // If the user didn't stop the method prematurely and we're showing the tooltip, focus it
+ if(allow !== FALSE && state) { this.focus(event); }
+
+ // If the state hasn't changed or the user stopped it, return early
+ if(!allow || identicalState) { return this; }
+
+ // Set ARIA hidden attribute
+ $.attr(tooltip[0], 'aria-hidden', !!!state);
+
+ // Execute state specific properties
+ if(state) {
+ // Store show origin coordinates
+ cache.origin = cloneEvent(this.mouse);
+
+ // Update tooltip content & title if it's a dynamic function
+ if($.isFunction(contentOptions.text)) { this._updateContent(contentOptions.text, FALSE); }
+ if($.isFunction(contentOptions.title)) { this._updateTitle(contentOptions.title, FALSE); }
+
+ // Cache mousemove events for positioning purposes (if not already tracking)
+ if(!trackingBound && posOptions.target === 'mouse' && posOptions.adjust.mouse) {
+ $(document).bind('mousemove.'+NAMESPACE, this._storeMouse);
+ trackingBound = TRUE;
+ }
+
+ // Update the tooltip position (set width first to prevent viewport/max-width issues)
+ if(!width) { tooltip.css('width', tooltip.outerWidth(FALSE)); }
+ this.reposition(event, arguments[2]);
+ if(!width) { tooltip.css('width', ''); }
+
+ // Hide other tooltips if tooltip is solo
+ if(!!opts.solo) {
+ (typeof opts.solo === 'string' ? $(opts.solo) : $(SELECTOR, opts.solo))
+ .not(tooltip).not(opts.target).qtip('hide', $.Event('tooltipsolo'));
+ }
+ }
+ else {
+ // Clear show timer if we're hiding
+ clearTimeout(this.timers.show);
+
+ // Remove cached origin on hide
+ delete cache.origin;
+
+ // Remove mouse tracking event if not needed (all tracking qTips are hidden)
+ if(trackingBound && !$(SELECTOR+'[tracking="true"]:visible', opts.solo).not(tooltip).length) {
+ $(document).unbind('mousemove.'+NAMESPACE);
+ trackingBound = FALSE;
+ }
+
+ // Blur the tooltip
+ this.blur(event);
+ }
+
+ // Define post-animation, state specific properties
+ after = $.proxy(function() {
+ if(state) {
+ // Prevent antialias from disappearing in IE by removing filter
+ if(BROWSER.ie) { tooltip[0].style.removeAttribute('filter'); }
+
+ // Remove overflow setting to prevent tip bugs
+ tooltip.css('overflow', '');
+
+ // Autofocus elements if enabled
+ if('string' === typeof opts.autofocus) {
+ $(this.options.show.autofocus, tooltip).focus();
+ }
+
+ // If set, hide tooltip when inactive for delay period
+ this.options.show.target.trigger('qtip-'+this.id+'-inactive');
+ }
+ else {
+ // Reset CSS states
+ tooltip.css({
+ display: '',
+ visibility: '',
+ opacity: '',
+ left: '',
+ top: ''
+ });
+ }
+
+ // tooltipvisible/tooltiphidden events
+ this._trigger(state ? 'visible' : 'hidden');
+ }, this);
+
+ // If no effect type is supplied, use a simple toggle
+ if(opts.effect === FALSE || animate === FALSE) {
+ tooltip[ type ]();
+ after();
+ }
+
+ // Use custom function if provided
+ else if($.isFunction(opts.effect)) {
+ tooltip.stop(1, 1);
+ opts.effect.call(tooltip, this);
+ tooltip.queue('fx', function(n) {
+ after(); n();
+ });
+ }
+
+ // Use basic fade function by default
+ else { tooltip.fadeTo(90, state ? 1 : 0, after); }
+
+ // If inactive hide method is set, active it
+ if(state) { opts.target.trigger('qtip-'+this.id+'-inactive'); }
+
+ return this;
+};
+
+PROTOTYPE.show = function(event) { return this.toggle(TRUE, event); };
+
+PROTOTYPE.hide = function(event) { return this.toggle(FALSE, event); };
+
+;PROTOTYPE.focus = function(event) {
+ if(!this.rendered || this.destroyed) { return this; }
+
+ var qtips = $(SELECTOR),
+ tooltip = this.tooltip,
+ curIndex = parseInt(tooltip[0].style.zIndex, 10),
+ newIndex = QTIP.zindex + qtips.length,
+ focusedElem;
+
+ // Only update the z-index if it has changed and tooltip is not already focused
+ if(!tooltip.hasClass(CLASS_FOCUS)) {
+ // tooltipfocus event
+ if(this._trigger('focus', [newIndex], event)) {
+ // Only update z-index's if they've changed
+ if(curIndex !== newIndex) {
+ // Reduce our z-index's and keep them properly ordered
+ qtips.each(function() {
+ if(this.style.zIndex > curIndex) {
+ this.style.zIndex = this.style.zIndex - 1;
+ }
+ });
+
+ // Fire blur event for focused tooltip
+ qtips.filter('.' + CLASS_FOCUS).qtip('blur', event);
+ }
+
+ // Set the new z-index
+ tooltip.addClass(CLASS_FOCUS)[0].style.zIndex = newIndex;
+ }
+ }
+
+ return this;
+};
+
+PROTOTYPE.blur = function(event) {
+ if(!this.rendered || this.destroyed) { return this; }
+
+ // Set focused status to FALSE
+ this.tooltip.removeClass(CLASS_FOCUS);
+
+ // tooltipblur event
+ this._trigger('blur', [ this.tooltip.css('zIndex') ], event);
+
+ return this;
+};
+
+;PROTOTYPE.disable = function(state) {
+ if(this.destroyed) { return this; }
+
+ // If 'toggle' is passed, toggle the current state
+ if(state === 'toggle') {
+ state = !(this.rendered ? this.tooltip.hasClass(CLASS_DISABLED) : this.disabled);
+ }
+
+ // Disable if no state passed
+ else if('boolean' !== typeof state) {
+ state = TRUE;
+ }
+
+ if(this.rendered) {
+ this.tooltip.toggleClass(CLASS_DISABLED, state)
+ .attr('aria-disabled', state);
+ }
+
+ this.disabled = !!state;
+
+ return this;
+};
+
+PROTOTYPE.enable = function() { return this.disable(FALSE); };
+
+;PROTOTYPE._createButton = function()
+{
+ var self = this,
+ elements = this.elements,
+ tooltip = elements.tooltip,
+ button = this.options.content.button,
+ isString = typeof button === 'string',
+ close = isString ? button : 'Close tooltip';
+
+ if(elements.button) { elements.button.remove(); }
+
+ // Use custom button if one was supplied by user, else use default
+ if(button.jquery) {
+ elements.button = button;
+ }
+ else {
+ elements.button = $('<a />', {
+ 'class': 'qtip-close ' + (this.options.style.widget ? '' : NAMESPACE+'-icon'),
+ 'title': close,
+ 'aria-label': close
+ })
+ .prepend(
+ $('<span />', {
+ 'class': 'ui-icon ui-icon-close',
+ 'html': '&times;'
+ })
+ );
+ }
+
+ // Create button and setup attributes
+ elements.button.appendTo(elements.titlebar || tooltip)
+ .attr('role', 'button')
+ .click(function(event) {
+ if(!tooltip.hasClass(CLASS_DISABLED)) { self.hide(event); }
+ return FALSE;
+ });
+};
+
+PROTOTYPE._updateButton = function(button)
+{
+ // Make sure tooltip is rendered and if not, return
+ if(!this.rendered) { return FALSE; }
+
+ var elem = this.elements.button;
+ if(button) { this._createButton(); }
+ else { elem.remove(); }
+};
+
+;// Widget class creator
+function createWidgetClass(cls) {
+ return WIDGET.concat('').join(cls ? '-'+cls+' ' : ' ');
+}
+
+// Widget class setter method
+PROTOTYPE._setWidget = function()
+{
+ var on = this.options.style.widget,
+ elements = this.elements,
+ tooltip = elements.tooltip,
+ disabled = tooltip.hasClass(CLASS_DISABLED);
+
+ tooltip.removeClass(CLASS_DISABLED);
+ CLASS_DISABLED = on ? 'ui-state-disabled' : 'qtip-disabled';
+ tooltip.toggleClass(CLASS_DISABLED, disabled);
+
+ tooltip.toggleClass('ui-helper-reset '+createWidgetClass(), on).toggleClass(CLASS_DEFAULT, this.options.style.def && !on);
+
+ if(elements.content) {
+ elements.content.toggleClass( createWidgetClass('content'), on);
+ }
+ if(elements.titlebar) {
+ elements.titlebar.toggleClass( createWidgetClass('header'), on);
+ }
+ if(elements.button) {
+ elements.button.toggleClass(NAMESPACE+'-icon', !on);
+ }
+};;function cloneEvent(event) {
+ return event && {
+ type: event.type,
+ pageX: event.pageX,
+ pageY: event.pageY,
+ target: event.target,
+ relatedTarget: event.relatedTarget,
+ scrollX: event.scrollX || window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft,
+ scrollY: event.scrollY || window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop
+ } || {};
+}
+
+function delay(callback, duration) {
+ // If tooltip has displayed, start hide timer
+ if(duration > 0) {
+ return setTimeout(
+ $.proxy(callback, this), duration
+ );
+ }
+ else{ callback.call(this); }
+}
+
+function showMethod(event) {
+ if(this.tooltip.hasClass(CLASS_DISABLED)) { return FALSE; }
+
+ // Clear hide timers
+ clearTimeout(this.timers.show);
+ clearTimeout(this.timers.hide);
+
+ // Start show timer
+ this.timers.show = delay.call(this,
+ function() { this.toggle(TRUE, event); },
+ this.options.show.delay
+ );
+}
+
+function hideMethod(event) {
+ if(this.tooltip.hasClass(CLASS_DISABLED)) { return FALSE; }
+
+ // Check if new target was actually the tooltip element
+ var relatedTarget = $(event.relatedTarget),
+ ontoTooltip = relatedTarget.closest(SELECTOR)[0] === this.tooltip[0],
+ ontoTarget = relatedTarget[0] === this.options.show.target[0];
+
+ // Clear timers and stop animation queue
+ clearTimeout(this.timers.show);
+ clearTimeout(this.timers.hide);
+
+ // Prevent hiding if tooltip is fixed and event target is the tooltip.
+ // Or if mouse positioning is enabled and cursor momentarily overlaps
+ if(this !== relatedTarget[0] &&
+ (this.options.position.target === 'mouse' && ontoTooltip) ||
+ (this.options.hide.fixed && (
+ (/mouse(out|leave|move)/).test(event.type) && (ontoTooltip || ontoTarget))
+ ))
+ {
+ try {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ } catch(e) {}
+
+ return;
+ }
+
+ // If tooltip has displayed, start hide timer
+ this.timers.hide = delay.call(this,
+ function() { this.toggle(FALSE, event); },
+ this.options.hide.delay,
+ this
+ );
+}
+
+function inactiveMethod(event) {
+ if(this.tooltip.hasClass(CLASS_DISABLED) || !this.options.hide.inactive) { return FALSE; }
+
+ // Clear timer
+ clearTimeout(this.timers.inactive);
+
+ this.timers.inactive = delay.call(this,
+ function(){ this.hide(event); },
+ this.options.hide.inactive
+ );
+}
+
+function repositionMethod(event) {
+ if(this.rendered && this.tooltip[0].offsetWidth > 0) { this.reposition(event); }
+}
+
+// Store mouse coordinates
+PROTOTYPE._storeMouse = function(event) {
+ (this.mouse = cloneEvent(event)).type = 'mousemove';
+};
+
+// Bind events
+PROTOTYPE._bind = function(targets, events, method, suffix, context) {
+ var ns = '.' + this._id + (suffix ? '-'+suffix : '');
+ events.length && $(targets).bind(
+ (events.split ? events : events.join(ns + ' ')) + ns,
+ $.proxy(method, context || this)
+ );
+};
+PROTOTYPE._unbind = function(targets, suffix) {
+ $(targets).unbind('.' + this._id + (suffix ? '-'+suffix : ''));
+};
+
+// Apply common event handlers using delegate (avoids excessive .bind calls!)
+var ns = '.'+NAMESPACE;
+function delegate(selector, events, method) {
+ $(document.body).delegate(selector,
+ (events.split ? events : events.join(ns + ' ')) + ns,
+ function() {
+ var api = QTIP.api[ $.attr(this, ATTR_ID) ];
+ api && !api.disabled && method.apply(api, arguments);
+ }
+ );
+}
+
+$(function() {
+ delegate(SELECTOR, ['mouseenter', 'mouseleave'], function(event) {
+ var state = event.type === 'mouseenter',
+ tooltip = $(event.currentTarget),
+ target = $(event.relatedTarget || event.target),
+ options = this.options;
+
+ // On mouseenter...
+ if(state) {
+ // Focus the tooltip on mouseenter (z-index stacking)
+ this.focus(event);
+
+ // Clear hide timer on tooltip hover to prevent it from closing
+ tooltip.hasClass(CLASS_FIXED) && !tooltip.hasClass(CLASS_DISABLED) && clearTimeout(this.timers.hide);
+ }
+
+ // On mouseleave...
+ else {
+ // Hide when we leave the tooltip and not onto the show target (if a hide event is set)
+ if(options.position.target === 'mouse' && options.hide.event &&
+ options.show.target && !target.closest(options.show.target[0]).length) {
+ this.hide(event);
+ }
+ }
+
+ // Add hover class
+ tooltip.toggleClass(CLASS_HOVER, state);
+ });
+
+ // Define events which reset the 'inactive' event handler
+ delegate('['+ATTR_ID+']', INACTIVE_EVENTS, inactiveMethod);
+});
+
+// Event trigger
+PROTOTYPE._trigger = function(type, args, event) {
+ var callback = $.Event('tooltip'+type);
+ callback.originalEvent = (event && $.extend({}, event)) || this.cache.event || NULL;
+
+ this.triggering = type;
+ this.tooltip.trigger(callback, [this].concat(args || []));
+ this.triggering = FALSE;
+
+ return !callback.isDefaultPrevented();
+};
+
+PROTOTYPE._bindEvents = function(showEvents, hideEvents, showTarget, hideTarget, showMethod, hideMethod) {
+ // If hide and show targets are the same...
+ if(hideTarget.add(showTarget).length === hideTarget.length) {
+ var toggleEvents = [];
+
+ // Filter identical show/hide events
+ hideEvents = $.map(hideEvents, function(type) {
+ var showIndex = $.inArray(type, showEvents);
+
+ // Both events are identical, remove from both hide and show events
+ // and append to toggleEvents
+ if(showIndex > -1) {
+ toggleEvents.push( showEvents.splice( showIndex, 1 )[0] );
+ return;
+ }
+
+ return type;
+ });
+
+ // Toggle events are special case of identical show/hide events, which happen in sequence
+ toggleEvents.length && this._bind(showTarget, toggleEvents, function(event) {
+ var state = this.rendered ? this.tooltip[0].offsetWidth > 0 : false;
+ (state ? hideMethod : showMethod).call(this, event);
+ });
+ }
+
+ // Apply show/hide/toggle events
+ this._bind(showTarget, showEvents, showMethod);
+ this._bind(hideTarget, hideEvents, hideMethod);
+};
+
+PROTOTYPE._assignInitialEvents = function(event) {
+ var options = this.options,
+ showTarget = options.show.target,
+ hideTarget = options.hide.target,
+ showEvents = options.show.event ? $.trim('' + options.show.event).split(' ') : [],
+ hideEvents = options.hide.event ? $.trim('' + options.hide.event).split(' ') : [];
+
+ /*
+ * Make sure hoverIntent functions properly by using mouseleave as a hide event if
+ * mouseenter/mouseout is used for show.event, even if it isn't in the users options.
+ */
+ if(/mouse(over|enter)/i.test(options.show.event) && !/mouse(out|leave)/i.test(options.hide.event)) {
+ hideEvents.push('mouseleave');
+ }
+
+ /*
+ * Also make sure initial mouse targetting works correctly by caching mousemove coords
+ * on show targets before the tooltip has rendered. Also set onTarget when triggered to
+ * keep mouse tracking working.
+ */
+ this._bind(showTarget, 'mousemove', function(event) {
+ this._storeMouse(event);
+ this.cache.onTarget = TRUE;
+ });
+
+ // Define hoverIntent function
+ function hoverIntent(event) {
+ // Only continue if tooltip isn't disabled
+ if(this.disabled || this.destroyed) { return FALSE; }
+
+ // Cache the event data
+ this.cache.event = cloneEvent(event);
+ this.cache.target = event ? $(event.target) : [undefined];
+
+ // Start the event sequence
+ clearTimeout(this.timers.show);
+ this.timers.show = delay.call(this,
+ function() { this.render(typeof event === 'object' || options.show.ready); },
+ options.show.delay
+ );
+ }
+
+ // Filter and bind events
+ this._bindEvents(showEvents, hideEvents, showTarget, hideTarget, hoverIntent, function() {
+ clearTimeout(this.timers.show);
+ });
+
+ // Prerendering is enabled, create tooltip now
+ if(options.show.ready || options.prerender) { hoverIntent.call(this, event); }
+};
+
+// Event assignment method
+PROTOTYPE._assignEvents = function() {
+ var self = this,
+ options = this.options,
+ posOptions = options.position,
+
+ tooltip = this.tooltip,
+ showTarget = options.show.target,
+ hideTarget = options.hide.target,
+ containerTarget = posOptions.container,
+ viewportTarget = posOptions.viewport,
+ documentTarget = $(document),
+ bodyTarget = $(document.body),
+ windowTarget = $(window),
+
+ showEvents = options.show.event ? $.trim('' + options.show.event).split(' ') : [],
+ hideEvents = options.hide.event ? $.trim('' + options.hide.event).split(' ') : [];
+
+
+ // Assign passed event callbacks
+ $.each(options.events, function(name, callback) {
+ self._bind(tooltip, name === 'toggle' ? ['tooltipshow','tooltiphide'] : ['tooltip'+name], callback, null, tooltip);
+ });
+
+ // Hide tooltips when leaving current window/frame (but not select/option elements)
+ if(/mouse(out|leave)/i.test(options.hide.event) && options.hide.leave === 'window') {
+ this._bind(documentTarget, ['mouseout', 'blur'], function(event) {
+ if(!/select|option/.test(event.target.nodeName) && !event.relatedTarget) {
+ this.hide(event);
+ }
+ });
+ }
+
+ // Enable hide.fixed by adding appropriate class
+ if(options.hide.fixed) {
+ hideTarget = hideTarget.add( tooltip.addClass(CLASS_FIXED) );
+ }
+
+ /*
+ * Make sure hoverIntent functions properly by using mouseleave to clear show timer if
+ * mouseenter/mouseout is used for show.event, even if it isn't in the users options.
+ */
+ else if(/mouse(over|enter)/i.test(options.show.event)) {
+ this._bind(hideTarget, 'mouseleave', function() {
+ clearTimeout(this.timers.show);
+ });
+ }
+
+ // Hide tooltip on document mousedown if unfocus events are enabled
+ if(('' + options.hide.event).indexOf('unfocus') > -1) {
+ this._bind(containerTarget.closest('html'), ['mousedown', 'touchstart'], function(event) {
+ var elem = $(event.target),
+ enabled = this.rendered && !this.tooltip.hasClass(CLASS_DISABLED) && this.tooltip[0].offsetWidth > 0,
+ isAncestor = elem.parents(SELECTOR).filter(this.tooltip[0]).length > 0;
+
+ if(elem[0] !== this.target[0] && elem[0] !== this.tooltip[0] && !isAncestor &&
+ !this.target.has(elem[0]).length && enabled
+ ) {
+ this.hide(event);
+ }
+ });
+ }
+
+ // Check if the tooltip hides when inactive
+ if('number' === typeof options.hide.inactive) {
+ // Bind inactive method to show target(s) as a custom event
+ this._bind(showTarget, 'qtip-'+this.id+'-inactive', inactiveMethod);
+
+ // Define events which reset the 'inactive' event handler
+ this._bind(hideTarget.add(tooltip), QTIP.inactiveEvents, inactiveMethod, '-inactive');
+ }
+
+ // Filter and bind events
+ this._bindEvents(showEvents, hideEvents, showTarget, hideTarget, showMethod, hideMethod);
+
+ // Mouse movement bindings
+ this._bind(showTarget.add(tooltip), 'mousemove', function(event) {
+ // Check if the tooltip hides when mouse is moved a certain distance
+ if('number' === typeof options.hide.distance) {
+ var origin = this.cache.origin || {},
+ limit = this.options.hide.distance,
+ abs = Math.abs;
+
+ // Check if the movement has gone beyond the limit, and hide it if so
+ if(abs(event.pageX - origin.pageX) >= limit || abs(event.pageY - origin.pageY) >= limit) {
+ this.hide(event);
+ }
+ }
+
+ // Cache mousemove coords on show targets
+ this._storeMouse(event);
+ });
+
+ // Mouse positioning events
+ if(posOptions.target === 'mouse') {
+ // If mouse adjustment is on...
+ if(posOptions.adjust.mouse) {
+ // Apply a mouseleave event so we don't get problems with overlapping
+ if(options.hide.event) {
+ // Track if we're on the target or not
+ this._bind(showTarget, ['mouseenter', 'mouseleave'], function(event) {
+ this.cache.onTarget = event.type === 'mouseenter';
+ });
+ }
+
+ // Update tooltip position on mousemove
+ this._bind(documentTarget, 'mousemove', function(event) {
+ // Update the tooltip position only if the tooltip is visible and adjustment is enabled
+ if(this.rendered && this.cache.onTarget && !this.tooltip.hasClass(CLASS_DISABLED) && this.tooltip[0].offsetWidth > 0) {
+ this.reposition(event);
+ }
+ });
+ }
+ }
+
+ // Adjust positions of the tooltip on window resize if enabled
+ if(posOptions.adjust.resize || viewportTarget.length) {
+ this._bind( $.event.special.resize ? viewportTarget : windowTarget, 'resize', repositionMethod );
+ }
+
+ // Adjust tooltip position on scroll of the window or viewport element if present
+ if(posOptions.adjust.scroll) {
+ this._bind( windowTarget.add(posOptions.container), 'scroll', repositionMethod );
+ }
+};
+
+// Un-assignment method
+PROTOTYPE._unassignEvents = function() {
+ var targets = [
+ this.options.show.target[0],
+ this.options.hide.target[0],
+ this.rendered && this.tooltip[0],
+ this.options.position.container[0],
+ this.options.position.viewport[0],
+ this.options.position.container.closest('html')[0], // unfocus
+ window,
+ document
+ ];
+
+ this._unbind($([]).pushStack( $.grep(targets, function(i) {
+ return typeof i === 'object';
+ })));
+};
+
+;// Initialization method
+function init(elem, id, opts) {
+ var obj, posOptions, attr, config, title,
+
+ // Setup element references
+ docBody = $(document.body),
+
+ // Use document body instead of document element if needed
+ newTarget = elem[0] === document ? docBody : elem,
+
+ // Grab metadata from element if plugin is present
+ metadata = (elem.metadata) ? elem.metadata(opts.metadata) : NULL,
+
+ // If metadata type if HTML5, grab 'name' from the object instead, or use the regular data object otherwise
+ metadata5 = opts.metadata.type === 'html5' && metadata ? metadata[opts.metadata.name] : NULL,
+
+ // Grab data from metadata.name (or data-qtipopts as fallback) using .data() method,
+ html5 = elem.data(opts.metadata.name || 'qtipopts');
+
+ // If we don't get an object returned attempt to parse it manualyl without parseJSON
+ try { html5 = typeof html5 === 'string' ? $.parseJSON(html5) : html5; } catch(e) {}
+
+ // Merge in and sanitize metadata
+ config = $.extend(TRUE, {}, QTIP.defaults, opts,
+ typeof html5 === 'object' ? sanitizeOptions(html5) : NULL,
+ sanitizeOptions(metadata5 || metadata));
+
+ // Re-grab our positioning options now we've merged our metadata and set id to passed value
+ posOptions = config.position;
+ config.id = id;
+
+ // Setup missing content if none is detected
+ if('boolean' === typeof config.content.text) {
+ attr = elem.attr(config.content.attr);
+
+ // Grab from supplied attribute if available
+ if(config.content.attr !== FALSE && attr) { config.content.text = attr; }
+
+ // No valid content was found, abort render
+ else { return FALSE; }
+ }
+
+ // Setup target options
+ if(!posOptions.container.length) { posOptions.container = docBody; }
+ if(posOptions.target === FALSE) { posOptions.target = newTarget; }
+ if(config.show.target === FALSE) { config.show.target = newTarget; }
+ if(config.show.solo === TRUE) { config.show.solo = posOptions.container.closest('body'); }
+ if(config.hide.target === FALSE) { config.hide.target = newTarget; }
+ if(config.position.viewport === TRUE) { config.position.viewport = posOptions.container; }
+
+ // Ensure we only use a single container
+ posOptions.container = posOptions.container.eq(0);
+
+ // Convert position corner values into x and y strings
+ posOptions.at = new CORNER(posOptions.at, TRUE);
+ posOptions.my = new CORNER(posOptions.my);
+
+ // Destroy previous tooltip if overwrite is enabled, or skip element if not
+ if(elem.data(NAMESPACE)) {
+ if(config.overwrite) {
+ elem.qtip('destroy', true);
+ }
+ else if(config.overwrite === FALSE) {
+ return FALSE;
+ }
+ }
+
+ // Add has-qtip attribute
+ elem.attr(ATTR_HAS, id);
+
+ // Remove title attribute and store it if present
+ if(config.suppress && (title = elem.attr('title'))) {
+ // Final attr call fixes event delegatiom and IE default tooltip showing problem
+ elem.removeAttr('title').attr(oldtitle, title).attr('title', '');
+ }
+
+ // Initialize the tooltip and add API reference
+ obj = new QTip(elem, config, id, !!attr);
+ elem.data(NAMESPACE, obj);
+
+ // Catch remove/removeqtip events on target element to destroy redundant tooltip
+ elem.one('remove.qtip-'+id+' removeqtip.qtip-'+id, function() {
+ var api; if((api = $(this).data(NAMESPACE))) { api.destroy(true); }
+ });
+
+ return obj;
+}
+
+// jQuery $.fn extension method
+QTIP = $.fn.qtip = function(options, notation, newValue)
+{
+ var command = ('' + options).toLowerCase(), // Parse command
+ returned = NULL,
+ args = $.makeArray(arguments).slice(1),
+ event = args[args.length - 1],
+ opts = this[0] ? $.data(this[0], NAMESPACE) : NULL;
+
+ // Check for API request
+ if((!arguments.length && opts) || command === 'api') {
+ return opts;
+ }
+
+ // Execute API command if present
+ else if('string' === typeof options) {
+ this.each(function() {
+ var api = $.data(this, NAMESPACE);
+ if(!api) { return TRUE; }
+
+ // Cache the event if possible
+ if(event && event.timeStamp) { api.cache.event = event; }
+
+ // Check for specific API commands
+ if(notation && (command === 'option' || command === 'options')) {
+ if(newValue !== undefined || $.isPlainObject(notation)) {
+ api.set(notation, newValue);
+ }
+ else {
+ returned = api.get(notation);
+ return FALSE;
+ }
+ }
+
+ // Execute API command
+ else if(api[command]) {
+ api[command].apply(api, args);
+ }
+ });
+
+ return returned !== NULL ? returned : this;
+ }
+
+ // No API commands. validate provided options and setup qTips
+ else if('object' === typeof options || !arguments.length) {
+ // Sanitize options first
+ opts = sanitizeOptions($.extend(TRUE, {}, options));
+
+ return this.each(function(i) {
+ var api, id;
+
+ // Find next available ID, or use custom ID if provided
+ id = $.isArray(opts.id) ? opts.id[i] : opts.id;
+ id = !id || id === FALSE || id.length < 1 || QTIP.api[id] ? QTIP.nextid++ : id;
+
+ // Initialize the qTip and re-grab newly sanitized options
+ api = init($(this), id, opts);
+ if(api === FALSE) { return TRUE; }
+ else { QTIP.api[id] = api; }
+
+ // Initialize plugins
+ $.each(PLUGINS, function() {
+ if(this.initialize === 'initialize') { this(api); }
+ });
+
+ // Assign initial pre-render events
+ api._assignInitialEvents(event);
+ });
+ }
+};
+
+// Expose class
+$.qtip = QTip;
+
+// Populated in render method
+QTIP.api = {};
+;$.each({
+ /* Allow other plugins to successfully retrieve the title of an element with a qTip applied */
+ attr: function(attr, val) {
+ if(this.length) {
+ var self = this[0],
+ title = 'title',
+ api = $.data(self, 'qtip');
+
+ if(attr === title && api && 'object' === typeof api && api.options.suppress) {
+ if(arguments.length < 2) {
+ return $.attr(self, oldtitle);
+ }
+
+ // If qTip is rendered and title was originally used as content, update it
+ if(api && api.options.content.attr === title && api.cache.attr) {
+ api.set('content.text', val);
+ }
+
+ // Use the regular attr method to set, then cache the result
+ return this.attr(oldtitle, val);
+ }
+ }
+
+ return $.fn['attr'+replaceSuffix].apply(this, arguments);
+ },
+
+ /* Allow clone to correctly retrieve cached title attributes */
+ clone: function(keepData) {
+ var titles = $([]), title = 'title',
+
+ // Clone our element using the real clone method
+ elems = $.fn['clone'+replaceSuffix].apply(this, arguments);
+
+ // Grab all elements with an oldtitle set, and change it to regular title attribute, if keepData is false
+ if(!keepData) {
+ elems.filter('['+oldtitle+']').attr('title', function() {
+ return $.attr(this, oldtitle);
+ })
+ .removeAttr(oldtitle);
+ }
+
+ return elems;
+ }
+}, function(name, func) {
+ if(!func || $.fn[name+replaceSuffix]) { return TRUE; }
+
+ var old = $.fn[name+replaceSuffix] = $.fn[name];
+ $.fn[name] = function() {
+ return func.apply(this, arguments) || old.apply(this, arguments);
+ };
+});
+
+/* Fire off 'removeqtip' handler in $.cleanData if jQuery UI not present (it already does similar).
+ * This snippet is taken directly from jQuery UI source code found here:
+ * http://code.jquery.com/ui/jquery-ui-git.js
+ */
+if(!$.ui) {
+ $['cleanData'+replaceSuffix] = $.cleanData;
+ $.cleanData = function( elems ) {
+ for(var i = 0, elem; (elem = $( elems[i] )).length; i++) {
+ if(elem.attr(ATTR_HAS)) {
+ try { elem.triggerHandler('removeqtip'); }
+ catch( e ) {}
+ }
+ }
+ $['cleanData'+replaceSuffix].apply(this, arguments);
+ };
+}
+
+;// qTip version
+QTIP.version = '2.2.0';
+
+// Base ID for all qTips
+QTIP.nextid = 0;
+
+// Inactive events array
+QTIP.inactiveEvents = INACTIVE_EVENTS;
+
+// Base z-index for all qTips
+QTIP.zindex = 15000;
+
+// Define configuration defaults
+QTIP.defaults = {
+ prerender: FALSE,
+ id: FALSE,
+ overwrite: TRUE,
+ suppress: TRUE,
+ content: {
+ text: TRUE,
+ attr: 'title',
+ title: FALSE,
+ button: FALSE
+ },
+ position: {
+ my: 'top left',
+ at: 'bottom right',
+ target: FALSE,
+ container: FALSE,
+ viewport: FALSE,
+ adjust: {
+ x: 0, y: 0,
+ mouse: TRUE,
+ scroll: TRUE,
+ resize: TRUE,
+ method: 'flipinvert flipinvert'
+ },
+ effect: function(api, pos, viewport) {
+ $(this).animate(pos, {
+ duration: 200,
+ queue: FALSE
+ });
+ }
+ },
+ show: {
+ target: FALSE,
+ event: 'mouseenter',
+ effect: TRUE,
+ delay: 90,
+ solo: FALSE,
+ ready: FALSE,
+ autofocus: FALSE
+ },
+ hide: {
+ target: FALSE,
+ event: 'mouseleave',
+ effect: TRUE,
+ delay: 0,
+ fixed: FALSE,
+ inactive: FALSE,
+ leave: 'window',
+ distance: FALSE
+ },
+ style: {
+ classes: '',
+ widget: FALSE,
+ width: FALSE,
+ height: FALSE,
+ def: TRUE
+ },
+ events: {
+ render: NULL,
+ move: NULL,
+ show: NULL,
+ hide: NULL,
+ toggle: NULL,
+ visible: NULL,
+ hidden: NULL,
+ focus: NULL,
+ blur: NULL
+ }
+};
+
+;var TIP,
+
+// .bind()/.on() namespace
+TIPNS = '.qtip-tip',
+
+// Common CSS strings
+MARGIN = 'margin',
+BORDER = 'border',
+COLOR = 'color',
+BG_COLOR = 'background-color',
+TRANSPARENT = 'transparent',
+IMPORTANT = ' !important',
+
+// Check if the browser supports <canvas/> elements
+HASCANVAS = !!document.createElement('canvas').getContext,
+
+// Invalid colour values used in parseColours()
+INVALID = /rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i;
+
+// Camel-case method, taken from jQuery source
+// http://code.jquery.com/jquery-1.8.0.js
+function camel(s) { return s.charAt(0).toUpperCase() + s.slice(1); }
+
+/*
+ * Modified from Modernizr's testPropsAll()
+ * http://modernizr.com/downloads/modernizr-latest.js
+ */
+var cssProps = {}, cssPrefixes = ["Webkit", "O", "Moz", "ms"];
+function vendorCss(elem, prop) {
+ var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
+ props = (prop + ' ' + cssPrefixes.join(ucProp + ' ') + ucProp).split(' '),
+ cur, val, i = 0;
+
+ // If the property has already been mapped...
+ if(cssProps[prop]) { return elem.css(cssProps[prop]); }
+
+ while((cur = props[i++])) {
+ if((val = elem.css(cur)) !== undefined) {
+ return cssProps[prop] = cur, val;
+ }
+ }
+}
+
+// Parse a given elements CSS property into an int
+function intCss(elem, prop) {
+ return Math.ceil(parseFloat(vendorCss(elem, prop)));
+}
+
+
+// VML creation (for IE only)
+if(!HASCANVAS) {
+ var createVML = function(tag, props, style) {
+ return '<qtipvml:'+tag+' xmlns="urn:schemas-microsoft.com:vml" class="qtip-vml" '+(props||'')+
+ ' style="behavior: url(#default#VML); '+(style||'')+ '" />';
+ };
+}
+
+// Canvas only definitions
+else {
+ var PIXEL_RATIO = window.devicePixelRatio || 1,
+ BACKING_STORE_RATIO = (function() {
+ var context = document.createElement('canvas').getContext('2d');
+ return context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio ||
+ context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || 1;
+ }()),
+ SCALE = PIXEL_RATIO / BACKING_STORE_RATIO;
+}
+
+
+function Tip(qtip, options) {
+ this._ns = 'tip';
+ this.options = options;
+ this.offset = options.offset;
+ this.size = [ options.width, options.height ];
+
+ // Initialize
+ this.init( (this.qtip = qtip) );
+}
+
+$.extend(Tip.prototype, {
+ init: function(qtip) {
+ var context, tip;
+
+ // Create tip element and prepend to the tooltip
+ tip = this.element = qtip.elements.tip = $('<div />', { 'class': NAMESPACE+'-tip' }).prependTo(qtip.tooltip);
+
+ // Create tip drawing element(s)
+ if(HASCANVAS) {
+ // save() as soon as we create the canvas element so FF2 doesn't bork on our first restore()!
+ context = $('<canvas />').appendTo(this.element)[0].getContext('2d');
+
+ // Setup constant parameters
+ context.lineJoin = 'miter';
+ context.miterLimit = 100000;
+ context.save();
+ }
+ else {
+ context = createVML('shape', 'coordorigin="0,0"', 'position:absolute;');
+ this.element.html(context + context);
+
+ // Prevent mousing down on the tip since it causes problems with .live() handling in IE due to VML
+ qtip._bind( $('*', tip).add(tip), ['click', 'mousedown'], function(event) { event.stopPropagation(); }, this._ns);
+ }
+
+ // Bind update events
+ qtip._bind(qtip.tooltip, 'tooltipmove', this.reposition, this._ns, this);
+
+ // Create it
+ this.create();
+ },
+
+ _swapDimensions: function() {
+ this.size[0] = this.options.height;
+ this.size[1] = this.options.width;
+ },
+ _resetDimensions: function() {
+ this.size[0] = this.options.width;
+ this.size[1] = this.options.height;
+ },
+
+ _useTitle: function(corner) {
+ var titlebar = this.qtip.elements.titlebar;
+ return titlebar && (
+ corner.y === TOP || (corner.y === CENTER && this.element.position().top + (this.size[1] / 2) + this.options.offset < titlebar.outerHeight(TRUE))
+ );
+ },
+
+ _parseCorner: function(corner) {
+ var my = this.qtip.options.position.my;
+
+ // Detect corner and mimic properties
+ if(corner === FALSE || my === FALSE) {
+ corner = FALSE;
+ }
+ else if(corner === TRUE) {
+ corner = new CORNER( my.string() );
+ }
+ else if(!corner.string) {
+ corner = new CORNER(corner);
+ corner.fixed = TRUE;
+ }
+
+ return corner;
+ },
+
+ _parseWidth: function(corner, side, use) {
+ var elements = this.qtip.elements,
+ prop = BORDER + camel(side) + 'Width';
+
+ return (use ? intCss(use, prop) : (
+ intCss(elements.content, prop) ||
+ intCss(this._useTitle(corner) && elements.titlebar || elements.content, prop) ||
+ intCss(elements.tooltip, prop)
+ )) || 0;
+ },
+
+ _parseRadius: function(corner) {
+ var elements = this.qtip.elements,
+ prop = BORDER + camel(corner.y) + camel(corner.x) + 'Radius';
+
+ return BROWSER.ie < 9 ? 0 :
+ intCss(this._useTitle(corner) && elements.titlebar || elements.content, prop) ||
+ intCss(elements.tooltip, prop) || 0;
+ },
+
+ _invalidColour: function(elem, prop, compare) {
+ var val = elem.css(prop);
+ return !val || (compare && val === elem.css(compare)) || INVALID.test(val) ? FALSE : val;
+ },
+
+ _parseColours: function(corner) {
+ var elements = this.qtip.elements,
+ tip = this.element.css('cssText', ''),
+ borderSide = BORDER + camel(corner[ corner.precedance ]) + camel(COLOR),
+ colorElem = this._useTitle(corner) && elements.titlebar || elements.content,
+ css = this._invalidColour, color = [];
+
+ // Attempt to detect the background colour from various elements, left-to-right precedance
+ color[0] = css(tip, BG_COLOR) || css(colorElem, BG_COLOR) || css(elements.content, BG_COLOR) ||
+ css(elements.tooltip, BG_COLOR) || tip.css(BG_COLOR);
+
+ // Attempt to detect the correct border side colour from various elements, left-to-right precedance
+ color[1] = css(tip, borderSide, COLOR) || css(colorElem, borderSide, COLOR) ||
+ css(elements.content, borderSide, COLOR) || css(elements.tooltip, borderSide, COLOR) || elements.tooltip.css(borderSide);
+
+ // Reset background and border colours
+ $('*', tip).add(tip).css('cssText', BG_COLOR+':'+TRANSPARENT+IMPORTANT+';'+BORDER+':0'+IMPORTANT+';');
+
+ return color;
+ },
+
+ _calculateSize: function(corner) {
+ var y = corner.precedance === Y,
+ width = this.options['width'],
+ height = this.options['height'],
+ isCenter = corner.abbrev() === 'c',
+ base = (y ? width: height) * (isCenter ? 0.5 : 1),
+ pow = Math.pow,
+ round = Math.round,
+ bigHyp, ratio, result,
+
+ smallHyp = Math.sqrt( pow(base, 2) + pow(height, 2) ),
+ hyp = [ (this.border / base) * smallHyp, (this.border / height) * smallHyp ];
+
+ hyp[2] = Math.sqrt( pow(hyp[0], 2) - pow(this.border, 2) );
+ hyp[3] = Math.sqrt( pow(hyp[1], 2) - pow(this.border, 2) );
+
+ bigHyp = smallHyp + hyp[2] + hyp[3] + (isCenter ? 0 : hyp[0]);
+ ratio = bigHyp / smallHyp;
+
+ result = [ round(ratio * width), round(ratio * height) ];
+ return y ? result : result.reverse();
+ },
+
+ // Tip coordinates calculator
+ _calculateTip: function(corner, size, scale) {
+ scale = scale || 1;
+ size = size || this.size;
+
+ var width = size[0] * scale,
+ height = size[1] * scale,
+ width2 = Math.ceil(width / 2), height2 = Math.ceil(height / 2),
+
+ // Define tip coordinates in terms of height and width values
+ tips = {
+ br: [0,0, width,height, width,0],
+ bl: [0,0, width,0, 0,height],
+ tr: [0,height, width,0, width,height],
+ tl: [0,0, 0,height, width,height],
+ tc: [0,height, width2,0, width,height],
+ bc: [0,0, width,0, width2,height],
+ rc: [0,0, width,height2, 0,height],
+ lc: [width,0, width,height, 0,height2]
+ };
+
+ // Set common side shapes
+ tips.lt = tips.br; tips.rt = tips.bl;
+ tips.lb = tips.tr; tips.rb = tips.tl;
+
+ return tips[ corner.abbrev() ];
+ },
+
+ // Tip coordinates drawer (canvas)
+ _drawCoords: function(context, coords) {
+ context.beginPath();
+ context.moveTo(coords[0], coords[1]);
+ context.lineTo(coords[2], coords[3]);
+ context.lineTo(coords[4], coords[5]);
+ context.closePath();
+ },
+
+ create: function() {
+ // Determine tip corner
+ var c = this.corner = (HASCANVAS || BROWSER.ie) && this._parseCorner(this.options.corner);
+
+ // If we have a tip corner...
+ if( (this.enabled = !!this.corner && this.corner.abbrev() !== 'c') ) {
+ // Cache it
+ this.qtip.cache.corner = c.clone();
+
+ // Create it
+ this.update();
+ }
+
+ // Toggle tip element
+ this.element.toggle(this.enabled);
+
+ return this.corner;
+ },
+
+ update: function(corner, position) {
+ if(!this.enabled) { return this; }
+
+ var elements = this.qtip.elements,
+ tip = this.element,
+ inner = tip.children(),
+ options = this.options,
+ curSize = this.size,
+ mimic = options.mimic,
+ round = Math.round,
+ color, precedance, context,
+ coords, bigCoords, translate, newSize, border, BACKING_STORE_RATIO;
+
+ // Re-determine tip if not already set
+ if(!corner) { corner = this.qtip.cache.corner || this.corner; }
+
+ // Use corner property if we detect an invalid mimic value
+ if(mimic === FALSE) { mimic = corner; }
+
+ // Otherwise inherit mimic properties from the corner object as necessary
+ else {
+ mimic = new CORNER(mimic);
+ mimic.precedance = corner.precedance;
+
+ if(mimic.x === 'inherit') { mimic.x = corner.x; }
+ else if(mimic.y === 'inherit') { mimic.y = corner.y; }
+ else if(mimic.x === mimic.y) {
+ mimic[ corner.precedance ] = corner[ corner.precedance ];
+ }
+ }
+ precedance = mimic.precedance;
+
+ // Ensure the tip width.height are relative to the tip position
+ if(corner.precedance === X) { this._swapDimensions(); }
+ else { this._resetDimensions(); }
+
+ // Update our colours
+ color = this.color = this._parseColours(corner);
+
+ // Detect border width, taking into account colours
+ if(color[1] !== TRANSPARENT) {
+ // Grab border width
+ border = this.border = this._parseWidth(corner, corner[corner.precedance]);
+
+ // If border width isn't zero, use border color as fill if it's not invalid (1.0 style tips)
+ if(options.border && border < 1 && !INVALID.test(color[1])) { color[0] = color[1]; }
+
+ // Set border width (use detected border width if options.border is true)
+ this.border = border = options.border !== TRUE ? options.border : border;
+ }
+
+ // Border colour was invalid, set border to zero
+ else { this.border = border = 0; }
+
+ // Determine tip size
+ newSize = this.size = this._calculateSize(corner);
+ tip.css({
+ width: newSize[0],
+ height: newSize[1],
+ lineHeight: newSize[1]+'px'
+ });
+
+ // Calculate tip translation
+ if(corner.precedance === Y) {
+ translate = [
+ round(mimic.x === LEFT ? border : mimic.x === RIGHT ? newSize[0] - curSize[0] - border : (newSize[0] - curSize[0]) / 2),
+ round(mimic.y === TOP ? newSize[1] - curSize[1] : 0)
+ ];
+ }
+ else {
+ translate = [
+ round(mimic.x === LEFT ? newSize[0] - curSize[0] : 0),
+ round(mimic.y === TOP ? border : mimic.y === BOTTOM ? newSize[1] - curSize[1] - border : (newSize[1] - curSize[1]) / 2)
+ ];
+ }
+
+ // Canvas drawing implementation
+ if(HASCANVAS) {
+ // Grab canvas context and clear/save it
+ context = inner[0].getContext('2d');
+ context.restore(); context.save();
+ context.clearRect(0,0,6000,6000);
+
+ // Calculate coordinates
+ coords = this._calculateTip(mimic, curSize, SCALE);
+ bigCoords = this._calculateTip(mimic, this.size, SCALE);
+
+ // Set the canvas size using calculated size
+ inner.attr(WIDTH, newSize[0] * SCALE).attr(HEIGHT, newSize[1] * SCALE);
+ inner.css(WIDTH, newSize[0]).css(HEIGHT, newSize[1]);
+
+ // Draw the outer-stroke tip
+ this._drawCoords(context, bigCoords);
+ context.fillStyle = color[1];
+ context.fill();
+
+ // Draw the actual tip
+ context.translate(translate[0] * SCALE, translate[1] * SCALE);
+ this._drawCoords(context, coords);
+ context.fillStyle = color[0];
+ context.fill();
+ }
+
+ // VML (IE Proprietary implementation)
+ else {
+ // Calculate coordinates
+ coords = this._calculateTip(mimic);
+
+ // Setup coordinates string
+ coords = 'm' + coords[0] + ',' + coords[1] + ' l' + coords[2] +
+ ',' + coords[3] + ' ' + coords[4] + ',' + coords[5] + ' xe';
+
+ // Setup VML-specific offset for pixel-perfection
+ translate[2] = border && /^(r|b)/i.test(corner.string()) ?
+ BROWSER.ie === 8 ? 2 : 1 : 0;
+
+ // Set initial CSS
+ inner.css({
+ coordsize: (newSize[0]+border) + ' ' + (newSize[1]+border),
+ antialias: ''+(mimic.string().indexOf(CENTER) > -1),
+ left: translate[0] - (translate[2] * Number(precedance === X)),
+ top: translate[1] - (translate[2] * Number(precedance === Y)),
+ width: newSize[0] + border,
+ height: newSize[1] + border
+ })
+ .each(function(i) {
+ var $this = $(this);
+
+ // Set shape specific attributes
+ $this[ $this.prop ? 'prop' : 'attr' ]({
+ coordsize: (newSize[0]+border) + ' ' + (newSize[1]+border),
+ path: coords,
+ fillcolor: color[0],
+ filled: !!i,
+ stroked: !i
+ })
+ .toggle(!!(border || i));
+
+ // Check if border is enabled and add stroke element
+ !i && $this.html( createVML(
+ 'stroke', 'weight="'+(border*2)+'px" color="'+color[1]+'" miterlimit="1000" joinstyle="miter"'
+ ) );
+ });
+ }
+
+ // Opera bug #357 - Incorrect tip position
+ // https://github.com/Craga89/qTip2/issues/367
+ window.opera && setTimeout(function() {
+ elements.tip.css({
+ display: 'inline-block',
+ visibility: 'visible'
+ });
+ }, 1);
+
+ // Position if needed
+ if(position !== FALSE) { this.calculate(corner, newSize); }
+ },
+
+ calculate: function(corner, size) {
+ if(!this.enabled) { return FALSE; }
+
+ var self = this,
+ elements = this.qtip.elements,
+ tip = this.element,
+ userOffset = this.options.offset,
+ isWidget = elements.tooltip.hasClass('ui-widget'),
+ position = { },
+ precedance, corners;
+
+ // Inherit corner if not provided
+ corner = corner || this.corner;
+ precedance = corner.precedance;
+
+ // Determine which tip dimension to use for adjustment
+ size = size || this._calculateSize(corner);
+
+ // Setup corners and offset array
+ corners = [ corner.x, corner.y ];
+ if(precedance === X) { corners.reverse(); }
+
+ // Calculate tip position
+ $.each(corners, function(i, side) {
+ var b, bc, br;
+
+ if(side === CENTER) {
+ b = precedance === Y ? LEFT : TOP;
+ position[ b ] = '50%';
+ position[MARGIN+'-' + b] = -Math.round(size[ precedance === Y ? 0 : 1 ] / 2) + userOffset;
+ }
+ else {
+ b = self._parseWidth(corner, side, elements.tooltip);
+ bc = self._parseWidth(corner, side, elements.content);
+ br = self._parseRadius(corner);
+
+ position[ side ] = Math.max(-self.border, i ? bc : (userOffset + (br > b ? br : -b)));
+ }
+ });
+
+ // Adjust for tip size
+ position[ corner[precedance] ] -= size[ precedance === X ? 0 : 1 ];
+
+ // Set and return new position
+ tip.css({ margin: '', top: '', bottom: '', left: '', right: '' }).css(position);
+ return position;
+ },
+
+ reposition: function(event, api, pos, viewport) {
+ if(!this.enabled) { return; }
+
+ var cache = api.cache,
+ newCorner = this.corner.clone(),
+ adjust = pos.adjusted,
+ method = api.options.position.adjust.method.split(' '),
+ horizontal = method[0],
+ vertical = method[1] || method[0],
+ shift = { left: FALSE, top: FALSE, x: 0, y: 0 },
+ offset, css = {}, props;
+
+ function shiftflip(direction, precedance, popposite, side, opposite) {
+ // Horizontal - Shift or flip method
+ if(direction === SHIFT && newCorner.precedance === precedance && adjust[side] && newCorner[popposite] !== CENTER) {
+ newCorner.precedance = newCorner.precedance === X ? Y : X;
+ }
+ else if(direction !== SHIFT && adjust[side]){
+ newCorner[precedance] = newCorner[precedance] === CENTER ?
+ (adjust[side] > 0 ? side : opposite) : (newCorner[precedance] === side ? opposite : side);
+ }
+ }
+
+ function shiftonly(xy, side, opposite) {
+ if(newCorner[xy] === CENTER) {
+ css[MARGIN+'-'+side] = shift[xy] = offset[MARGIN+'-'+side] - adjust[side];
+ }
+ else {
+ props = offset[opposite] !== undefined ?
+ [ adjust[side], -offset[side] ] : [ -adjust[side], offset[side] ];
+
+ if( (shift[xy] = Math.max(props[0], props[1])) > props[0] ) {
+ pos[side] -= adjust[side];
+ shift[side] = FALSE;
+ }
+
+ css[ offset[opposite] !== undefined ? opposite : side ] = shift[xy];
+ }
+ }
+
+ // If our tip position isn't fixed e.g. doesn't adjust with viewport...
+ if(this.corner.fixed !== TRUE) {
+ // Perform shift/flip adjustments
+ shiftflip(horizontal, X, Y, LEFT, RIGHT);
+ shiftflip(vertical, Y, X, TOP, BOTTOM);
+
+ // Update and redraw the tip if needed (check cached details of last drawn tip)
+ if(newCorner.string() !== cache.corner.string() && (cache.cornerTop !== adjust.top || cache.cornerLeft !== adjust.left)) {
+ this.update(newCorner, FALSE);
+ }
+ }
+
+ // Setup tip offset properties
+ offset = this.calculate(newCorner);
+
+ // Readjust offset object to make it left/top
+ if(offset.right !== undefined) { offset.left = -offset.right; }
+ if(offset.bottom !== undefined) { offset.top = -offset.bottom; }
+ offset.user = this.offset;
+
+ // Perform shift adjustments
+ if(shift.left = (horizontal === SHIFT && !!adjust.left)) { shiftonly(X, LEFT, RIGHT); }
+ if(shift.top = (vertical === SHIFT && !!adjust.top)) { shiftonly(Y, TOP, BOTTOM); }
+
+ /*
+ * If the tip is adjusted in both dimensions, or in a
+ * direction that would cause it to be anywhere but the
+ * outer border, hide it!
+ */
+ this.element.css(css).toggle(
+ !((shift.x && shift.y) || (newCorner.x === CENTER && shift.y) || (newCorner.y === CENTER && shift.x))
+ );
+
+ // Adjust position to accomodate tip dimensions
+ pos.left -= offset.left.charAt ? offset.user :
+ horizontal !== SHIFT || shift.top || !shift.left && !shift.top ? offset.left + this.border : 0;
+ pos.top -= offset.top.charAt ? offset.user :
+ vertical !== SHIFT || shift.left || !shift.left && !shift.top ? offset.top + this.border : 0;
+
+ // Cache details
+ cache.cornerLeft = adjust.left; cache.cornerTop = adjust.top;
+ cache.corner = newCorner.clone();
+ },
+
+ destroy: function() {
+ // Unbind events
+ this.qtip._unbind(this.qtip.tooltip, this._ns);
+
+ // Remove the tip element(s)
+ if(this.qtip.elements.tip) {
+ this.qtip.elements.tip.find('*')
+ .remove().end().remove();
+ }
+ }
+});
+
+TIP = PLUGINS.tip = function(api) {
+ return new Tip(api, api.options.style.tip);
+};
+
+// Initialize tip on render
+TIP.initialize = 'render';
+
+// Setup plugin sanitization options
+TIP.sanitize = function(options) {
+ if(options.style && 'tip' in options.style) {
+ var opts = options.style.tip;
+ if(typeof opts !== 'object') { opts = options.style.tip = { corner: opts }; }
+ if(!(/string|boolean/i).test(typeof opts.corner)) { opts.corner = TRUE; }
+ }
+};
+
+// Add new option checks for the plugin
+CHECKS.tip = {
+ '^position.my|style.tip.(corner|mimic|border)$': function() {
+ // Make sure a tip can be drawn
+ this.create();
+
+ // Reposition the tooltip
+ this.qtip.reposition();
+ },
+ '^style.tip.(height|width)$': function(obj) {
+ // Re-set dimensions and redraw the tip
+ this.size = [ obj.width, obj.height ];
+ this.update();
+
+ // Reposition the tooltip
+ this.qtip.reposition();
+ },
+ '^content.title|style.(classes|widget)$': function() {
+ this.update();
+ }
+};
+
+// Extend original qTip defaults
+$.extend(TRUE, QTIP.defaults, {
+ style: {
+ tip: {
+ corner: TRUE,
+ mimic: FALSE,
+ width: 6,
+ height: 6,
+ border: TRUE,
+ offset: 0
+ }
+ }
+});
+
+;var MODAL, OVERLAY,
+ MODALCLASS = 'qtip-modal',
+ MODALSELECTOR = '.'+MODALCLASS;
+
+OVERLAY = function()
+{
+ var self = this,
+ focusableElems = {},
+ current, onLast,
+ prevState, elem;
+
+ // Modified code from jQuery UI 1.10.0 source
+ // http://code.jquery.com/ui/1.10.0/jquery-ui.js
+ function focusable(element) {
+ // Use the defined focusable checker when possible
+ if($.expr[':'].focusable) { return $.expr[':'].focusable; }
+
+ var isTabIndexNotNaN = !isNaN($.attr(element, 'tabindex')),
+ nodeName = element.nodeName && element.nodeName.toLowerCase(),
+ map, mapName, img;
+
+ if('area' === nodeName) {
+ map = element.parentNode;
+ mapName = map.name;
+ if(!element.href || !mapName || map.nodeName.toLowerCase() !== 'map') {
+ return false;
+ }
+ img = $('img[usemap=#' + mapName + ']')[0];
+ return !!img && img.is(':visible');
+ }
+ return (/input|select|textarea|button|object/.test( nodeName ) ?
+ !element.disabled :
+ 'a' === nodeName ?
+ element.href || isTabIndexNotNaN :
+ isTabIndexNotNaN
+ );
+ }
+
+ // Focus inputs using cached focusable elements (see update())
+ function focusInputs(blurElems) {
+ // Blurring body element in IE causes window.open windows to unfocus!
+ if(focusableElems.length < 1 && blurElems.length) { blurElems.not('body').blur(); }
+
+ // Focus the inputs
+ else { focusableElems.first().focus(); }
+ }
+
+ // Steal focus from elements outside tooltip
+ function stealFocus(event) {
+ if(!elem.is(':visible')) { return; }
+
+ var target = $(event.target),
+ tooltip = current.tooltip,
+ container = target.closest(SELECTOR),
+ targetOnTop;
+
+ // Determine if input container target is above this
+ targetOnTop = container.length < 1 ? FALSE :
+ (parseInt(container[0].style.zIndex, 10) > parseInt(tooltip[0].style.zIndex, 10));
+
+ // If we're showing a modal, but focus has landed on an input below
+ // this modal, divert focus to the first visible input in this modal
+ // or if we can't find one... the tooltip itself
+ if(!targetOnTop && target.closest(SELECTOR)[0] !== tooltip[0]) {
+ focusInputs(target);
+ }
+
+ // Detect when we leave the last focusable element...
+ onLast = event.target === focusableElems[focusableElems.length - 1];
+ }
+
+ $.extend(self, {
+ init: function() {
+ // Create document overlay
+ elem = self.elem = $('<div />', {
+ id: 'qtip-overlay',
+ html: '<div></div>',
+ mousedown: function() { return FALSE; }
+ })
+ .hide();
+
+ // Make sure we can't focus anything outside the tooltip
+ $(document.body).bind('focusin'+MODALSELECTOR, stealFocus);
+
+ // Apply keyboard "Escape key" close handler
+ $(document).bind('keydown'+MODALSELECTOR, function(event) {
+ if(current && current.options.show.modal.escape && event.keyCode === 27) {
+ current.hide(event);
+ }
+ });
+
+ // Apply click handler for blur option
+ elem.bind('click'+MODALSELECTOR, function(event) {
+ if(current && current.options.show.modal.blur) {
+ current.hide(event);
+ }
+ });
+
+ return self;
+ },
+
+ update: function(api) {
+ // Update current API reference
+ current = api;
+
+ // Update focusable elements if enabled
+ if(api.options.show.modal.stealfocus !== FALSE) {
+ focusableElems = api.tooltip.find('*').filter(function() {
+ return focusable(this);
+ });
+ }
+ else { focusableElems = []; }
+ },
+
+ toggle: function(api, state, duration) {
+ var docBody = $(document.body),
+ tooltip = api.tooltip,
+ options = api.options.show.modal,
+ effect = options.effect,
+ type = state ? 'show': 'hide',
+ visible = elem.is(':visible'),
+ visibleModals = $(MODALSELECTOR).filter(':visible:not(:animated)').not(tooltip),
+ zindex;
+
+ // Set active tooltip API reference
+ self.update(api);
+
+ // If the modal can steal the focus...
+ // Blur the current item and focus anything in the modal we an
+ if(state && options.stealfocus !== FALSE) {
+ focusInputs( $(':focus') );
+ }
+
+ // Toggle backdrop cursor style on show
+ elem.toggleClass('blurs', options.blur);
+
+ // Append to body on show
+ if(state) {
+ elem.appendTo(document.body);
+ }
+
+ // Prevent modal from conflicting with show.solo, and don't hide backdrop is other modals are visible
+ if((elem.is(':animated') && visible === state && prevState !== FALSE) || (!state && visibleModals.length)) {
+ return self;
+ }
+
+ // Stop all animations
+ elem.stop(TRUE, FALSE);
+
+ // Use custom function if provided
+ if($.isFunction(effect)) {
+ effect.call(elem, state);
+ }
+
+ // If no effect type is supplied, use a simple toggle
+ else if(effect === FALSE) {
+ elem[ type ]();
+ }
+
+ // Use basic fade function
+ else {
+ elem.fadeTo( parseInt(duration, 10) || 90, state ? 1 : 0, function() {
+ if(!state) { elem.hide(); }
+ });
+ }
+
+ // Reset position and detach from body on hide
+ if(!state) {
+ elem.queue(function(next) {
+ elem.css({ left: '', top: '' });
+ if(!$(MODALSELECTOR).length) { elem.detach(); }
+ next();
+ });
+ }
+
+ // Cache the state
+ prevState = state;
+
+ // If the tooltip is destroyed, set reference to null
+ if(current.destroyed) { current = NULL; }
+
+ return self;
+ }
+ });
+
+ self.init();
+};
+OVERLAY = new OVERLAY();
+
+function Modal(api, options) {
+ this.options = options;
+ this._ns = '-modal';
+
+ this.init( (this.qtip = api) );
+}
+
+$.extend(Modal.prototype, {
+ init: function(qtip) {
+ var tooltip = qtip.tooltip;
+
+ // If modal is disabled... return
+ if(!this.options.on) { return this; }
+
+ // Set overlay reference
+ qtip.elements.overlay = OVERLAY.elem;
+
+ // Add unique attribute so we can grab modal tooltips easily via a SELECTOR, and set z-index
+ tooltip.addClass(MODALCLASS).css('z-index', QTIP.modal_zindex + $(MODALSELECTOR).length);
+
+ // Apply our show/hide/focus modal events
+ qtip._bind(tooltip, ['tooltipshow', 'tooltiphide'], function(event, api, duration) {
+ var oEvent = event.originalEvent;
+
+ // Make sure mouseout doesn't trigger a hide when showing the modal and mousing onto backdrop
+ if(event.target === tooltip[0]) {
+ if(oEvent && event.type === 'tooltiphide' && /mouse(leave|enter)/.test(oEvent.type) && $(oEvent.relatedTarget).closest(OVERLAY.elem[0]).length) {
+ try { event.preventDefault(); } catch(e) {}
+ }
+ else if(!oEvent || (oEvent && oEvent.type !== 'tooltipsolo')) {
+ this.toggle(event, event.type === 'tooltipshow', duration);
+ }
+ }
+ }, this._ns, this);
+
+ // Adjust modal z-index on tooltip focus
+ qtip._bind(tooltip, 'tooltipfocus', function(event, api) {
+ // If focus was cancelled before it reached us, don't do anything
+ if(event.isDefaultPrevented() || event.target !== tooltip[0]) { return; }
+
+ var qtips = $(MODALSELECTOR),
+
+ // Keep the modal's lower than other, regular qtips
+ newIndex = QTIP.modal_zindex + qtips.length,
+ curIndex = parseInt(tooltip[0].style.zIndex, 10);
+
+ // Set overlay z-index
+ OVERLAY.elem[0].style.zIndex = newIndex - 1;
+
+ // Reduce modal z-index's and keep them properly ordered
+ qtips.each(function() {
+ if(this.style.zIndex > curIndex) {
+ this.style.zIndex -= 1;
+ }
+ });
+
+ // Fire blur event for focused tooltip
+ qtips.filter('.' + CLASS_FOCUS).qtip('blur', event.originalEvent);
+
+ // Set the new z-index
+ tooltip.addClass(CLASS_FOCUS)[0].style.zIndex = newIndex;
+
+ // Set current
+ OVERLAY.update(api);
+
+ // Prevent default handling
+ try { event.preventDefault(); } catch(e) {}
+ }, this._ns, this);
+
+ // Focus any other visible modals when this one hides
+ qtip._bind(tooltip, 'tooltiphide', function(event) {
+ if(event.target === tooltip[0]) {
+ $(MODALSELECTOR).filter(':visible').not(tooltip).last().qtip('focus', event);
+ }
+ }, this._ns, this);
+ },
+
+ toggle: function(event, state, duration) {
+ // Make sure default event hasn't been prevented
+ if(event && event.isDefaultPrevented()) { return this; }
+
+ // Toggle it
+ OVERLAY.toggle(this.qtip, !!state, duration);
+ },
+
+ destroy: function() {
+ // Remove modal class
+ this.qtip.tooltip.removeClass(MODALCLASS);
+
+ // Remove bound events
+ this.qtip._unbind(this.qtip.tooltip, this._ns);
+
+ // Delete element reference
+ OVERLAY.toggle(this.qtip, FALSE);
+ delete this.qtip.elements.overlay;
+ }
+});
+
+
+MODAL = PLUGINS.modal = function(api) {
+ return new Modal(api, api.options.show.modal);
+};
+
+// Setup sanitiztion rules
+MODAL.sanitize = function(opts) {
+ if(opts.show) {
+ if(typeof opts.show.modal !== 'object') { opts.show.modal = { on: !!opts.show.modal }; }
+ else if(typeof opts.show.modal.on === 'undefined') { opts.show.modal.on = TRUE; }
+ }
+};
+
+// Base z-index for all modal tooltips (use qTip core z-index as a base)
+QTIP.modal_zindex = QTIP.zindex - 200;
+
+// Plugin needs to be initialized on render
+MODAL.initialize = 'render';
+
+// Setup option set checks
+CHECKS.modal = {
+ '^show.modal.(on|blur)$': function() {
+ // Initialise
+ this.destroy();
+ this.init();
+
+ // Show the modal if not visible already and tooltip is visible
+ this.qtip.elems.overlay.toggle(
+ this.qtip.tooltip[0].offsetWidth > 0
+ );
+ }
+};
+
+// Extend original api defaults
+$.extend(TRUE, QTIP.defaults, {
+ show: {
+ modal: {
+ on: FALSE,
+ effect: TRUE,
+ blur: TRUE,
+ stealfocus: TRUE,
+ escape: TRUE
+ }
+ }
+});
+;PLUGINS.viewport = function(api, position, posOptions, targetWidth, targetHeight, elemWidth, elemHeight)
+{
+ var target = posOptions.target,
+ tooltip = api.elements.tooltip,
+ my = posOptions.my,
+ at = posOptions.at,
+ adjust = posOptions.adjust,
+ method = adjust.method.split(' '),
+ methodX = method[0],
+ methodY = method[1] || method[0],
+ viewport = posOptions.viewport,
+ container = posOptions.container,
+ cache = api.cache,
+ adjusted = { left: 0, top: 0 },
+ fixed, newMy, newClass, containerOffset, containerStatic,
+ viewportWidth, viewportHeight, viewportScroll, viewportOffset;
+
+ // If viewport is not a jQuery element, or it's the window/document, or no adjustment method is used... return
+ if(!viewport.jquery || target[0] === window || target[0] === document.body || adjust.method === 'none') {
+ return adjusted;
+ }
+
+ // Cach container details
+ containerOffset = container.offset() || adjusted;
+ containerStatic = container.css('position') === 'static';
+
+ // Cache our viewport details
+ fixed = tooltip.css('position') === 'fixed';
+ viewportWidth = viewport[0] === window ? viewport.width() : viewport.outerWidth(FALSE);
+ viewportHeight = viewport[0] === window ? viewport.height() : viewport.outerHeight(FALSE);
+ viewportScroll = { left: fixed ? 0 : viewport.scrollLeft(), top: fixed ? 0 : viewport.scrollTop() };
+ viewportOffset = viewport.offset() || adjusted;
+
+ // Generic calculation method
+ function calculate(side, otherSide, type, adjust, side1, side2, lengthName, targetLength, elemLength) {
+ var initialPos = position[side1],
+ mySide = my[side],
+ atSide = at[side],
+ isShift = type === SHIFT,
+ myLength = mySide === side1 ? elemLength : mySide === side2 ? -elemLength : -elemLength / 2,
+ atLength = atSide === side1 ? targetLength : atSide === side2 ? -targetLength : -targetLength / 2,
+ sideOffset = viewportScroll[side1] + viewportOffset[side1] - (containerStatic ? 0 : containerOffset[side1]),
+ overflow1 = sideOffset - initialPos,
+ overflow2 = initialPos + elemLength - (lengthName === WIDTH ? viewportWidth : viewportHeight) - sideOffset,
+ offset = myLength - (my.precedance === side || mySide === my[otherSide] ? atLength : 0) - (atSide === CENTER ? targetLength / 2 : 0);
+
+ // shift
+ if(isShift) {
+ offset = (mySide === side1 ? 1 : -1) * myLength;
+
+ // Adjust position but keep it within viewport dimensions
+ position[side1] += overflow1 > 0 ? overflow1 : overflow2 > 0 ? -overflow2 : 0;
+ position[side1] = Math.max(
+ -containerOffset[side1] + viewportOffset[side1],
+ initialPos - offset,
+ Math.min(
+ Math.max(
+ -containerOffset[side1] + viewportOffset[side1] + (lengthName === WIDTH ? viewportWidth : viewportHeight),
+ initialPos + offset
+ ),
+ position[side1],
+
+ // Make sure we don't adjust complete off the element when using 'center'
+ mySide === 'center' ? initialPos - myLength : 1E9
+ )
+ );
+
+ }
+
+ // flip/flipinvert
+ else {
+ // Update adjustment amount depending on if using flipinvert or flip
+ adjust *= (type === FLIPINVERT ? 2 : 0);
+
+ // Check for overflow on the left/top
+ if(overflow1 > 0 && (mySide !== side1 || overflow2 > 0)) {
+ position[side1] -= offset + adjust;
+ newMy.invert(side, side1);
+ }
+
+ // Check for overflow on the bottom/right
+ else if(overflow2 > 0 && (mySide !== side2 || overflow1 > 0) ) {
+ position[side1] -= (mySide === CENTER ? -offset : offset) + adjust;
+ newMy.invert(side, side2);
+ }
+
+ // Make sure we haven't made things worse with the adjustment and reset if so
+ if(position[side1] < viewportScroll && -position[side1] > overflow2) {
+ position[side1] = initialPos; newMy = my.clone();
+ }
+ }
+
+ return position[side1] - initialPos;
+ }
+
+ // Set newMy if using flip or flipinvert methods
+ if(methodX !== 'shift' || methodY !== 'shift') { newMy = my.clone(); }
+
+ // Adjust position based onviewport and adjustment options
+ adjusted = {
+ left: methodX !== 'none' ? calculate( X, Y, methodX, adjust.x, LEFT, RIGHT, WIDTH, targetWidth, elemWidth ) : 0,
+ top: methodY !== 'none' ? calculate( Y, X, methodY, adjust.y, TOP, BOTTOM, HEIGHT, targetHeight, elemHeight ) : 0
+ };
+
+ // Set tooltip position class if it's changed
+ if(newMy && cache.lastClass !== (newClass = NAMESPACE + '-pos-' + newMy.abbrev())) {
+ tooltip.removeClass(api.cache.lastClass).addClass( (api.cache.lastClass = newClass) );
+ }
+
+ return adjusted;
+};
+;PLUGINS.polys = {
+ // POLY area coordinate calculator
+ // Special thanks to Ed Cradock for helping out with this.
+ // Uses a binary search algorithm to find suitable coordinates.
+ polygon: function(baseCoords, corner) {
+ var result = {
+ width: 0, height: 0,
+ position: {
+ top: 1e10, right: 0,
+ bottom: 0, left: 1e10
+ },
+ adjustable: FALSE
+ },
+ i = 0, next,
+ coords = [],
+ compareX = 1, compareY = 1,
+ realX = 0, realY = 0,
+ newWidth, newHeight;
+
+ // First pass, sanitize coords and determine outer edges
+ i = baseCoords.length; while(i--) {
+ next = [ parseInt(baseCoords[--i], 10), parseInt(baseCoords[i+1], 10) ];
+
+ if(next[0] > result.position.right){ result.position.right = next[0]; }
+ if(next[0] < result.position.left){ result.position.left = next[0]; }
+ if(next[1] > result.position.bottom){ result.position.bottom = next[1]; }
+ if(next[1] < result.position.top){ result.position.top = next[1]; }
+
+ coords.push(next);
+ }
+
+ // Calculate height and width from outer edges
+ newWidth = result.width = Math.abs(result.position.right - result.position.left);
+ newHeight = result.height = Math.abs(result.position.bottom - result.position.top);
+
+ // If it's the center corner...
+ if(corner.abbrev() === 'c') {
+ result.position = {
+ left: result.position.left + (result.width / 2),
+ top: result.position.top + (result.height / 2)
+ };
+ }
+ else {
+ // Second pass, use a binary search algorithm to locate most suitable coordinate
+ while(newWidth > 0 && newHeight > 0 && compareX > 0 && compareY > 0)
+ {
+ newWidth = Math.floor(newWidth / 2);
+ newHeight = Math.floor(newHeight / 2);
+
+ if(corner.x === LEFT){ compareX = newWidth; }
+ else if(corner.x === RIGHT){ compareX = result.width - newWidth; }
+ else{ compareX += Math.floor(newWidth / 2); }
+
+ if(corner.y === TOP){ compareY = newHeight; }
+ else if(corner.y === BOTTOM){ compareY = result.height - newHeight; }
+ else{ compareY += Math.floor(newHeight / 2); }
+
+ i = coords.length; while(i--)
+ {
+ if(coords.length < 2){ break; }
+
+ realX = coords[i][0] - result.position.left;
+ realY = coords[i][1] - result.position.top;
+
+ if((corner.x === LEFT && realX >= compareX) ||
+ (corner.x === RIGHT && realX <= compareX) ||
+ (corner.x === CENTER && (realX < compareX || realX > (result.width - compareX))) ||
+ (corner.y === TOP && realY >= compareY) ||
+ (corner.y === BOTTOM && realY <= compareY) ||
+ (corner.y === CENTER && (realY < compareY || realY > (result.height - compareY)))) {
+ coords.splice(i, 1);
+ }
+ }
+ }
+ result.position = { left: coords[0][0], top: coords[0][1] };
+ }
+
+ return result;
+ },
+
+ rect: function(ax, ay, bx, by) {
+ return {
+ width: Math.abs(bx - ax),
+ height: Math.abs(by - ay),
+ position: {
+ left: Math.min(ax, bx),
+ top: Math.min(ay, by)
+ }
+ };
+ },
+
+ _angles: {
+ tc: 3 / 2, tr: 7 / 4, tl: 5 / 4,
+ bc: 1 / 2, br: 1 / 4, bl: 3 / 4,
+ rc: 2, lc: 1, c: 0
+ },
+ ellipse: function(cx, cy, rx, ry, corner) {
+ var c = PLUGINS.polys._angles[ corner.abbrev() ],
+ rxc = c === 0 ? 0 : rx * Math.cos( c * Math.PI ),
+ rys = ry * Math.sin( c * Math.PI );
+
+ return {
+ width: (rx * 2) - Math.abs(rxc),
+ height: (ry * 2) - Math.abs(rys),
+ position: {
+ left: cx + rxc,
+ top: cy + rys
+ },
+ adjustable: FALSE
+ };
+ },
+ circle: function(cx, cy, r, corner) {
+ return PLUGINS.polys.ellipse(cx, cy, r, r, corner);
+ }
+};;PLUGINS.svg = function(api, svg, corner)
+{
+ var doc = $(document),
+ elem = svg[0],
+ root = $(elem.ownerSVGElement),
+ xScale = 1, yScale = 1,
+ complex = true,
+ rootWidth, rootHeight,
+ mtx, transformed, viewBox,
+ len, next, i, points,
+ result, position, dimensions;
+
+ // Ascend the parentNode chain until we find an element with getBBox()
+ while(!elem.getBBox) { elem = elem.parentNode; }
+ if(!elem.getBBox || !elem.parentNode) { return FALSE; }
+
+ // Determine dimensions where possible
+ rootWidth = root.attr('width') || root.width() || parseInt(root.css('width'), 10);
+ rootHeight = root.attr('height') || root.height() || parseInt(root.css('height'), 10);
+
+ // Add stroke characteristics to scaling
+ var strokeWidth2 = (parseInt(svg.css('stroke-width'), 10) || 0) / 2;
+ if(strokeWidth2) {
+ xScale += strokeWidth2 / rootWidth;
+ yScale += strokeWidth2 / rootHeight;
+ }
+
+ // Determine which shape calculation to use
+ switch(elem.nodeName) {
+ case 'ellipse':
+ case 'circle':
+ result = PLUGINS.polys.ellipse(
+ elem.cx.baseVal.value,
+ elem.cy.baseVal.value,
+ (elem.rx || elem.r).baseVal.value + strokeWidth2,
+ (elem.ry || elem.r).baseVal.value + strokeWidth2,
+ corner
+ );
+ break;
+
+ case 'line':
+ case 'polygon':
+ case 'polyline':
+ // Determine points object (line has none, so mimic using array)
+ points = elem.points || [
+ { x: elem.x1.baseVal.value, y: elem.y1.baseVal.value },
+ { x: elem.x2.baseVal.value, y: elem.y2.baseVal.value }
+ ];
+
+ for(result = [], i = -1, len = points.numberOfItems || points.length; ++i < len;) {
+ next = points.getItem ? points.getItem(i) : points[i];
+ result.push.apply(result, [next.x, next.y]);
+ }
+
+ result = PLUGINS.polys.polygon(result, corner);
+ break;
+
+ // Unknown shape or rectangle? Use bounding box
+ default:
+ result = elem.getBoundingClientRect();
+ result = {
+ width: result.width, height: result.height,
+ position: {
+ left: result.left,
+ top: result.top
+ }
+ };
+ complex = false;
+ break;
+ }
+
+ // Shortcut assignments
+ position = result.position;
+ root = root[0];
+
+ // If the shape was complex (i.e. not using bounding box calculations)
+ if(complex) {
+ // Convert position into a pixel value
+ if(root.createSVGPoint) {
+ mtx = elem.getScreenCTM();
+ points = root.createSVGPoint();
+
+ points.x = position.left;
+ points.y = position.top;
+ transformed = points.matrixTransform( mtx );
+ position.left = transformed.x;
+ position.top = transformed.y;
+ }
+
+ // Calculate viewBox characteristics
+ if(root.viewBox && (viewBox = root.viewBox.baseVal) && viewBox.width && viewBox.height) {
+ xScale *= rootWidth / viewBox.width;
+ yScale *= rootHeight / viewBox.height;
+ }
+ }
+
+ // Adjust by scroll offset
+ position.left += doc.scrollLeft();
+ position.top += doc.scrollTop();
+
+ return result;
+};;PLUGINS.imagemap = function(api, area, corner, adjustMethod)
+{
+ if(!area.jquery) { area = $(area); }
+
+ var shape = area.attr('shape').toLowerCase().replace('poly', 'polygon'),
+ image = $('img[usemap="#'+area.parent('map').attr('name')+'"]'),
+ coordsString = $.trim(area.attr('coords')),
+ coordsArray = coordsString.replace(/,$/, '').split(','),
+ imageOffset, coords, i, next, result, len;
+
+ // If we can't find the image using the map...
+ if(!image.length) { return FALSE; }
+
+ // Pass coordinates string if polygon
+ if(shape === 'polygon') {
+ result = PLUGINS.polys.polygon(coordsArray, corner);
+ }
+
+ // Otherwise parse the coordinates and pass them as arguments
+ else if(PLUGINS.polys[shape]) {
+ for(i = -1, len = coordsArray.length, coords = []; ++i < len;) {
+ coords.push( parseInt(coordsArray[i], 10) );
+ }
+
+ result = PLUGINS.polys[shape].apply(
+ this, coords.concat(corner)
+ );
+ }
+
+ // If no shapre calculation method was found, return false
+ else { return FALSE; }
+
+ // Make sure we account for padding and borders on the image
+ imageOffset = image.offset();
+ imageOffset.left += Math.ceil((image.outerWidth(FALSE) - image.width()) / 2);
+ imageOffset.top += Math.ceil((image.outerHeight(FALSE) - image.height()) / 2);
+
+ // Add image position to offset coordinates
+ result.position.left += imageOffset.left;
+ result.position.top += imageOffset.top;
+
+ return result;
+};;var IE6,
+
+/*
+ * BGIFrame adaption (http://plugins.jquery.com/project/bgiframe)
+ * Special thanks to Brandon Aaron
+ */
+BGIFRAME = '<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:\'\';" ' +
+ ' style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=0); ' +
+ '-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";"></iframe>';
+
+function Ie6(api, qtip) {
+ this._ns = 'ie6';
+ this.init( (this.qtip = api) );
+}
+
+$.extend(Ie6.prototype, {
+ _scroll : function() {
+ var overlay = this.qtip.elements.overlay;
+ overlay && (overlay[0].style.top = $(window).scrollTop() + 'px');
+ },
+
+ init: function(qtip) {
+ var tooltip = qtip.tooltip,
+ scroll;
+
+ // Create the BGIFrame element if needed
+ if($('select, object').length < 1) {
+ this.bgiframe = qtip.elements.bgiframe = $(BGIFRAME).appendTo(tooltip);
+
+ // Update BGIFrame on tooltip move
+ qtip._bind(tooltip, 'tooltipmove', this.adjustBGIFrame, this._ns, this);
+ }
+
+ // redraw() container for width/height calculations
+ this.redrawContainer = $('<div/>', { id: NAMESPACE+'-rcontainer' })
+ .appendTo(document.body);
+
+ // Fixup modal plugin if present too
+ if( qtip.elements.overlay && qtip.elements.overlay.addClass('qtipmodal-ie6fix') ) {
+ qtip._bind(window, ['scroll', 'resize'], this._scroll, this._ns, this);
+ qtip._bind(tooltip, ['tooltipshow'], this._scroll, this._ns, this);
+ }
+
+ // Set dimensions
+ this.redraw();
+ },
+
+ adjustBGIFrame: function() {
+ var tooltip = this.qtip.tooltip,
+ dimensions = {
+ height: tooltip.outerHeight(FALSE),
+ width: tooltip.outerWidth(FALSE)
+ },
+ plugin = this.qtip.plugins.tip,
+ tip = this.qtip.elements.tip,
+ tipAdjust, offset;
+
+ // Adjust border offset
+ offset = parseInt(tooltip.css('borderLeftWidth'), 10) || 0;
+ offset = { left: -offset, top: -offset };
+
+ // Adjust for tips plugin
+ if(plugin && tip) {
+ tipAdjust = (plugin.corner.precedance === 'x') ? [WIDTH, LEFT] : [HEIGHT, TOP];
+ offset[ tipAdjust[1] ] -= tip[ tipAdjust[0] ]();
+ }
+
+ // Update bgiframe
+ this.bgiframe.css(offset).css(dimensions);
+ },
+
+ // Max/min width simulator function
+ redraw: function() {
+ if(this.qtip.rendered < 1 || this.drawing) { return this; }
+
+ var tooltip = this.qtip.tooltip,
+ style = this.qtip.options.style,
+ container = this.qtip.options.position.container,
+ perc, width, max, min;
+
+ // Set drawing flag
+ this.qtip.drawing = 1;
+
+ // If tooltip has a set height/width, just set it... like a boss!
+ if(style.height) { tooltip.css(HEIGHT, style.height); }
+ if(style.width) { tooltip.css(WIDTH, style.width); }
+
+ // Simulate max/min width if not set width present...
+ else {
+ // Reset width and add fluid class
+ tooltip.css(WIDTH, '').appendTo(this.redrawContainer);
+
+ // Grab our tooltip width (add 1 if odd so we don't get wrapping problems.. huzzah!)
+ width = tooltip.width();
+ if(width % 2 < 1) { width += 1; }
+
+ // Grab our max/min properties
+ max = tooltip.css('maxWidth') || '';
+ min = tooltip.css('minWidth') || '';
+
+ // Parse into proper pixel values
+ perc = (max + min).indexOf('%') > -1 ? container.width() / 100 : 0;
+ max = ((max.indexOf('%') > -1 ? perc : 1) * parseInt(max, 10)) || width;
+ min = ((min.indexOf('%') > -1 ? perc : 1) * parseInt(min, 10)) || 0;
+
+ // Determine new dimension size based on max/min/current values
+ width = max + min ? Math.min(Math.max(width, min), max) : width;
+
+ // Set the newly calculated width and remvoe fluid class
+ tooltip.css(WIDTH, Math.round(width)).appendTo(container);
+ }
+
+ // Set drawing flag
+ this.drawing = 0;
+
+ return this;
+ },
+
+ destroy: function() {
+ // Remove iframe
+ this.bgiframe && this.bgiframe.remove();
+
+ // Remove bound events
+ this.qtip._unbind([window, this.qtip.tooltip], this._ns);
+ }
+});
+
+IE6 = PLUGINS.ie6 = function(api) {
+ // Proceed only if the browser is IE6
+ return BROWSER.ie === 6 ? new Ie6(api) : FALSE;
+};
+
+IE6.initialize = 'render';
+
+CHECKS.ie6 = {
+ '^content|style$': function() {
+ this.redraw();
+ }
+};;}));
+}( window, document ));
+
+
diff --git a/docs/htmldoc/js/jquery.qtip.min.css b/docs/htmldoc/js/jquery.qtip.min.css
new file mode 100644
index 0000000..fc172a4
--- /dev/null
+++ b/docs/htmldoc/js/jquery.qtip.min.css
@@ -0,0 +1,2 @@
+/* qTip2 v2.2.0 basic css3 | qtip2.com | Licensed MIT, GPL | Thu Nov 21 2013 20:35:00 */
+.qtip{position:absolute;left:-28000px;top:-28000px;display:none;max-width:280px;min-width:50px;font-size:10.5px;line-height:12px;direction:ltr;box-shadow:none;padding:0}.qtip-content{position:relative;padding:5px 9px;overflow:hidden;text-align:left;word-wrap:break-word}.qtip-titlebar{position:relative;padding:5px 35px 5px 10px;overflow:hidden;border-width:0 0 1px;font-weight:700}.qtip-titlebar+.qtip-content{border-top-width:0!important}.qtip-close{position:absolute;right:-9px;top:-9px;cursor:pointer;outline:medium none;border-width:1px;border-style:solid;border-color:transparent}.qtip-titlebar .qtip-close{right:4px;top:50%;margin-top:-9px}* html .qtip-titlebar .qtip-close{top:16px}.qtip-titlebar .ui-icon,.qtip-icon .ui-icon{display:block;text-indent:-1000em;direction:ltr}.qtip-icon,.qtip-icon .ui-icon{-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;text-decoration:none}.qtip-icon .ui-icon{width:18px;height:14px;line-height:14px;text-align:center;text-indent:0;font:400 bold 10px/13px Tahoma,sans-serif;color:inherit;background:transparent none no-repeat -100em -100em}.qtip-focus{}.qtip-hover{}.qtip-default{border-width:1px;border-style:solid;border-color:#F1D031;background-color:#FFFFA3;color:#555}.qtip-default .qtip-titlebar{background-color:#FFEF93}.qtip-default .qtip-icon{border-color:#CCC;background:#F1F1F1;color:#777}.qtip-default .qtip-titlebar .qtip-close{border-color:#AAA;color:#111} .qtip-light{background-color:#fff;border-color:#E2E2E2;color:#454545}.qtip-light .qtip-titlebar{background-color:#f1f1f1} .qtip-dark{background-color:#505050;border-color:#303030;color:#f3f3f3}.qtip-dark .qtip-titlebar{background-color:#404040}.qtip-dark .qtip-icon{border-color:#444}.qtip-dark .qtip-titlebar .ui-state-hover{border-color:#303030} .qtip-cream{background-color:#FBF7AA;border-color:#F9E98E;color:#A27D35}.qtip-cream .qtip-titlebar{background-color:#F0DE7D}.qtip-cream .qtip-close .qtip-icon{background-position:-82px 0} .qtip-red{background-color:#F78B83;border-color:#D95252;color:#912323}.qtip-red .qtip-titlebar{background-color:#F06D65}.qtip-red .qtip-close .qtip-icon{background-position:-102px 0}.qtip-red .qtip-icon{border-color:#D95252}.qtip-red .qtip-titlebar .ui-state-hover{border-color:#D95252} .qtip-green{background-color:#CAED9E;border-color:#90D93F;color:#3F6219}.qtip-green .qtip-titlebar{background-color:#B0DE78}.qtip-green .qtip-close .qtip-icon{background-position:-42px 0} .qtip-blue{background-color:#E5F6FE;border-color:#ADD9ED;color:#5E99BD}.qtip-blue .qtip-titlebar{background-color:#D0E9F5}.qtip-blue .qtip-close .qtip-icon{background-position:-2px 0}.qtip-shadow{-webkit-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);-moz-box-shadow:1px 1px 3px 1px rgba(0,0,0,.15);box-shadow:1px 1px 3px 1px rgba(0,0,0,.15)}.qtip-rounded,.qtip-tipsy,.qtip-bootstrap{-moz-border-radius:5px;-webkit-border-radius:5px;border-radius:5px}.qtip-rounded .qtip-titlebar{-moz-border-radius:4px 4px 0 0;-webkit-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.qtip-youtube{-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 3px #333;-moz-box-shadow:0 0 3px #333;box-shadow:0 0 3px #333;color:#fff;border-width:0;background:#4A4A4A;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#4A4A4A),color-stop(100%,#000));background-image:-webkit-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-moz-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-ms-linear-gradient(top,#4A4A4A 0,#000 100%);background-image:-o-linear-gradient(top,#4A4A4A 0,#000 100%)}.qtip-youtube .qtip-titlebar{background-color:#4A4A4A;background-color:rgba(0,0,0,0)}.qtip-youtube .qtip-content{padding:.75em;font:12px arial,sans-serif;filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);-ms-filter:"progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr=#4a4a4a, EndColorStr=#000000);"}.qtip-youtube .qtip-icon{border-color:#222}.qtip-youtube .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-jtools{background:#232323;background:rgba(0,0,0,.7);background-image:-webkit-gradient(linear,left top,left bottom,from(#717171),to(#232323));background-image:-moz-linear-gradient(top,#717171,#232323);background-image:-webkit-linear-gradient(top,#717171,#232323);background-image:-ms-linear-gradient(top,#717171,#232323);background-image:-o-linear-gradient(top,#717171,#232323);border:2px solid #ddd;border:2px solid rgba(241,241,241,1);-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-webkit-box-shadow:0 0 12px #333;-moz-box-shadow:0 0 12px #333;box-shadow:0 0 12px #333}.qtip-jtools .qtip-titlebar{background-color:transparent;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#717171, endColorstr=#4A4A4A)"}.qtip-jtools .qtip-content{filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#4A4A4A, endColorstr=#232323)"}.qtip-jtools .qtip-titlebar,.qtip-jtools .qtip-content{background:transparent;color:#fff;border:0 dashed transparent}.qtip-jtools .qtip-icon{border-color:#555}.qtip-jtools .qtip-titlebar .ui-state-hover{border-color:#333}.qtip-cluetip{-webkit-box-shadow:4px 4px 5px rgba(0,0,0,.4);-moz-box-shadow:4px 4px 5px rgba(0,0,0,.4);box-shadow:4px 4px 5px rgba(0,0,0,.4);background-color:#D9D9C2;color:#111;border:0 dashed transparent}.qtip-cluetip .qtip-titlebar{background-color:#87876A;color:#fff;border:0 dashed transparent}.qtip-cluetip .qtip-icon{border-color:#808064}.qtip-cluetip .qtip-titlebar .ui-state-hover{border-color:#696952;color:#696952}.qtip-tipsy{background:#000;background:rgba(0,0,0,.87);color:#fff;border:0 solid transparent;font-size:11px;font-family:'Lucida Grande',sans-serif;font-weight:700;line-height:16px;text-shadow:0 1px #000}.qtip-tipsy .qtip-titlebar{padding:6px 35px 0 10px;background-color:transparent}.qtip-tipsy .qtip-content{padding:6px 10px}.qtip-tipsy .qtip-icon{border-color:#222;text-shadow:none}.qtip-tipsy .qtip-titlebar .ui-state-hover{border-color:#303030}.qtip-tipped{border:3px solid #959FA9;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-color:#F9F9F9;color:#454545;font-weight:400;font-family:serif}.qtip-tipped .qtip-titlebar{border-bottom-width:0;color:#fff;background:#3A79B8;background-image:-webkit-gradient(linear,left top,left bottom,from(#3A79B8),to(#2E629D));background-image:-webkit-linear-gradient(top,#3A79B8,#2E629D);background-image:-moz-linear-gradient(top,#3A79B8,#2E629D);background-image:-ms-linear-gradient(top,#3A79B8,#2E629D);background-image:-o-linear-gradient(top,#3A79B8,#2E629D);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D);-ms-filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr=#3A79B8, endColorstr=#2E629D)"}.qtip-tipped .qtip-icon{border:2px solid #285589;background:#285589}.qtip-tipped .qtip-icon .ui-icon{background-color:#FBFBFB;color:#555}.qtip-bootstrap{font-size:14px;line-height:20px;color:#333;padding:1px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.qtip-bootstrap .qtip-titlebar{padding:8px 14px;margin:0;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.qtip-bootstrap .qtip-titlebar .qtip-close{right:11px;top:45%;border-style:none}.qtip-bootstrap .qtip-content{padding:9px 14px}.qtip-bootstrap .qtip-icon{background:transparent}.qtip-bootstrap .qtip-icon .ui-icon{width:auto;height:auto;float:right;font-size:20px;font-weight:700;line-height:18px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.qtip-bootstrap .qtip-icon .ui-icon:hover{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}.qtip:not(.ie9haxors) div.qtip-content,.qtip:not(.ie9haxors) div.qtip-titlebar{filter:none;-ms-filter:none}.qtip .qtip-tip{margin:0 auto;overflow:hidden;z-index:10}x:-o-prefocus,.qtip .qtip-tip{visibility:hidden}.qtip .qtip-tip,.qtip .qtip-tip .qtip-vml,.qtip .qtip-tip canvas{position:absolute;color:#123456;background:transparent;border:0 dashed transparent}.qtip .qtip-tip canvas{top:0;left:0}.qtip .qtip-tip .qtip-vml{behavior:url(#default#VML);display:inline-block;visibility:visible}#qtip-overlay{position:fixed;left:0;top:0;width:100%;height:100%}#qtip-overlay.blurs{cursor:pointer}#qtip-overlay div{position:absolute;left:0;top:0;width:100%;height:100%;background-color:#000;opacity:.7;filter:alpha(opacity=70);-ms-filter:"alpha(Opacity=70)"}.qtipmodal-ie6fix{position:absolute!important} \ No newline at end of file
diff --git a/docs/htmldoc/js/jquery.qtip.min.js b/docs/htmldoc/js/jquery.qtip.min.js
new file mode 100644
index 0000000..3ae7bbe
--- /dev/null
+++ b/docs/htmldoc/js/jquery.qtip.min.js
@@ -0,0 +1,4 @@
+/* qTip2 v2.2.0 tips modal viewport svg imagemap ie6 | qtip2.com | Licensed MIT, GPL | Thu Nov 21 2013 20:34:59 */
+(function(t,e,i){(function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):jQuery&&!jQuery.fn.qtip&&t(jQuery)})(function(s){"use strict";function o(t,e,i,o){this.id=i,this.target=t,this.tooltip=E,this.elements={target:t},this._id=X+"-"+i,this.timers={img:{}},this.options=e,this.plugins={},this.cache={event:{},target:s(),disabled:k,attr:o,onTooltip:k,lastClass:""},this.rendered=this.destroyed=this.disabled=this.waiting=this.hiddenDuringWait=this.positioning=this.triggering=k}function n(t){return t===E||"object"!==s.type(t)}function r(t){return!(s.isFunction(t)||t&&t.attr||t.length||"object"===s.type(t)&&(t.jquery||t.then))}function a(t){var e,i,o,a;return n(t)?k:(n(t.metadata)&&(t.metadata={type:t.metadata}),"content"in t&&(e=t.content,n(e)||e.jquery||e.done?e=t.content={text:i=r(e)?k:e}:i=e.text,"ajax"in e&&(o=e.ajax,a=o&&o.once!==k,delete e.ajax,e.text=function(t,e){var n=i||s(this).attr(e.options.content.attr)||"Loading...",r=s.ajax(s.extend({},o,{context:e})).then(o.success,E,o.error).then(function(t){return t&&a&&e.set("content.text",t),t},function(t,i,s){e.destroyed||0===t.status||e.set("content.text",i+": "+s)});return a?n:(e.set("content.text",n),r)}),"title"in e&&(n(e.title)||(e.button=e.title.button,e.title=e.title.text),r(e.title||k)&&(e.title=k))),"position"in t&&n(t.position)&&(t.position={my:t.position,at:t.position}),"show"in t&&n(t.show)&&(t.show=t.show.jquery?{target:t.show}:t.show===W?{ready:W}:{event:t.show}),"hide"in t&&n(t.hide)&&(t.hide=t.hide.jquery?{target:t.hide}:{event:t.hide}),"style"in t&&n(t.style)&&(t.style={classes:t.style}),s.each(R,function(){this.sanitize&&this.sanitize(t)}),t)}function h(t,e){for(var i,s=0,o=t,n=e.split(".");o=o[n[s++]];)n.length>s&&(i=o);return[i||t,n.pop()]}function l(t,e){var i,s,o;for(i in this.checks)for(s in this.checks[i])(o=RegExp(s,"i").exec(t))&&(e.push(o),("builtin"===i||this.plugins[i])&&this.checks[i][s].apply(this.plugins[i]||this,e))}function c(t){return G.concat("").join(t?"-"+t+" ":" ")}function d(i){return i&&{type:i.type,pageX:i.pageX,pageY:i.pageY,target:i.target,relatedTarget:i.relatedTarget,scrollX:i.scrollX||t.pageXOffset||e.body.scrollLeft||e.documentElement.scrollLeft,scrollY:i.scrollY||t.pageYOffset||e.body.scrollTop||e.documentElement.scrollTop}||{}}function p(t,e){return e>0?setTimeout(s.proxy(t,this),e):(t.call(this),i)}function u(t){return this.tooltip.hasClass(ee)?k:(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this.timers.show=p.call(this,function(){this.toggle(W,t)},this.options.show.delay),i)}function f(t){if(this.tooltip.hasClass(ee))return k;var e=s(t.relatedTarget),i=e.closest(U)[0]===this.tooltip[0],o=e[0]===this.options.show.target[0];if(clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this!==e[0]&&"mouse"===this.options.position.target&&i||this.options.hide.fixed&&/mouse(out|leave|move)/.test(t.type)&&(i||o))try{t.preventDefault(),t.stopImmediatePropagation()}catch(n){}else this.timers.hide=p.call(this,function(){this.toggle(k,t)},this.options.hide.delay,this)}function g(t){return this.tooltip.hasClass(ee)||!this.options.hide.inactive?k:(clearTimeout(this.timers.inactive),this.timers.inactive=p.call(this,function(){this.hide(t)},this.options.hide.inactive),i)}function m(t){this.rendered&&this.tooltip[0].offsetWidth>0&&this.reposition(t)}function v(t,i,o){s(e.body).delegate(t,(i.split?i:i.join(he+" "))+he,function(){var t=T.api[s.attr(this,H)];t&&!t.disabled&&o.apply(t,arguments)})}function y(t,i,n){var r,h,l,c,d,p=s(e.body),u=t[0]===e?p:t,f=t.metadata?t.metadata(n.metadata):E,g="html5"===n.metadata.type&&f?f[n.metadata.name]:E,m=t.data(n.metadata.name||"qtipopts");try{m="string"==typeof m?s.parseJSON(m):m}catch(v){}if(c=s.extend(W,{},T.defaults,n,"object"==typeof m?a(m):E,a(g||f)),h=c.position,c.id=i,"boolean"==typeof c.content.text){if(l=t.attr(c.content.attr),c.content.attr===k||!l)return k;c.content.text=l}if(h.container.length||(h.container=p),h.target===k&&(h.target=u),c.show.target===k&&(c.show.target=u),c.show.solo===W&&(c.show.solo=h.container.closest("body")),c.hide.target===k&&(c.hide.target=u),c.position.viewport===W&&(c.position.viewport=h.container),h.container=h.container.eq(0),h.at=new z(h.at,W),h.my=new z(h.my),t.data(X))if(c.overwrite)t.qtip("destroy",!0);else if(c.overwrite===k)return k;return t.attr(Y,i),c.suppress&&(d=t.attr("title"))&&t.removeAttr("title").attr(se,d).attr("title",""),r=new o(t,c,i,!!l),t.data(X,r),t.one("remove.qtip-"+i+" removeqtip.qtip-"+i,function(){var t;(t=s(this).data(X))&&t.destroy(!0)}),r}function b(t){return t.charAt(0).toUpperCase()+t.slice(1)}function w(t,e){var s,o,n=e.charAt(0).toUpperCase()+e.slice(1),r=(e+" "+be.join(n+" ")+n).split(" "),a=0;if(ye[e])return t.css(ye[e]);for(;s=r[a++];)if((o=t.css(s))!==i)return ye[e]=s,o}function _(t,e){return Math.ceil(parseFloat(w(t,e)))}function x(t,e){this._ns="tip",this.options=e,this.offset=e.offset,this.size=[e.width,e.height],this.init(this.qtip=t)}function q(t,e){this.options=e,this._ns="-modal",this.init(this.qtip=t)}function C(t){this._ns="ie6",this.init(this.qtip=t)}var T,j,z,M,I,W=!0,k=!1,E=null,S="x",L="y",A="width",B="height",D="top",F="left",O="bottom",P="right",N="center",$="flipinvert",V="shift",R={},X="qtip",Y="data-hasqtip",H="data-qtip-id",G=["ui-widget","ui-tooltip"],U="."+X,Q="click dblclick mousedown mouseup mousemove mouseleave mouseenter".split(" "),J=X+"-fixed",K=X+"-default",Z=X+"-focus",te=X+"-hover",ee=X+"-disabled",ie="_replacedByqTip",se="oldtitle",oe={ie:function(){for(var t=3,i=e.createElement("div");(i.innerHTML="<!--[if gt IE "+ ++t+"]><i></i><![endif]-->")&&i.getElementsByTagName("i")[0];);return t>4?t:0/0}(),iOS:parseFloat((""+(/CPU.*OS ([0-9_]{1,5})|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent)||[0,""])[1]).replace("undefined","3_2").replace("_",".").replace("_",""))||k};j=o.prototype,j._when=function(t){return s.when.apply(s,t)},j.render=function(t){if(this.rendered||this.destroyed)return this;var e,i=this,o=this.options,n=this.cache,r=this.elements,a=o.content.text,h=o.content.title,l=o.content.button,c=o.position,d=("."+this._id+" ",[]);return s.attr(this.target[0],"aria-describedby",this._id),this.tooltip=r.tooltip=e=s("<div/>",{id:this._id,"class":[X,K,o.style.classes,X+"-pos-"+o.position.my.abbrev()].join(" "),width:o.style.width||"",height:o.style.height||"",tracking:"mouse"===c.target&&c.adjust.mouse,role:"alert","aria-live":"polite","aria-atomic":k,"aria-describedby":this._id+"-content","aria-hidden":W}).toggleClass(ee,this.disabled).attr(H,this.id).data(X,this).appendTo(c.container).append(r.content=s("<div />",{"class":X+"-content",id:this._id+"-content","aria-atomic":W})),this.rendered=-1,this.positioning=W,h&&(this._createTitle(),s.isFunction(h)||d.push(this._updateTitle(h,k))),l&&this._createButton(),s.isFunction(a)||d.push(this._updateContent(a,k)),this.rendered=W,this._setWidget(),s.each(R,function(t){var e;"render"===this.initialize&&(e=this(i))&&(i.plugins[t]=e)}),this._unassignEvents(),this._assignEvents(),this._when(d).then(function(){i._trigger("render"),i.positioning=k,i.hiddenDuringWait||!o.show.ready&&!t||i.toggle(W,n.event,k),i.hiddenDuringWait=k}),T.api[this.id]=this,this},j.destroy=function(t){function e(){if(!this.destroyed){this.destroyed=W;var t=this.target,e=t.attr(se);this.rendered&&this.tooltip.stop(1,0).find("*").remove().end().remove(),s.each(this.plugins,function(){this.destroy&&this.destroy()}),clearTimeout(this.timers.show),clearTimeout(this.timers.hide),this._unassignEvents(),t.removeData(X).removeAttr(H).removeAttr(Y).removeAttr("aria-describedby"),this.options.suppress&&e&&t.attr("title",e).removeAttr(se),this._unbind(t),this.options=this.elements=this.cache=this.timers=this.plugins=this.mouse=E,delete T.api[this.id]}}return this.destroyed?this.target:(t===W&&"hide"!==this.triggering||!this.rendered?e.call(this):(this.tooltip.one("tooltiphidden",s.proxy(e,this)),!this.triggering&&this.hide()),this.target)},M=j.checks={builtin:{"^id$":function(t,e,i,o){var n=i===W?T.nextid:i,r=X+"-"+n;n!==k&&n.length>0&&!s("#"+r).length?(this._id=r,this.rendered&&(this.tooltip[0].id=this._id,this.elements.content[0].id=this._id+"-content",this.elements.title[0].id=this._id+"-title")):t[e]=o},"^prerender":function(t,e,i){i&&!this.rendered&&this.render(this.options.show.ready)},"^content.text$":function(t,e,i){this._updateContent(i)},"^content.attr$":function(t,e,i,s){this.options.content.text===this.target.attr(s)&&this._updateContent(this.target.attr(i))},"^content.title$":function(t,e,s){return s?(s&&!this.elements.title&&this._createTitle(),this._updateTitle(s),i):this._removeTitle()},"^content.button$":function(t,e,i){this._updateButton(i)},"^content.title.(text|button)$":function(t,e,i){this.set("content."+e,i)},"^position.(my|at)$":function(t,e,i){"string"==typeof i&&(t[e]=new z(i,"at"===e))},"^position.container$":function(t,e,i){this.rendered&&this.tooltip.appendTo(i)},"^show.ready$":function(t,e,i){i&&(!this.rendered&&this.render(W)||this.toggle(W))},"^style.classes$":function(t,e,i,s){this.rendered&&this.tooltip.removeClass(s).addClass(i)},"^style.(width|height)":function(t,e,i){this.rendered&&this.tooltip.css(e,i)},"^style.widget|content.title":function(){this.rendered&&this._setWidget()},"^style.def":function(t,e,i){this.rendered&&this.tooltip.toggleClass(K,!!i)},"^events.(render|show|move|hide|focus|blur)$":function(t,e,i){this.rendered&&this.tooltip[(s.isFunction(i)?"":"un")+"bind"]("tooltip"+e,i)},"^(show|hide|position).(event|target|fixed|inactive|leave|distance|viewport|adjust)":function(){if(this.rendered){var t=this.options.position;this.tooltip.attr("tracking","mouse"===t.target&&t.adjust.mouse),this._unassignEvents(),this._assignEvents()}}}},j.get=function(t){if(this.destroyed)return this;var e=h(this.options,t.toLowerCase()),i=e[0][e[1]];return i.precedance?i.string():i};var ne=/^position\.(my|at|adjust|target|container|viewport)|style|content|show\.ready/i,re=/^prerender|show\.ready/i;j.set=function(t,e){if(this.destroyed)return this;var o,n=this.rendered,r=k,c=this.options;return this.checks,"string"==typeof t?(o=t,t={},t[o]=e):t=s.extend({},t),s.each(t,function(e,o){if(n&&re.test(e))return delete t[e],i;var a,l=h(c,e.toLowerCase());a=l[0][l[1]],l[0][l[1]]=o&&o.nodeType?s(o):o,r=ne.test(e)||r,t[e]=[l[0],l[1],o,a]}),a(c),this.positioning=W,s.each(t,s.proxy(l,this)),this.positioning=k,this.rendered&&this.tooltip[0].offsetWidth>0&&r&&this.reposition("mouse"===c.position.target?E:this.cache.event),this},j._update=function(t,e){var i=this,o=this.cache;return this.rendered&&t?(s.isFunction(t)&&(t=t.call(this.elements.target,o.event,this)||""),s.isFunction(t.then)?(o.waiting=W,t.then(function(t){return o.waiting=k,i._update(t,e)},E,function(t){return i._update(t,e)})):t===k||!t&&""!==t?k:(t.jquery&&t.length>0?e.empty().append(t.css({display:"block",visibility:"visible"})):e.html(t),this._waitForContent(e).then(function(t){t.images&&t.images.length&&i.rendered&&i.tooltip[0].offsetWidth>0&&i.reposition(o.event,!t.length)}))):k},j._waitForContent=function(t){var e=this.cache;return e.waiting=W,(s.fn.imagesLoaded?t.imagesLoaded():s.Deferred().resolve([])).done(function(){e.waiting=k}).promise()},j._updateContent=function(t,e){this._update(t,this.elements.content,e)},j._updateTitle=function(t,e){this._update(t,this.elements.title,e)===k&&this._removeTitle(k)},j._createTitle=function(){var t=this.elements,e=this._id+"-title";t.titlebar&&this._removeTitle(),t.titlebar=s("<div />",{"class":X+"-titlebar "+(this.options.style.widget?c("header"):"")}).append(t.title=s("<div />",{id:e,"class":X+"-title","aria-atomic":W})).insertBefore(t.content).delegate(".qtip-close","mousedown keydown mouseup keyup mouseout",function(t){s(this).toggleClass("ui-state-active ui-state-focus","down"===t.type.substr(-4))}).delegate(".qtip-close","mouseover mouseout",function(t){s(this).toggleClass("ui-state-hover","mouseover"===t.type)}),this.options.content.button&&this._createButton()},j._removeTitle=function(t){var e=this.elements;e.title&&(e.titlebar.remove(),e.titlebar=e.title=e.button=E,t!==k&&this.reposition())},j.reposition=function(i,o){if(!this.rendered||this.positioning||this.destroyed)return this;this.positioning=W;var n,r,a=this.cache,h=this.tooltip,l=this.options.position,c=l.target,d=l.my,p=l.at,u=l.viewport,f=l.container,g=l.adjust,m=g.method.split(" "),v=h.outerWidth(k),y=h.outerHeight(k),b=0,w=0,_=h.css("position"),x={left:0,top:0},q=h[0].offsetWidth>0,C=i&&"scroll"===i.type,T=s(t),j=f[0].ownerDocument,z=this.mouse;if(s.isArray(c)&&2===c.length)p={x:F,y:D},x={left:c[0],top:c[1]};else if("mouse"===c)p={x:F,y:D},!z||!z.pageX||!g.mouse&&i&&i.pageX?i&&i.pageX||((!g.mouse||this.options.show.distance)&&a.origin&&a.origin.pageX?i=a.origin:(!i||i&&("resize"===i.type||"scroll"===i.type))&&(i=a.event)):i=z,"static"!==_&&(x=f.offset()),j.body.offsetWidth!==(t.innerWidth||j.documentElement.clientWidth)&&(r=s(e.body).offset()),x={left:i.pageX-x.left+(r&&r.left||0),top:i.pageY-x.top+(r&&r.top||0)},g.mouse&&C&&z&&(x.left-=(z.scrollX||0)-T.scrollLeft(),x.top-=(z.scrollY||0)-T.scrollTop());else{if("event"===c?i&&i.target&&"scroll"!==i.type&&"resize"!==i.type?a.target=s(i.target):i.target||(a.target=this.elements.target):"event"!==c&&(a.target=s(c.jquery?c:this.elements.target)),c=a.target,c=s(c).eq(0),0===c.length)return this;c[0]===e||c[0]===t?(b=oe.iOS?t.innerWidth:c.width(),w=oe.iOS?t.innerHeight:c.height(),c[0]===t&&(x={top:(u||c).scrollTop(),left:(u||c).scrollLeft()})):R.imagemap&&c.is("area")?n=R.imagemap(this,c,p,R.viewport?m:k):R.svg&&c&&c[0].ownerSVGElement?n=R.svg(this,c,p,R.viewport?m:k):(b=c.outerWidth(k),w=c.outerHeight(k),x=c.offset()),n&&(b=n.width,w=n.height,r=n.offset,x=n.position),x=this.reposition.offset(c,x,f),(oe.iOS>3.1&&4.1>oe.iOS||oe.iOS>=4.3&&4.33>oe.iOS||!oe.iOS&&"fixed"===_)&&(x.left-=T.scrollLeft(),x.top-=T.scrollTop()),(!n||n&&n.adjustable!==k)&&(x.left+=p.x===P?b:p.x===N?b/2:0,x.top+=p.y===O?w:p.y===N?w/2:0)}return x.left+=g.x+(d.x===P?-v:d.x===N?-v/2:0),x.top+=g.y+(d.y===O?-y:d.y===N?-y/2:0),R.viewport?(x.adjusted=R.viewport(this,x,l,b,w,v,y),r&&x.adjusted.left&&(x.left+=r.left),r&&x.adjusted.top&&(x.top+=r.top)):x.adjusted={left:0,top:0},this._trigger("move",[x,u.elem||u],i)?(delete x.adjusted,o===k||!q||isNaN(x.left)||isNaN(x.top)||"mouse"===c||!s.isFunction(l.effect)?h.css(x):s.isFunction(l.effect)&&(l.effect.call(h,this,s.extend({},x)),h.queue(function(t){s(this).css({opacity:"",height:""}),oe.ie&&this.style.removeAttribute("filter"),t()})),this.positioning=k,this):this},j.reposition.offset=function(t,i,o){function n(t,e){i.left+=e*t.scrollLeft(),i.top+=e*t.scrollTop()}if(!o[0])return i;var r,a,h,l,c=s(t[0].ownerDocument),d=!!oe.ie&&"CSS1Compat"!==e.compatMode,p=o[0];do"static"!==(a=s.css(p,"position"))&&("fixed"===a?(h=p.getBoundingClientRect(),n(c,-1)):(h=s(p).position(),h.left+=parseFloat(s.css(p,"borderLeftWidth"))||0,h.top+=parseFloat(s.css(p,"borderTopWidth"))||0),i.left-=h.left+(parseFloat(s.css(p,"marginLeft"))||0),i.top-=h.top+(parseFloat(s.css(p,"marginTop"))||0),r||"hidden"===(l=s.css(p,"overflow"))||"visible"===l||(r=s(p)));while(p=p.offsetParent);return r&&(r[0]!==c[0]||d)&&n(r,1),i};var ae=(z=j.reposition.Corner=function(t,e){t=(""+t).replace(/([A-Z])/," $1").replace(/middle/gi,N).toLowerCase(),this.x=(t.match(/left|right/i)||t.match(/center/)||["inherit"])[0].toLowerCase(),this.y=(t.match(/top|bottom|center/i)||["inherit"])[0].toLowerCase(),this.forceY=!!e;var i=t.charAt(0);this.precedance="t"===i||"b"===i?L:S}).prototype;ae.invert=function(t,e){this[t]=this[t]===F?P:this[t]===P?F:e||this[t]},ae.string=function(){var t=this.x,e=this.y;return t===e?t:this.precedance===L||this.forceY&&"center"!==e?e+" "+t:t+" "+e},ae.abbrev=function(){var t=this.string().split(" ");return t[0].charAt(0)+(t[1]&&t[1].charAt(0)||"")},ae.clone=function(){return new z(this.string(),this.forceY)},j.toggle=function(t,i){var o=this.cache,n=this.options,r=this.tooltip;if(i){if(/over|enter/.test(i.type)&&/out|leave/.test(o.event.type)&&n.show.target.add(i.target).length===n.show.target.length&&r.has(i.relatedTarget).length)return this;o.event=d(i)}if(this.waiting&&!t&&(this.hiddenDuringWait=W),!this.rendered)return t?this.render(1):this;if(this.destroyed||this.disabled)return this;var a,h,l,c=t?"show":"hide",p=this.options[c],u=(this.options[t?"hide":"show"],this.options.position),f=this.options.content,g=this.tooltip.css("width"),m=this.tooltip.is(":visible"),v=t||1===p.target.length,y=!i||2>p.target.length||o.target[0]===i.target;return(typeof t).search("boolean|number")&&(t=!m),a=!r.is(":animated")&&m===t&&y,h=a?E:!!this._trigger(c,[90]),this.destroyed?this:(h!==k&&t&&this.focus(i),!h||a?this:(s.attr(r[0],"aria-hidden",!t),t?(o.origin=d(this.mouse),s.isFunction(f.text)&&this._updateContent(f.text,k),s.isFunction(f.title)&&this._updateTitle(f.title,k),!I&&"mouse"===u.target&&u.adjust.mouse&&(s(e).bind("mousemove."+X,this._storeMouse),I=W),g||r.css("width",r.outerWidth(k)),this.reposition(i,arguments[2]),g||r.css("width",""),p.solo&&("string"==typeof p.solo?s(p.solo):s(U,p.solo)).not(r).not(p.target).qtip("hide",s.Event("tooltipsolo"))):(clearTimeout(this.timers.show),delete o.origin,I&&!s(U+'[tracking="true"]:visible',p.solo).not(r).length&&(s(e).unbind("mousemove."+X),I=k),this.blur(i)),l=s.proxy(function(){t?(oe.ie&&r[0].style.removeAttribute("filter"),r.css("overflow",""),"string"==typeof p.autofocus&&s(this.options.show.autofocus,r).focus(),this.options.show.target.trigger("qtip-"+this.id+"-inactive")):r.css({display:"",visibility:"",opacity:"",left:"",top:""}),this._trigger(t?"visible":"hidden")},this),p.effect===k||v===k?(r[c](),l()):s.isFunction(p.effect)?(r.stop(1,1),p.effect.call(r,this),r.queue("fx",function(t){l(),t()})):r.fadeTo(90,t?1:0,l),t&&p.target.trigger("qtip-"+this.id+"-inactive"),this))},j.show=function(t){return this.toggle(W,t)},j.hide=function(t){return this.toggle(k,t)},j.focus=function(t){if(!this.rendered||this.destroyed)return this;var e=s(U),i=this.tooltip,o=parseInt(i[0].style.zIndex,10),n=T.zindex+e.length;return i.hasClass(Z)||this._trigger("focus",[n],t)&&(o!==n&&(e.each(function(){this.style.zIndex>o&&(this.style.zIndex=this.style.zIndex-1)}),e.filter("."+Z).qtip("blur",t)),i.addClass(Z)[0].style.zIndex=n),this},j.blur=function(t){return!this.rendered||this.destroyed?this:(this.tooltip.removeClass(Z),this._trigger("blur",[this.tooltip.css("zIndex")],t),this)},j.disable=function(t){return this.destroyed?this:("toggle"===t?t=!(this.rendered?this.tooltip.hasClass(ee):this.disabled):"boolean"!=typeof t&&(t=W),this.rendered&&this.tooltip.toggleClass(ee,t).attr("aria-disabled",t),this.disabled=!!t,this)},j.enable=function(){return this.disable(k)},j._createButton=function(){var t=this,e=this.elements,i=e.tooltip,o=this.options.content.button,n="string"==typeof o,r=n?o:"Close tooltip";e.button&&e.button.remove(),e.button=o.jquery?o:s("<a />",{"class":"qtip-close "+(this.options.style.widget?"":X+"-icon"),title:r,"aria-label":r}).prepend(s("<span />",{"class":"ui-icon ui-icon-close",html:"&times;"})),e.button.appendTo(e.titlebar||i).attr("role","button").click(function(e){return i.hasClass(ee)||t.hide(e),k})},j._updateButton=function(t){if(!this.rendered)return k;var e=this.elements.button;t?this._createButton():e.remove()},j._setWidget=function(){var t=this.options.style.widget,e=this.elements,i=e.tooltip,s=i.hasClass(ee);i.removeClass(ee),ee=t?"ui-state-disabled":"qtip-disabled",i.toggleClass(ee,s),i.toggleClass("ui-helper-reset "+c(),t).toggleClass(K,this.options.style.def&&!t),e.content&&e.content.toggleClass(c("content"),t),e.titlebar&&e.titlebar.toggleClass(c("header"),t),e.button&&e.button.toggleClass(X+"-icon",!t)},j._storeMouse=function(t){(this.mouse=d(t)).type="mousemove"},j._bind=function(t,e,i,o,n){var r="."+this._id+(o?"-"+o:"");e.length&&s(t).bind((e.split?e:e.join(r+" "))+r,s.proxy(i,n||this))},j._unbind=function(t,e){s(t).unbind("."+this._id+(e?"-"+e:""))};var he="."+X;s(function(){v(U,["mouseenter","mouseleave"],function(t){var e="mouseenter"===t.type,i=s(t.currentTarget),o=s(t.relatedTarget||t.target),n=this.options;e?(this.focus(t),i.hasClass(J)&&!i.hasClass(ee)&&clearTimeout(this.timers.hide)):"mouse"===n.position.target&&n.hide.event&&n.show.target&&!o.closest(n.show.target[0]).length&&this.hide(t),i.toggleClass(te,e)}),v("["+H+"]",Q,g)}),j._trigger=function(t,e,i){var o=s.Event("tooltip"+t);return o.originalEvent=i&&s.extend({},i)||this.cache.event||E,this.triggering=t,this.tooltip.trigger(o,[this].concat(e||[])),this.triggering=k,!o.isDefaultPrevented()},j._bindEvents=function(t,e,o,n,r,a){if(n.add(o).length===n.length){var h=[];e=s.map(e,function(e){var o=s.inArray(e,t);return o>-1?(h.push(t.splice(o,1)[0]),i):e}),h.length&&this._bind(o,h,function(t){var e=this.rendered?this.tooltip[0].offsetWidth>0:!1;(e?a:r).call(this,t)})}this._bind(o,t,r),this._bind(n,e,a)},j._assignInitialEvents=function(t){function e(t){return this.disabled||this.destroyed?k:(this.cache.event=d(t),this.cache.target=t?s(t.target):[i],clearTimeout(this.timers.show),this.timers.show=p.call(this,function(){this.render("object"==typeof t||o.show.ready)},o.show.delay),i)}var o=this.options,n=o.show.target,r=o.hide.target,a=o.show.event?s.trim(""+o.show.event).split(" "):[],h=o.hide.event?s.trim(""+o.hide.event).split(" "):[];/mouse(over|enter)/i.test(o.show.event)&&!/mouse(out|leave)/i.test(o.hide.event)&&h.push("mouseleave"),this._bind(n,"mousemove",function(t){this._storeMouse(t),this.cache.onTarget=W}),this._bindEvents(a,h,n,r,e,function(){clearTimeout(this.timers.show)}),(o.show.ready||o.prerender)&&e.call(this,t)},j._assignEvents=function(){var i=this,o=this.options,n=o.position,r=this.tooltip,a=o.show.target,h=o.hide.target,l=n.container,c=n.viewport,d=s(e),p=(s(e.body),s(t)),v=o.show.event?s.trim(""+o.show.event).split(" "):[],y=o.hide.event?s.trim(""+o.hide.event).split(" "):[];s.each(o.events,function(t,e){i._bind(r,"toggle"===t?["tooltipshow","tooltiphide"]:["tooltip"+t],e,null,r)}),/mouse(out|leave)/i.test(o.hide.event)&&"window"===o.hide.leave&&this._bind(d,["mouseout","blur"],function(t){/select|option/.test(t.target.nodeName)||t.relatedTarget||this.hide(t)}),o.hide.fixed?h=h.add(r.addClass(J)):/mouse(over|enter)/i.test(o.show.event)&&this._bind(h,"mouseleave",function(){clearTimeout(this.timers.show)}),(""+o.hide.event).indexOf("unfocus")>-1&&this._bind(l.closest("html"),["mousedown","touchstart"],function(t){var e=s(t.target),i=this.rendered&&!this.tooltip.hasClass(ee)&&this.tooltip[0].offsetWidth>0,o=e.parents(U).filter(this.tooltip[0]).length>0;e[0]===this.target[0]||e[0]===this.tooltip[0]||o||this.target.has(e[0]).length||!i||this.hide(t)}),"number"==typeof o.hide.inactive&&(this._bind(a,"qtip-"+this.id+"-inactive",g),this._bind(h.add(r),T.inactiveEvents,g,"-inactive")),this._bindEvents(v,y,a,h,u,f),this._bind(a.add(r),"mousemove",function(t){if("number"==typeof o.hide.distance){var e=this.cache.origin||{},i=this.options.hide.distance,s=Math.abs;(s(t.pageX-e.pageX)>=i||s(t.pageY-e.pageY)>=i)&&this.hide(t)}this._storeMouse(t)}),"mouse"===n.target&&n.adjust.mouse&&(o.hide.event&&this._bind(a,["mouseenter","mouseleave"],function(t){this.cache.onTarget="mouseenter"===t.type}),this._bind(d,"mousemove",function(t){this.rendered&&this.cache.onTarget&&!this.tooltip.hasClass(ee)&&this.tooltip[0].offsetWidth>0&&this.reposition(t)})),(n.adjust.resize||c.length)&&this._bind(s.event.special.resize?c:p,"resize",m),n.adjust.scroll&&this._bind(p.add(n.container),"scroll",m)},j._unassignEvents=function(){var i=[this.options.show.target[0],this.options.hide.target[0],this.rendered&&this.tooltip[0],this.options.position.container[0],this.options.position.viewport[0],this.options.position.container.closest("html")[0],t,e];this._unbind(s([]).pushStack(s.grep(i,function(t){return"object"==typeof t})))},T=s.fn.qtip=function(t,e,o){var n=(""+t).toLowerCase(),r=E,h=s.makeArray(arguments).slice(1),l=h[h.length-1],c=this[0]?s.data(this[0],X):E;return!arguments.length&&c||"api"===n?c:"string"==typeof t?(this.each(function(){var t=s.data(this,X);if(!t)return W;if(l&&l.timeStamp&&(t.cache.event=l),!e||"option"!==n&&"options"!==n)t[n]&&t[n].apply(t,h);else{if(o===i&&!s.isPlainObject(e))return r=t.get(e),k;t.set(e,o)}}),r!==E?r:this):"object"!=typeof t&&arguments.length?i:(c=a(s.extend(W,{},t)),this.each(function(t){var e,o;return o=s.isArray(c.id)?c.id[t]:c.id,o=!o||o===k||1>o.length||T.api[o]?T.nextid++:o,e=y(s(this),o,c),e===k?W:(T.api[o]=e,s.each(R,function(){"initialize"===this.initialize&&this(e)}),e._assignInitialEvents(l),i)}))},s.qtip=o,T.api={},s.each({attr:function(t,e){if(this.length){var i=this[0],o="title",n=s.data(i,"qtip");if(t===o&&n&&"object"==typeof n&&n.options.suppress)return 2>arguments.length?s.attr(i,se):(n&&n.options.content.attr===o&&n.cache.attr&&n.set("content.text",e),this.attr(se,e))}return s.fn["attr"+ie].apply(this,arguments)},clone:function(t){var e=(s([]),s.fn["clone"+ie].apply(this,arguments));return t||e.filter("["+se+"]").attr("title",function(){return s.attr(this,se)}).removeAttr(se),e}},function(t,e){if(!e||s.fn[t+ie])return W;var i=s.fn[t+ie]=s.fn[t];s.fn[t]=function(){return e.apply(this,arguments)||i.apply(this,arguments)}}),s.ui||(s["cleanData"+ie]=s.cleanData,s.cleanData=function(t){for(var e,i=0;(e=s(t[i])).length;i++)if(e.attr(Y))try{e.triggerHandler("removeqtip")}catch(o){}s["cleanData"+ie].apply(this,arguments)}),T.version="2.2.0",T.nextid=0,T.inactiveEvents=Q,T.zindex=15e3,T.defaults={prerender:k,id:k,overwrite:W,suppress:W,content:{text:W,attr:"title",title:k,button:k},position:{my:"top left",at:"bottom right",target:k,container:k,viewport:k,adjust:{x:0,y:0,mouse:W,scroll:W,resize:W,method:"flipinvert flipinvert"},effect:function(t,e){s(this).animate(e,{duration:200,queue:k})}},show:{target:k,event:"mouseenter",effect:W,delay:90,solo:k,ready:k,autofocus:k},hide:{target:k,event:"mouseleave",effect:W,delay:0,fixed:k,inactive:k,leave:"window",distance:k},style:{classes:"",widget:k,width:k,height:k,def:W},events:{render:E,move:E,show:E,hide:E,toggle:E,visible:E,hidden:E,focus:E,blur:E}};var le,ce="margin",de="border",pe="color",ue="background-color",fe="transparent",ge=" !important",me=!!e.createElement("canvas").getContext,ve=/rgba?\(0, 0, 0(, 0)?\)|transparent|#123456/i,ye={},be=["Webkit","O","Moz","ms"];if(me)var we=t.devicePixelRatio||1,_e=function(){var t=e.createElement("canvas").getContext("2d");return t.backingStorePixelRatio||t.webkitBackingStorePixelRatio||t.mozBackingStorePixelRatio||t.msBackingStorePixelRatio||t.oBackingStorePixelRatio||1}(),xe=we/_e;else var qe=function(t,e,i){return"<qtipvml:"+t+' xmlns="urn:schemas-microsoft.com:vml" class="qtip-vml" '+(e||"")+' style="behavior: url(#default#VML); '+(i||"")+'" />'};s.extend(x.prototype,{init:function(t){var e,i;i=this.element=t.elements.tip=s("<div />",{"class":X+"-tip"}).prependTo(t.tooltip),me?(e=s("<canvas />").appendTo(this.element)[0].getContext("2d"),e.lineJoin="miter",e.miterLimit=1e5,e.save()):(e=qe("shape",'coordorigin="0,0"',"position:absolute;"),this.element.html(e+e),t._bind(s("*",i).add(i),["click","mousedown"],function(t){t.stopPropagation()},this._ns)),t._bind(t.tooltip,"tooltipmove",this.reposition,this._ns,this),this.create()},_swapDimensions:function(){this.size[0]=this.options.height,this.size[1]=this.options.width},_resetDimensions:function(){this.size[0]=this.options.width,this.size[1]=this.options.height},_useTitle:function(t){var e=this.qtip.elements.titlebar;return e&&(t.y===D||t.y===N&&this.element.position().top+this.size[1]/2+this.options.offset<e.outerHeight(W))},_parseCorner:function(t){var e=this.qtip.options.position.my;return t===k||e===k?t=k:t===W?t=new z(e.string()):t.string||(t=new z(t),t.fixed=W),t},_parseWidth:function(t,e,i){var s=this.qtip.elements,o=de+b(e)+"Width";return(i?_(i,o):_(s.content,o)||_(this._useTitle(t)&&s.titlebar||s.content,o)||_(s.tooltip,o))||0},_parseRadius:function(t){var e=this.qtip.elements,i=de+b(t.y)+b(t.x)+"Radius";return 9>oe.ie?0:_(this._useTitle(t)&&e.titlebar||e.content,i)||_(e.tooltip,i)||0},_invalidColour:function(t,e,i){var s=t.css(e);return!s||i&&s===t.css(i)||ve.test(s)?k:s},_parseColours:function(t){var e=this.qtip.elements,i=this.element.css("cssText",""),o=de+b(t[t.precedance])+b(pe),n=this._useTitle(t)&&e.titlebar||e.content,r=this._invalidColour,a=[];return a[0]=r(i,ue)||r(n,ue)||r(e.content,ue)||r(e.tooltip,ue)||i.css(ue),a[1]=r(i,o,pe)||r(n,o,pe)||r(e.content,o,pe)||r(e.tooltip,o,pe)||e.tooltip.css(o),s("*",i).add(i).css("cssText",ue+":"+fe+ge+";"+de+":0"+ge+";"),a},_calculateSize:function(t){var e,i,s,o=t.precedance===L,n=this.options.width,r=this.options.height,a="c"===t.abbrev(),h=(o?n:r)*(a?.5:1),l=Math.pow,c=Math.round,d=Math.sqrt(l(h,2)+l(r,2)),p=[this.border/h*d,this.border/r*d];return p[2]=Math.sqrt(l(p[0],2)-l(this.border,2)),p[3]=Math.sqrt(l(p[1],2)-l(this.border,2)),e=d+p[2]+p[3]+(a?0:p[0]),i=e/d,s=[c(i*n),c(i*r)],o?s:s.reverse()},_calculateTip:function(t,e,i){i=i||1,e=e||this.size;var s=e[0]*i,o=e[1]*i,n=Math.ceil(s/2),r=Math.ceil(o/2),a={br:[0,0,s,o,s,0],bl:[0,0,s,0,0,o],tr:[0,o,s,0,s,o],tl:[0,0,0,o,s,o],tc:[0,o,n,0,s,o],bc:[0,0,s,0,n,o],rc:[0,0,s,r,0,o],lc:[s,0,s,o,0,r]};return a.lt=a.br,a.rt=a.bl,a.lb=a.tr,a.rb=a.tl,a[t.abbrev()]},_drawCoords:function(t,e){t.beginPath(),t.moveTo(e[0],e[1]),t.lineTo(e[2],e[3]),t.lineTo(e[4],e[5]),t.closePath()},create:function(){var t=this.corner=(me||oe.ie)&&this._parseCorner(this.options.corner);return(this.enabled=!!this.corner&&"c"!==this.corner.abbrev())&&(this.qtip.cache.corner=t.clone(),this.update()),this.element.toggle(this.enabled),this.corner},update:function(e,i){if(!this.enabled)return this;var o,n,r,a,h,l,c,d,p=this.qtip.elements,u=this.element,f=u.children(),g=this.options,m=this.size,v=g.mimic,y=Math.round;e||(e=this.qtip.cache.corner||this.corner),v===k?v=e:(v=new z(v),v.precedance=e.precedance,"inherit"===v.x?v.x=e.x:"inherit"===v.y?v.y=e.y:v.x===v.y&&(v[e.precedance]=e[e.precedance])),n=v.precedance,e.precedance===S?this._swapDimensions():this._resetDimensions(),o=this.color=this._parseColours(e),o[1]!==fe?(d=this.border=this._parseWidth(e,e[e.precedance]),g.border&&1>d&&!ve.test(o[1])&&(o[0]=o[1]),this.border=d=g.border!==W?g.border:d):this.border=d=0,c=this.size=this._calculateSize(e),u.css({width:c[0],height:c[1],lineHeight:c[1]+"px"}),l=e.precedance===L?[y(v.x===F?d:v.x===P?c[0]-m[0]-d:(c[0]-m[0])/2),y(v.y===D?c[1]-m[1]:0)]:[y(v.x===F?c[0]-m[0]:0),y(v.y===D?d:v.y===O?c[1]-m[1]-d:(c[1]-m[1])/2)],me?(r=f[0].getContext("2d"),r.restore(),r.save(),r.clearRect(0,0,6e3,6e3),a=this._calculateTip(v,m,xe),h=this._calculateTip(v,this.size,xe),f.attr(A,c[0]*xe).attr(B,c[1]*xe),f.css(A,c[0]).css(B,c[1]),this._drawCoords(r,h),r.fillStyle=o[1],r.fill(),r.translate(l[0]*xe,l[1]*xe),this._drawCoords(r,a),r.fillStyle=o[0],r.fill()):(a=this._calculateTip(v),a="m"+a[0]+","+a[1]+" l"+a[2]+","+a[3]+" "+a[4]+","+a[5]+" xe",l[2]=d&&/^(r|b)/i.test(e.string())?8===oe.ie?2:1:0,f.css({coordsize:c[0]+d+" "+(c[1]+d),antialias:""+(v.string().indexOf(N)>-1),left:l[0]-l[2]*Number(n===S),top:l[1]-l[2]*Number(n===L),width:c[0]+d,height:c[1]+d}).each(function(t){var e=s(this);e[e.prop?"prop":"attr"]({coordsize:c[0]+d+" "+(c[1]+d),path:a,fillcolor:o[0],filled:!!t,stroked:!t}).toggle(!(!d&&!t)),!t&&e.html(qe("stroke",'weight="'+2*d+'px" color="'+o[1]+'" miterlimit="1000" joinstyle="miter"'))})),t.opera&&setTimeout(function(){p.tip.css({display:"inline-block",visibility:"visible"})},1),i!==k&&this.calculate(e,c)},calculate:function(t,e){if(!this.enabled)return k;var i,o,n=this,r=this.qtip.elements,a=this.element,h=this.options.offset,l=(r.tooltip.hasClass("ui-widget"),{});return t=t||this.corner,i=t.precedance,e=e||this._calculateSize(t),o=[t.x,t.y],i===S&&o.reverse(),s.each(o,function(s,o){var a,c,d;o===N?(a=i===L?F:D,l[a]="50%",l[ce+"-"+a]=-Math.round(e[i===L?0:1]/2)+h):(a=n._parseWidth(t,o,r.tooltip),c=n._parseWidth(t,o,r.content),d=n._parseRadius(t),l[o]=Math.max(-n.border,s?c:h+(d>a?d:-a)))
+}),l[t[i]]-=e[i===S?0:1],a.css({margin:"",top:"",bottom:"",left:"",right:""}).css(l),l},reposition:function(t,e,s){function o(t,e,i,s,o){t===V&&l.precedance===e&&c[s]&&l[i]!==N?l.precedance=l.precedance===S?L:S:t!==V&&c[s]&&(l[e]=l[e]===N?c[s]>0?s:o:l[e]===s?o:s)}function n(t,e,o){l[t]===N?g[ce+"-"+e]=f[t]=r[ce+"-"+e]-c[e]:(a=r[o]!==i?[c[e],-r[e]]:[-c[e],r[e]],(f[t]=Math.max(a[0],a[1]))>a[0]&&(s[e]-=c[e],f[e]=k),g[r[o]!==i?o:e]=f[t])}if(this.enabled){var r,a,h=e.cache,l=this.corner.clone(),c=s.adjusted,d=e.options.position.adjust.method.split(" "),p=d[0],u=d[1]||d[0],f={left:k,top:k,x:0,y:0},g={};this.corner.fixed!==W&&(o(p,S,L,F,P),o(u,L,S,D,O),l.string()===h.corner.string()||h.cornerTop===c.top&&h.cornerLeft===c.left||this.update(l,k)),r=this.calculate(l),r.right!==i&&(r.left=-r.right),r.bottom!==i&&(r.top=-r.bottom),r.user=this.offset,(f.left=p===V&&!!c.left)&&n(S,F,P),(f.top=u===V&&!!c.top)&&n(L,D,O),this.element.css(g).toggle(!(f.x&&f.y||l.x===N&&f.y||l.y===N&&f.x)),s.left-=r.left.charAt?r.user:p!==V||f.top||!f.left&&!f.top?r.left+this.border:0,s.top-=r.top.charAt?r.user:u!==V||f.left||!f.left&&!f.top?r.top+this.border:0,h.cornerLeft=c.left,h.cornerTop=c.top,h.corner=l.clone()}},destroy:function(){this.qtip._unbind(this.qtip.tooltip,this._ns),this.qtip.elements.tip&&this.qtip.elements.tip.find("*").remove().end().remove()}}),le=R.tip=function(t){return new x(t,t.options.style.tip)},le.initialize="render",le.sanitize=function(t){if(t.style&&"tip"in t.style){var e=t.style.tip;"object"!=typeof e&&(e=t.style.tip={corner:e}),/string|boolean/i.test(typeof e.corner)||(e.corner=W)}},M.tip={"^position.my|style.tip.(corner|mimic|border)$":function(){this.create(),this.qtip.reposition()},"^style.tip.(height|width)$":function(t){this.size=[t.width,t.height],this.update(),this.qtip.reposition()},"^content.title|style.(classes|widget)$":function(){this.update()}},s.extend(W,T.defaults,{style:{tip:{corner:W,mimic:k,width:6,height:6,border:W,offset:0}}});var Ce,Te,je="qtip-modal",ze="."+je;Te=function(){function t(t){if(s.expr[":"].focusable)return s.expr[":"].focusable;var e,i,o,n=!isNaN(s.attr(t,"tabindex")),r=t.nodeName&&t.nodeName.toLowerCase();return"area"===r?(e=t.parentNode,i=e.name,t.href&&i&&"map"===e.nodeName.toLowerCase()?(o=s("img[usemap=#"+i+"]")[0],!!o&&o.is(":visible")):!1):/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||n:n}function i(t){1>c.length&&t.length?t.not("body").blur():c.first().focus()}function o(t){if(h.is(":visible")){var e,o=s(t.target),a=n.tooltip,l=o.closest(U);e=1>l.length?k:parseInt(l[0].style.zIndex,10)>parseInt(a[0].style.zIndex,10),e||o.closest(U)[0]===a[0]||i(o),r=t.target===c[c.length-1]}}var n,r,a,h,l=this,c={};s.extend(l,{init:function(){return h=l.elem=s("<div />",{id:"qtip-overlay",html:"<div></div>",mousedown:function(){return k}}).hide(),s(e.body).bind("focusin"+ze,o),s(e).bind("keydown"+ze,function(t){n&&n.options.show.modal.escape&&27===t.keyCode&&n.hide(t)}),h.bind("click"+ze,function(t){n&&n.options.show.modal.blur&&n.hide(t)}),l},update:function(e){n=e,c=e.options.show.modal.stealfocus!==k?e.tooltip.find("*").filter(function(){return t(this)}):[]},toggle:function(t,o,r){var c=(s(e.body),t.tooltip),d=t.options.show.modal,p=d.effect,u=o?"show":"hide",f=h.is(":visible"),g=s(ze).filter(":visible:not(:animated)").not(c);return l.update(t),o&&d.stealfocus!==k&&i(s(":focus")),h.toggleClass("blurs",d.blur),o&&h.appendTo(e.body),h.is(":animated")&&f===o&&a!==k||!o&&g.length?l:(h.stop(W,k),s.isFunction(p)?p.call(h,o):p===k?h[u]():h.fadeTo(parseInt(r,10)||90,o?1:0,function(){o||h.hide()}),o||h.queue(function(t){h.css({left:"",top:""}),s(ze).length||h.detach(),t()}),a=o,n.destroyed&&(n=E),l)}}),l.init()},Te=new Te,s.extend(q.prototype,{init:function(t){var e=t.tooltip;return this.options.on?(t.elements.overlay=Te.elem,e.addClass(je).css("z-index",T.modal_zindex+s(ze).length),t._bind(e,["tooltipshow","tooltiphide"],function(t,i,o){var n=t.originalEvent;if(t.target===e[0])if(n&&"tooltiphide"===t.type&&/mouse(leave|enter)/.test(n.type)&&s(n.relatedTarget).closest(Te.elem[0]).length)try{t.preventDefault()}catch(r){}else(!n||n&&"tooltipsolo"!==n.type)&&this.toggle(t,"tooltipshow"===t.type,o)},this._ns,this),t._bind(e,"tooltipfocus",function(t,i){if(!t.isDefaultPrevented()&&t.target===e[0]){var o=s(ze),n=T.modal_zindex+o.length,r=parseInt(e[0].style.zIndex,10);Te.elem[0].style.zIndex=n-1,o.each(function(){this.style.zIndex>r&&(this.style.zIndex-=1)}),o.filter("."+Z).qtip("blur",t.originalEvent),e.addClass(Z)[0].style.zIndex=n,Te.update(i);try{t.preventDefault()}catch(a){}}},this._ns,this),t._bind(e,"tooltiphide",function(t){t.target===e[0]&&s(ze).filter(":visible").not(e).last().qtip("focus",t)},this._ns,this),i):this},toggle:function(t,e,s){return t&&t.isDefaultPrevented()?this:(Te.toggle(this.qtip,!!e,s),i)},destroy:function(){this.qtip.tooltip.removeClass(je),this.qtip._unbind(this.qtip.tooltip,this._ns),Te.toggle(this.qtip,k),delete this.qtip.elements.overlay}}),Ce=R.modal=function(t){return new q(t,t.options.show.modal)},Ce.sanitize=function(t){t.show&&("object"!=typeof t.show.modal?t.show.modal={on:!!t.show.modal}:t.show.modal.on===i&&(t.show.modal.on=W))},T.modal_zindex=T.zindex-200,Ce.initialize="render",M.modal={"^show.modal.(on|blur)$":function(){this.destroy(),this.init(),this.qtip.elems.overlay.toggle(this.qtip.tooltip[0].offsetWidth>0)}},s.extend(W,T.defaults,{show:{modal:{on:k,effect:W,blur:W,stealfocus:W,escape:W}}}),R.viewport=function(i,s,o,n,r,a,h){function l(t,e,i,o,n,r,a,h,l){var c=s[n],p=_[t],b=x[t],w=i===V,q=p===n?l:p===r?-l:-l/2,C=b===n?h:b===r?-h:-h/2,T=v[n]+y[n]-(f?0:u[n]),j=T-c,z=c+l-(a===A?g:m)-T,M=q-(_.precedance===t||p===_[e]?C:0)-(b===N?h/2:0);return w?(M=(p===n?1:-1)*q,s[n]+=j>0?j:z>0?-z:0,s[n]=Math.max(-u[n]+y[n],c-M,Math.min(Math.max(-u[n]+y[n]+(a===A?g:m),c+M),s[n],"center"===p?c-q:1e9))):(o*=i===$?2:0,j>0&&(p!==n||z>0)?(s[n]-=M+o,d.invert(t,n)):z>0&&(p!==r||j>0)&&(s[n]-=(p===N?-M:M)+o,d.invert(t,r)),v>s[n]&&-s[n]>z&&(s[n]=c,d=_.clone())),s[n]-c}var c,d,p,u,f,g,m,v,y,b=o.target,w=i.elements.tooltip,_=o.my,x=o.at,q=o.adjust,C=q.method.split(" "),T=C[0],j=C[1]||C[0],z=o.viewport,M=o.container,I=i.cache,W={left:0,top:0};return z.jquery&&b[0]!==t&&b[0]!==e.body&&"none"!==q.method?(u=M.offset()||W,f="static"===M.css("position"),c="fixed"===w.css("position"),g=z[0]===t?z.width():z.outerWidth(k),m=z[0]===t?z.height():z.outerHeight(k),v={left:c?0:z.scrollLeft(),top:c?0:z.scrollTop()},y=z.offset()||W,("shift"!==T||"shift"!==j)&&(d=_.clone()),W={left:"none"!==T?l(S,L,T,q.x,F,P,A,n,a):0,top:"none"!==j?l(L,S,j,q.y,D,O,B,r,h):0},d&&I.lastClass!==(p=X+"-pos-"+d.abbrev())&&w.removeClass(i.cache.lastClass).addClass(i.cache.lastClass=p),W):W},R.polys={polygon:function(t,e){var i,s,o,n={width:0,height:0,position:{top:1e10,right:0,bottom:0,left:1e10},adjustable:k},r=0,a=[],h=1,l=1,c=0,d=0;for(r=t.length;r--;)i=[parseInt(t[--r],10),parseInt(t[r+1],10)],i[0]>n.position.right&&(n.position.right=i[0]),i[0]<n.position.left&&(n.position.left=i[0]),i[1]>n.position.bottom&&(n.position.bottom=i[1]),i[1]<n.position.top&&(n.position.top=i[1]),a.push(i);if(s=n.width=Math.abs(n.position.right-n.position.left),o=n.height=Math.abs(n.position.bottom-n.position.top),"c"===e.abbrev())n.position={left:n.position.left+n.width/2,top:n.position.top+n.height/2};else{for(;s>0&&o>0&&h>0&&l>0;)for(s=Math.floor(s/2),o=Math.floor(o/2),e.x===F?h=s:e.x===P?h=n.width-s:h+=Math.floor(s/2),e.y===D?l=o:e.y===O?l=n.height-o:l+=Math.floor(o/2),r=a.length;r--&&!(2>a.length);)c=a[r][0]-n.position.left,d=a[r][1]-n.position.top,(e.x===F&&c>=h||e.x===P&&h>=c||e.x===N&&(h>c||c>n.width-h)||e.y===D&&d>=l||e.y===O&&l>=d||e.y===N&&(l>d||d>n.height-l))&&a.splice(r,1);n.position={left:a[0][0],top:a[0][1]}}return n},rect:function(t,e,i,s){return{width:Math.abs(i-t),height:Math.abs(s-e),position:{left:Math.min(t,i),top:Math.min(e,s)}}},_angles:{tc:1.5,tr:7/4,tl:5/4,bc:.5,br:.25,bl:.75,rc:2,lc:1,c:0},ellipse:function(t,e,i,s,o){var n=R.polys._angles[o.abbrev()],r=0===n?0:i*Math.cos(n*Math.PI),a=s*Math.sin(n*Math.PI);return{width:2*i-Math.abs(r),height:2*s-Math.abs(a),position:{left:t+r,top:e+a},adjustable:k}},circle:function(t,e,i,s){return R.polys.ellipse(t,e,i,i,s)}},R.svg=function(t,i,o){for(var n,r,a,h,l,c,d,p,u,f,g,m=s(e),v=i[0],y=s(v.ownerSVGElement),b=1,w=1,_=!0;!v.getBBox;)v=v.parentNode;if(!v.getBBox||!v.parentNode)return k;n=y.attr("width")||y.width()||parseInt(y.css("width"),10),r=y.attr("height")||y.height()||parseInt(y.css("height"),10);var x=(parseInt(i.css("stroke-width"),10)||0)/2;switch(x&&(b+=x/n,w+=x/r),v.nodeName){case"ellipse":case"circle":f=R.polys.ellipse(v.cx.baseVal.value,v.cy.baseVal.value,(v.rx||v.r).baseVal.value+x,(v.ry||v.r).baseVal.value+x,o);break;case"line":case"polygon":case"polyline":for(u=v.points||[{x:v.x1.baseVal.value,y:v.y1.baseVal.value},{x:v.x2.baseVal.value,y:v.y2.baseVal.value}],f=[],p=-1,c=u.numberOfItems||u.length;c>++p;)d=u.getItem?u.getItem(p):u[p],f.push.apply(f,[d.x,d.y]);f=R.polys.polygon(f,o);break;default:f=v.getBoundingClientRect(),f={width:f.width,height:f.height,position:{left:f.left,top:f.top}},_=!1}return g=f.position,y=y[0],_&&(y.createSVGPoint&&(a=v.getScreenCTM(),u=y.createSVGPoint(),u.x=g.left,u.y=g.top,h=u.matrixTransform(a),g.left=h.x,g.top=h.y),y.viewBox&&(l=y.viewBox.baseVal)&&l.width&&l.height&&(b*=n/l.width,w*=r/l.height)),g.left+=m.scrollLeft(),g.top+=m.scrollTop(),f},R.imagemap=function(t,e,i){e.jquery||(e=s(e));var o,n,r,a,h,l=e.attr("shape").toLowerCase().replace("poly","polygon"),c=s('img[usemap="#'+e.parent("map").attr("name")+'"]'),d=s.trim(e.attr("coords")),p=d.replace(/,$/,"").split(",");if(!c.length)return k;if("polygon"===l)a=R.polys.polygon(p,i);else{if(!R.polys[l])return k;for(r=-1,h=p.length,n=[];h>++r;)n.push(parseInt(p[r],10));a=R.polys[l].apply(this,n.concat(i))}return o=c.offset(),o.left+=Math.ceil((c.outerWidth(k)-c.width())/2),o.top+=Math.ceil((c.outerHeight(k)-c.height())/2),a.position.left+=o.left,a.position.top+=o.top,a};var Me,Ie='<iframe class="qtip-bgiframe" frameborder="0" tabindex="-1" src="javascript:\'\';" style="display:block; position:absolute; z-index:-1; filter:alpha(opacity=0); -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";"></iframe>';s.extend(C.prototype,{_scroll:function(){var e=this.qtip.elements.overlay;e&&(e[0].style.top=s(t).scrollTop()+"px")},init:function(i){var o=i.tooltip;1>s("select, object").length&&(this.bgiframe=i.elements.bgiframe=s(Ie).appendTo(o),i._bind(o,"tooltipmove",this.adjustBGIFrame,this._ns,this)),this.redrawContainer=s("<div/>",{id:X+"-rcontainer"}).appendTo(e.body),i.elements.overlay&&i.elements.overlay.addClass("qtipmodal-ie6fix")&&(i._bind(t,["scroll","resize"],this._scroll,this._ns,this),i._bind(o,["tooltipshow"],this._scroll,this._ns,this)),this.redraw()},adjustBGIFrame:function(){var t,e,i=this.qtip.tooltip,s={height:i.outerHeight(k),width:i.outerWidth(k)},o=this.qtip.plugins.tip,n=this.qtip.elements.tip;e=parseInt(i.css("borderLeftWidth"),10)||0,e={left:-e,top:-e},o&&n&&(t="x"===o.corner.precedance?[A,F]:[B,D],e[t[1]]-=n[t[0]]()),this.bgiframe.css(e).css(s)},redraw:function(){if(1>this.qtip.rendered||this.drawing)return this;var t,e,i,s,o=this.qtip.tooltip,n=this.qtip.options.style,r=this.qtip.options.position.container;return this.qtip.drawing=1,n.height&&o.css(B,n.height),n.width?o.css(A,n.width):(o.css(A,"").appendTo(this.redrawContainer),e=o.width(),1>e%2&&(e+=1),i=o.css("maxWidth")||"",s=o.css("minWidth")||"",t=(i+s).indexOf("%")>-1?r.width()/100:0,i=(i.indexOf("%")>-1?t:1)*parseInt(i,10)||e,s=(s.indexOf("%")>-1?t:1)*parseInt(s,10)||0,e=i+s?Math.min(Math.max(e,s),i):e,o.css(A,Math.round(e)).appendTo(r)),this.drawing=0,this},destroy:function(){this.bgiframe&&this.bgiframe.remove(),this.qtip._unbind([t,this.qtip.tooltip],this._ns)}}),Me=R.ie6=function(t){return 6===oe.ie?new C(t):k},Me.initialize="render",M.ie6={"^content|style$":function(){this.redraw()}}})})(window,document);
+//@ sourceMappingURL=http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.0/jquery.qtip.min.map \ No newline at end of file
diff --git a/docs/htmldoc/libgraph.html b/docs/htmldoc/libgraph.html
new file mode 100644
index 0000000..dbcda1f
--- /dev/null
+++ b/docs/htmldoc/libgraph.html
@@ -0,0 +1,245 @@
+<html>
+<head>
+<style>
+#cy {
+ width: 100%;
+ height: -moz-calc(100% - 2em);
+ height: -webkit-calc(100% - 2em);
+ height: -o-calc(100% - 2em);
+ height: 95%;
+ display: block;
+}
+
+.button {
+ -moz-box-shadow:inset 0px 1px 0px 0px #ffffff;
+ -webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;
+ box-shadow:inset 0px 1px 0px 0px #ffffff;
+ background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #f9f9f9), color-stop(1, #e9e9e9));
+ background:-moz-linear-gradient(top, #f9f9f9 5%, #e9e9e9 100%);
+ background:-webkit-linear-gradient(top, #f9f9f9 5%, #e9e9e9 100%);
+ background:-o-linear-gradient(top, #f9f9f9 5%, #e9e9e9 100%);
+ background:-ms-linear-gradient(top, #f9f9f9 5%, #e9e9e9 100%);
+ background:linear-gradient(to bottom, #f9f9f9 5%, #e9e9e9 100%);
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f9f9f9', endColorstr='#e9e9e9',GradientType=0);
+ background-color:#f9f9f9;
+ -moz-border-radius:6px;
+ -webkit-border-radius:6px;
+ border-radius:6px;
+ border:1px solid #dcdcdc;
+ display:inline-block;
+ cursor:pointer;
+ color:#666666;
+ font-family:Arial;
+ font-size:15px;
+ font-weight:bold;
+ padding:6px 24px;
+ text-decoration:none;
+ text-shadow:0px 1px 0px #ffffff;
+}
+.button:hover {
+ background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #e9e9e9), color-stop(1, #f9f9f9));
+ background:-moz-linear-gradient(top, #e9e9e9 5%, #f9f9f9 100%);
+ background:-webkit-linear-gradient(top, #e9e9e9 5%, #f9f9f9 100%);
+ background:-o-linear-gradient(top, #e9e9e9 5%, #f9f9f9 100%);
+ background:-ms-linear-gradient(top, #e9e9e9 5%, #f9f9f9 100%);
+ background:linear-gradient(to bottom, #e9e9e9 5%, #f9f9f9 100%);
+ filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#e9e9e9', endColorstr='#f9f9f9',GradientType=0);
+ background-color:#e9e9e9;
+}
+.button:active {
+ position:relative;
+ top:1px;
+}
+.button-bar {
+ margin-left:auto;
+ width: auto;
+ position: absolute;
+ right: 10px;
+}
+.zoom-in:before { font-size:12pt; content: "+" }
+.zoom-out:before { font-size:12pt; content: "-" }
+.zoom-expand:before { font-size:12pt; content: "fit" }
+</style>
+<link href="js/jquery.qtip.min.css" rel="stylesheet" type="text/css" />
+<link href="js/cytoscape.js-panzoom.css" rel="stylesheet" type="text/css" />
+
+<script src="js/jquery-2.0.3.min.js"></script>
+<script src="js/cytoscape.min.js"></script>
+<script src="js/dagre.min.js"></script>
+<script src="js/cytoscape-dagre.js"></script>
+<script src="js/jquery.qtip.min.js"></script>
+<script src="js/cytoscape-qtip.js"></script>
+<script src="js/cytoscape-panzoom.js"></script>
+
+<script src="depend.js"></script>
+
+<script type="text/javascript">
+$(document).ready(function(){
+ var cy = window.cy = cytoscape({
+ container: document.getElementById('cy'), // container to render in
+ elements: depends,
+ style: [
+ { selector: '.hidden',
+ style: {
+ 'display': 'none',
+ }},
+ { selector: "node",
+ style: {
+ 'width': 'mapData(score, 0, 0.006769776522008331, 20, 60)',
+ 'height': 'mapData(score, 0, 0.006769776522008331, 20, 60)',
+ 'content':'data(name)',
+ 'font-size':'18pt',
+ 'font-weight':'bold',
+ 'text-valign':'center',
+ 'text-halign':'center',
+ 'text-outline-color': 'white',
+ 'border-color': function(e) {
+ if (e.data('released') === 'yes') {return 'green'}
+ else {return '#ccc'}
+ },
+ 'border-width': '2px',
+ 'border-style': 'dashed',
+ 'background-color': 'white',
+ 'text-outline-width':'1px',
+ 'color':'#555',
+ 'overlay-padding':'6px',
+ 'z-index':'10',
+ }},
+ { selector: '$node > node',
+ style: {
+ 'background-color': 'rgba(255,255,255,0.5)',
+ 'border-style' : 'dotted',
+ 'border-width' : '1',
+ 'border-color' : 'blue',
+ 'padding' : '1em',
+ 'label': 'data(name)',
+ 'text-valign':'top',
+ 'text-halign':'center',
+ 'z-index': 99,
+ }},
+ { selector: 'edge',
+ style: {
+ 'width': 3,
+ 'line-color': '#ccc',
+ 'target-arrow-color': '#ccc',
+ 'target-arrow-shape': 'triangle',
+ }},
+ { selector: '.red',
+ style: {
+ 'line-color': 'red',
+ 'target-arrow-color': 'red',
+ 'target-arrow-shape': 'triangle',
+ 'z-index': 100,
+ }},
+ ],
+ ready: function(){ window.cy = this; },
+ layout: {
+ name: 'dagre',
+ fit: false,
+ edgeSep: 10,
+ padding: 5,
+ animate: false,
+ },
+ textureOnViewport: true,
+ }); // end: var cy = cytoscape(...
+
+ cy.on('tap', 'node', function(evt){
+ var node = evt.cyTarget;
+ var g = node.data('name');
+ node.connectedEdges().forEach(function(e){ e.toggleClass('red') });
+ if (g == '+') { collapse_this('#' + node.parent().id()); }
+ });
+
+ cy.nodes().forEach(function(n){
+ var g = n.data('name');
+
+ if (g == '+') {
+ n.addClass('hidden');
+ n.relativePosition({ x: 0, y:0 });
+ };
+ if (g == '-') {
+ var x = n.relativePosition('x');
+ var y = n.relativePosition('y');
+ n.relativePosition({ x: -x, y: -y });
+ };
+
+ if (n.isChild() && g != '+' && g !='-') {
+ n.qtip({
+ content: [
+ { name: 'View coqdoc',
+ url: 'mathcomp.' + n.parent().data('name') + '.' + g + '.html'
+ },
+ ].map(function( link ){
+ return '<a target="_blank" href="' + link.url + '">' +
+ link.name + '</a>';
+ }).join('<br />\n'),
+ position: { my: 'top center', at: 'bottom center' },
+ style: { classes: 'qtip-bootstrap', tip: { width: 16, height: 8 } },
+ });
+ } else if (n.isParent()) {
+ n.qtip({
+ content: [
+ { name: 'Collapse',
+ url: n.id(),
+ },
+ ].map(function( link ){
+ return '<a href="#" onclick="collapse_this(\'#' + link.url +
+ '\');">' + link.name + '</a>';
+ }).join('<br />\n'),
+ position: { my: 'top center', at: 'bottom center' },
+ style: { classes: 'qtip-bootstrap', tip: { width: 16, height: 8 } },
+ });
+
+ }
+ });
+
+ cy.center();
+
+ cy.panzoom({
+ // icon class names
+ sliderHandleIcon: 'zoom-slide',
+ zoomInIcon: 'zoom-in',
+ zoomOutIcon: 'zoom-out',
+ resetIcon: 'zoom-expand'
+});
+});
+
+
+function collapse_this(id) {
+ cy.$(id).children().forEach(function(e) {
+ e.toggleClass('hidden');
+ if (e.data('name') == '+' && !e.hasClass('hidden')) {
+ e.relativePosition({ x: 0, y:0 });
+ }
+ });
+}
+
+function collapse() {
+ cy.nodes().forEach(function(n){
+ if (n.isParent()) { collapse_this('#' + n.id()) }
+ });
+ cy.layout();
+ cy.fit();
+ cy.center();
+ cy.reset();
+}
+
+function no_red() {
+ cy.edges().forEach(function(e) { e.removeClass('red'); });
+}
+</script>
+</head>
+<body>
+ <div id="cy">
+ </div>
+ <div>
+ Nodes and clusters can be dragged around and clicked.
+ When a node/cluster is clicked its links are highlighted
+ and a contextual menu pops up. Clusters can be collapsed.
+ </div>
+ <div class="button-bar">
+ <div class="button" onclick="collapse()">collapse all</div>
+ <div class="button" onclick="no_red()">clear red edges</div>
+ </div>
+</body>
+</html>
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 0000000..c1c0909
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,106 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <title>Mathematical Components</title>
+
+ <link rel="stylesheet" href="stylesheets/styles.css">
+ <link rel="stylesheet" href="stylesheets/github-light.css">
+ <meta name="viewport" content="width=device-width">
+ <!--[if lt IE 9]>
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+ </head>
+ <body>
+ <div class="wrapper">
+ <header>
+ <h1>Mathematical Components</h1>
+ <p> Libraries of formalized mathematics</p>
+
+ <p class="view"><a href="https://github.com/math-comp/math-comp">View the Project on GitHub <small>math-comp/math-comp</small></a></p>
+
+
+ <!-- <ul> -->
+ <!-- <li><a href="https://github.com/math-comp/math-comp/zipball/master">Download <strong>ZIP File</strong></a></li> -->
+ <!-- <li><a href="https://github.com/math-comp/math-comp/tarball/master">Download <strong>TAR Ball</strong></a></li> -->
+ <!-- <li><a href="https://github.com/math-comp/math-comp">View On <strong>GitHub</strong></a></li> -->
+ <!-- </ul> -->
+ </header>
+
+ <section>
+ <h3>
+<a id="about" class="anchor" href="#about" aria-hidden="true"><span class="octicon octicon-link"></span></a>About</h3>
+
+<p> The Mathematical Components library for
+ <a href="http://www.coq.inria.fr">Coq</a> has its origins in
+the formal proof of the Four Colour Theorem. Since then it has grown
+to cover many areas of mathematics and has been used for
+large scale projects like the formal proof of the Odd Order Theorem.
+</p><p>
+The library is written using the Ssreflect proof language that is an integral
+part of the distribution.
+</p>
+
+<h3>
+<a id="releases" class="anchor" href="#releases" aria-hidden="true"><span class="octicon octicon-link"></span></a>Getting the library</h3>
+
+<p> The current stable release of the
+Mathematical Components library can be
+<a href="https://github.com/math-comp/math-comp/releases">downloaded from github</a>.
+<br/>
+Older versions of the library are available
+in the <a href="http://ssr.msr-inria.inria.fr/FTP/">historic archive</a>.
+</p>
+
+<h3>
+<a id="documentation" class="anchor" href="#documentation" aria-hidden="true"><span class="octicon octicon-link"></span></a>Documentation</h3>
+
+<p>
+Each source files features a documentation header which
+describes the concepts and notations introduced in that file.
+The <a href="htmldoc/index.html">coqdoc presentation</a> of the source files can be browsed online.
+</p>
+<p>
+The <a href="htmldoc/libgraph.html">library graph</a> can be browsed interactively.
+</p>
+<p>
+The Ssreflect language comes with a dedicated
+<a href="http://hal.inria.fr/inria-00258384/en">reference manual</a>.
+</p>
+<p>We also wrote a <a href="https://math-comp.github.io/mcb/">book</a> introducing the techniques for writing
+algorithms and proofs and describing the design ideas of the library.
+</p>
+<h3>
+<a id="contact" class="anchor" href="#contact" aria-hidden="true"><span class="octicon octicon-link"></span></a>Contact</h3>
+
+<p>
+Interested?
+<a href="mailto:sympa@inria.fr?subject=SUBSCRIBE%20ssreflect">Subscribe to the ssreflect mailing list</a>
+and let us know what you are using our libraries for, ask questions, etc.
+You can also browse the <a href="https://sympa.inria.fr/sympa/arc/ssreflect">archives of the list</a> or consult the
+<a href="https://sympa.inria.fr/sympa/info/ssreflect">general information page</a>.
+</p>
+<h3>
+<a id="authors-and-contributors" class="anchor" href="#authors-and-contributors" aria-hidden="true"><span class="octicon octicon-link"></span></a>Authors and Contributors</h3>
+
+<p> The Mathematical Components library and the Ssreflect proof language
+are developed by the
+<a href="http://www.msr-inria.fr/projects/mathematical-components-2/">Mathematical Components team</a>, at the
+<a href="http://www.msr-inria.fr/">Inria -- Microsoft Research Joint Centre</a>.
+</p>
+ <p style="text-align:center;">
+ <a href="http://www.msr-inria.fr/"><img src="./logo-MS-Research-Inria-Joint-Centre.png" alt="Microsoft Research - Inria Joint Centre" style="width:50%;margin-left:auto;margin-right:auto;"/></a>
+ </p>
+
+ </section>
+
+ <footer>
+ <p><small>Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
+ </footer>
+
+ </div>
+ <script src="javascripts/scale.fix.js"></script>
+
+ </body>
+</html>
diff --git a/docs/javascripts/scale.fix.js b/docs/javascripts/scale.fix.js
new file mode 100644
index 0000000..87a40ca
--- /dev/null
+++ b/docs/javascripts/scale.fix.js
@@ -0,0 +1,17 @@
+var metas = document.getElementsByTagName('meta');
+var i;
+if (navigator.userAgent.match(/iPhone/i)) {
+ for (i=0; i<metas.length; i++) {
+ if (metas[i].name == "viewport") {
+ metas[i].content = "width=device-width, minimum-scale=1.0, maximum-scale=1.0";
+ }
+ }
+ document.addEventListener("gesturestart", gestureStart, false);
+}
+function gestureStart() {
+ for (i=0; i<metas.length; i++) {
+ if (metas[i].name == "viewport") {
+ metas[i].content = "width=device-width, minimum-scale=0.25, maximum-scale=1.6";
+ }
+ }
+} \ No newline at end of file
diff --git a/docs/logo-MS-Research-Inria-Joint-Centre.png b/docs/logo-MS-Research-Inria-Joint-Centre.png
new file mode 100644
index 0000000..0e298ea
--- /dev/null
+++ b/docs/logo-MS-Research-Inria-Joint-Centre.png
Binary files differ
diff --git a/docs/oo.html b/docs/oo.html
new file mode 100644
index 0000000..6f90a40
--- /dev/null
+++ b/docs/oo.html
@@ -0,0 +1,88 @@
+<!doctype html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta http-equiv="X-UA-Compatible" content="chrome=1">
+ <title>A Formal Proof of The Odd Order Theorem</title>
+
+ <link rel="stylesheet" href="stylesheets/styles.css">
+ <link rel="stylesheet" href="stylesheets/github-light.css">
+ <meta name="viewport" content="width=device-width">
+ <!--[if lt IE 9]>
+ <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
+ <![endif]-->
+ </head>
+ <body>
+ <div class="wrapper">
+ <header>
+ <h1>A Formal Proof of The Odd Order Theorem</h1>
+ <p> A formalized and machine-checked proof,
+ using the Coq proof assistant</p>
+
+ <p class="view"><a href="https://github.com/math-comp/math-comp">View the Sources on GitHub <small>math-comp/math-comp</small></a></p>
+
+ </header>
+
+ <section>
+ <h3>
+<a id="about" class="anchor" href="#about" aria-hidden="true"><span class="octicon octicon-link"></span></a>About</h3>
+
+
+ <p> Blah blah...
+ </p>
+ <p> TODO : a Q&A page
+
+</p>
+
+<h3>
+<a id="borwsing" class="anchor" href="#releases"
+ aria-hidden="true"><span class="octicon
+ octicon-link"></span></a>Browsing
+ the files</h3>
+
+<p> TODO
+</p>
+
+<h3>
+<a id="releases" class="anchor" href="#releases"
+ aria-hidden="true"><span class="octicon
+ octicon-link"></span></a>Getting
+ the libraries</h3>
+
+<p>
+TODO
+</p>
+
+<h3>
+<a id="contact" class="anchor" href="#contact" aria-hidden="true"><span class="octicon octicon-link"></span></a>Contact</h3>
+
+<p>
+Any question?
+<a href="mailto:sympa@inria.fr?subject=SUBSCRIBE%20ssreflect">Subscribe to the ssreflect mailing list</a>
+and let us know what you are using our libraries for, ask questions, etc.
+You can also browse the <a href="https://sympa.inria.fr/sympa/arc/ssreflect">archives of the list</a> or consult the
+<a href="https://sympa.inria.fr/sympa/info/ssreflect">general information page</a>.
+</p>
+<h3>
+<a id="authors-and-contributors" class="anchor" href="#authors-and-contributors" aria-hidden="true"><span class="octicon octicon-link"></span></a>Authors and Contributors</h3>
+
+<p> The Odd Order library, the Mathematical Components library and the
+ Ssreflect proof language are developed by the
+<a href="http://www.msr-inria.fr/projects/mathematical-components-2/">Mathematical Components team</a>, at the
+<a href="http://www.msr-inria.fr/">Inria -- Microsoft Research Joint Centre</a>.
+</p>
+ <p style="text-align:center;">
+ <a href="http://www.msr-inria.fr/"><img src="./logo-MS-Research-Inria-Joint-Centre.png" alt="Microsoft Research - Inria Joint Centre" style="width:50%;margin-left:auto;margin-right:auto;"/></a>
+ </p>
+
+ </section>
+
+ <footer>
+ <p><small>Theme by <a href="https://github.com/orderedlist">orderedlist</a></small></p>
+ </footer>
+
+ </div>
+ <script src="javascripts/scale.fix.js"></script>
+
+ </body>
+</html>
diff --git a/docs/params.json b/docs/params.json
new file mode 100644
index 0000000..47288a6
--- /dev/null
+++ b/docs/params.json
@@ -0,0 +1 @@
+{"name":"Math-comp","tagline":"Mathematical Components","body":"### Welcome to GitHub Pages.\r\nThis automatic page generator is the easiest way to create beautiful pages for all of your projects. Author your page content here [using GitHub Flavored Markdown](https://guides.github.com/features/mastering-markdown/), select a template crafted by a designer, and publish. After your page is generated, you can check out the new `gh-pages` branch locally. If you’re using GitHub Desktop, simply sync your repository and you’ll see the new branch.\r\n\r\n### Designer Templates\r\nWe’ve crafted some handsome templates for you to use. Go ahead and click 'Continue to layouts' to browse through them. You can easily go back to edit your page before publishing. After publishing your page, you can revisit the page generator and switch to another theme. Your Page content will be preserved.\r\n\r\n### Creating pages manually\r\nIf you prefer to not use the automatic generator, push a branch named `gh-pages` to your repository to create a page manually. In addition to supporting regular HTML content, GitHub Pages support Jekyll, a simple, blog aware static site generator. Jekyll makes it easy to create site-wide headers and footers without having to copy them across every page. It also offers intelligent blog support and other advanced templating features.\r\n\r\n### Authors and Contributors\r\nYou can @mention a GitHub username to generate a link to their profile. The resulting `<a>` element will link to the contributor’s GitHub Profile. For example: In 2007, Chris Wanstrath (@defunkt), PJ Hyett (@pjhyett), and Tom Preston-Werner (@mojombo) founded GitHub.\r\n\r\n### Support or Contact\r\nHaving trouble with Pages? Check out our [documentation](https://help.github.com/pages) or [contact support](https://github.com/contact) and we’ll help you sort it out.\r\n","google":"","note":"Don't delete this file! It's used internally to help with page regeneration."} \ No newline at end of file
diff --git a/docs/stylesheets/github-light.css b/docs/stylesheets/github-light.css
new file mode 100644
index 0000000..872a6f4
--- /dev/null
+++ b/docs/stylesheets/github-light.css
@@ -0,0 +1,116 @@
+/*
+ Copyright 2014 GitHub Inc.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+.pl-c /* comment */ {
+ color: #969896;
+}
+
+.pl-c1 /* constant, markup.raw, meta.diff.header, meta.module-reference, meta.property-name, support, support.constant, support.variable, variable.other.constant */,
+.pl-s .pl-v /* string variable */ {
+ color: #0086b3;
+}
+
+.pl-e /* entity */,
+.pl-en /* entity.name */ {
+ color: #795da3;
+}
+
+.pl-s .pl-s1 /* string source */,
+.pl-smi /* storage.modifier.import, storage.modifier.package, storage.type.java, variable.other, variable.parameter.function */ {
+ color: #333;
+}
+
+.pl-ent /* entity.name.tag */ {
+ color: #63a35c;
+}
+
+.pl-k /* keyword, storage, storage.type */ {
+ color: #a71d5d;
+}
+
+.pl-pds /* punctuation.definition.string, string.regexp.character-class */,
+.pl-s /* string */,
+.pl-s .pl-pse .pl-s1 /* string punctuation.section.embedded source */,
+.pl-sr /* string.regexp */,
+.pl-sr .pl-cce /* string.regexp constant.character.escape */,
+.pl-sr .pl-sra /* string.regexp string.regexp.arbitrary-repitition */,
+.pl-sr .pl-sre /* string.regexp source.ruby.embedded */ {
+ color: #183691;
+}
+
+.pl-v /* variable */ {
+ color: #ed6a43;
+}
+
+.pl-id /* invalid.deprecated */ {
+ color: #b52a1d;
+}
+
+.pl-ii /* invalid.illegal */ {
+ background-color: #b52a1d;
+ color: #f8f8f8;
+}
+
+.pl-sr .pl-cce /* string.regexp constant.character.escape */ {
+ color: #63a35c;
+ font-weight: bold;
+}
+
+.pl-ml /* markup.list */ {
+ color: #693a17;
+}
+
+.pl-mh /* markup.heading */,
+.pl-mh .pl-en /* markup.heading entity.name */,
+.pl-ms /* meta.separator */ {
+ color: #1d3e81;
+ font-weight: bold;
+}
+
+.pl-mq /* markup.quote */ {
+ color: #008080;
+}
+
+.pl-mi /* markup.italic */ {
+ color: #333;
+ font-style: italic;
+}
+
+.pl-mb /* markup.bold */ {
+ color: #333;
+ font-weight: bold;
+}
+
+.pl-md /* markup.deleted, meta.diff.header.from-file */ {
+ background-color: #ffecec;
+ color: #bd2c00;
+}
+
+.pl-mi1 /* markup.inserted, meta.diff.header.to-file */ {
+ background-color: #eaffea;
+ color: #55a532;
+}
+
+.pl-mdr /* meta.diff.range */ {
+ color: #795da3;
+ font-weight: bold;
+}
+
+.pl-mo /* meta.output */ {
+ color: #1d3e81;
+}
+
diff --git a/docs/stylesheets/styles.css b/docs/stylesheets/styles.css
new file mode 100644
index 0000000..811e3d2
--- /dev/null
+++ b/docs/stylesheets/styles.css
@@ -0,0 +1,324 @@
+@font-face {
+ font-family: 'Noto Sans';
+ font-weight: 400;
+ font-style: normal;
+ src: url('../fonts/Noto-Sans-regular/Noto-Sans-regular.eot');
+ src: url('../fonts/Noto-Sans-regular/Noto-Sans-regular.eot?#iefix') format('embedded-opentype'),
+ local('Noto Sans'),
+ local('Noto-Sans-regular'),
+ url('../fonts/Noto-Sans-regular/Noto-Sans-regular.woff2') format('woff2'),
+ url('../fonts/Noto-Sans-regular/Noto-Sans-regular.woff') format('woff'),
+ url('../fonts/Noto-Sans-regular/Noto-Sans-regular.ttf') format('truetype'),
+ url('../fonts/Noto-Sans-regular/Noto-Sans-regular.svg#NotoSans') format('svg');
+}
+
+@font-face {
+ font-family: 'Noto Sans';
+ font-weight: 700;
+ font-style: normal;
+ src: url('../fonts/Noto-Sans-700/Noto-Sans-700.eot');
+ src: url('../fonts/Noto-Sans-700/Noto-Sans-700.eot?#iefix') format('embedded-opentype'),
+ local('Noto Sans Bold'),
+ local('Noto-Sans-700'),
+ url('../fonts/Noto-Sans-700/Noto-Sans-700.woff2') format('woff2'),
+ url('../fonts/Noto-Sans-700/Noto-Sans-700.woff') format('woff'),
+ url('../fonts/Noto-Sans-700/Noto-Sans-700.ttf') format('truetype'),
+ url('../fonts/Noto-Sans-700/Noto-Sans-700.svg#NotoSans') format('svg');
+}
+
+@font-face {
+ font-family: 'Noto Sans';
+ font-weight: 400;
+ font-style: italic;
+ src: url('../fonts/Noto-Sans-italic/Noto-Sans-italic.eot');
+ src: url('../fonts/Noto-Sans-italic/Noto-Sans-italic.eot?#iefix') format('embedded-opentype'),
+ local('Noto Sans Italic'),
+ local('Noto-Sans-italic'),
+ url('../fonts/Noto-Sans-italic/Noto-Sans-italic.woff2') format('woff2'),
+ url('../fonts/Noto-Sans-italic/Noto-Sans-italic.woff') format('woff'),
+ url('../fonts/Noto-Sans-italic/Noto-Sans-italic.ttf') format('truetype'),
+ url('../fonts/Noto-Sans-italic/Noto-Sans-italic.svg#NotoSans') format('svg');
+}
+
+@font-face {
+ font-family: 'Noto Sans';
+ font-weight: 700;
+ font-style: italic;
+ src: url('../fonts/Noto-Sans-700italic/Noto-Sans-700italic.eot');
+ src: url('../fonts/Noto-Sans-700italic/Noto-Sans-700italic.eot?#iefix') format('embedded-opentype'),
+ local('Noto Sans Bold Italic'),
+ local('Noto-Sans-700italic'),
+ url('../fonts/Noto-Sans-700italic/Noto-Sans-700italic.woff2') format('woff2'),
+ url('../fonts/Noto-Sans-700italic/Noto-Sans-700italic.woff') format('woff'),
+ url('../fonts/Noto-Sans-700italic/Noto-Sans-700italic.ttf') format('truetype'),
+ url('../fonts/Noto-Sans-700italic/Noto-Sans-700italic.svg#NotoSans') format('svg');
+}
+
+body {
+ background-color: #fff;
+ padding:50px;
+ font: 16px/1.5 "Noto Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ color:#727272;
+ font-weight:400;
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color:#222;
+ margin:0 0 20px;
+}
+
+p, ul, ol, table, pre, dl {
+ margin:0 0 20px;
+}
+
+h1, h2, h3 {
+ line-height:1.1;
+}
+
+h1 {
+ font-size:28px;
+}
+
+h2 {
+ color:#393939;
+}
+
+h3, h4, h5, h6 {
+ color:#494949;
+}
+
+a {
+ color:#39c;
+ text-decoration:none;
+}
+
+a:hover {
+ color:#069;
+}
+
+a small {
+ font-size:11px;
+ color:#777;
+ margin-top:-0.3em;
+ display:block;
+}
+
+a:hover small {
+ color:#777;
+}
+
+.wrapper {
+ width:860px;
+ margin:0 auto;
+}
+
+blockquote {
+ border-left:1px solid #e5e5e5;
+ margin:0;
+ padding:0 0 0 20px;
+ font-style:italic;
+}
+
+code, pre {
+ font-family:Monaco, Bitstream Vera Sans Mono, Lucida Console, Terminal, Consolas, Liberation Mono, DejaVu Sans Mono, Courier New, monospace;
+ color:#333;
+ font-size:12px;
+}
+
+pre {
+ padding:8px 15px;
+ background: #f8f8f8;
+ border-radius:5px;
+ border:1px solid #e5e5e5;
+ overflow-x: auto;
+}
+
+table {
+ width:100%;
+ border-collapse:collapse;
+}
+
+th, td {
+ text-align:left;
+ padding:5px 10px;
+ border-bottom:1px solid #e5e5e5;
+}
+
+dt {
+ color:#444;
+ font-weight:700;
+}
+
+th {
+ color:#444;
+}
+
+img {
+ max-width:100%;
+}
+
+header {
+ width:270px;
+ float:left;
+ position:fixed;
+ -webkit-font-smoothing:subpixel-antialiased;
+}
+
+header ul {
+ list-style:none;
+ height:40px;
+ padding:0;
+ background: #f4f4f4;
+ border-radius:5px;
+ border:1px solid #e0e0e0;
+ width:270px;
+}
+
+header li {
+ width:89px;
+ float:left;
+ border-right:1px solid #e0e0e0;
+ height:40px;
+}
+
+header li:first-child a {
+ border-radius:5px 0 0 5px;
+}
+
+header li:last-child a {
+ border-radius:0 5px 5px 0;
+}
+
+header ul a {
+ line-height:1;
+ font-size:11px;
+ color:#999;
+ display:block;
+ text-align:center;
+ padding-top:6px;
+ height:34px;
+}
+
+header ul a:hover {
+ color:#999;
+}
+
+header ul a:active {
+ background-color:#f0f0f0;
+}
+
+strong {
+ color:#222;
+ font-weight:700;
+}
+
+header ul li + li + li {
+ border-right:none;
+ width:89px;
+}
+
+header ul a strong {
+ font-size:14px;
+ display:block;
+ color:#222;
+}
+
+section {
+ width:500px;
+ float:right;
+ padding-bottom:50px;
+}
+
+small {
+ font-size:11px;
+}
+
+hr {
+ border:0;
+ background:#e5e5e5;
+ height:1px;
+ margin:0 0 20px;
+}
+
+footer {
+ width:270px;
+ float:left;
+ position:fixed;
+ bottom:50px;
+ -webkit-font-smoothing:subpixel-antialiased;
+}
+
+@media print, screen and (max-width: 960px) {
+
+ div.wrapper {
+ width:auto;
+ margin:0;
+ }
+
+ header, section, footer {
+ float:none;
+ position:static;
+ width:auto;
+ }
+
+ header {
+ padding-right:320px;
+ }
+
+ section {
+ border:1px solid #e5e5e5;
+ border-width:1px 0;
+ padding:20px 0;
+ margin:0 0 20px;
+ }
+
+ header a small {
+ display:inline;
+ }
+
+ header ul {
+ position:absolute;
+ right:50px;
+ top:52px;
+ }
+}
+
+@media print, screen and (max-width: 720px) {
+ body {
+ word-wrap:break-word;
+ }
+
+ header {
+ padding:0;
+ }
+
+ header ul, header p.view {
+ position:static;
+ }
+
+ pre, code {
+ word-wrap:normal;
+ }
+}
+
+@media print, screen and (max-width: 480px) {
+ body {
+ padding:15px;
+ }
+
+ header ul {
+ width:99%;
+ }
+
+ header li, header ul li + li + li {
+ width:33%;
+ }
+}
+
+@media print {
+ body {
+ padding:0.4in;
+ font-size:12pt;
+ color:#444;
+ }
+}