diff options
| author | Enrico Tassi | 2015-12-11 16:54:22 +0100 |
|---|---|---|
| committer | Enrico Tassi | 2015-12-11 16:54:22 +0100 |
| commit | 353eb61703f64f6d0f520720fdb0d08a1cf727c3 (patch) | |
| tree | 565da23979fed4060320b8291108a7148ac37b46 /htmldoc | |
| parent | f943e8d62fe88b0e387f94f23e1990b996d9f8a3 (diff) | |
coqdoc + interactive graph browsing
It is still rough, but better than nothing.
Diffstat (limited to 'htmldoc')
| -rw-r--r-- | htmldoc/Makefile | 32 | ||||
| -rwxr-xr-x | htmldoc/buildlibgraph | 162 | ||||
| -rw-r--r-- | htmldoc/js/cytoscape-dagre.js | 192 | ||||
| -rw-r--r-- | htmldoc/js/cytoscape-panzoom.js | 550 | ||||
| -rw-r--r-- | htmldoc/js/cytoscape-qtip.js | 362 | ||||
| -rw-r--r-- | htmldoc/js/cytoscape.js | 24515 | ||||
| -rw-r--r-- | htmldoc/js/cytoscape.js-panzoom.css | 203 | ||||
| -rw-r--r-- | htmldoc/js/cytoscape.min.js | 26 | ||||
| -rw-r--r-- | htmldoc/js/dagre.js | 16396 | ||||
| -rw-r--r-- | htmldoc/js/dagre.min.js | 6 | ||||
| -rw-r--r-- | htmldoc/js/jquery-2.0.3.js | 8829 | ||||
| -rw-r--r-- | htmldoc/js/jquery-2.0.3.min.js | 6 | ||||
| -rw-r--r-- | htmldoc/js/jquery.qtip.css | 623 | ||||
| -rw-r--r-- | htmldoc/js/jquery.qtip.js | 3440 | ||||
| -rw-r--r-- | htmldoc/js/jquery.qtip.min.css | 2 | ||||
| -rw-r--r-- | htmldoc/js/jquery.qtip.min.js | 4 | ||||
| -rw-r--r-- | htmldoc/libgraph.html | 244 |
17 files changed, 55592 insertions, 0 deletions
diff --git a/htmldoc/Makefile b/htmldoc/Makefile new file mode 100644 index 0000000..5386dca --- /dev/null +++ b/htmldoc/Makefile @@ -0,0 +1,32 @@ +H=@ + +ifeq "$(COQBIN)" "" +COQBIN=$(dir $(shell which coqtop))/ +endif + +SRC=$(shell cd ../mathcomp; ls */*.v | grep -v ssrtest/ | 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/htmldoc/buildlibgraph b/htmldoc/buildlibgraph new file mode 100755 index 0000000..8544f1f --- /dev/null +++ b/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: | grep -v ssrtest > 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/htmldoc/js/cytoscape-dagre.js b/htmldoc/js/cytoscape-dagre.js new file mode 100644 index 0000000..c93288b --- /dev/null +++ b/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/htmldoc/js/cytoscape-panzoom.js b/htmldoc/js/cytoscape-panzoom.js new file mode 100644 index 0000000..4680775 --- /dev/null +++ b/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/htmldoc/js/cytoscape-qtip.js b/htmldoc/js/cytoscape-qtip.js new file mode 100644 index 0000000..43ad8b9 --- /dev/null +++ b/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/htmldoc/js/cytoscape.js b/htmldoc/js/cytoscape.js new file mode 100644 index 0000000..601e6db --- /dev/null +++ b/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/htmldoc/js/cytoscape.js-panzoom.css b/htmldoc/js/cytoscape.js-panzoom.css new file mode 100644 index 0000000..46d9a36 --- /dev/null +++ b/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/htmldoc/js/cytoscape.min.js b/htmldoc/js/cytoscape.min.js new file mode 100644 index 0000000..a498936 --- /dev/null +++ b/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/htmldoc/js/dagre.js b/htmldoc/js/dagre.js new file mode 100644 index 0000000..830997b --- /dev/null +++ b/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 = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '`': '`' + }; + + /** Used to map HTML entities to characters. */ + var htmlUnescapes = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'", + '`': '`' + }; + + /** 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, & 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, & 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><script></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 + * `&`, `<`, `>`, `"`, `'`, and ``` 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, & 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/htmldoc/js/dagre.min.js b/htmldoc/js/dagre.min.js new file mode 100644 index 0000000..b7a9bbc --- /dev/null +++ b/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={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};var htmlUnescapes={"&":"&","<":"<",">":">",""":'"',"'":"'","`":"`"};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&¤t===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/htmldoc/js/jquery-2.0.3.js b/htmldoc/js/jquery-2.0.3.js new file mode 100644 index 0000000..ebc6c18 --- /dev/null +++ b/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/htmldoc/js/jquery-2.0.3.min.js b/htmldoc/js/jquery-2.0.3.min.js new file mode 100644 index 0000000..2be209d --- /dev/null +++ b/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/htmldoc/js/jquery.qtip.css b/htmldoc/js/jquery.qtip.css new file mode 100644 index 0000000..c2dcb30 --- /dev/null +++ b/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/htmldoc/js/jquery.qtip.js b/htmldoc/js/jquery.qtip.js new file mode 100644 index 0000000..52443c0 --- /dev/null +++ b/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': '×' + }) + ); + } + + // 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/htmldoc/js/jquery.qtip.min.css b/htmldoc/js/jquery.qtip.min.css new file mode 100644 index 0000000..fc172a4 --- /dev/null +++ b/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/htmldoc/js/jquery.qtip.min.js b/htmldoc/js/jquery.qtip.min.js new file mode 100644 index 0000000..3ae7bbe --- /dev/null +++ b/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:"×"})),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/htmldoc/libgraph.html b/htmldoc/libgraph.html new file mode 100644 index 0000000..909e13c --- /dev/null +++ b/htmldoc/libgraph.html @@ -0,0 +1,244 @@ +<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, + } + }); // 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> |
