diff --git a/.travis.yml b/.travis.yml index de764f665..a7c1b4e8c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,15 @@ before_install: - "npm install -g grunt-cli" - "export DISPLAY=:99.0" - "sh -e /etc/init.d/xvfb start" +# Meteor Tinytest support + - "curl https://install.meteor.com | /bin/sh" + - export PATH="$HOME/.meteor:$PATH" + - "npm install -g spacejam" install: - "npm install" - "bower install" + +script: + - "npm test" + - "spacejam test-packages ./" + diff --git a/GruntFile.js b/GruntFile.js index e14209864..e604673e5 100644 --- a/GruntFile.js +++ b/GruntFile.js @@ -1,4 +1,5 @@ module.exports = function(grunt) { + var _pkg = grunt.file.readJSON('package.json'); //Project configuration. grunt.initConfig({ diff --git a/README.md b/README.md index a49d35775..ec1285afd 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,8 @@ Inspired by the work of Mike Bostock's [Towards Reusable Charts](http://bost.ocks.org/mike/chart/), and supported by a combined effort of [Novus](http://www.novus.com) and the NVD3 community. -[View Examples](http://nvd3-community.github.io/nvd3/) | [NEW Documentation!](http://nvd3-community.github.io/nvd3/examples/documentation.html) | Development build status: [![Build Status](https://travis-ci.org/novus/nvd3.svg?branch=development)](https://travis-ci.org/novus/nvd3) +[View Examples](http://nvd3-community.github.io/nvd3/) | [NEW Documentation!](http://nvd3-community.github.io/nvd3/examples/documentation.html) | Development build status: [![Build Status](https://travis-ci.org/novus/nvd3.svg?branch=master)](https://travis-ci.org/novus/nvd3) + ## Usage Simply add the `nv.d3` assets to your project and include them in your HTML. @@ -16,7 +17,12 @@ Simply add the `nv.d3` assets to your project and include them in your HTML. * Prefer minified assets (`.min`) for production. ### Dependencies -NVD3 depends on [d3.js](http://d3js.org/), and is tested on version 3.3.13. There is currently [a minor bug](https://github.com/novus/nvd3/issues/760) associated with version 3.5. + +NVD3 should work with the latest [d3.js](http://d3js.org/) version 3.5.3 and later. + +**Minimum D3 version required: 3.4.4** + +Along with `pieChart` options `padAngle` and `cornerRadius`, the interactive guideline tooltip now requires these later versions of D3 (3.4.4+, specifically, to get interactive tooltips). The interactive guide lines rely on the more recent `d3.bisector()` method which treats accessors taking two parameters (the second being the element index) as comparators (see [d3.bisector()](https://github.com/mbostock/d3/wiki/Arrays#d3_bisector)). ## Supported Browsers @@ -30,6 +36,18 @@ NVD3 runs best on WebKit based browsers. ## Changelog +**1.8.1** Changes: + +* Tooltips were refactored - If you have customized your tooltips, note that you may need to adjust your custom functions as the data passed has changed format. See the new [tooltip options](https://nvd3-community.github.io/nvd3/examples/documentation.html#tooltip) for more details. +* Added boxplot charts | [example](https://nvd3-community.github.io/nvd3/examples/boxPlot.html) +* Added candlestick charts | [example](https://nvd3-community.github.io/nvd3/examples/candlestickChart.html) +* Added extra donut chart abilities | [examples](https://nvd3-community.github.io/nvd3/examples/monitoringChart.html) +* Added sunburst Charts | [example](https://nvd3-community.github.io/nvd3/examples/sunburst.html) +* Time Series | [example](https://nvd3-community.github.io/nvd3/examples/TimeSeries.html) +* Another legend format available | [example](https://nvd3-community.github.io/nvd3/examples/stackedAreaChart.html) +* Lots of bug fixes (see closed issues) +* (for all examples, see [here](https://nvd3-community.github.io/nvd3/)) + **1.7.1** Changes: * Fixed axis.staggerLabels bug. @@ -69,13 +87,19 @@ from the issues/pulls from the original project. # Bugs -Found a bug? Check out the `development` branch and make sure it's not already fixed first! If you don't see a related fix, please [open an issue](https://github.com/novus/nvd3/issues). +Found a bug? Check out the latest from the `master` branch and make sure it's not already fixed first! If you don't see a related fix, please [open an issue](https://github.com/novus/nvd3/issues). + +--- + +# Optional dependencies + +Including [Fastdom](https://github.com/wilsonpage/fastdom) in your project can greatly increase the performance of the line chart (particularly in Firefox and Internet Explorer) by batching DOM read and write operations to avoid [layout thrashing](http://wilsonpage.co.uk/preventing-layout-thrashing/). NVD3 will take advantage of Fastdom if present. --- # Contributing -If one of [the existing models](https://github.com/nvd3-community/nvd3/tree/development/src/models) +If one of [the existing models](https://github.com/novus/nvd3/tree/master/src/models) doesn't meet your needs, fork the project, implement the model and an example using it, send us a pull request, for consideration for inclusion in the project. @@ -83,7 +107,7 @@ If you'd like to contribute consistently, show me what you've got with some good ### A few rules for pull requests -1. Please commit to the `development` branch +1. Please commit to the `master` branch 2. Do NOT check in anything under the `build` directory, it clutters up the commit and just gets overwritten later. 3. All new features must come with unit test coverage 4. Bug fixes should come with unit tests that prove their fix @@ -97,23 +121,27 @@ only include the source files you changed! ### Tips for Testing * Unit tests were written in Karma and Mocha. Follow instructions in **Building Latest** to get npm packages setup. This may not work on Windows machines. +* Run `bower install` to get bower dependencies. * Run `grunt` to start the unit tests. * Also visually inspect the HTML pages in the **examples/ and test/ folders**. Make sure there are no glaring errors. * Novus now uses Travis CI for continuous integration. Visit [our travis build page](https://travis-ci.org/novus/nvd3/) to see the latest status. +#### Meteor Tinytests +* Any Meteor-specific features can be tested from the command line using `tinytest` and [Spacejam](https://www.npmjs.com/package/spacejam) +* `spacejam` can be installed by running `npm install -g spacejam`. +* Tinytests can then be executed by running `spacejam test-packages ./` from this project's root. + --- ## Building latest -1. First clone the repository and checkout the "development" branch -2. make sure nodejs is installed via your system's package manager. -3. Install grunt-cli and bower: npm install -g bower grunt-cli - -> have node download it's required modules with: npm install +1. First clone the repository and checkout the `master` branch +2. make sure `nodejs` is installed via your system's package manager. +3. Install `grunt`, `grunt-cli`, and `bower`: `npm install -g grunt grunt-cli bower` -> install grunt globally: sudo npm install -g grunt +> have node download nvd3's required modules with: `npm install` -> build with: grunt production +> build with: `grunt production` You should now have a `build` directory with the js and css files within. diff --git a/bower.json b/bower.json index d846f8569..39b276773 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,5 @@ { "name": "nvd3", - "version": "1.7.1", "homepage": "http://www.nvd3.org", "authors": [ "Bob Monteverde", @@ -20,9 +19,9 @@ "svg", "charts" ], - "license": "Apache License, v2.0", + "license": "Apache-2.0", "dependencies": { - "d3": "~3.3.13" + "d3": "^3.4.4" }, "ignore": [ "**/.*", @@ -37,8 +36,5 @@ "*.xml", "*.json", "*.md" - ], - "devDependencies": { - "d3": "~3.3.13" - } + ] } diff --git a/build/nv.d3.css b/build/nv.d3.css index 26453e88f..a1f8ef877 100644 --- a/build/nv.d3.css +++ b/build/nv.d3.css @@ -1,645 +1,644 @@ -/******************** - * SVG CSS - */ - - -svg { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - /* Trying to get SVG to act like a greedy block in all browsers */ - display: block; - width:100%; - height:100%; -} - -/******************** - Default CSS for an svg element nvd3 used -*/ -svg.nvd3-svg { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -ms-user-select: none; - -moz-user-select: none; - user-select: none; - display: block; -} - -/******************** - Box shadow and border radius styling -*/ -.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip { - -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); - -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); - box-shadow: 0 5px 10px rgba(0,0,0,.2); - - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} - -/******************** - * TOOLTIP CSS - */ - -.nvtooltip { - position: absolute; - background-color: rgba(255,255,255,1.0); - padding: 1px; - border: 1px solid rgba(0,0,0,.2); - z-index: 10000; - - font-family: Arial; - font-size: 13px; - text-align: left; - pointer-events: none; - - white-space: nowrap; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -/*Give tooltips that old fade in transition by - putting a "with-transitions" class on the container div. -*/ -.nvtooltip.with-transitions, .with-transitions .nvtooltip { - transition: opacity 50ms linear; - -moz-transition: opacity 50ms linear; - -webkit-transition: opacity 50ms linear; - - transition-delay: 200ms; - -moz-transition-delay: 200ms; - -webkit-transition-delay: 200ms; -} - -.nvtooltip.x-nvtooltip, -.nvtooltip.y-nvtooltip { - padding: 8px; -} - -.nvtooltip h3 { - margin: 0; - padding: 4px 14px; - line-height: 18px; - font-weight: normal; - background-color: rgba(247,247,247,0.75); - text-align: center; - - border-bottom: 1px solid #ebebeb; - - -webkit-border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - border-radius: 1px 5px 0 0; -} - -.nvtooltip p { - margin: 0; - padding: 5px 14px; - text-align: center; -} - -.nvtooltip span { - display: inline-block; - margin: 2px 0; -} - -.nvtooltip table { - margin: 6px; - border-spacing:0; -} - - -.nvtooltip table td { - padding: 2px 9px 2px 0; - vertical-align: middle; -} - -.nvtooltip table td.key { - font-weight:normal; -} -.nvtooltip table td.value { - text-align: right; - font-weight: bold; -} - -.nvtooltip table tr.highlight td { - padding: 1px 9px 1px 0; - border-bottom-style: solid; - border-bottom-width: 1px; - border-top-style: solid; - border-top-width: 1px; -} - -.nvtooltip table td.legend-color-guide div { - width: 8px; - height: 8px; - vertical-align: middle; -} - -.nvtooltip .footer { - padding: 3px; - text-align: center; -} - -.nvtooltip-pending-removal { - position: absolute; - pointer-events: none; -} - -.nvd3 text { - font: normal 12px Arial; -} - -.nvd3 .title { - font: bold 14px Arial; -} - -.nvd3 .nv-background { - fill: white; - fill-opacity: 0; -} - -.nvd3.nv-noData { - font-size: 18px; - font-weight: bold; -} - - -/********** -* Brush -*/ - -.nv-brush .extent { - fill-opacity: .125; - shape-rendering: crispEdges; -} - - -/********** -* Legend -*/ - -.nvd3 .nv-legend .nv-series { - cursor: pointer; -} - -.nvd3 .nv-legend .nv-disabled circle { - fill-opacity: 0; -} - - -/********** -* Axes -*/ - -.axis { - opacity: 1; -} - -.axis.nv-disabled { - opacity: 0; -} - -.nvd3 .nv-axis { - pointer-events:none; -} - -.nvd3 .nv-axis path { - fill: none; - stroke: #000; - stroke-opacity: .75; - shape-rendering: crispEdges; -} - -.nvd3 .nv-axis path.domain { - stroke-opacity: .75; -} - -.nvd3 .nv-axis.nv-x path.domain { - stroke-opacity: 0; -} - -.nvd3 .nv-axis line { - fill: none; - stroke: #e5e5e5; - shape-rendering: crispEdges; -} - -.nvd3 .nv-axis .zero line, -/*this selector may not be necessary*/ .nvd3 .nv-axis line.zero { - stroke-opacity: .75; -} - -.nvd3 .nv-axis .nv-axisMaxMin text { - font-weight: bold; -} - -.nvd3 .x .nv-axis .nv-axisMaxMin text, -.nvd3 .x2 .nv-axis .nv-axisMaxMin text, -.nvd3 .x3 .nv-axis .nv-axisMaxMin text { - text-anchor: middle -} - - -/********** -* Brush -*/ - -.nv-brush .resize path { - fill: #eee; - stroke: #666; -} - - -/********** -* Bars -*/ - -.nvd3 .nv-bars .negative rect { - zfill: brown; -} - -.nvd3 .nv-bars rect { - zfill: steelblue; - fill-opacity: .75; - - transition: fill-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear; -} - -.nvd3 .nv-bars rect.hover { - fill-opacity: 1; -} - -.nvd3 .nv-bars .hover rect { - fill: lightblue; -} - -.nvd3 .nv-bars text { - fill: rgba(0,0,0,0); -} - -.nvd3 .nv-bars .hover text { - fill: rgba(0,0,0,1); -} - - -/********** -* Bars -*/ - -.nvd3 .nv-multibar .nv-groups rect, -.nvd3 .nv-multibarHorizontal .nv-groups rect, -.nvd3 .nv-discretebar .nv-groups rect { - stroke-opacity: 0; - - transition: fill-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear; -} - -.nvd3 .nv-multibar .nv-groups rect:hover, -.nvd3 .nv-multibarHorizontal .nv-groups rect:hover, -.nvd3 .nv-discretebar .nv-groups rect:hover { - fill-opacity: 1; -} - -.nvd3 .nv-discretebar .nv-groups text, -.nvd3 .nv-multibarHorizontal .nv-groups text { - font-weight: bold; - fill: rgba(0,0,0,1); - stroke: rgba(0,0,0,0); -} - -/*********** -* Pie Chart -*/ - -.nvd3.nv-pie path { - stroke-opacity: 0; - transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -} - -.nvd3.nv-pie .nv-pie-title { - font-size: 24px; - fill: rgba(19, 196, 249, 0.59); -} - -.nvd3.nv-pie .nv-slice text { - stroke: #000; - stroke-width: 0; -} - -.nvd3.nv-pie path { - stroke: #fff; - stroke-width: 1px; - stroke-opacity: 1; -} - -.nvd3.nv-pie .hover path { - fill-opacity: .7; -} -.nvd3.nv-pie .nv-label { - pointer-events: none; -} -.nvd3.nv-pie .nv-label rect { - fill-opacity: 0; - stroke-opacity: 0; -} - -/********** -* Lines -*/ - -.nvd3 .nv-groups path.nv-line { - fill: none; - stroke-width: 1.5px; -} - -.nvd3 .nv-groups path.nv-line.nv-thin-line { - stroke-width: 1px; -} - - -.nvd3 .nv-groups path.nv-area { - stroke: none; -} - -.nvd3 .nv-line.hover path { - stroke-width: 6px; -} - -.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { - fill-opacity: 0; - stroke-opacity: 0; -} - -.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { - fill-opacity: .5 !important; - stroke-opacity: .5 !important; -} - - -.with-transitions .nvd3 .nv-groups .nv-point { - transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -} - -.nvd3.nv-scatter .nv-groups .nv-point.hover, -.nvd3 .nv-groups .nv-point.hover { - stroke-width: 7px; - fill-opacity: .95 !important; - stroke-opacity: .95 !important; -} - - -.nvd3 .nv-point-paths path { - stroke: #aaa; - stroke-opacity: 0; - fill: #eee; - fill-opacity: 0; -} - - - -.nvd3 .nv-indexLine { - cursor: ew-resize; -} - - -/********** -* Distribution -*/ - -.nvd3 .nv-distribution { - pointer-events: none; -} - - -/********** -* Scatter -*/ - -.nvd3 .nv-groups .nv-point.hover { - stroke-width: 20px; - stroke-opacity: .5; -} - -.nvd3 .nv-scatter .nv-point.hover { +/* nvd3 version 1.8.1-dev (https://github.com/novus/nvd3) 2015-09-10 */ +.nvd3 .nv-axis { + pointer-events:none; + opacity: 1; +} + +.nvd3 .nv-axis path { + fill: none; + stroke: #000; + stroke-opacity: .75; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis path.domain { + stroke-opacity: .75; +} + +.nvd3 .nv-axis.nv-x path.domain { + stroke-opacity: 0; +} + +.nvd3 .nv-axis line { + fill: none; + stroke: #e5e5e5; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis .zero line, + /*this selector may not be necessary*/ .nvd3 .nv-axis line.zero { + stroke-opacity: .75; +} + +.nvd3 .nv-axis .nv-axisMaxMin text { + font-weight: bold; +} + +.nvd3 .x .nv-axis .nv-axisMaxMin text, +.nvd3 .x2 .nv-axis .nv-axisMaxMin text, +.nvd3 .x3 .nv-axis .nv-axisMaxMin text { + text-anchor: middle +} + +.nvd3 .nv-axis.nv-disabled { + opacity: 0; +} + +.nvd3 .nv-bars rect { + fill-opacity: .75; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-bars rect.hover { + fill-opacity: 1; +} + +.nvd3 .nv-bars .hover rect { + fill: lightblue; +} + +.nvd3 .nv-bars text { + fill: rgba(0,0,0,0); +} + +.nvd3 .nv-bars .hover text { + fill: rgba(0,0,0,1); +} + +.nvd3 .nv-multibar .nv-groups rect, +.nvd3 .nv-multibarHorizontal .nv-groups rect, +.nvd3 .nv-discretebar .nv-groups rect { + stroke-opacity: 0; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-multibar .nv-groups rect:hover, +.nvd3 .nv-multibarHorizontal .nv-groups rect:hover, +.nvd3 .nv-candlestickBar .nv-ticks rect:hover, +.nvd3 .nv-discretebar .nv-groups rect:hover { + fill-opacity: 1; +} + +.nvd3 .nv-discretebar .nv-groups text, +.nvd3 .nv-multibarHorizontal .nv-groups text { + font-weight: bold; + fill: rgba(0,0,0,1); + stroke: rgba(0,0,0,0); +} + +/* boxplot CSS */ +.nvd3 .nv-boxplot circle { + fill-opacity: 0.5; +} + +.nvd3 .nv-boxplot circle:hover { fill-opacity: 1; } - -/********** -* Stacked Area -*/ - -.nvd3.nv-stackedarea path.nv-area { - fill-opacity: .7; - stroke-opacity: 0; - transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; -} - -.nvd3.nv-stackedarea path.nv-area.hover { - fill-opacity: .9; -} - - -.nvd3.nv-stackedarea .nv-groups .nv-point { - stroke-opacity: 0; - fill-opacity: 0; -} - - -/********** -* Line Plus Bar -*/ - -.nvd3.nv-linePlusBar .nv-bar rect { - fill-opacity: .75; -} - -.nvd3.nv-linePlusBar .nv-bar rect:hover { +.nvd3 .nv-boxplot rect:hover { fill-opacity: 1; } - -/********** -* Bullet -*/ - -.nvd3.nv-bullet { font: 10px sans-serif; } -.nvd3.nv-bullet .nv-measure { fill-opacity: .8; } -.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } -.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } -.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } -.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } -.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } -.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } -.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } -.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } -.nvd3.nv-bullet .nv-subtitle { fill: #999; } - - -.nvd3.nv-bullet .nv-range { - fill: #bababa; - fill-opacity: .4; -} -.nvd3.nv-bullet .nv-range:hover { - fill-opacity: .7; -} - - -/********** -* Sparkline -*/ - -.nvd3.nv-sparkline path { - fill: none; -} - -.nvd3.nv-sparklineplus g.nv-hoverValue { - pointer-events: none; -} - -.nvd3.nv-sparklineplus .nv-hoverValue line { - stroke: #333; - stroke-width: 1.5px; - } - -.nvd3.nv-sparklineplus, -.nvd3.nv-sparklineplus g { - pointer-events: all; -} - -.nvd3 .nv-hoverArea { - fill-opacity: 0; - stroke-opacity: 0; -} - -.nvd3.nv-sparklineplus .nv-xValue, -.nvd3.nv-sparklineplus .nv-yValue { - stroke-width: 0; - font-size: .9em; - font-weight: normal; -} - -.nvd3.nv-sparklineplus .nv-yValue { - stroke: #f66; -} - -.nvd3.nv-sparklineplus .nv-maxValue { - stroke: #2ca02c; - fill: #2ca02c; -} - -.nvd3.nv-sparklineplus .nv-minValue { - stroke: #d62728; - fill: #d62728; -} - -.nvd3.nv-sparklineplus .nv-currentValue { - font-weight: bold; - font-size: 1.1em; -} - -/********** -* historical stock -*/ - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick { - stroke-width: 1px; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { - stroke-width: 2px; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { - stroke: #2ca02c; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { - stroke: #d62728; -} - -.nvd3.nv-historicalStockChart .nv-axis .nv-axislabel { - font-weight: bold; -} - -.nvd3.nv-historicalStockChart .nv-dragTarget { - fill-opacity: 0; - stroke: none; - cursor: move; -} - -.nvd3 .nv-brush .extent { - fill-opacity: 0 !important; -} - -.nvd3 .nv-brushBackground rect { - stroke: #000; - stroke-width: .4; - fill: #fff; - fill-opacity: .7; -} - - -/********** -* Parallel Coordinates -*/ - -.nvd3 .background path { - fill: none; - stroke: #EEE; - stroke-opacity: .4; - shape-rendering: crispEdges; -} - -.nvd3 .foreground path { - fill: none; - stroke-opacity: .7; -} - -.nvd3 .brush .extent { - fill-opacity: .3; - stroke: #fff; - shape-rendering: crispEdges; -} - -.nvd3 .axis line, .axis path { - fill: none; - stroke: #000; - shape-rendering: crispEdges; -} - -.nvd3 .axis text { - text-shadow: 0 1px 0 #fff; -} - -/**** -Interactive Layer -*/ -.nvd3 .nv-interactiveGuideLine { - pointer-events:none; -} -.nvd3 line.nv-guideline { - stroke: #ccc; -} \ No newline at end of file +.nvd3 line.nv-boxplot-median { + stroke: black; +} + +.nv-boxplot-tick:hover { + stroke-width: 2.5px; +} +/* bullet */ +.nvd3.nv-bullet { font: 10px sans-serif; } +.nvd3.nv-bullet .nv-measure { fill-opacity: .8; } +.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } +.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } +.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } +.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } +.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } +.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } +.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } +.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } +.nvd3.nv-bullet .nv-subtitle { fill: #999; } + + +.nvd3.nv-bullet .nv-range { + fill: #bababa; + fill-opacity: .4; +} +.nvd3.nv-bullet .nv-range:hover { + fill-opacity: .7; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick { + stroke-width: 1px; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover { + stroke-width: 2px; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect { + stroke: #2ca02c; + fill: #2ca02c; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect { + stroke: #d62728; + fill: #d62728; +} + +.with-transitions .nv-candlestickBar .nv-ticks .nv-tick { + transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-candlestickBar .nv-ticks line { + stroke: #333; +} + + +.nvd3 .nv-legend .nv-disabled rect { + /*fill-opacity: 0;*/ +} + +.nvd3 .nv-check-box .nv-box { + fill-opacity:0; + stroke-width:2; +} + +.nvd3 .nv-check-box .nv-check { + fill-opacity:0; + stroke-width:4; +} + +.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check { + fill-opacity:0; + stroke-opacity:0; +} + +.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check { + opacity: 0; +} + +/* line plus bar */ +.nvd3.nv-linePlusBar .nv-bar rect { + fill-opacity: .75; +} + +.nvd3.nv-linePlusBar .nv-bar rect:hover { + fill-opacity: 1; +} +.nvd3 .nv-groups path.nv-line { + fill: none; +} + +.nvd3 .nv-groups path.nv-area { + stroke: none; +} + +.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { + fill-opacity: .5 !important; + stroke-opacity: .5 !important; +} + + +.with-transitions .nvd3 .nv-groups .nv-point { + transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-scatter .nv-groups .nv-point.hover, +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 7px; + fill-opacity: .95 !important; + stroke-opacity: .95 !important; +} + + +.nvd3 .nv-point-paths path { + stroke: #aaa; + stroke-opacity: 0; + fill: #eee; + fill-opacity: 0; +} + + + +.nvd3 .nv-indexLine { + cursor: ew-resize; +} + +/******************** + * SVG CSS + */ + +/******************** + Default CSS for an svg element nvd3 used +*/ +svg.nvd3-svg { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -ms-user-select: none; + -moz-user-select: none; + user-select: none; + display: block; + width:100%; + height:100%; +} + +/******************** + Box shadow and border radius styling +*/ +.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip { + -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); + -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); + box-shadow: 0 5px 10px rgba(0,0,0,.2); + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + + +.nvd3 text { + font: normal 12px Arial; +} + +.nvd3 .title { + font: bold 14px Arial; +} + +.nvd3 .nv-background { + fill: white; + fill-opacity: 0; +} + +.nvd3.nv-noData { + font-size: 18px; + font-weight: bold; +} + + +/********** +* Brush +*/ + +.nv-brush .extent { + fill-opacity: .125; + shape-rendering: crispEdges; +} + +.nv-brush .resize path { + fill: #eee; + stroke: #666; +} + + +/********** +* Legend +*/ + +.nvd3 .nv-legend .nv-series { + cursor: pointer; +} + +.nvd3 .nv-legend .nv-disabled circle { + fill-opacity: 0; +} + +/* focus */ +.nvd3 .nv-brush .extent { + fill-opacity: 0 !important; +} + +.nvd3 .nv-brushBackground rect { + stroke: #000; + stroke-width: .4; + fill: #fff; + fill-opacity: .7; +} + + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick { + stroke-width: 1px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { + stroke-width: 2px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { + stroke: #2ca02c; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { + stroke: #d62728; +} + + +.nvd3 .background path { + fill: none; + stroke: #EEE; + stroke-opacity: .4; + shape-rendering: crispEdges; +} + +.nvd3 .foreground path { + fill: none; + stroke-opacity: .7; +} + +.nvd3 .nv-parallelCoordinates-brush .extent +{ + fill: #fff; + fill-opacity: .6; + stroke: gray; + shape-rendering: crispEdges; +} + +.nvd3 .nv-parallelCoordinates .hover { + fill-opacity: 1; + stroke-width: 3px; +} + + +.nvd3 .missingValuesline line { + fill: none; + stroke: black; + stroke-width: 1; + stroke-opacity: 1; + stroke-dasharray: 5, 5; +} +.nvd3.nv-pie path { + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-pie .nv-pie-title { + font-size: 24px; + fill: rgba(19, 196, 249, 0.59); +} + +.nvd3.nv-pie .nv-slice text { + stroke: #000; + stroke-width: 0; +} + +.nvd3.nv-pie path { + stroke: #fff; + stroke-width: 1px; + stroke-opacity: 1; +} + +.nvd3.nv-pie .hover path { + fill-opacity: .7; +} +.nvd3.nv-pie .nv-label { + pointer-events: none; +} +.nvd3.nv-pie .nv-label rect { + fill-opacity: 0; + stroke-opacity: 0; +} + +/* scatter */ +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 20px; + stroke-opacity: .5; +} + +.nvd3 .nv-scatter .nv-point.hover { + fill-opacity: 1; +} +.nv-noninteractive { + pointer-events: none; +} + +.nv-distx, .nv-disty { + pointer-events: none; +} + +/* sparkline */ +.nvd3.nv-sparkline path { + fill: none; +} + +.nvd3.nv-sparklineplus g.nv-hoverValue { + pointer-events: none; +} + +.nvd3.nv-sparklineplus .nv-hoverValue line { + stroke: #333; + stroke-width: 1.5px; +} + +.nvd3.nv-sparklineplus, +.nvd3.nv-sparklineplus g { + pointer-events: all; +} + +.nvd3 .nv-hoverArea { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-sparklineplus .nv-xValue, +.nvd3.nv-sparklineplus .nv-yValue { + stroke-width: 0; + font-size: .9em; + font-weight: normal; +} + +.nvd3.nv-sparklineplus .nv-yValue { + stroke: #f66; +} + +.nvd3.nv-sparklineplus .nv-maxValue { + stroke: #2ca02c; + fill: #2ca02c; +} + +.nvd3.nv-sparklineplus .nv-minValue { + stroke: #d62728; + fill: #d62728; +} + +.nvd3.nv-sparklineplus .nv-currentValue { + font-weight: bold; + font-size: 1.1em; +} +/* stacked area */ +.nvd3.nv-stackedarea path.nv-area { + fill-opacity: .7; + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; +} + +.nvd3.nv-stackedarea path.nv-area.hover { + fill-opacity: .9; +} + + +.nvd3.nv-stackedarea .nv-groups .nv-point { + stroke-opacity: 0; + fill-opacity: 0; +} + + +.nvtooltip { + position: absolute; + background-color: rgba(255,255,255,1.0); + color: rgba(0,0,0,1.0); + padding: 1px; + border: 1px solid rgba(0,0,0,.2); + z-index: 10000; + display: block; + + font-family: Arial; + font-size: 13px; + text-align: left; + pointer-events: none; + + white-space: nowrap; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.nvtooltip { + background: rgba(255,255,255, 0.8); + border: 1px solid rgba(0,0,0,0.5); + border-radius: 4px; +} + +/*Give tooltips that old fade in transition by + putting a "with-transitions" class on the container div. +*/ +.nvtooltip.with-transitions, .with-transitions .nvtooltip { + transition: opacity 50ms linear; + -moz-transition: opacity 50ms linear; + -webkit-transition: opacity 50ms linear; + + transition-delay: 200ms; + -moz-transition-delay: 200ms; + -webkit-transition-delay: 200ms; +} + +.nvtooltip.x-nvtooltip, +.nvtooltip.y-nvtooltip { + padding: 8px; +} + +.nvtooltip h3 { + margin: 0; + padding: 4px 14px; + line-height: 18px; + font-weight: normal; + background-color: rgba(247,247,247,0.75); + color: rgba(0,0,0,1.0); + text-align: center; + + 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; +} + +.nvtooltip p { + margin: 0; + padding: 5px 14px; + text-align: center; +} + +.nvtooltip span { + display: inline-block; + margin: 2px 0; +} + +.nvtooltip table { + margin: 6px; + border-spacing:0; +} + + +.nvtooltip table td { + padding: 2px 9px 2px 0; + vertical-align: middle; +} + +.nvtooltip table td.key { + font-weight: normal; +} +.nvtooltip table td.key.total { + font-weight: bold; +} +.nvtooltip table td.value { + text-align: right; + font-weight: bold; +} + +.nvtooltip table tr.highlight td { + padding: 1px 9px 1px 0; + border-bottom-style: solid; + border-bottom-width: 1px; + border-top-style: solid; + border-top-width: 1px; +} + +.nvtooltip table td.legend-color-guide div { + width: 8px; + height: 8px; + vertical-align: middle; +} + +.nvtooltip table td.legend-color-guide div { + width: 12px; + height: 12px; + border: 1px solid #999; +} + +.nvtooltip .footer { + padding: 3px; + text-align: center; +} + +.nvtooltip-pending-removal { + pointer-events: none; + display: none; +} + + +/**** +Interactive Layer +*/ +.nvd3 .nv-interactiveGuideLine { + pointer-events:none; +} +.nvd3 line.nv-guideline { + stroke: #ccc; +} diff --git a/build/nv.d3.js b/build/nv.d3.js index b7fe5f796..214c71ce5 100644 --- a/build/nv.d3.js +++ b/build/nv.d3.js @@ -1,9 +1,8 @@ -/* nvd3 version 1.7.1(https://github.com/novus/nvd3) 2015-02-08 */ +/* nvd3 version 1.8.1-dev (https://github.com/novus/nvd3) 2015-09-10 */ (function(){ -// set up main nv object on window -var nv = window.nv || {}; -window.nv = nv; +// set up main nv object +var nv = {}; // the major global objects under the nv namespace nv.dev = false; //set false when in production @@ -11,8 +10,8 @@ nv.tooltip = nv.tooltip || {}; // For the tooltip system nv.utils = nv.utils || {}; // Utility subsystem nv.models = nv.models || {}; //stores all the possible models/components nv.charts = {}; //stores all the ready to use charts -nv.graphs = []; //stores all the graphs currently on the page nv.logs = {}; //stores some statistics and potential error messages +nv.dom = {}; //DOM manipulation functions nv.dispatch = d3.dispatch('render_start', 'render_end'); @@ -72,14 +71,15 @@ nv.log = function() { }; // print console warning, should be used by deprecated functions -nv.deprecated = function(name) { - if (nv.dev && console && console.warn) { - console.warn('`' + name + '` has been deprecated.'); +nv.deprecated = function(name, info) { + if (console && console.warn) { + console.warn('nvd3 warning: `' + name + '` has been deprecated. ', info || ''); } }; -// render function is used to queue up chart rendering -// in non-blocking timeout functions +// The nv.render function is used to queue up chart rendering +// in non-blocking async functions. +// When all queued charts are done rendering, nv.dispatch.render_end is invoked. nv.render = function render(step) { // number of graphs to generate in each timeout loop step = step || 1; @@ -87,29 +87,44 @@ nv.render = function render(step) { nv.render.active = true; nv.dispatch.render_start(); - setTimeout(function() { + var renderLoop = function() { var chart, graph; for (var i = 0; i < step && (graph = nv.render.queue[i]); i++) { chart = graph.generate(); if (typeof graph.callback == typeof(Function)) graph.callback(chart); - nv.graphs.push(chart); } nv.render.queue.splice(0, i); - if (nv.render.queue.length) setTimeout(arguments.callee, 0); + if (nv.render.queue.length) { + setTimeout(renderLoop); + } else { nv.dispatch.render_end(); nv.render.active = false; } - }, 0); + }; + + setTimeout(renderLoop); }; nv.render.active = false; nv.render.queue = []; -// main function to use when adding a new graph, see examples +/* +Adds a chart to the async rendering queue. This method can take arguments in two forms: +nv.addGraph({ + generate: + callback: +}) +or +nv.addGraph(, ) +The generate function should contain code that creates the NVD3 model, sets options +on it, adds data to an SVG element, and invokes the chart model. The generate function +should return the chart model. See examples/lineChart.html for a usage example. +The callback function is optional, and it is called when the generate function completes. +*/ nv.addGraph = function(obj) { if (typeof arguments[0] === typeof(Function)) { obj = {generate: arguments[0], callback: arguments[1]}; @@ -120,10 +135,43 @@ nv.addGraph = function(obj) { if (!nv.render.active) { nv.render(); } +}; + +// Node/CommonJS exports +if (typeof(module) !== 'undefined' && typeof(exports) !== 'undefined') { + module.exports = nv; +} + +if (typeof(window) !== 'undefined') { + window.nv = nv; +} +/* Facade for queueing DOM write operations + * with Fastdom (https://github.com/wilsonpage/fastdom) + * if available. + * This could easily be extended to support alternate + * implementations in the future. + */ +nv.dom.write = function(callback) { + if (window.fastdom !== undefined) { + return fastdom.write(callback); + } + return callback(); +}; + +/* Facade for queueing DOM read operations + * with Fastdom (https://github.com/wilsonpage/fastdom) + * if available. + * This could easily be extended to support alternate + * implementations in the future. + */ +nv.dom.read = function(callback) { + if (window.fastdom !== undefined) { + return fastdom.read(callback); + } + return callback(); };/* Utility class to handle creation of an interactive layer. This places a rectangle on top of the chart. When you mouse move over it, it sends a dispatch containing the X-coordinate. It can also render a vertical line where the mouse is located. - dispatch.elementMousemove is the important event to latch onto. It is fired whenever the mouse moves over the rectangle. The dispatch is given one object which contains the mouseX/Y location. It also has 'pointXValue', which is the conversion of mouseX to the x-axis scale. @@ -131,26 +179,21 @@ nv.addGraph = function(obj) { nv.interactiveGuideline = function() { "use strict"; - var tooltip = nv.models.tooltip(); - - //Public settings - var width = null; - var height = null; - - //Please pass in the bounding chart's top and left margins - //This is important for calculating the correct mouseX/Y positions. - var margin = {left: 0, top: 0} - , xScale = d3.scale.linear() - , yScale = d3.scale.linear() - , dispatch = d3.dispatch('elementMousemove', 'elementMouseout', 'elementClick', 'elementDblclick') - , showGuideLine = true; - //Must pass in the bounding chart's container. - //The mousemove event is attached to this container. - var svgContainer = null; - - // check if IE by looking for activeX - var isMSIE = "ActiveXObject" in window; + var margin = { left: 0, top: 0 } //Pass the chart's top and left magins. Used to calculate the mouseX/Y. + , width = null + , height = null + , xScale = d3.scale.linear() + , dispatch = d3.dispatch('elementMousemove', 'elementMouseout', 'elementClick', 'elementDblclick', 'elementMouseDown', 'elementMouseUp') + , showGuideLine = true + , svgContainer = null // Must pass the chart's svg, we'll use its mousemove event. + , tooltip = nv.models.tooltip() + , isMSIE = "ActiveXObject" in window // Checkt if IE by looking for activeX. + ; + tooltip + .duration(0) + .hideDelay(0) + .hidden(false); function layer(selection) { selection.each(function(data) { @@ -219,7 +262,8 @@ nv.interactiveGuideline = function() { if (isMSIE) { if (d3.event.relatedTarget && d3.event.relatedTarget.ownerSVGElement === undefined - && d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass)) { + && (d3.event.relatedTarget.className === undefined + || d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass))) { return; } @@ -229,7 +273,10 @@ nv.interactiveGuideline = function() { mouseY: mouseY }); layer.renderGuideLine(null); //hide the guideline + tooltip.hidden(true); return; + } else { + tooltip.hidden(false); } var pointXValue = xScale.invert(mouseX); @@ -256,32 +303,54 @@ nv.interactiveGuideline = function() { pointXValue: pointXValue }); } + + // if user presses mouse down the layer, fire elementMouseDown + if (d3.event.type === 'mousedown') { + dispatch.elementMouseDown({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + } + + // if user presses mouse down the layer, fire elementMouseUp + if (d3.event.type === 'mouseup') { + dispatch.elementMouseUp({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + } } svgContainer + .on("touchmove",mouseHandler) .on("mousemove",mouseHandler, true) .on("mouseout" ,mouseHandler,true) + .on("mousedown" ,mouseHandler,true) + .on("mouseup" ,mouseHandler,true) .on("dblclick" ,mouseHandler) .on("click", mouseHandler) ; + layer.guideLine = null; //Draws a vertical guideline at the given X postion. layer.renderGuideLine = function(x) { if (!showGuideLine) return; - var line = wrap.select(".nv-interactiveGuideLine") - .selectAll("line") - .data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String); - - line.enter() - .append("line") - .attr("class", "nv-guideline") - .attr("x1", function(d) { return d;}) - .attr("x2", function(d) { return d;}) - .attr("y1", availableHeight) - .attr("y2",0) - ; - line.exit().remove(); - + if (layer.guideLine && layer.guideLine.attr("x1") === x) return; + nv.dom.write(function() { + var line = wrap.select(".nv-interactiveGuideLine") + .selectAll("line") + .data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String); + line.enter() + .append("line") + .attr("class", "nv-guideline") + .attr("x1", function(d) { return d;}) + .attr("x2", function(d) { return d;}) + .attr("y1", availableHeight) + .attr("y2",0); + line.exit().remove(); + }); } }); } @@ -331,13 +400,10 @@ nv.interactiveGuideline = function() { /* Utility class that uses d3.bisect to find the index in a given array, where a search value can be inserted. This is different from normal bisectLeft; this function finds the nearest index to insert the search value. - For instance, lets say your array is [1,2,3,5,10,30], and you search for 28. Normal d3.bisectLeft will return 4, because 28 is inserted after the number 10. But interactiveBisect will return 5 because 28 is closer to 30 than 10. - Unit tests can be found in: interactiveBisectTest.html - Has the following known issues: * Will not work if the data points move backwards (ie, 10,9,8,7, etc) or if the data points are in random order. * Won't work if there are duplicate x coordinate values. @@ -347,15 +413,30 @@ nv.interactiveBisect = function (values, searchVal, xAccessor) { if (! (values instanceof Array)) { return null; } + var _xAccessor; if (typeof xAccessor !== 'function') { - xAccessor = function(d,i) { + _xAccessor = function(d) { return d.x; } + } else { + _xAccessor = xAccessor; } + var _cmp = function(d, v) { + // Accessors are no longer passed the index of the element along with + // the element itself when invoked by d3.bisector. + // + // Starting at D3 v3.4.4, d3.bisector() started inspecting the + // function passed to determine if it should consider it an accessor + // or a comparator. This meant that accessors that take two arguments + // (expecting an index as the second parameter) are treated as + // comparators where the second argument is the search value against + // which the first argument is compared. + return _xAccessor(d) - v; + }; - var bisect = d3.bisector(xAccessor).left; + var bisect = d3.bisector(_cmp).left; var index = d3.max([0, bisect(values,searchVal) - 1]); - var currentValue = xAccessor(values[index], index); + var currentValue = _xAccessor(values[index]); if (typeof currentValue === 'undefined') { currentValue = index; @@ -366,7 +447,7 @@ nv.interactiveBisect = function (values, searchVal, xAccessor) { } var nextIndex = d3.min([index+1, values.length - 1]); - var nextValue = xAccessor(values[nextIndex], nextIndex); + var nextValue = _xAccessor(values[nextIndex]); if (typeof nextValue === 'undefined') { nextValue = nextIndex; @@ -389,541 +470,385 @@ nv.nearestValueIndex = function (values, searchVal, threshold) { var yDistMax = Infinity, indexToHighlight = null; values.forEach(function(d,i) { var delta = Math.abs(searchVal - d); - if ( delta <= yDistMax && delta < threshold) { + if ( d != null && delta <= yDistMax && delta < threshold) { yDistMax = delta; indexToHighlight = i; } }); return indexToHighlight; }; -/* Tooltip rendering model for nvd3 charts. - window.nv.models.tooltip is the updated,new way to render tooltips. - window.nv.tooltip.show is the old tooltip code. - window.nv.tooltip.* also has various helper methods. +/* Model which can be instantiated to handle tooltip rendering. + Example usage: + var tip = nv.models.tooltip().gravity('w').distance(23) + .data(myDataObject); + tip(); //just invoke the returned function to render tooltip. */ -(function() { +nv.models.tooltip = function() { "use strict"; - window.nv.tooltip = {}; - /* Model which can be instantiated to handle tooltip rendering. - Example usage: - var tip = nv.models.tooltip().gravity('w').distance(23) - .data(myDataObject); + /* + Tooltip data. If data is given in the proper format, a consistent tooltip is generated. + Example Format of data: + { + key: "Date", + value: "August 2009", + series: [ + {key: "Series 1", value: "Value 1", color: "#000"}, + {key: "Series 2", value: "Value 2", color: "#00f"} + ] + } + */ + var id = "nvtooltip-" + Math.floor(Math.random() * 100000) // Generates a unique id when you create a new tooltip() object. + , data = null + , gravity = 'w' // Can be 'n','s','e','w'. Determines how tooltip is positioned. + , distance = 25 // Distance to offset tooltip from the mouse location. + , snapDistance = 0 // Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect) + , fixedTop = null // If not null, this fixes the top position of the tooltip. + , classes = null // Attaches additional CSS classes to the tooltip DIV that is created. + , chartContainer = null // Parent dom element of the SVG that holds the chart. + , hidden = true // Start off hidden, toggle with hide/show functions below. + , hideDelay = 200 // Delay (in ms) before the tooltip hides after calling hide(). + , tooltip = null // d3 select of the tooltip div. + , lastPosition = { left: null, top: null } // Last position the tooltip was in. + , enabled = true // True -> tooltips are rendered. False -> don't render tooltips. + , duration = 100 // Tooltip movement duration, in ms. + , headerEnabled = true // If is to show the tooltip header. + , nvPointerEventsClass = "nv-pointer-events-none" // CSS class to specify whether element should not have mouse events. + ; - tip(); //just invoke the returned function to render tooltip. + /* + Function that returns the position (relative to the viewport) the tooltip should be placed in. + Should return: { + left: , + top: + } */ - window.nv.models.tooltip = function() { - //HTML contents of the tooltip. If null, the content is generated via the data variable. - var content = null; - - /* - Tooltip data. If data is given in the proper format, a consistent tooltip is generated. - Example Format of data: - { - key: "Date", - value: "August 2009", - series: [ - {key: "Series 1", value: "Value 1", color: "#000"}, - {key: "Series 2", value: "Value 2", color: "#00f"} - ] - } - */ - var data = null; - - var gravity = 'w' //Can be 'n','s','e','w'. Determines how tooltip is positioned. - ,distance = 50 //Distance to offset tooltip from the mouse location. - ,snapDistance = 25 //Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect) - , fixedTop = null //If not null, this fixes the top position of the tooltip. - , classes = null //Attaches additional CSS classes to the tooltip DIV that is created. - , chartContainer = null //Parent DIV, of the SVG Container that holds the chart. - , tooltipElem = null //actual DOM element representing the tooltip. - , position = {left: null, top: null} //Relative position of the tooltip inside chartContainer. - , enabled = true; //True -> tooltips are rendered. False -> don't render tooltips. - - //Generates a unique id when you create a new tooltip() object - var id = "nvtooltip-" + Math.floor(Math.random() * 100000); - - //CSS class to specify whether element should not have mouse events. - var nvPointerEventsClass = "nv-pointer-events-none"; - - //Format function for the tooltip values column - var valueFormatter = function(d,i) { - return d; + var position = function() { + //EDIT get the mouse position relative to the nvd3 element and set the tooltip to absolute + var container = chartContainer ? chartContainer : document.body; + var rect = container.getBoundingClientRect(); + return { + left: d3.event.clientX - rect.left, + top: d3.event.clientY - rect.top }; + //END EDIT + }; - //Format function for the tooltip header value. - var headerFormatter = function(d) { - return d; - }; + // Format function for the tooltip values column. + var valueFormatter = function(d, i) { + return d; + }; - //By default, the tooltip model renders a beautiful table inside a DIV. - //You can override this function if a custom tooltip is desired. - var contentGenerator = function(d) { - if (content != null) { - return content; - } + // Format function for the tooltip header value. + var headerFormatter = function(d) { + return d; + }; - if (d == null) { - return ''; - } + var keyFormatter = function(d, i) { + return d; + }; + + // By default, the tooltip model renders a beautiful table inside a DIV. + // You can override this function if a custom tooltip is desired. + var contentGenerator = function(d) { + if (d === null) { + return ''; + } - var table = d3.select(document.createElement("table")); + var table = d3.select(document.createElement("table")); + if (headerEnabled) { var theadEnter = table.selectAll("thead") .data([d]) .enter().append("thead"); theadEnter.append("tr") .append("td") - .attr("colspan",3) + .attr("colspan", 3) .append("strong") - .classed("x-value",true) + .classed("x-value", true) .html(headerFormatter(d.value)); - - var tbodyEnter = table.selectAll("tbody") - .data([d]) - .enter().append("tbody"); - - var trowEnter = tbodyEnter.selectAll("tr") - .data(function(p) { return p.series}) - .enter() - .append("tr") - .classed("highlight", function(p) { return p.highlight}); - - trowEnter.append("td") - .classed("legend-color-guide",true) - .append("div") - .style("background-color", function(p) { return p.color}); - - trowEnter.append("td") - .classed("key",true) - .html(function(p) {return p.key}); - - trowEnter.append("td") - .classed("value",true) - .html(function(p,i) { return valueFormatter(p.value,i) }); - - - trowEnter.selectAll("td").each(function(p) { - if (p.highlight) { - var opacityScale = d3.scale.linear().domain([0,1]).range(["#fff",p.color]); - var opacity = 0.6; - d3.select(this) - .style("border-bottom-color", opacityScale(opacity)) - .style("border-top-color", opacityScale(opacity)) - ; - } - }); - - //EDIT - //add info about a post to tooltip when hover over a post icon - if (d.postMarkerTooltip) { - var tfootEnter = tbodyEnter.selectAll("tfoot") - .data([d]) - .enter() - .append("tfoot"); - - tfootEnter.append("tr") - .append("td") - .attr("colspan",3) - .append("strong") - .html(function(p) { return p.postMarkerTooltip.label }); - - tfootEnter.append("tr") - .append("td") - .attr("colspan",3) - .html(function(p) { return d3.time.format('%x %I %p')(p.postMarkerTooltip.postDate) }); - } - //END EDIT - - var html = table.node().outerHTML; - if (d.footer !== undefined) - html += ""; - return html; - - }; - - var dataSeriesExists = function(d) { - if (d && d.series && d.series.length > 0) { - return true; - } - return false; - }; - - //In situations where the chart is in a 'viewBox', re-position the tooltip based on how far chart is zoomed. - function convertViewBoxRatio() { - if (chartContainer) { - var svg = d3.select(chartContainer); - if (svg.node().tagName !== "svg") { - svg = svg.select("svg"); - } - var viewBox = (svg.node()) ? svg.attr('viewBox') : null; - if (viewBox) { - viewBox = viewBox.split(' '); - var ratio = parseInt(svg.style('width')) / viewBox[2]; - - position.left = position.left * ratio; - position.top = position.top * ratio; - } - } } - //Creates new tooltip container, or uses existing one on DOM. - function getTooltipContainer(newContent) { - var body; - if (chartContainer) { - body = d3.select(chartContainer); - } else { - body = d3.select("body"); - } - - var container = body.select(".nvtooltip"); - if (container.node() === null) { - //Create new tooltip div if it doesn't exist on DOM. - container = body.append("div") - .attr("class", "nvtooltip " + (classes? classes: "xy-tooltip")) - .attr("id",id) + //EDIT + var tbodyEnter = table.selectAll("tbody") + .data([d]) + .enter().append("tbody"); + //END EDIT + + var trowEnter = tbodyEnter.selectAll("tr") + .data(function(p) { return p.series; }) + .enter() + .append("tr") + .classed("highlight", function(p) { return p.highlight}); + + trowEnter.append("td") + .classed("legend-color-guide",true) + .append("div") + .style("background-color", function(p) { return p.color}); + + trowEnter.append("td") + .classed("key",true) + .classed("total",function(p) { return !!p.total}) + .html(function(p, i) { return keyFormatter(p.key, i)}); + + trowEnter.append("td") + .classed("value",true) + .html(function(p, i) { return valueFormatter(p.value, i) }); + + trowEnter.selectAll("td").each(function(p) { + if (p.highlight) { + var opacityScale = d3.scale.linear().domain([0,1]).range(["#fff",p.color]); + var opacity = 0.6; + d3.select(this) + .style("border-bottom-color", opacityScale(opacity)) + .style("border-top-color", opacityScale(opacity)) ; } + }); - container.node().innerHTML = newContent; - container.style("top",0).style("left",0).style("opacity",0); - container.selectAll("div, table, td, tr").classed(nvPointerEventsClass,true) - container.classed(nvPointerEventsClass,true); - return container.node(); - } - - //Draw the tooltip onto the DOM. - function nvtooltip() { - if (!enabled) return; - if (!dataSeriesExists(data)) return; - - convertViewBoxRatio(); - - var left = position.left; - var top = (fixedTop != null) ? fixedTop : position.top; - var container = getTooltipContainer(contentGenerator(data)); - tooltipElem = container; - if (chartContainer) { - var svgComp = chartContainer.getElementsByTagName("svg")[0]; - var boundRect = (svgComp) ? svgComp.getBoundingClientRect() : chartContainer.getBoundingClientRect(); - var svgOffset = {left:0,top:0}; - if (svgComp) { - var svgBound = svgComp.getBoundingClientRect(); - var chartBound = chartContainer.getBoundingClientRect(); - var svgBoundTop = svgBound.top; - - //Defensive code. Sometimes, svgBoundTop can be a really negative - // number, like -134254. That's a bug. - // If such a number is found, use zero instead. FireFox bug only - if (svgBoundTop < 0) { - var containerBound = chartContainer.getBoundingClientRect(); - svgBoundTop = (Math.abs(svgBoundTop) > containerBound.height) ? 0 : svgBoundTop; - } - svgOffset.top = Math.abs(svgBoundTop - chartBound.top); - svgOffset.left = Math.abs(svgBound.left - chartBound.left); - } - //If the parent container is an overflow
with scrollbars, subtract the scroll offsets. - //You need to also add any offset between the element and its containing
- //Finally, add any offset of the containing
on the whole page. - left += chartContainer.offsetLeft + svgOffset.left - 2*chartContainer.scrollLeft; - top += chartContainer.offsetTop + svgOffset.top - 2*chartContainer.scrollTop; - } - - if (snapDistance && snapDistance > 0) { - top = Math.floor(top/snapDistance) * snapDistance; - } - - nv.tooltip.calcTooltipPosition([left,top], gravity, distance, container); - return nvtooltip; - } - - nvtooltip.nvPointerEventsClass = nvPointerEventsClass; - - nvtooltip.content = function(_) { - if (!arguments.length) return content; - content = _; - return nvtooltip; - }; - - //Returns tooltipElem...not able to set it. - nvtooltip.tooltipElem = function() { - return tooltipElem; - }; - - nvtooltip.contentGenerator = function(_) { - if (!arguments.length) return contentGenerator; - if (typeof _ === 'function') { - contentGenerator = _; - } - return nvtooltip; - }; - - nvtooltip.data = function(_) { - if (!arguments.length) return data; - data = _; - return nvtooltip; - }; - - nvtooltip.gravity = function(_) { - if (!arguments.length) return gravity; - gravity = _; - return nvtooltip; - }; - - nvtooltip.distance = function(_) { - if (!arguments.length) return distance; - distance = _; - return nvtooltip; - }; - - nvtooltip.snapDistance = function(_) { - if (!arguments.length) return snapDistance; - snapDistance = _; - return nvtooltip; - }; - - nvtooltip.classes = function(_) { - if (!arguments.length) return classes; - classes = _; - return nvtooltip; - }; - - nvtooltip.chartContainer = function(_) { - if (!arguments.length) return chartContainer; - chartContainer = _; - return nvtooltip; - }; - - nvtooltip.position = function(_) { - if (!arguments.length) return position; - position.left = (typeof _.left !== 'undefined') ? _.left : position.left; - position.top = (typeof _.top !== 'undefined') ? _.top : position.top; - return nvtooltip; - }; - - nvtooltip.fixedTop = function(_) { - if (!arguments.length) return fixedTop; - fixedTop = _; - return nvtooltip; - }; - - nvtooltip.enabled = function(_) { - if (!arguments.length) return enabled; - enabled = _; - return nvtooltip; - }; - - nvtooltip.valueFormatter = function(_) { - if (!arguments.length) return valueFormatter; - if (typeof _ === 'function') { - valueFormatter = _; - } - return nvtooltip; - }; - - nvtooltip.headerFormatter = function(_) { - if (!arguments.length) return headerFormatter; - if (typeof _ === 'function') { - headerFormatter = _; - } - return nvtooltip; - }; - - //id() is a read-only function. You can't use it to set the id. - nvtooltip.id = function() { - return id; - }; - - return nvtooltip; - }; - - //Original tooltip.show function. Kept for backward compatibility. - // pos = [left,top] - nv.tooltip.show = function(pos, content, gravity, dist, parentContainer, classes) { + //EDIT + //add info about a post to tooltip when hover over a post icon + if (d.postMarkerTooltip) { + var tfootEnter = tbodyEnter.selectAll("tfoot") + .data([d]) + .enter() + .append("tfoot"); - //Create new tooltip div if it doesn't exist on DOM. - var container = document.createElement('div'); - container.className = 'nvtooltip ' + (classes ? classes : 'xy-tooltip'); + tfootEnter.append("tr") + .append("td") + .attr("colspan",3) + .append("strong") + .html(function(p) { return p.postMarkerTooltip.label }); - var body = parentContainer; - if ( !parentContainer || parentContainer.tagName.match(/g|svg/i)) { - //If the parent element is an SVG element, place tooltip in the element. - body = document.getElementsByTagName('body')[0]; + tfootEnter.append("tr") + .append("td") + .attr("colspan",3) + .html(function(p) { return d3.time.format('%x %I %p')(p.postMarkerTooltip.postDate) }); } + //END EDIT - container.style.left = 0; - container.style.top = 0; - container.style.opacity = 0; - // Content can also be dom element - if (typeof content !== 'string') - container.appendChild(content); - else - container.innerHTML = content; - body.appendChild(container); - - //If the parent container is an overflow
with scrollbars, subtract the scroll offsets. - if (parentContainer) { - pos[0] = pos[0] - parentContainer.scrollLeft; - pos[1] = pos[1] - parentContainer.scrollTop; - } - nv.tooltip.calcTooltipPosition(pos, gravity, dist, container); - }; + var html = table.node().outerHTML; + if (d.footer !== undefined) + html += ""; + return html; - //Looks up the ancestry of a DOM element, and returns the first NON-svg node. - nv.tooltip.findFirstNonSVGParent = function(Elem) { - while(Elem.tagName.match(/^g|svg$/i) !== null) { - Elem = Elem.parentNode; - } - return Elem; }; - //Finds the total offsetTop of a given DOM element. - //Looks up the entire ancestry of an element, up to the first relatively positioned element. - nv.tooltip.findTotalOffsetTop = function ( Elem, initialTop ) { - var offsetTop = initialTop; - - do { - if( !isNaN( Elem.offsetTop ) ) { - offsetTop += (Elem.offsetTop); + var dataSeriesExists = function(d) { + if (d && d.series) { + if (d.series instanceof Array) { + return !!d.series.length; } - } while( Elem = Elem.offsetParent ); - return offsetTop; - }; - - //Finds the total offsetLeft of a given DOM element. - //Looks up the entire ancestry of an element, up to the first relatively positioned element. - nv.tooltip.findTotalOffsetLeft = function ( Elem, initialLeft) { - var offsetLeft = initialLeft; - - do { - if( !isNaN( Elem.offsetLeft ) ) { - offsetLeft += (Elem.offsetLeft); + // if object, it's okay just convert to array of the object + if (d.series instanceof Object) { + d.series = [d.series]; + return true; } - } while( Elem = Elem.offsetParent ); - return offsetLeft; + } + return false; }; - //Global utility function to render a tooltip on the DOM. - //pos = [left,top] coordinates of where to place the tooltip, relative to the SVG chart container. - //gravity = how to orient the tooltip - //dist = how far away from the mouse to place tooltip - //container = tooltip DIV - nv.tooltip.calcTooltipPosition = function(pos, gravity, dist, container) { - - var height = parseInt(container.offsetHeight), - width = parseInt(container.offsetWidth), - windowWidth = nv.utils.windowSize().width, - windowHeight = nv.utils.windowSize().height, - scrollTop = window.pageYOffset, - scrollLeft = window.pageXOffset, - left, top; - - windowHeight = window.innerWidth >= document.body.scrollWidth ? windowHeight : windowHeight - 16; - windowWidth = window.innerHeight >= document.body.scrollHeight ? windowWidth : windowWidth - 16; - - gravity = gravity || 's'; - dist = dist || 20; - - var tooltipTop = function ( Elem ) { - return nv.tooltip.findTotalOffsetTop(Elem, top); - }; - - var tooltipLeft = function ( Elem ) { - return nv.tooltip.findTotalOffsetLeft(Elem,left); - }; + // Calculates the gravity offset of the tooltip. Parameter is position of tooltip + // relative to the viewport. + var calcGravityOffset = function(pos) { + var height = tooltip.node().offsetHeight, + width = tooltip.node().offsetWidth, + clientWidth = document.documentElement.clientWidth, // Don't want scrollbars. + clientHeight = document.documentElement.clientHeight, // Don't want scrollbars. + left, top, tmp; + // calculate position based on gravity switch (gravity) { case 'e': - left = pos[0] - width - dist; - top = pos[1] - (height / 2); - var tLeft = tooltipLeft(container); - var tTop = tooltipTop(container); - if (tLeft < scrollLeft) left = pos[0] + dist > scrollLeft ? pos[0] + dist : scrollLeft - tLeft + left; - if (tTop < scrollTop) top = scrollTop - tTop + top; - if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height; + left = - width - distance; + top = - (height / 2); + if(pos.left + left < 0) left = distance; + if((tmp = pos.top + top) < 0) top -= tmp; + if((tmp = pos.top + top + height) > clientHeight) top -= tmp - clientHeight; break; case 'w': - left = pos[0] + dist; - top = pos[1] - (height / 2); - var tLeft = tooltipLeft(container); - var tTop = tooltipTop(container); - if (tLeft + width > windowWidth) left = pos[0] - width - dist; - if (tTop < scrollTop) top = scrollTop + 5; - if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height; + left = distance; + top = - (height / 2); + if (pos.left + left + width > clientWidth) left = - width - distance; + if ((tmp = pos.top + top) < 0) top -= tmp; + if ((tmp = pos.top + top + height) > clientHeight) top -= tmp - clientHeight; break; case 'n': - left = pos[0] - (width / 2) - 5; - top = pos[1] + dist; - var tLeft = tooltipLeft(container); - var tTop = tooltipTop(container); - if (tLeft < scrollLeft) left = scrollLeft + 5; - if (tLeft + width > windowWidth) left = left - width/2 + 5; - if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height; + left = - (width / 2) - 5; // - 5 is an approximation of the mouse's height. + top = distance; + if (pos.top + top + height > clientHeight) top = - height - distance; + if ((tmp = pos.left + left) < 0) left -= tmp; + if ((tmp = pos.left + left + width) > clientWidth) left -= tmp - clientWidth; break; case 's': - left = pos[0] - (width / 2); - top = pos[1] - height - dist; - var tLeft = tooltipLeft(container); - var tTop = tooltipTop(container); - if (tLeft < scrollLeft) left = scrollLeft + 5; - if (tLeft + width > windowWidth) left = left - width/2 + 5; - if (scrollTop > tTop) top = scrollTop; + left = - (width / 2); + top = - height - distance; + if (pos.top + top < 0) top = distance; + if ((tmp = pos.left + left) < 0) left -= tmp; + if ((tmp = pos.left + left + width) > clientWidth) left -= tmp - clientWidth; break; - case 'none': - left = pos[0]; - top = pos[1] - dist; - var tLeft = tooltipLeft(container); - var tTop = tooltipTop(container); + case 'center': + left = - (width / 2); + top = - (height / 2); + break; + default: + left = 0; + top = 0; break; } - container.style.left = left+'px'; - container.style.top = top+'px'; - container.style.opacity = 1; - container.style.position = 'absolute'; + return { 'left': left, 'top': top }; + }; + + /* + Positions the tooltip in the correct place, as given by the position() function. + */ + var positionTooltip = function() { + nv.dom.read(function() { + var pos = position(), + gravityOffset = calcGravityOffset(pos), + left = pos.left + gravityOffset.left, + top = pos.top + gravityOffset.top; + //console.log(pos); + + // delay hiding a bit to avoid flickering + if (hidden) { + tooltip + .interrupt() + .transition() + .delay(hideDelay) + .duration(0) + .style('opacity', 0); + } else { + // using tooltip.style('transform') returns values un-usable for tween + var old_translate = 'translate(' + lastPosition.left + 'px, ' + lastPosition.top + 'px)'; + var new_translate = 'translate(' + left + 'px, ' + top + 'px)'; + var translateInterpolator = d3.interpolateString(old_translate, new_translate); + var is_hidden = tooltip.style('opacity') < 0.1; + + tooltip + .interrupt() // cancel running transitions + .transition() + .duration(is_hidden ? 0 : duration) + // using tween since some versions of d3 can't auto-tween a translate on a div + .styleTween('transform', function (d) { + return translateInterpolator; + }, 'important') + // Safari has its own `-webkit-transform` and does not support `transform` + .styleTween('-webkit-transform', function (d) { + return translateInterpolator; + }) + .style('-ms-transform', new_translate) + .style('opacity', 1); + } - return container; + lastPosition.left = left; + lastPosition.top = top; + }); }; - //Global utility function to remove tooltips from the DOM. - nv.tooltip.cleanup = function() { - - // Find the tooltips, mark them for removal by this class (so others cleanups won't find it) - var tooltips = document.getElementsByClassName('nvtooltip'); - var purging = []; - while(tooltips.length) { - purging.push(tooltips[0]); - tooltips[0].style.transitionDelay = '0 !important'; - tooltips[0].style.opacity = 0; - tooltips[0].className = 'nvtooltip-pending-removal'; + // Creates new tooltip container, or uses existing one on DOM. + function initTooltip() { + if (!tooltip) { + var container = chartContainer ? chartContainer : document.body; + + // Create new tooltip div if it doesn't exist on DOM. + tooltip = d3.select(container).append("div") + .attr("class", "nvtooltip " + (classes ? classes : "xy-tooltip")) + .attr("id", id); + tooltip.style("top", 0).style("left", 0); + tooltip.style('opacity', 0); + //EDIT absolute position tooltip to work in modal + tooltip.style('position', 'absolute'); + //END EDIT + tooltip.selectAll("div, table, td, tr").classed(nvPointerEventsClass, true); + tooltip.classed(nvPointerEventsClass, true); } + } - setTimeout(function() { + // Draw the tooltip onto the DOM. + function nvtooltip() { + if (!enabled) return; + if (!dataSeriesExists(data)) return; - while (purging.length) { - var removeMe = purging.pop(); - removeMe.parentNode.removeChild(removeMe); + nv.dom.write(function () { + initTooltip(); + // Generate data and set it into tooltip. + // Bonus - If you override contentGenerator and return falsey you can use something like + // React or Knockout to bind the data for your tooltip. + var newContent = contentGenerator(data); + if (newContent) { + tooltip.node().innerHTML = newContent; } - }, 500); - }; -})(); + positionTooltip(); + }); + + return nvtooltip; + } + + nvtooltip.nvPointerEventsClass = nvPointerEventsClass; + nvtooltip.options = nv.utils.optionsFunc.bind(nvtooltip); + + nvtooltip._options = Object.create({}, { + // simple read/write options + duration: {get: function(){return duration;}, set: function(_){duration=_;}}, + gravity: {get: function(){return gravity;}, set: function(_){gravity=_;}}, + distance: {get: function(){return distance;}, set: function(_){distance=_;}}, + snapDistance: {get: function(){return snapDistance;}, set: function(_){snapDistance=_;}}, + classes: {get: function(){return classes;}, set: function(_){classes=_;}}, + chartContainer: {get: function(){return chartContainer;}, set: function(_){chartContainer=_;}}, + enabled: {get: function(){return enabled;}, set: function(_){enabled=_;}}, + hideDelay: {get: function(){return hideDelay;}, set: function(_){hideDelay=_;}}, + contentGenerator: {get: function(){return contentGenerator;}, set: function(_){contentGenerator=_;}}, + valueFormatter: {get: function(){return valueFormatter;}, set: function(_){valueFormatter=_;}}, + headerFormatter: {get: function(){return headerFormatter;}, set: function(_){headerFormatter=_;}}, + keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}}, + headerEnabled: {get: function(){return headerEnabled;}, set: function(_){headerEnabled=_;}}, + position: {get: function(){return position;}, set: function(_){position=_;}}, + + // options with extra logic + hidden: {get: function(){return hidden;}, set: function(_){ + if (hidden != _) { + hidden = !!_; + nvtooltip(); + } + }}, + data: {get: function(){return data;}, set: function(_){ + // if showing a single data point, adjust data format with that + if (_.point) { + _.value = _.point.x; + _.series = _.series || {}; + _.series.value = _.point.y; + _.series.color = _.point.color || _.series.color; + } + data = _; + }}, + + // read only properties + node: {get: function(){return tooltip.node();}, set: function(_){}}, + id: {get: function(){return id;}, set: function(_){}} + }); + + nv.utils.initOptions(nvtooltip); + return nvtooltip; +}; /* Gets the browser window size - Returns object with height and width properties */ nv.utils.windowSize = function() { // Sane defaults var size = {width: 640, height: 480}; - // Earlier IE uses Doc.body - if (document.body && document.body.offsetWidth) { - size.width = document.body.offsetWidth; - size.height = document.body.offsetHeight; + // Most recent browsers use + if (window.innerWidth && window.innerHeight) { + size.width = window.innerWidth; + size.height = window.innerHeight; + return (size); } // IE can use depending on mode it is in @@ -933,17 +858,19 @@ nv.utils.windowSize = function() { size.width = document.documentElement.offsetWidth; size.height = document.documentElement.offsetHeight; + return (size); } - // Most recent browsers use - if (window.innerWidth && window.innerHeight) { - size.width = window.innerWidth; - size.height = window.innerHeight; + // Earlier IE uses Doc.body + if (document.body && document.body.offsetWidth) { + size.width = document.body.offsetWidth; + size.height = document.body.offsetHeight; + return (size); } + return (size); }; - /* Binds callback function to run when window is resized */ @@ -965,19 +892,25 @@ nv.utils.windowResize = function(handler) { /* Backwards compatible way to implement more d3-like coloring of graphs. -If passed an array, wrap it in a function which implements the old behavior -Else return what was passed in +Can take in nothing, an array, or a function/scale +To use a normal scale, get the range and pass that because we must be able +to take two arguments and use the index to keep backward compatibility */ nv.utils.getColor = function(color) { //if you pass in nothing, get default colors back - if (!arguments.length) { + if (color === undefined) { return nv.utils.defaultColor(); - //if passed an array, wrap it in a function - } else if(color instanceof Array) { - return function(d, i) { return d.color || color[i % color.length]; }; + //if passed an array, turn it into a color scale + // use isArray, instanceof fails if d3 range is created in an iframe + } else if(Array.isArray(color)) { + var color_scale = d3.scale.ordinal().range(color); + return function(d, i) { + var key = i === undefined ? d : i; + return d.color || color_scale(key); + }; - //if passed a function, return the function, or whatever it may be + //if passed a function or scale, return it, or whatever it may be //external libs, such as angularjs-nvd3-directives use this } else { //can't really help it if someone passes rubbish as color @@ -987,13 +920,12 @@ nv.utils.getColor = function(color) { /* -Default color chooser uses the index of an object as before. +Default color chooser uses a color scale of 20 colors from D3 + https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors */ nv.utils.defaultColor = function() { - var colors = d3.scale.category20().range(); - return function(d, i) { - return d.color || colors[i % colors.length] - }; + // get range of the scale so we'll turn it into our own function. + return nv.utils.getColor(d3.scale.category20().range()); }; @@ -1068,7 +1000,7 @@ nv.utils.calcApproxTextWidth = function (svgTextElem) { if (typeof svgTextElem.style === 'function' && typeof svgTextElem.text === 'function') { - var fontSize = parseInt(svgTextElem.style("font-size").replace("px","")); + var fontSize = parseInt(svgTextElem.style("font-size").replace("px",""), 10); var textLength = svgTextElem.text().length; return textLength * fontSize * 0.5; } @@ -1197,7 +1129,7 @@ gives: {a: 2, b: 3, c: 4} nv.utils.deepExtend = function(dst){ var sources = arguments.length > 1 ? [].slice.call(arguments, 1) : []; sources.forEach(function(source) { - for (key in source) { + for (var key in source) { var isArray = dst[key] instanceof Array; var isObject = typeof dst[key] === 'object'; var srcObj = typeof source[key] === 'object'; @@ -1292,12 +1224,10 @@ chart.options({ showXAxis: true, tooltips: true }); - To enable in the chart: chart.options = nv.utils.optionsFunc.bind(chart); */ nv.utils.optionsFunc = function(args) { - nv.deprecated('nv.utils.optionsFunc'); if (args) { d3.map(args).forEach((function(key,value) { if (typeof this[key] === "function") { @@ -1312,7 +1242,6 @@ nv.utils.optionsFunc = function(args) { /* numTicks: requested number of ticks data: the chart data - returns the number of ticks to actually use on X axis, based on chart data to avoid duplicate ticks with the same value */ @@ -1350,7 +1279,6 @@ nv.utils.calcTicksY = function(numTicks, data) { Add a particular option from an options object onto chart Options exposed on a chart are a getter/setter function that returns chart on set to mimic typical d3 option chaining, e.g. svg.option1('a').option2('b'); - option objects should be generated via Object.create() to provide the option of manipulating data via get/set functions. */ @@ -1361,9 +1289,19 @@ nv.utils.initOption = function(chart, name) { } else { chart[name] = function (_) { if (!arguments.length) return chart._options[name]; + chart._overrides[name] = true; chart._options[name] = _; return chart; }; + // calling the option as _option will ignore if set by option already + // so nvd3 can set options internally but the stop if set manually + chart['_' + name] = function(_) { + if (!arguments.length) return chart._options[name]; + if (!chart._overrides[name]) { + chart._options[name] = _; + } + return chart; + } } }; @@ -1372,6 +1310,7 @@ nv.utils.initOption = function(chart, name) { Add all options in an options object to the chart */ nv.utils.initOptions = function(chart) { + chart._overrides = chart._overrides || {}; var ops = Object.getOwnPropertyNames(chart._options || {}); var calls = Object.getOwnPropertyNames(chart._calls || {}); ops = ops.concat(calls); @@ -1469,7 +1408,93 @@ Runs common initialize code on the svg before the chart builds nv.utils.initSVG = function(svg) { svg.classed({'nvd3-svg':true}); }; -nv.models.axis = function() { + + +/* +Sanitize and provide default for the container height. +*/ +nv.utils.sanitizeHeight = function(height, container) { + return (height || parseInt(container.style('height'), 10) || 400); +}; + + +/* +Sanitize and provide default for the container width. +*/ +nv.utils.sanitizeWidth = function(width, container) { + return (width || parseInt(container.style('width'), 10) || 960); +}; + + +/* +Calculate the available height for a chart. +*/ +nv.utils.availableHeight = function(height, container, margin) { + return nv.utils.sanitizeHeight(height, container) - margin.top - margin.bottom; +}; + +/* +Calculate the available width for a chart. +*/ +nv.utils.availableWidth = function(width, container, margin) { + return nv.utils.sanitizeWidth(width, container) - margin.left - margin.right; +}; + +/* +Clear any rendered chart components and display a chart's 'noData' message +*/ +nv.utils.noData = function(chart, container) { + var opt = chart.options(), + margin = opt.margin(), + noData = opt.noData(), + data = (noData == null) ? ["No Data Available."] : [noData], + height = nv.utils.availableHeight(null, container, margin), + width = nv.utils.availableWidth(null, container, margin), + x = margin.left + width/2, + y = margin.top + height/2; + + //Remove any previously created chart components + container.selectAll('g').remove(); + + var noDataText = container.selectAll('.nv-noData').data(data); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', x) + .attr('y', y) + .text(function(t){ return t; }); +}; + +/* + Wrap long labels. + */ +nv.utils.wrapTicks = function (text, width) { + text.each(function() { + var text = d3.select(this), + words = text.text().split(/\s+/).reverse(), + word, + line = [], + lineNumber = 0, + lineHeight = 1.1, + y = text.attr("y"), + dy = parseFloat(text.attr("dy")), + tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em"); + while (word = words.pop()) { + line.push(word); + tspan.text(line.join(" ")); + if (tspan.node().getComputedTextLength() > width) { + line.pop(); + tspan.text(line.join(" ")); + line = [word]; + tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word); + } + } + }); +};nv.models.axis = function() { "use strict"; //============================================================ @@ -1484,7 +1509,6 @@ nv.models.axis = function() { , height = 60 //only used for tickLabel currently , axisLabelText = null , showMaxMin = true //TODO: showMaxMin should be disabled on all ordinal scaled axes - , highlightZero = true , rotateLabels = 0 , rotateYLabel = true , staggerLabels = false @@ -1493,8 +1517,6 @@ nv.models.axis = function() { , axisLabelDistance = 0 , duration = 250 , dispatch = d3.dispatch('renderEnd') - , axisRendered = false - , maxMinRendered = false ; axis .scale(scale) @@ -1519,7 +1541,7 @@ nv.models.axis = function() { var wrap = container.selectAll('g.nv-wrap.nv-axis').data([data]); var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-axis'); var gEnter = wrapEnter.append('g'); - var g = wrap.select('g') + var g = wrap.select('g'); if (ticks !== null) axis.ticks(ticks); @@ -1540,25 +1562,30 @@ nv.models.axis = function() { .data([axisLabelText || null]); axisLabel.exit().remove(); + var xLabelMargin; + var axisMaxMin; + var w; switch (axis.orient()) { case 'top': axisLabel.enter().append('text').attr('class', 'nv-axislabel'); - var w; - if (scale.range().length < 2) { - w = 0; + w = 0; + if (scale.range().length === 1) { + w = isOrdinal ? scale.range()[0] * 2 + scale.rangeBand() : 0; } else if (scale.range().length === 2) { - w = scale.range()[1]; - } else { - w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]); - } + w = isOrdinal ? scale.range()[0] + scale.range()[1] + scale.rangeBand() : scale.range()[1]; + } else if ( scale.range().length > 2){ + w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]); + }; axisLabel .attr('text-anchor', 'middle') .attr('y', 0) .attr('x', w/2); if (showMaxMin) { - var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') .data(scale.domain()); - axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text'); + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ') + }).append('text'); axisMaxMin.exit().remove(); axisMaxMin .attr('transform', function(d,i) { @@ -1579,42 +1606,49 @@ nv.models.axis = function() { } break; case 'bottom': - var xLabelMargin = axisLabelDistance + 36; + xLabelMargin = axisLabelDistance + 36; var maxTextWidth = 30; + var textHeight = 0; var xTicks = g.selectAll('g').select("text"); + var rotateLabelsRule = ''; if (rotateLabels%360) { //Calculate the longest xTick width xTicks.each(function(d,i){ - var width = this.getBoundingClientRect().width; + var box = this.getBoundingClientRect(); + var width = box.width; + textHeight = box.height; if(width > maxTextWidth) maxTextWidth = width; }); + rotateLabelsRule = 'rotate(' + rotateLabels + ' 0,' + (textHeight/2 + axis.tickPadding()) + ')'; //Convert to radians before calculating sin. Add 30 to margin for healthy padding. var sin = Math.abs(Math.sin(rotateLabels*Math.PI/180)); - var xLabelMargin = (sin ? sin*maxTextWidth : maxTextWidth)+30; + xLabelMargin = (sin ? sin*maxTextWidth : maxTextWidth)+30; //Rotate all xTicks xTicks - .attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' }) + .attr('transform', rotateLabelsRule) .style('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end'); } axisLabel.enter().append('text').attr('class', 'nv-axislabel'); - var w; - if (scale.range().length < 2) { - w = 0; + w = 0; + if (scale.range().length === 1) { + w = isOrdinal ? scale.range()[0] * 2 + scale.rangeBand() : 0; } else if (scale.range().length === 2) { - w = scale.range()[1]; - } else { + w = isOrdinal ? scale.range()[0] + scale.range()[1] + scale.rangeBand() : scale.range()[1]; + } else if ( scale.range().length > 2){ w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]); - } + }; axisLabel .attr('text-anchor', 'middle') .attr('y', xLabelMargin) .attr('x', w/2); if (showMaxMin) { //if (showMaxMin && !isOrdinal) { - var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') //.data(scale.domain()) .data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]); - axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text'); + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ') + }).append('text'); axisMaxMin.exit().remove(); axisMaxMin .attr('transform', function(d,i) { @@ -1623,7 +1657,7 @@ nv.models.axis = function() { .select('text') .attr('dy', '.71em') .attr('y', axis.tickPadding()) - .attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' }) + .attr('transform', rotateLabelsRule) .style('text-anchor', rotateLabels ? (rotateLabels%360 > 0 ? 'start' : 'end') : 'middle') .text(function(d,i) { var v = fmt(d); @@ -1646,12 +1680,14 @@ nv.models.axis = function() { axisLabel .style('text-anchor', rotateYLabel ? 'middle' : 'begin') .attr('transform', rotateYLabel ? 'rotate(90)' : '') - .attr('y', rotateYLabel ? (-Math.max(margin.right,width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart - .attr('x', rotateYLabel ? (scale.range()[0] / 2) : axis.tickPadding()); + .attr('y', rotateYLabel ? (-Math.max(margin.right, width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart + .attr('x', rotateYLabel ? (d3.max(scale.range()) / 2) : axis.tickPadding()); if (showMaxMin) { - var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') .data(scale.domain()); - axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text') + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ') + }).append('text') .style('opacity', 0); axisMaxMin.exit().remove(); axisMaxMin @@ -1663,7 +1699,7 @@ nv.models.axis = function() { .attr('y', 0) .attr('x', axis.tickPadding()) .style('text-anchor', 'start') - .text(function(d,i) { + .text(function(d, i) { var v = fmt(d); return ('' + v).match('NaN') ? '' : v; }); @@ -1688,12 +1724,14 @@ nv.models.axis = function() { axisLabel .style('text-anchor', rotateYLabel ? 'middle' : 'end') .attr('transform', rotateYLabel ? 'rotate(-90)' : '') - .attr('y', rotateYLabel ? (-Math.max(margin.left,width) + 25 - (axisLabelDistance || 0)) : -10) - .attr('x', rotateYLabel ? (-scale.range()[0] / 2) : -axis.tickPadding()); + .attr('y', rotateYLabel ? (-Math.max(margin.left, width) + 25 - (axisLabelDistance || 0)) : -10) + .attr('x', rotateYLabel ? (-d3.max(scale.range()) / 2) : -axis.tickPadding()); if (showMaxMin) { - var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') .data(scale.domain()); - axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text') + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ') + }).append('text') .style('opacity', 0); axisMaxMin.exit().remove(); axisMaxMin @@ -1747,7 +1785,7 @@ nv.models.axis = function() { .each(function(d,i) { try { if (i) // i== 1, max position - maxMinRange.push(scale(d) - this.getBoundingClientRect().width - 4) //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case) + maxMinRange.push(scale(d) - this.getBoundingClientRect().width - 4); //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case) else // i==0, min position maxMinRange.push(scale(d) + this.getBoundingClientRect().width + 4) }catch (err) { @@ -1758,7 +1796,7 @@ nv.models.axis = function() { } }); // the g's wrapping each tick - g.selectAll('g').each(function(d,i) { + g.selectAll('g').each(function(d, i) { if (scale(d) < maxMinRange[0] || scale(d) > maxMinRange[1]) { if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL d3.select(this).remove(); @@ -1768,14 +1806,18 @@ nv.models.axis = function() { }); } - //highlight zero line ... Maybe should not be an option and should just be in CSS? - if (highlightZero) { - g.selectAll('.tick') - .filter(function (d) { - return !parseFloat(Math.round(this.__data__ * 100000) / 1000000) && (this.__data__ !== undefined) - }) //this is because sometimes the 0 tick is a very small fraction, TODO: think of cleaner technique - .classed('zero', true); - } + //Highlight zero tick line + g.selectAll('.tick') + .filter(function (d) { + /* + The filter needs to return only ticks at or near zero. + Numbers like 0.00001 need to count as zero as well, + and the arithmetic trick below solves that. + */ + return !parseFloat(Math.round(d * 100000) / 1000000) && (d !== undefined) + }) + .classed('zero', true); + //store old scales for use in transitions on update scale0 = scale.copy(); @@ -1800,7 +1842,6 @@ nv.models.axis = function() { staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, rotateYLabel: {get: function(){return rotateYLabel;}, set: function(_){rotateYLabel=_;}}, - highlightZero: {get: function(){return highlightZero;}, set: function(_){highlightZero=_;}}, showMaxMin: {get: function(){return showMaxMin;}, set: function(_){showMaxMin=_;}}, axisLabel: {get: function(){return axisLabelText;}, set: function(_){axisLabelText=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, @@ -1832,12 +1873,7 @@ nv.models.axis = function() { return chart; }; - -// Chart design based on the recommendations of Stephen Few. Implementation -// based on the work of Clint Ivy, Jamie Love, and Jason Davies. -// http://projects.instantcognition.com/protovis/bulletchart/ - -nv.models.bullet = function() { +nv.models.boxPlot = function() { "use strict"; //============================================================ @@ -1845,10 +1881,569 @@ nv.models.bullet = function() { //------------------------------------------------------------ var margin = {top: 0, right: 0, bottom: 0, left: 0} - , orient = 'left' // TODO top & bottom - , reverse = false - , ranges = function(d) { return d.ranges } - , markers = function(d) { return d.markers ? d.markers : [0] } + , width = 960 + , height = 500 + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , x = d3.scale.ordinal() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , color = nv.utils.defaultColor() + , container = null + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') + , duration = 250 + , maxBoxWidth = null + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0; + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup Scales + x .domain(xDomain || data.map(function(d,i) { return getX(d,i); })) + .rangeBands(xRange || [0, availableWidth], .1); + + // if we know yDomain, no need to calculate + var yData = [] + if (!yDomain) { + // (y-range is based on quartiles, whiskers and outliers) + + // lower values + var yMin = d3.min(data.map(function(d) { + var min_arr = []; + + min_arr.push(d.values.Q1); + if (d.values.hasOwnProperty('whisker_low') && d.values.whisker_low !== null) { min_arr.push(d.values.whisker_low); } + if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { min_arr = min_arr.concat(d.values.outliers); } + + return d3.min(min_arr); + })); + + // upper values + var yMax = d3.max(data.map(function(d) { + var max_arr = []; + + max_arr.push(d.values.Q3); + if (d.values.hasOwnProperty('whisker_high') && d.values.whisker_high !== null) { max_arr.push(d.values.whisker_high); } + if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { max_arr = max_arr.concat(d.values.outliers); } + + return d3.max(max_arr); + })); + + yData = [ yMin, yMax ] ; + } + + y.domain(yDomain || yData); + y.range(yRange || [availableHeight, 0]); + + //store old scales if they exist + x0 = x0 || x; + y0 = y0 || y.copy().range([y(0),y(0)]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var boxplots = wrap.selectAll('.nv-boxplot').data(function(d) { return d }); + var boxEnter = boxplots.enter().append('g').style('stroke-opacity', 1e-6).style('fill-opacity', 1e-6); + boxplots + .attr('class', 'nv-boxplot') + .attr('transform', function(d,i,j) { return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05) + ', 0)'; }) + .classed('hover', function(d) { return d.hover }); + boxplots + .watchTransition(renderWatch, 'nv-boxplot: boxplots') + .style('stroke-opacity', 1) + .style('fill-opacity', .75) + .delay(function(d,i) { return i * duration / data.length }) + .attr('transform', function(d,i) { + return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05) + ', 0)'; + }); + boxplots.exit().remove(); + + // ----- add the SVG elements for each boxPlot ----- + + // conditionally append whisker lines + boxEnter.each(function(d,i) { + var box = d3.select(this); + + ['low', 'high'].forEach(function(key) { + if (d.values.hasOwnProperty('whisker_' + key) && d.values['whisker_' + key] !== null) { + box.append('line') + .style('stroke', (d.color) ? d.color : color(d,i)) + .attr('class', 'nv-boxplot-whisker nv-boxplot-' + key); + + box.append('line') + .style('stroke', (d.color) ? d.color : color(d,i)) + .attr('class', 'nv-boxplot-tick nv-boxplot-' + key); + } + }); + }); + + // outliers + // TODO: support custom colors here + var outliers = boxplots.selectAll('.nv-boxplot-outlier').data(function(d) { + if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { return d.values.outliers; } + else { return []; } + }); + outliers.enter().append('circle') + .style('fill', function(d,i,j) { return color(d,j) }).style('stroke', function(d,i,j) { return color(d,j) }) + .on('mouseover', function(d,i,j) { + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + series: { key: d, color: color(d,j) }, + e: d3.event + }); + }) + .on('mouseout', function(d,i,j) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + series: { key: d, color: color(d,j) }, + e: d3.event + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({e: d3.event}); + }); + + outliers.attr('class', 'nv-boxplot-outlier'); + outliers + .watchTransition(renderWatch, 'nv-boxplot: nv-boxplot-outlier') + .attr('cx', x.rangeBand() * .45) + .attr('cy', function(d,i,j) { return y(d); }) + .attr('r', '3'); + outliers.exit().remove(); + + var box_width = function() { return (maxBoxWidth === null ? x.rangeBand() * .9 : Math.min(75, x.rangeBand() * .9)); }; + var box_left = function() { return x.rangeBand() * .45 - box_width()/2; }; + var box_right = function() { return x.rangeBand() * .45 + box_width()/2; }; + + // update whisker lines and ticks + ['low', 'high'].forEach(function(key) { + var endpoint = (key === 'low') ? 'Q1' : 'Q3'; + + boxplots.select('line.nv-boxplot-whisker.nv-boxplot-' + key) + .watchTransition(renderWatch, 'nv-boxplot: boxplots') + .attr('x1', x.rangeBand() * .45 ) + .attr('y1', function(d,i) { return y(d.values['whisker_' + key]); }) + .attr('x2', x.rangeBand() * .45 ) + .attr('y2', function(d,i) { return y(d.values[endpoint]); }); + + boxplots.select('line.nv-boxplot-tick.nv-boxplot-' + key) + .watchTransition(renderWatch, 'nv-boxplot: boxplots') + .attr('x1', box_left ) + .attr('y1', function(d,i) { return y(d.values['whisker_' + key]); }) + .attr('x2', box_right ) + .attr('y2', function(d,i) { return y(d.values['whisker_' + key]); }); + }); + + ['low', 'high'].forEach(function(key) { + boxEnter.selectAll('.nv-boxplot-' + key) + .on('mouseover', function(d,i,j) { + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + series: { key: d.values['whisker_' + key], color: color(d,j) }, + e: d3.event + }); + }) + .on('mouseout', function(d,i,j) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + series: { key: d.values['whisker_' + key], color: color(d,j) }, + e: d3.event + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({e: d3.event}); + }); + }); + + // boxes + boxEnter.append('rect') + .attr('class', 'nv-boxplot-box') + // tooltip events + .on('mouseover', function(d,i) { + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + key: d.label, + value: d.label, + series: [ + { key: 'Q3', value: d.values.Q3, color: d.color || color(d,i) }, + { key: 'Q2', value: d.values.Q2, color: d.color || color(d,i) }, + { key: 'Q1', value: d.values.Q1, color: d.color || color(d,i) } + ], + data: d, + index: i, + e: d3.event + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + key: d.label, + value: d.label, + series: [ + { key: 'Q3', value: d.values.Q3, color: d.color || color(d,i) }, + { key: 'Q2', value: d.values.Q2, color: d.color || color(d,i) }, + { key: 'Q1', value: d.values.Q1, color: d.color || color(d,i) } + ], + data: d, + index: i, + e: d3.event + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({e: d3.event}); + }); + + // box transitions + boxplots.select('rect.nv-boxplot-box') + .watchTransition(renderWatch, 'nv-boxplot: boxes') + .attr('y', function(d,i) { return y(d.values.Q3); }) + .attr('width', box_width) + .attr('x', box_left ) + + .attr('height', function(d,i) { return Math.abs(y(d.values.Q3) - y(d.values.Q1)) || 1 }) + .style('fill', function(d,i) { return d.color || color(d,i) }) + .style('stroke', function(d,i) { return d.color || color(d,i) }); + + // median line + boxEnter.append('line').attr('class', 'nv-boxplot-median'); + + boxplots.select('line.nv-boxplot-median') + .watchTransition(renderWatch, 'nv-boxplot: boxplots line') + .attr('x1', box_left) + .attr('y1', function(d,i) { return y(d.values.Q2); }) + .attr('x2', box_right) + .attr('y2', function(d,i) { return y(d.values.Q2); }); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + }); + + renderWatch.renderEnd('nv-boxplot immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + maxBoxWidth: {get: function(){return maxBoxWidth;}, set: function(_){maxBoxWidth=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + // rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; +nv.models.boxPlotChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var boxplot = nv.models.boxPlot() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + ; + + var margin = {top: 15, right: 10, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.getColor() + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , staggerLabels = false + , tooltip = nv.models.tooltip() + , x + , y + , noData = "No Data Available." + , dispatch = d3.dispatch('beforeUpdate', 'renderEnd') + , duration = 250 + ; + + xAxis + .orient('bottom') + .showMaxMin(false) + .tickFormat(function(d) { return d }) + ; + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + .tickFormat(d3.format(',.1f')) + ; + + tooltip.duration(0); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(boxplot); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + chart.update = function() { + dispatch.beforeUpdate(); + container.transition().duration(duration).call(chart); + }; + chart.container = this; + + // Display No Data message if there's nothing to show. (quartiles required at minimum) + if (!data || !data.length || + !data.filter(function(d) { return d.values.hasOwnProperty("Q1") && d.values.hasOwnProperty("Q2") && d.values.hasOwnProperty("Q3"); }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = boxplot.xScale(); + y = boxplot.yScale().clamp(true); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-boxPlotWithAxes').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-boxPlotWithAxes').append('g'); + var defsEnter = gEnter.append('defs'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis') + .append('g').attr('class', 'nv-zeroLine') + .append('line'); + + gEnter.append('g').attr('class', 'nv-barsWrap'); + + g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Main Chart Component(s) + boxplot + .width(availableWidth) + .height(availableHeight); + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })) + + barsWrap.transition().call(boxplot); + + + defsEnter.append('clipPath') + .attr('id', 'nv-x-label-clip-' + boxplot.id()) + .append('rect'); + + g.select('#nv-x-label-clip-' + boxplot.id() + ' rect') + .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1)) + .attr('height', 16) + .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 )); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis').attr('transform', 'translate(0,' + y.range()[0] + ')'); + g.select('.nv-x.nv-axis').call(xAxis); + + var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); + if (staggerLabels) { + xTicks + .selectAll('text') + .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' }) + } + } + + if (showYAxis) { + yAxis + .scale(y) + .ticks( Math.floor(availableHeight/36) ) // can't use nv.utils.calcTicksY with Object data + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis').call(yAxis); + } + + // Zero line + g.select(".nv-zeroLine line") + .attr("x1",0) + .attr("x2",availableWidth) + .attr("y1", y(0)) + .attr("y2", y(0)) + ; + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + }); + + renderWatch.renderEnd('nv-boxplot chart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + boxplot.dispatch.on('elementMouseover.tooltip', function(evt) { + tooltip.data(evt).hidden(false); + }); + + boxplot.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.data(evt).hidden(true); + }); + + boxplot.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.boxplot = boxplot; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + boxplot.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + boxplot.color(color); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }} + }); + + nv.utils.inheritOptions(chart, boxplot); + nv.utils.initOptions(chart); + + return chart; +} + +// Chart design based on the recommendations of Stephen Few. Implementation +// based on the work of Clint Ivy, Jamie Love, and Jason Davies. +// http://projects.instantcognition.com/protovis/bulletchart/ + +nv.models.bullet = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , orient = 'left' // TODO top & bottom + , reverse = false + , ranges = function(d) { return d.ranges } + , markers = function(d) { return d.markers ? d.markers : [0] } , measures = function(d) { return d.measures } , rangeLabels = function(d) { return d.rangeLabels ? d.rangeLabels : [] } , markerLabels = function(d) { return d.markerLabels ? d.markerLabels : [] } @@ -1856,16 +2451,18 @@ nv.models.bullet = function() { , forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.) , width = 380 , height = 30 + , container = null , tickFormat = null , color = nv.utils.getColor(['#1f77b4']) - , dispatch = d3.dispatch('elementMouseover', 'elementMouseout') + , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove') ; function chart(selection) { selection.each(function(d, i) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); nv.utils.initSVG(container); var rangez = ranges.call(this, d, i).slice().sort(d3.descending), @@ -1903,7 +2500,6 @@ nv.models.bullet = function() { gEnter.append('rect').attr('class', 'nv-range nv-rangeAvg'); gEnter.append('rect').attr('class', 'nv-range nv-rangeMin'); gEnter.append('rect').attr('class', 'nv-measure'); - gEnter.append('path').attr('class', 'nv-markerTriangle'); wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -1944,54 +2540,83 @@ nv.models.bullet = function() { dispatch.elementMouseover({ value: measurez[0], label: measureLabelz[0] || 'Current', - pos: [x1(measurez[0]), availableHeight/2] + color: d3.select(this).style("fill") + }) + }) + .on('mousemove', function() { + dispatch.elementMousemove({ + value: measurez[0], + label: measureLabelz[0] || 'Current', + color: d3.select(this).style("fill") }) }) .on('mouseout', function() { dispatch.elementMouseout({ value: measurez[0], - label: measureLabelz[0] || 'Current' + label: measureLabelz[0] || 'Current', + color: d3.select(this).style("fill") }) }); var h3 = availableHeight / 6; - if (markerz[0]) { - g.selectAll('path.nv-markerTriangle') - .attr('transform', function(d) { return 'translate(' + x1(markerz[0]) + ',' + (availableHeight / 2) + ')' }) - .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z') - .on('mouseover', function() { - dispatch.elementMouseover({ - value: markerz[0], - label: markerLabelz[0] || 'Previous', - pos: [x1(markerz[0]), availableHeight/2] - }) + + var markerData = markerz.map( function(marker, index) { + return {value: marker, label: markerLabelz[index]} + }); + gEnter + .selectAll("path.nv-markerTriangle") + .data(markerData) + .enter() + .append('path') + .attr('class', 'nv-markerTriangle') + .attr('transform', function(d) { return 'translate(' + x1(d.value) + ',' + (availableHeight / 2) + ')' }) + .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z') + .on('mouseover', function(d) { + dispatch.elementMouseover({ + value: d.value, + label: d.label || 'Previous', + color: d3.select(this).style("fill"), + pos: [x1(d.value), availableHeight/2] + }) + + }) + .on('mousemove', function(d) { + dispatch.elementMousemove({ + value: d.value, + label: d.label || 'Previous', + color: d3.select(this).style("fill") }) - .on('mouseout', function() { - dispatch.elementMouseout({ - value: markerz[0], - label: markerLabelz[0] || 'Previous' - }) - }); - } else { - g.selectAll('path.nv-markerTriangle').remove(); - } + }) + .on('mouseout', function(d, i) { + dispatch.elementMouseout({ + value: d.value, + label: d.label || 'Previous', + color: d3.select(this).style("fill") + }) + }); wrap.selectAll('.nv-range') .on('mouseover', function(d,i) { var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum"); - dispatch.elementMouseover({ value: d, label: label, - pos: [x1(d), availableHeight/2] + color: d3.select(this).style("fill") + }) + }) + .on('mousemove', function() { + dispatch.elementMousemove({ + value: measurez[0], + label: measureLabelz[0] || 'Previous', + color: d3.select(this).style("fill") }) }) .on('mouseout', function(d,i) { var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum"); - dispatch.elementMouseout({ value: d, - label: label + label: label, + color: d3.select(this).style("fill") }) }); }); @@ -2048,8 +2673,8 @@ nv.models.bulletChart = function() { // Public Variables with Default Settings //------------------------------------------------------------ - var bullet = nv.models.bullet() - ; + var bullet = nv.models.bullet(); + var tooltip = nv.models.tooltip(); var orient = 'left' // TODO top & bottom , reverse = false @@ -2060,34 +2685,21 @@ nv.models.bulletChart = function() { , width = null , height = 55 , tickFormat = null - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

' + x + '

' + - '

' + y + '

' - } - , noData = 'No Data Available.' - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide') + , ticks = null + , noData = null + , dispatch = d3.dispatch() ; - //============================================================ - // Private Variables - //------------------------------------------------------------ - - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ) + margin.left, - top = e.pos[1] + ( offsetElement.offsetTop || 0) + margin.top, - content = tooltip(e.key, e.label, e.value, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'e' : 'w', null, offsetElement); - }; + tooltip + .duration(0) + .headerEnabled(false); function chart(selection) { selection.each(function(d, i) { var container = d3.select(this); nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, + var availableWidth = nv.utils.availableWidth(width, container, margin), availableHeight = height - margin.top - margin.bottom, that = this; @@ -2096,18 +2708,7 @@ nv.models.bulletChart = function() { // Display No Data message if there's nothing to show. if (!d || !ranges.call(this, d, i)) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', 18 + margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -2156,128 +2757,350 @@ nv.models.bulletChart = function() { .attr('dy', '1em') .text(function(d) { return d.subtitle; }); - bullet - .width(availableWidth) - .height(availableHeight) + bullet + .width(availableWidth) + .height(availableHeight) + + var bulletWrap = g.select('.nv-bulletWrap'); + d3.transition(bulletWrap).call(bullet); + + // Compute the tick format. + var format = tickFormat || x1.tickFormat( availableWidth / 100 ); + + // Update the tick groups. + var tick = g.selectAll('g.nv-tick') + .data(x1.ticks( ticks ? ticks : (availableWidth / 50) ), function(d) { + return this.textContent || format(d); + }); + + // Initialize the ticks with the old scale, x0. + var tickEnter = tick.enter().append('g') + .attr('class', 'nv-tick') + .attr('transform', function(d) { return 'translate(' + x0(d) + ',0)' }) + .style('opacity', 1e-6); + + tickEnter.append('line') + .attr('y1', availableHeight) + .attr('y2', availableHeight * 7 / 6); + + tickEnter.append('text') + .attr('text-anchor', 'middle') + .attr('dy', '1em') + .attr('y', availableHeight * 7 / 6) + .text(format); + + // Transition the updating ticks to the new scale, x1. + var tickUpdate = d3.transition(tick) + .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' }) + .style('opacity', 1); + + tickUpdate.select('line') + .attr('y1', availableHeight) + .attr('y2', availableHeight * 7 / 6); + + tickUpdate.select('text') + .attr('y', availableHeight * 7 / 6); + + // Transition the exiting ticks to the new scale, x1. + d3.transition(tick.exit()) + .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' }) + .style('opacity', 1e-6) + .remove(); + }); + + d3.timer.flush(); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + bullet.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: evt.label, + value: evt.value, + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + bullet.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + bullet.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.bullet = bullet; + chart.dispatch = dispatch; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + ranges: {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good) + markers: {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal) + measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast) + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + tickFormat: {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}}, + ticks: {get: function(){return ticks;}, set: function(_){ticks=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom + orient = _; + reverse = orient == 'right' || orient == 'bottom'; + }} + }); + + nv.utils.inheritOptions(chart, bullet); + nv.utils.initOptions(chart); + + return chart; +}; + + + +nv.models.candlestickBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container + , x = d3.scale.linear() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , getOpen = function(d) { return d.open } + , getClose = function(d) { return d.close } + , getHigh = function(d) { return d.high } + , getLow = function(d) { return d.low } + , forceX = [] + , forceY = [] + , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart + , clipEdge = true + , color = nv.utils.defaultColor() + , interactive = false + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + function chart(selection) { + selection.each(function(data) { + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + nv.utils.initSVG(container); + + // Width of the candlestick bars. + var barWidth = (availableWidth / data[0].values.length) * .45; + + // Setup Scales + x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) )); - var bulletWrap = g.select('.nv-bulletWrap'); - d3.transition(bulletWrap).call(bullet); + if (padData) + x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); + else + x.range(xRange || [5 + barWidth / 2, availableWidth - barWidth / 2 - 5]); - // Compute the tick format. - var format = tickFormat || x1.tickFormat( availableWidth / 100 ); + y.domain(yDomain || [ + d3.min(data[0].values.map(getLow).concat(forceY)), + d3.max(data[0].values.map(getHigh).concat(forceY)) + ] + ).range(yRange || [availableHeight, 0]); - // Update the tick groups. - var tick = g.selectAll('g.nv-tick') - .data(x1.ticks( availableWidth / 50 ), function(d) { - return this.textContent || format(d); - }); + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); - // Initialize the ticks with the old scale, x0. - var tickEnter = tick.enter().append('g') - .attr('class', 'nv-tick') - .attr('transform', function(d) { return 'translate(' + x0(d) + ',0)' }) - .style('opacity', 1e-6); + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01]) + : y.domain([-1,1]); - tickEnter.append('line') - .attr('y1', availableHeight) - .attr('y2', availableHeight * 7 / 6); + // Setup containers and skeleton of chart + var wrap = d3.select(this).selectAll('g.nv-wrap.nv-candlestickBar').data([data[0].values]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-candlestickBar'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); - tickEnter.append('text') - .attr('text-anchor', 'middle') - .attr('dy', '1em') - .attr('y', availableHeight * 7 / 6) - .text(format); + gEnter.append('g').attr('class', 'nv-ticks'); - // Transition the updating ticks to the new scale, x1. - var tickUpdate = d3.transition(tick) - .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' }) - .style('opacity', 1); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - tickUpdate.select('line') - .attr('y1', availableHeight) - .attr('y2', availableHeight * 7 / 6); + container + .on('click', function(d,i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); - tickUpdate.select('text') - .attr('y', availableHeight * 7 / 6); + defsEnter.append('clipPath') + .attr('id', 'nv-chart-clip-path-' + id) + .append('rect'); - // Transition the exiting ticks to the new scale, x1. - d3.transition(tick.exit()) - .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' }) - .style('opacity', 1e-6) - .remove(); + wrap.select('#nv-chart-clip-path-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); - //============================================================ - // Event Handling/Dispatching (in chart's scope) - //------------------------------------------------------------ + g .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : ''); - dispatch.on('tooltipShow', function(e) { - e.key = d.title; - if (tooltips) showTooltip(e, that.parentNode); - }); + var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick') + .data(function(d) { return d }); + ticks.exit().remove(); + + var tickGroups = ticks.enter().append('g'); + + // The colors are currently controlled by CSS. + ticks + .attr('class', function(d, i, j) { return (getOpen(d, i) > getClose(d, i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i}); + + var lines = tickGroups.append('line') + .attr('class', 'nv-candlestick-lines') + .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; }) + .attr('x1', 0) + .attr('y1', function(d, i) { return y(getHigh(d, i)); }) + .attr('x2', 0) + .attr('y2', function(d, i) { return y(getLow(d, i)); }); + + var rects = tickGroups.append('rect') + .attr('class', 'nv-candlestick-rects nv-bars') + .attr('transform', function(d, i) { + return 'translate(' + (x(getX(d, i)) - barWidth/2) + ',' + + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0)) + + ')'; + }) + .attr('x', 0) + .attr('y', 0) + .attr('width', barWidth) + .attr('height', function(d, i) { + var open = getOpen(d, i); + var close = getClose(d, i); + return open > close ? y(close) - y(open) : y(open) - y(close); + }); + ticks.select('.nv-candlestick-lines').transition() + .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; }) + .attr('x1', 0) + .attr('y1', function(d, i) { return y(getHigh(d, i)); }) + .attr('x2', 0) + .attr('y2', function(d, i) { return y(getLow(d, i)); }); + + ticks.select('.nv-candlestick-rects').transition() + .attr('transform', function(d, i) { + return 'translate(' + (x(getX(d, i)) - barWidth/2) + ',' + + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0)) + + ')'; + }) + .attr('x', 0) + .attr('y', 0) + .attr('width', barWidth) + .attr('height', function(d, i) { + var open = getOpen(d, i); + var close = getClose(d, i); + return open > close ? y(close) - y(open) : y(open) - y(close); + }); }); - d3.timer.flush(); return chart; } - //============================================================ - // Event Handling/Dispatching (out of chart's scope) - //------------------------------------------------------------ - - bullet.dispatch.on('elementMouseover.tooltip', function(e) { - dispatch.tooltipShow(e); - }); - bullet.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); + //Create methods to allow outside functions to highlight a specific bar. + chart.highlightPoint = function(pointIndex, isHoverOver) { + chart.clearHighlights(); + container.select(".nv-candlestickBar .nv-tick-0-" + pointIndex) + .classed("hover", isHoverOver) + ; + }; - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); - }); + chart.clearHighlights = function() { + container.select(".nv-candlestickBar .nv-tick.hover") + .classed("hover", false) + ; + }; //============================================================ // Expose Public Variables //------------------------------------------------------------ - chart.bullet = bullet; chart.dispatch = dispatch; chart.options = nv.utils.optionsFunc.bind(chart); chart._options = Object.create({}, { // simple options, just get/set the necessary values - ranges: {get: function(){return ranges;}, set: function(_){ranges=_;}}, // ranges (bad, satisfactory, good) - markers: {get: function(){return markers;}, set: function(_){markers=_;}}, // markers (previous, goal) - measures: {get: function(){return measures;}, set: function(_){measures=_;}}, // measures (actual, forecast) width: {get: function(){return width;}, set: function(_){width=_;}}, - height: {get: function(){return height;}, set: function(_){height=_;}}, - tickFormat: {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, - noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + padData: {get: function(){return padData;}, set: function(_){padData=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}}, + + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + open: {get: function(){return getOpen();}, set: function(_){getOpen=_;}}, + close: {get: function(){return getClose();}, set: function(_){getClose=_;}}, + high: {get: function(){return getHigh;}, set: function(_){getHigh=_;}}, + low: {get: function(){return getLow;}, set: function(_){getLow=_;}}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ - margin.top = _.top !== undefined ? _.top : margin.top; - margin.right = _.right !== undefined ? _.right : margin.right; - margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; - margin.left = _.left !== undefined ? _.left : margin.left; + margin.top = _.top != undefined ? _.top : margin.top; + margin.right = _.right != undefined ? _.right : margin.right; + margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom; + margin.left = _.left != undefined ? _.left : margin.left; }}, - orient: {get: function(){return orient;}, set: function(_){ // left, right, top, bottom - orient = _; - reverse = orient == 'right' || orient == 'bottom'; + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); }} }); - nv.utils.inheritOptions(chart, bullet); nv.utils.initOptions(chart); - return chart; }; - - nv.models.cumulativeLineChart = function() { "use strict"; @@ -2291,6 +3114,7 @@ nv.models.cumulativeLineChart = function() { , legend = nv.models.legend() , controls = nv.models.legend() , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 30, bottom: 50, left: 60} @@ -2301,22 +3125,17 @@ nv.models.cumulativeLineChart = function() { , showXAxis = true , showYAxis = true , rightAlignYAxis = false - , tooltips = true , showControls = true , useInteractiveGuideline = false , rescaleY = true - , tooltip = function(key, x, y, e, graph) { - return '

' + key + '

' + - '

' + y + ' at ' + x + '

' - } , x //can be accessed via chart.xScale() , y //can be accessed via chart.yScale() , id = lines.id() , state = nv.utils.state() , defaultState = null - , noData = 'No Data Available.' + , noData = null , average = function(d) { return d.average } - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd') , transitionDuration = 250 , duration = 250 , noErrorCheck = false //if set to TRUE, will bypass an error check in the indexify function. @@ -2325,13 +3144,14 @@ nv.models.cumulativeLineChart = function() { state.index = 0; state.rescaleY = rescaleY; - xAxis - .orient('bottom') - .tickPadding(7) - ; - yAxis - .orient((rightAlignYAxis) ? 'right' : 'left') - ; + xAxis.orient('bottom').tickPadding(7); + yAxis.orient((rightAlignYAxis) ? 'right' : 'left'); + + tooltip.valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); controls.updateState(false); @@ -2344,16 +3164,6 @@ nv.models.cumulativeLineChart = function() { , renderWatch = nv.utils.renderWatch(dispatch, duration) ; - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, null, null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -2388,10 +3198,8 @@ nv.models.cumulativeLineChart = function() { container.classed('nv-chart-' + id, true); var that = this; - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { if (duration === 0) @@ -2448,18 +3256,7 @@ nv.models.cumulativeLineChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -2525,8 +3322,7 @@ nv.models.cumulativeLineChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.nv-legendWrap') @@ -2668,7 +3464,7 @@ nv.models.cumulativeLineChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/70, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/70, data) ) .tickSize(-availableHeight, 0); g.select('.nv-x.nv-axis') @@ -2680,7 +3476,7 @@ nv.models.cumulativeLineChart = function() { if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis') @@ -2777,9 +3573,7 @@ nv.models.cumulativeLineChart = function() { var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex), pointIndex); interactiveLayer.tooltip - .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) .chartContainer(that.parentNode) - .enabled(tooltips) .valueFormatter(function(d,i) { return yAxis.tickFormat()(d); }) @@ -2794,17 +3588,11 @@ nv.models.cumulativeLineChart = function() { }); interactiveLayer.dispatch.on("elementMouseout",function(e) { - dispatch.tooltipHide(); lines.clearHighlights(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined') { data.forEach(function(series,i) { series.disabled = e.disabled[i]; @@ -2841,17 +3629,18 @@ nv.models.cumulativeLineChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - lines.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - lines.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + lines.dispatch.on('elementMouseover.tooltip', function(evt) { + var point = { + x: chart.x()(evt.point), + y: chart.y()(evt.point), + color: evt.point.color + }; + evt.point = point; + tooltip.data(evt).hidden(false); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + lines.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) }); //============================================================ @@ -2899,10 +3688,12 @@ nv.models.cumulativeLineChart = function() { chart.dispatch = dispatch; chart.lines = lines; chart.legend = legend; + chart.controls = controls; chart.xAxis = xAxis; chart.yAxis = yAxis; chart.interactiveLayer = interactiveLayer; chart.state = state; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -2914,8 +3705,6 @@ nv.models.cumulativeLineChart = function() { showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, average: {get: function(){return average;}, set: function(_){average=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, @@ -2957,7 +3746,8 @@ nv.models.cumulativeLineChart = function() { nv.utils.initOptions(chart); return chart; -};//TODO: consider deprecating by adding necessary features to multiBar model +}; +//TODO: consider deprecating by adding necessary features to multiBar model nv.models.discreteBar = function() { "use strict"; @@ -2969,6 +3759,7 @@ nv.models.discreteBar = function() { , width = 960 , height = 500 , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container , x = d3.scale.ordinal() , y = d3.scale.linear() , getX = function(d) { return d.x } @@ -2981,7 +3772,7 @@ nv.models.discreteBar = function() { , yDomain , xRange , yRange - , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout','renderEnd') + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') , rectClass = 'discreteBar' , duration = 250 ; @@ -2997,8 +3788,9 @@ nv.models.discreteBar = function() { renderWatch.reset(); selection.each(function(data) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); nv.utils.initSVG(container); //add series index to each data point for reference @@ -3068,47 +3860,39 @@ nv.models.discreteBar = function() { .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here d3.select(this).classed('hover', true); dispatch.elementMouseover({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('mouseout', function(d,i) { d3.select(this).classed('hover', false); dispatch.elementMouseout({ - value: getY(d,i), - point: d, - series: data[d.series], - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('click', function(d,i) { dispatch.elementClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }) .on('dblclick', function(d,i) { dispatch.elementDblClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }); @@ -3225,6 +4009,7 @@ nv.models.discreteBarChart = function() { var discretebar = nv.models.discreteBar() , xAxis = nv.models.axis() , yAxis = nv.models.axis() + , tooltip = nv.models.tooltip() ; var margin = {top: 15, right: 10, bottom: 50, left: 60} @@ -3235,21 +4020,17 @@ nv.models.discreteBarChart = function() { , showYAxis = true , rightAlignYAxis = false , staggerLabels = false - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

' + x + '

' + - '

' + y + '

' - } + , wrapLabels = false + , rotateLabels = 0 , x , y - , noData = "No Data Available." - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'beforeUpdate','renderEnd') + , noData = null + , dispatch = d3.dispatch('beforeUpdate','renderEnd') , duration = 250 ; xAxis .orient('bottom') - .highlightZero(false) .showMaxMin(false) .tickFormat(function(d) { return d }) ; @@ -3258,20 +4039,20 @@ nv.models.discreteBarChart = function() { .tickFormat(d3.format(',.1f')) ; + tooltip + .duration(0) + .headerEnabled(false) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .keyFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(discretebar.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(discretebar.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var renderWatch = nv.utils.renderWatch(dispatch, duration); function chart(selection) { @@ -3284,10 +4065,8 @@ nv.models.discreteBarChart = function() { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { dispatch.beforeUpdate(); @@ -3297,18 +4076,7 @@ nv.models.discreteBarChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container); return chart; } else { container.selectAll('.nv-noData').remove(); @@ -3344,7 +4112,7 @@ nv.models.discreteBarChart = function() { .height(availableHeight); var barsWrap = g.select('.nv-barsWrap') - .datum(data.filter(function(d) { return !d.disabled })) + .datum(data.filter(function(d) { return !d.disabled })); barsWrap.transition().call(discretebar); @@ -3362,7 +4130,7 @@ nv.models.discreteBarChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight, 0); g.select('.nv-x.nv-axis') @@ -3372,15 +4140,27 @@ nv.models.discreteBarChart = function() { var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); if (staggerLabels) { xTicks - .selectAll('text') - .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' }) + .selectAll('text') + .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' }) + } + + if (rotateLabels) { + xTicks + .selectAll('.tick text') + .attr('transform', 'rotate(' + rotateLabels + ' 0,0)') + .style('text-anchor', rotateLabels > 0 ? 'start' : 'end'); + } + + if (wrapLabels) { + g.selectAll('.tick text') + .call(nv.utils.wrapTicks, chart.xAxis.rangeBand()) } } if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis').call(yAxis); @@ -3393,15 +4173,6 @@ nv.models.discreteBarChart = function() { .attr("y1", y(0)) .attr("y2", y(0)) ; - - //============================================================ - // Event Handling/Dispatching (in chart's scope) - //------------------------------------------------------------ - - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - }); renderWatch.renderEnd('discreteBar chart immediate'); @@ -3412,17 +4183,21 @@ nv.models.discreteBarChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - discretebar.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + discretebar.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: chart.x()(evt.data), + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - discretebar.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + discretebar.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + discretebar.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -3433,6 +4208,7 @@ nv.models.discreteBarChart = function() { chart.discretebar = discretebar; chart.xAxis = xAxis; chart.yAxis = yAxis; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -3441,10 +4217,10 @@ nv.models.discreteBarChart = function() { width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, + wrapLabels: {get: function(){return wrapLabels;}, set: function(_){wrapLabels=!!_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, // options that require extra logic in the setter @@ -3636,6 +4412,353 @@ nv.models.distribution = function() { return chart; } +nv.models.furiousLegend = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 5, right: 0, bottom: 5, left: 0} + , width = 400 + , height = 20 + , getKey = function(d) { return d.key } + , color = nv.utils.getColor() + , maxKeyLength = 20 //default value for key lengths + , align = true + , padding = 28 //define how much space between legend items. - recommend 32 for furious version + , rightAlign = true + , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch. + , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time) + , expanded = false + , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange') + , vers = 'classic' //Options are "classic" and "furious" + ; + + function chart(selection) { + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-legend').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g'); + var g = wrap.select('g'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var series = g.selectAll('.nv-series') + .data(function(d) { + if(vers != 'furious') return d; + + return d.filter(function(n) { + return expanded ? true : !n.disengaged; + }); + }); + var seriesEnter = series.enter().append('g').attr('class', 'nv-series') + + var seriesShape; + + if(vers == 'classic') { + seriesEnter.append('circle') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('r', 5); + + seriesShape = series.select('circle'); + } else if (vers == 'furious') { + seriesEnter.append('rect') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('rx', 3) + .attr('ry', 3); + + seriesShape = series.select('rect'); + + seriesEnter.append('g') + .attr('class', 'nv-check-box') + .property('innerHTML','') + .attr('transform', 'translate(-10,-8)scale(0.5)'); + + var seriesCheckbox = series.select('.nv-check-box'); + + seriesCheckbox.each(function(d,i) { + d3.select(this).selectAll('path') + .attr('stroke', setTextColor(d,i)); + }); + } + + seriesEnter.append('text') + .attr('text-anchor', 'start') + .attr('class','nv-legend-text') + .attr('dy', '.32em') + .attr('dx', '8'); + + var seriesText = series.select('text.nv-legend-text'); + + series + .on('mouseover', function(d,i) { + dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects + }) + .on('mouseout', function(d,i) { + dispatch.legendMouseout(d,i); + }) + .on('click', function(d,i) { + dispatch.legendClick(d,i); + // make sure we re-get data in case it was modified + var data = series.data(); + if (updateState) { + if(vers =='classic') { + if (radioButtonMode) { + //Radio button mode: set every series to disabled, + // and enable the clicked series. + data.forEach(function(series) { series.disabled = true}); + d.disabled = false; + } + else { + d.disabled = !d.disabled; + if (data.every(function(series) { return series.disabled})) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { series.disabled = false}); + } + } + } else if(vers == 'furious') { + if(expanded) { + d.disengaged = !d.disengaged; + d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled; + d.disabled = d.disengaged || d.userDisabled; + } else if (!expanded) { + d.disabled = !d.disabled; + d.userDisabled = d.disabled; + var engaged = data.filter(function(d) { return !d.disengaged; }); + if (engaged.every(function(series) { return series.userDisabled })) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { + series.disabled = series.userDisabled = false; + }); + } + } + } + dispatch.stateChange({ + disabled: data.map(function(d) { return !!d.disabled }), + disengaged: data.map(function(d) { return !!d.disengaged }) + }); + + } + }) + .on('dblclick', function(d,i) { + if(vers == 'furious' && expanded) return; + dispatch.legendDblclick(d,i); + if (updateState) { + // make sure we re-get data in case it was modified + var data = series.data(); + //the default behavior of NVD3 legends, when double clicking one, + // is to set all other series' to false, and make the double clicked series enabled. + data.forEach(function(series) { + series.disabled = true; + if(vers == 'furious') series.userDisabled = series.disabled; + }); + d.disabled = false; + if(vers == 'furious') d.userDisabled = d.disabled; + dispatch.stateChange({ + disabled: data.map(function(d) { return !!d.disabled }) + }); + } + }); + + series.classed('nv-disabled', function(d) { return d.userDisabled }); + series.exit().remove(); + + seriesText + .attr('fill', setTextColor) + .text(getKey); + + //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option) + // NEW ALIGNING CODE, TODO: clean up + + var versPadding; + switch(vers) { + case 'furious' : + versPadding = 23; + break; + case 'classic' : + versPadding = 20; + } + + if (align) { + + var seriesWidths = []; + series.each(function(d,i) { + var legendText; + if (getKey(d).length > maxKeyLength) { + var trimmedKey = getKey(d).substring(0, maxKeyLength); + legendText = d3.select(this).select('text').text(trimmedKey + "..."); + d3.select(this).append("svg:title").text(getKey(d)); + } else { + legendText = d3.select(this).select('text'); + } + var nodeTextLength; + try { + nodeTextLength = legendText.node().getComputedTextLength(); + // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead + if(nodeTextLength <= 0) throw Error(); + } + catch(e) { + nodeTextLength = nv.utils.calcApproxTextWidth(legendText); + } + + seriesWidths.push(nodeTextLength + padding); + }); + + var seriesPerRow = 0; + var legendWidth = 0; + var columnWidths = []; + + while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) { + columnWidths[seriesPerRow] = seriesWidths[seriesPerRow]; + legendWidth += seriesWidths[seriesPerRow++]; + } + if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row + + while ( legendWidth > availableWidth && seriesPerRow > 1 ) { + columnWidths = []; + seriesPerRow--; + + for (var k = 0; k < seriesWidths.length; k++) { + if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) ) + columnWidths[k % seriesPerRow] = seriesWidths[k]; + } + + legendWidth = columnWidths.reduce(function(prev, cur, index, array) { + return prev + cur; + }); + } + + var xPositions = []; + for (var i = 0, curX = 0; i < seriesPerRow; i++) { + xPositions[i] = curX; + curX += columnWidths[i]; + } + + series + .attr('transform', function(d, i) { + return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')'; + }); + + //position legend as far right as possible within the total width + if (rightAlign) { + g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')'); + } + else { + g.attr('transform', 'translate(0' + ',' + margin.top + ')'); + } + + height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding); + + } else { + + var ypos = 5, + newxpos = 5, + maxwidth = 0, + xpos; + series + .attr('transform', function(d, i) { + var length = d3.select(this).select('text').node().getComputedTextLength() + padding; + xpos = newxpos; + + if (width < margin.left + margin.right + xpos + length) { + newxpos = xpos = 5; + ypos += versPadding; + } + + newxpos += length; + if (newxpos > maxwidth) maxwidth = newxpos; + + return 'translate(' + xpos + ',' + ypos + ')'; + }); + + //position legend as far right as possible within the total width + g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')'); + + height = margin.top + margin.bottom + ypos + 15; + } + + if(vers == 'furious') { + // Size rectangles after text is placed + seriesShape + .attr('width', function(d,i) { + return seriesText[0][i].getComputedTextLength() + 27; + }) + .attr('height', 18) + .attr('y', -9) + .attr('x', -15) + } + + seriesShape + .style('fill', setBGColor) + .style('stroke', function(d,i) { return d.color || color(d, i) }); + }); + + function setTextColor(d,i) { + if(vers != 'furious') return '#000'; + if(expanded) { + return d.disengaged ? color(d,i) : '#fff'; + } else if (!expanded) { + return !!d.disabled ? color(d,i) : '#fff'; + } + } + + function setBGColor(d,i) { + if(expanded && vers == 'furious') { + return d.disengaged ? '#fff' : color(d,i); + } else { + return !!d.disabled ? '#fff' : color(d,i); + } + } + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + key: {get: function(){return getKey;}, set: function(_){getKey=_;}}, + align: {get: function(){return align;}, set: function(_){align=_;}}, + rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}}, + maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}}, + padding: {get: function(){return padding;}, set: function(_){padding=_;}}, + updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}}, + radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}}, + expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}}, + vers: {get: function(){return vers;}, set: function(_){vers=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; //TODO: consider deprecating and using multibar with single series for this nv.models.historicalBar = function() { "use strict"; @@ -3648,6 +4771,7 @@ nv.models.historicalBar = function() { , width = null , height = null , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null , x = d3.scale.linear() , y = d3.scale.linear() , getX = function(d) { return d.x } @@ -3661,7 +4785,7 @@ nv.models.historicalBar = function() { , yDomain , xRange , yRange - , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') , interactive = true ; @@ -3671,11 +4795,9 @@ nv.models.historicalBar = function() { selection.each(function(data) { renderWatch.reset(); - var container = d3.select(this); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right; - var availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); nv.utils.initSVG(container); @@ -3735,7 +4857,7 @@ nv.models.historicalBar = function() { .data(function(d) { return d }, function(d,i) {return getX(d,i)}); bars.exit().remove(); - var barsEnter = bars.enter().append('rect') + bars.enter().append('rect') .attr('x', 0 ) .attr('y', function(d,i) { return nv.utils.NaNtoZero(y(Math.max(0, getY(d,i)))) }) .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.abs(y(getY(d,i)) - y(0))) }) @@ -3744,12 +4866,9 @@ nv.models.historicalBar = function() { if (!interactive) return; d3.select(this).classed('hover', true); dispatch.elementMouseover({ - point: d, - series: data[0], - pos: [x(getX(d,i)), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: 0, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); }) @@ -3757,36 +4876,34 @@ nv.models.historicalBar = function() { if (!interactive) return; d3.select(this).classed('hover', false); dispatch.elementMouseout({ - point: d, - series: data[0], - pointIndex: i, - seriesIndex: 0, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + if (!interactive) return; + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('click', function(d,i) { if (!interactive) return; dispatch.elementClick({ - //label: d[label], - value: getY(d,i), data: d, index: i, - pos: [x(getX(d,i)), y(getY(d,i))], - e: d3.event, - id: id + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }) .on('dblclick', function(d,i) { if (!interactive) return; dispatch.elementDblClick({ - //label: d[label], - value: getY(d,i), data: d, index: i, - pos: [x(getX(d,i)), y(getY(d,i))], - e: d3.event, - id: id + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }); @@ -3818,14 +4935,14 @@ nv.models.historicalBar = function() { //Create methods to allow outside functions to highlight a specific bar. chart.highlightPoint = function(pointIndex, isHoverOver) { - d3.select(".nv-historicalBar-" + id) + container .select(".nv-bars .nv-bar-0-" + pointIndex) .classed("hover", isHoverOver) ; }; chart.clearHighlights = function() { - d3.select(".nv-historicalBar-" + id) + container .select(".nv-bars .nv-bar.hover") .classed("hover", false) ; @@ -3886,6 +5003,7 @@ nv.models.historicalBarChart = function(bar_model) { , yAxis = nv.models.axis() , legend = nv.models.legend() , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() ; @@ -3898,54 +5016,32 @@ nv.models.historicalBarChart = function(bar_model) { , showYAxis = true , rightAlignYAxis = false , useInteractiveGuideline = false - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

' + key + '

' + - '

' + y + ' at ' + x + '

' - } , x , y , state = {} , defaultState = null - , noData = 'No Data Available.' - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , noData = null + , dispatch = d3.dispatch('tooltipHide', 'stateChange', 'changeState', 'renderEnd') , transitionDuration = 250 ; - xAxis - .orient('bottom') - .tickPadding(7) - ; - yAxis - .orient( (rightAlignYAxis) ? 'right' : 'left') - ; + xAxis.orient('bottom').tickPadding(7); + yAxis.orient( (rightAlignYAxis) ? 'right' : 'left'); + tooltip + .duration(0) + .headerEnabled(false) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - - // New addition to calculate position if SVG is scaled with viewBox, may move TODO: consider implementing everywhere else - if (offsetElement) { - var svg = d3.select(offsetElement).select('svg'); - var viewBox = (svg.node()) ? svg.attr('viewBox') : null; - if (viewBox) { - viewBox = viewBox.split(' '); - var ratio = parseInt(svg.style('width')) / viewBox[2]; - e.pos[0] = e.pos[0] * ratio; - e.pos[1] = e.pos[1] * ratio; - } - } - - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(bars.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(bars.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, null, null, offsetElement); - }; var renderWatch = nv.utils.renderWatch(dispatch, 0); function chart(selection) { @@ -3958,11 +5054,8 @@ nv.models.historicalBarChart = function(bar_model) { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; - + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { container.transition().duration(transitionDuration).call(chart) }; chart.container = this; @@ -3983,18 +5076,7 @@ nv.models.historicalBarChart = function(bar_model) { // Display noData message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -4025,8 +5107,7 @@ nv.models.historicalBarChart = function(bar_model) { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } wrap.select('.nv-legendWrap') @@ -4064,6 +5145,7 @@ nv.models.historicalBarChart = function(bar_model) { if (showXAxis) { xAxis .scale(x) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight, 0); g.select('.nv-x.nv-axis') @@ -4076,7 +5158,7 @@ nv.models.historicalBarChart = function(bar_model) { if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis') @@ -4101,9 +5183,9 @@ nv.models.historicalBarChart = function(bar_model) { pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); bars.highlightPoint(pointIndex,true); var point = series.values[pointIndex]; - if (typeof point === 'undefined') return; - if (typeof singlePoint === 'undefined') singlePoint = point; - if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + if (point === undefined) return; + if (singlePoint === undefined) singlePoint = point; + if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); allData.push({ key: series.key, value: chart.y()(point, pointIndex), @@ -4114,18 +5196,15 @@ nv.models.historicalBarChart = function(bar_model) { var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); interactiveLayer.tooltip - .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) .chartContainer(that.parentNode) - .enabled(tooltips) .valueFormatter(function(d,i) { return yAxis.tickFormat()(d); }) - .data( - { + .data({ value: xValue, + index: pointIndex, series: allData - } - )(); + })(); interactiveLayer.renderGuideLine(pointXLocation); @@ -4165,12 +5244,7 @@ nv.models.historicalBarChart = function(bar_model) { chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined') { data.forEach(function(series,i) { series.disabled = e.disabled[i]; @@ -4191,17 +5265,21 @@ nv.models.historicalBarChart = function(bar_model) { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - bars.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + bars.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: chart.x()(evt.data), + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - bars.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + bars.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + bars.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -4215,6 +5293,7 @@ nv.models.historicalBarChart = function(bar_model) { chart.xAxis = xAxis; chart.yAxis = yAxis; chart.interactiveLayer = interactiveLayer; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -4225,8 +5304,6 @@ nv.models.historicalBarChart = function(bar_model) { showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, @@ -4267,7 +5344,7 @@ nv.models.historicalBarChart = function(bar_model) { }; -// ohlcChart is just a historical chart with oclc bars and some tweaks +// ohlcChart is just a historical chart with ohlc bars and some tweaks nv.models.ohlcBarChart = function() { var chart = nv.models.historicalBarChart(nv.models.ohlcBar()); @@ -4288,7 +5365,31 @@ nv.models.ohlcBarChart = function() { ''; }); return chart; -};nv.models.legend = function() { +}; + +// candlestickChart is just a historical chart with candlestick bars and some tweaks +nv.models.candlestickBarChart = function() { + var chart = nv.models.historicalBarChart(nv.models.candlestickBar()); + + // special default tooltip since we show multiple values per x + chart.useInteractiveGuideline(true); + chart.interactiveLayer.tooltip.contentGenerator(function(data) { + // we assume only one series exists for this chart + var d = data.series[0].data; + // match line colors as defined in nv.d3.css + var color = d.open < d.close ? "2ca02c" : "d62728"; + return '' + + '

' + data.value + '

' + + '' + + '' + + '' + + '' + + '' + + '
open:' + chart.yAxis.tickFormat()(d.open) + '
close:' + chart.yAxis.tickFormat()(d.close) + '
high' + chart.yAxis.tickFormat()(d.high) + '
low:' + chart.yAxis.tickFormat()(d.low) + '
'; + }); + return chart; +}; +nv.models.legend = function() { "use strict"; //============================================================ @@ -4299,12 +5400,16 @@ nv.models.ohlcBarChart = function() { , width = 400 , height = 20 , getKey = function(d) { return d.key } - , color = nv.utils.defaultColor() + , color = nv.utils.getColor() + , maxKeyLength = 20 //default value for key lengths , align = true + , padding = 32 //define how much space between legend items. - recommend 32 for furious version , rightAlign = true , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch. , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time) + , expanded = false , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange') + , vers = 'classic' //Options are "classic" and "furious" ; function chart(selection) { @@ -4318,12 +5423,66 @@ nv.models.ohlcBarChart = function() { var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g'); var g = wrap.select('g'); - wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); var series = g.selectAll('.nv-series') - .data(function(d) { return d }); - var seriesEnter = series.enter().append('g').attr('class', 'nv-series') + .data(function(d) { + if(vers != 'furious') return d; + + return d.filter(function(n) { + return expanded ? true : !n.disengaged; + }); + }); + + var seriesEnter = series.enter().append('g').attr('class', 'nv-series'); + var seriesShape; + + var versPadding; + switch(vers) { + case 'furious' : + versPadding = 23; + break; + case 'classic' : + versPadding = 20; + } + + if(vers == 'classic') { + seriesEnter.append('circle') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('r', 5); + + seriesShape = series.select('circle'); + } else if (vers == 'furious') { + seriesEnter.append('rect') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('rx', 3) + .attr('ry', 3); + seriesShape = series.select('.nv-legend-symbol'); + + seriesEnter.append('g') + .attr('class', 'nv-check-box') + .property('innerHTML','') + .attr('transform', 'translate(-10,-8)scale(0.5)'); + + var seriesCheckbox = series.select('.nv-check-box'); + + seriesCheckbox.each(function(d,i) { + d3.select(this).selectAll('path') + .attr('stroke', setTextColor(d,i)); + }); + } + + seriesEnter.append('text') + .attr('text-anchor', 'start') + .attr('class','nv-legend-text') + .attr('dy', '.32em') + .attr('dx', '8'); + + var seriesText = series.select('text.nv-legend-text'); + + series .on('mouseover', function(d,i) { dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects }) @@ -4332,63 +5491,91 @@ nv.models.ohlcBarChart = function() { }) .on('click', function(d,i) { dispatch.legendClick(d,i); + // make sure we re-get data in case it was modified + var data = series.data(); if (updateState) { - if (radioButtonMode) { - //Radio button mode: set every series to disabled, - // and enable the clicked series. - data.forEach(function(series) { series.disabled = true}); - d.disabled = false; - } - else { - d.disabled = !d.disabled; - if (data.every(function(series) { return series.disabled})) { - //the default behavior of NVD3 legends is, if every single series - // is disabled, turn all series' back on. - data.forEach(function(series) { series.disabled = false}); + if(vers =='classic') { + if (radioButtonMode) { + //Radio button mode: set every series to disabled, + // and enable the clicked series. + data.forEach(function(series) { series.disabled = true}); + d.disabled = false; + } + else { + d.disabled = !d.disabled; + if (data.every(function(series) { return series.disabled})) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { series.disabled = false}); + } + } + } else if(vers == 'furious') { + if(expanded) { + d.disengaged = !d.disengaged; + d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled; + d.disabled = d.disengaged || d.userDisabled; + } else if (!expanded) { + d.disabled = !d.disabled; + d.userDisabled = d.disabled; + var engaged = data.filter(function(d) { return !d.disengaged; }); + if (engaged.every(function(series) { return series.userDisabled })) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { + series.disabled = series.userDisabled = false; + }); + } } } dispatch.stateChange({ - disabled: data.map(function(d) { return !!d.disabled }) + disabled: data.map(function(d) { return !!d.disabled }), + disengaged: data.map(function(d) { return !!d.disengaged }) }); + } }) .on('dblclick', function(d,i) { + if(vers == 'furious' && expanded) return; dispatch.legendDblclick(d,i); if (updateState) { + // make sure we re-get data in case it was modified + var data = series.data(); //the default behavior of NVD3 legends, when double clicking one, // is to set all other series' to false, and make the double clicked series enabled. data.forEach(function(series) { series.disabled = true; + if(vers == 'furious') series.userDisabled = series.disabled; }); d.disabled = false; + if(vers == 'furious') d.userDisabled = d.disabled; dispatch.stateChange({ disabled: data.map(function(d) { return !!d.disabled }) }); } }); - seriesEnter.append('circle') - .style('stroke-width', 2) - .attr('class','nv-legend-symbol') - .attr('r', 5); - seriesEnter.append('text') - .attr('text-anchor', 'start') - .attr('class','nv-legend-text') - .attr('dy', '.32em') - .attr('dx', '8'); - series.classed('nv-disabled', function(d) { return d.disabled }); + + series.classed('nv-disabled', function(d) { return d.userDisabled }); series.exit().remove(); - series.select('circle') - .style('fill', function(d,i) { return d.color || color(d,i)}) - .style('stroke', function(d,i) { return d.color || color(d, i) }); - series.select('text').text(getKey); + + seriesText + .attr('fill', setTextColor) + .text(getKey); //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option) // NEW ALIGNING CODE, TODO: clean up + var legendWidth = 0; if (align) { var seriesWidths = []; series.each(function(d,i) { - var legendText = d3.select(this).select('text'); + var legendText; + if (getKey(d).length > maxKeyLength) { + var trimmedKey = getKey(d).substring(0, maxKeyLength); + legendText = d3.select(this).select('text').text(trimmedKey + "..."); + d3.select(this).append("svg:title").text(getKey(d)); + } else { + legendText = d3.select(this).select('text'); + } var nodeTextLength; try { nodeTextLength = legendText.node().getComputedTextLength(); @@ -4399,12 +5586,12 @@ nv.models.ohlcBarChart = function() { nodeTextLength = nv.utils.calcApproxTextWidth(legendText); } - seriesWidths.push(nodeTextLength + 28); // 28 is ~ the width of the circle plus some padding + seriesWidths.push(nodeTextLength + padding); }); var seriesPerRow = 0; - var legendWidth = 0; var columnWidths = []; + legendWidth = 0; while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) { columnWidths[seriesPerRow] = seriesWidths[seriesPerRow]; @@ -4434,28 +5621,18 @@ nv.models.ohlcBarChart = function() { series .attr('transform', function(d, i) { - return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * 20) + ')'; + return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')'; }); - var bg = g.insert('rect', 'g') - .attr('height', height) - .attr('width', legendWidth > 0 ? legendWidth : 0) - .attr('transform', 'translate(-10,-5)') - .style('fill', '#eee'); - - height = d3.select(this.parentNode.parentNode.parentNode).attr('height'); - //console.log('height: ' + height); - //position legend as far right as possible within the total width if (rightAlign) { - g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + (height - 50) + ')'); + g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')'); } else { - g.attr('transform', 'translate(0' + ',' + (height - 50) + ')'); - //console.log(g.attr('transform')); + g.attr('transform', 'translate(0' + ',' + margin.top + ')'); } - height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * 20); + height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding); } else { @@ -4465,17 +5642,20 @@ nv.models.ohlcBarChart = function() { xpos; series .attr('transform', function(d, i) { - var length = d3.select(this).select('text').node().getComputedTextLength() + 28; + var length = d3.select(this).select('text').node().getComputedTextLength() + padding; xpos = newxpos; if (width < margin.left + margin.right + xpos + length) { newxpos = xpos = 5; - ypos += 20; + ypos += versPadding; } newxpos += length; if (newxpos > maxwidth) maxwidth = newxpos; + if(legendWidth < xpos + maxwidth) { + legendWidth = xpos + maxwidth; + } return 'translate(' + xpos + ',' + ypos + ')'; }); @@ -4484,8 +5664,70 @@ nv.models.ohlcBarChart = function() { height = margin.top + margin.bottom + ypos + 15; } + + if(vers == 'furious') { + // Size rectangles after text is placed + seriesShape + .attr('width', function(d,i) { + return seriesText[0][i].getComputedTextLength() + 27; + }) + .attr('height', 18) + .attr('y', -9) + .attr('x', -15); + + // The background for the expanded legend (UI) + gEnter.insert('rect',':first-child') + .attr('class', 'nv-legend-bg') + .attr('fill', '#eee') + // .attr('stroke', '#444') + .attr('opacity',0); + + var seriesBG = g.select('.nv-legend-bg'); + + seriesBG + .transition().duration(300) + .attr('x', -versPadding ) + .attr('width', legendWidth + versPadding - 12) + .attr('height', height + 10) + .attr('y', -margin.top - 10) + .attr('opacity', expanded ? 1 : 0); + + + } + + seriesShape + .style('fill', setBGColor) + .style('fill-opacity', setBGOpacity) + .style('stroke', setBGColor); }); + function setTextColor(d,i) { + if(vers != 'furious') return '#000'; + if(expanded) { + return d.disengaged ? '#000' : '#fff'; + } else if (!expanded) { + if(!d.color) d.color = color(d,i); + return !!d.disabled ? d.color : '#fff'; + } + } + + function setBGColor(d,i) { + if(expanded && vers == 'furious') { + return d.disengaged ? '#eee' : d.color || color(d,i); + } else { + return d.color || color(d,i); + } + } + + + function setBGOpacity(d,i) { + if(expanded && vers == 'furious') { + return 1; + } else { + return !!d.disabled ? 0 : 1; + } + } + return chart; } @@ -4500,11 +5742,15 @@ nv.models.ohlcBarChart = function() { // simple options, just get/set the necessary values width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, - key: {get: function(){return getKey;}, set: function(_){getKey=_;}}, + key: {get: function(){return getKey;}, set: function(_){getKey=_;}}, align: {get: function(){return align;}, set: function(_){align=_;}}, + maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}}, rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}}, - updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}}, + padding: {get: function(){return padding;}, set: function(_){padding=_;}}, + updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}}, radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}}, + expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}}, + vers: {get: function(){return vers;}, set: function(_){vers=_;}}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ @@ -4535,6 +5781,8 @@ nv.models.line = function() { var margin = {top: 0, right: 0, bottom: 0, left: 0} , width = 960 , height = 500 + , container = null + , strokeWidth = 1.5 , color = nv.utils.defaultColor() // a function that returns a color , getX = function(d) { return d.x } // accessor to get the x value from a data point , getY = function(d) { return d.y } // accessor to get the y value from a data point @@ -4571,9 +5819,9 @@ nv.models.line = function() { renderWatch.reset(); renderWatch.models(scatter); selection.each(function(data) { - var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); nv.utils.initSVG(container); // Setup Scales @@ -4607,7 +5855,7 @@ nv.models.line = function() { .append('rect'); wrap.select('#nv-edge-clip-' + scatter.id() + ' rect') - .attr('width', availableWidth > 0 ? availableWidth : 0) + .attr('width', availableWidth) .attr('height', (availableHeight > 0) ? availableHeight : 0); g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : ''); @@ -4618,18 +5866,21 @@ nv.models.line = function() { .data(function(d) { return d }, function(d) { return d.key }); groups.enter().append('g') .style('stroke-opacity', 1e-6) + .style('stroke-width', function(d) { return d.strokeWidth || strokeWidth }) .style('fill-opacity', 1e-6); groups.exit().remove(); groups - .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .attr('class', function(d,i) { + return (d.classed || '') + ' nv-group nv-series-' + i; + }) .classed('hover', function(d) { return d.hover }) .style('fill', function(d,i){ return color(d, i) }) .style('stroke', function(d,i){ return color(d, i)}); groups.watchTransition(renderWatch, 'line: groups') .style('stroke-opacity', 1) - .style('fill-opacity', .5); + .style('fill-opacity', function(d) { return d.fillOpacity || .5}); var areaPaths = groups.selectAll('path.nv-area') .data(function(d) { return isArea(d) ? [d] : [] }); // this is done differently than lines because I need to check if series is an area @@ -4662,6 +5913,7 @@ nv.models.line = function() { var linePaths = groups.selectAll('path.nv-line') .data(function(d) { return [d.values] }); + linePaths.enter().append('path') .attr('class', 'nv-line') .attr('d', @@ -4697,9 +5949,9 @@ nv.models.line = function() { chart.dispatch = dispatch; chart.scatter = scatter; // Pass through events - scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); }) - scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); }) - scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); }) + scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); }); + scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); }); + scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); }); chart.options = nv.utils.optionsFunc.bind(chart); @@ -4757,6 +6009,7 @@ nv.models.lineChart = function() { , yAxis = nv.models.axis() , legend = nv.models.legend() , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 20, bottom: 50, left: 60} @@ -4768,45 +6021,32 @@ nv.models.lineChart = function() { , showYAxis = true , rightAlignYAxis = false , useInteractiveGuideline = false - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

' + key + '

' + - '

' + y + ' at ' + x + '

' - } , x , y , state = nv.utils.state() , defaultState = null - , noData = 'No Data Available.' + , noData = null , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') , duration = 250 ; - xAxis - .orient('bottom') - .tickPadding(7) - ; - yAxis - .orient((rightAlignYAxis) ? 'right' : 'left') - ; + // set options on sub-objects for this chart + xAxis.orient('bottom').tickPadding(7); + yAxis.orient(rightAlignYAxis ? 'right' : 'left'); + tooltip.valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, null, null, offsetElement); - }; - var renderWatch = nv.utils.renderWatch(dispatch, duration); - var stateGetter = function(data) { + var stateGetter = function(data) { return function(){ return { active: data.map(function(d) { return !d.disabled }) @@ -4833,11 +6073,12 @@ nv.models.lineChart = function() { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; - + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + //EDIT + if (availableWidth < 0) availableWidth = 0; + if (availableHeight < 0) availableHeight = 0; + //END EDIT chart.update = function() { if (duration === 0) @@ -4868,23 +6109,13 @@ nv.models.lineChart = function() { // Display noData message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); } + // Setup Scales x = lines.xScale(); y = lines.yScale(); @@ -4900,10 +6131,12 @@ nv.models.lineChart = function() { gEnter.append('g').attr('class', 'nv-linesWrap'); gEnter.append('g').attr('class', 'nv-legendWrap'); gEnter.append('g').attr('class', 'nv-interactive'); + //EDIT gEnter.append('g').attr('class', 'en-postMarkers'); + //END EDIT g.select("rect") - .attr("width", availableWidth > 0 ? availableWidth : 0) + .attr("width",availableWidth) .attr("height",(availableHeight > 0) ? availableHeight : 0); //EDIT @@ -4928,8 +6161,7 @@ nv.models.lineChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } wrap.select('.nv-legendWrap') @@ -5014,7 +6246,7 @@ nv.models.lineChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks(nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight, 0); g.select('.nv-x.nv-axis') @@ -5026,7 +6258,7 @@ nv.models.lineChart = function() { if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks(nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis') @@ -5054,14 +6286,17 @@ nv.models.lineChart = function() { }) .forEach(function(series,i) { pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); - lines.highlightPoint(i, pointIndex, true); var point = series.values[pointIndex]; - if (typeof point === 'undefined') return; - if (typeof singlePoint === 'undefined') singlePoint = point; - if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + var pointYValue = chart.y()(point, pointIndex); + if (pointYValue != null) { + lines.highlightPoint(i, pointIndex, true); + } + if (point === undefined) return; + if (singlePoint === undefined) singlePoint = point; + if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); allData.push({ key: series.key, - value: chart.y()(point, pointIndex), + value: pointYValue, color: color(series,series.seriesIndex) }); }); @@ -5076,31 +6311,31 @@ nv.models.lineChart = function() { } //EDIT var postMarkerTooltip; - postSeries.values.forEach(function(markerData) { - if (e.mouseX >= markerData.markerX && e.mouseX <= markerData.markerX + 16 && e.mouseY >= markerData.markerY && e.mouseY <= markerData.markerY + 16) { - postMarkerTooltip = { - label: markerData.label, - postDate: markerData.x - }; - } - }); - //END EDIT + if (postSeries) { + postSeries.values.forEach(function(markerData) { + if (e.mouseX >= markerData.markerX && e.mouseX <= markerData.markerX + 16 && e.mouseY >= markerData.markerY && e.mouseY <= markerData.markerY + 16) { + postMarkerTooltip = { + label: markerData.label, + postDate: markerData.x + }; + } + }); + } var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); + var obj = { + value: xValue, + index: pointIndex, + series: allData + }; + if (postMarkerTooltip) obj.postMarkerTooltip = postMarkerTooltip; interactiveLayer.tooltip - .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) .chartContainer(that.parentNode) - .enabled(tooltips) .valueFormatter(function(d,i) { - return yAxis.tickFormat()(d); + return d == null ? "N/A" : yAxis.tickFormat()(d); }) - .data( - { - value: xValue, - series: allData, - postMarkerTooltip: postMarkerTooltip - } - )(); + .data(obj)(); + //END EDIT interactiveLayer.renderGuideLine(pointXLocation); @@ -5131,16 +6366,10 @@ nv.models.lineChart = function() { }); interactiveLayer.dispatch.on("elementMouseout",function(e) { - dispatch.tooltipHide(); lines.clearHighlights(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) { data.forEach(function(series,i) { series.disabled = e.disabled[i]; @@ -5162,17 +6391,12 @@ nv.models.lineChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - lines.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - lines.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + lines.dispatch.on('elementMouseover.tooltip', function(evt) { + tooltip.data(evt).hidden(false); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + lines.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); //============================================================ @@ -5186,6 +6410,7 @@ nv.models.lineChart = function() { chart.xAxis = xAxis; chart.yAxis = yAxis; chart.interactiveLayer = interactiveLayer; + chart.tooltip = tooltip; chart.dispatch = dispatch; chart.options = nv.utils.optionsFunc.bind(chart); @@ -5197,8 +6422,6 @@ nv.models.lineChart = function() { showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, @@ -5258,6 +6481,7 @@ nv.models.linePlusBarChart = function() { , y4Axis = nv.models.axis() , legend = nv.models.legend() , brush = d3.svg.brush() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 30, bottom: 30, left: 60} @@ -5274,19 +6498,14 @@ nv.models.linePlusBarChart = function() { , focusHeight = 50 , extent , brushExtent = null - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

' + key + '

' + - '

' + y + ' at ' + x + '

'; - } , x , x2 , y1 , y2 , y3 , y4 - , noData = "No Data Available." - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush', 'stateChange', 'changeState') + , noData = null + , dispatch = d3.dispatch('brush', 'stateChange', 'changeState') , transitionDuration = 0 , state = nv.utils.state() , defaultState = null @@ -5294,50 +6513,25 @@ nv.models.linePlusBarChart = function() { , legendRightAxisHint = ' (right axis)' ; - lines - .clipEdge(true) - ; - lines2 - .interactive(false) - ; - xAxis - .orient('bottom') - .tickPadding(5) - ; - y1Axis - .orient('left') - ; - y2Axis - .orient('right') - ; - x2Axis - .orient('bottom') - .tickPadding(5) - ; - y3Axis - .orient('left') - ; - y4Axis - .orient('right') - ; + lines.clipEdge(true); + lines2.interactive(false); + // We don't want any points emitted for the focus chart's scatter graph. + lines2.pointActive(function(d) { return false }); + xAxis.orient('bottom').tickPadding(5); + y1Axis.orient('left'); + y2Axis.orient('right'); + x2Axis.orient('bottom').tickPadding(5); + y3Axis.orient('left'); + y4Axis.orient('right'); + + tooltip.headerEnabled(true).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - if (extent) { - e.pointIndex += Math.ceil(extent[0]); - } - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), - y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -5355,15 +6549,20 @@ nv.models.linePlusBarChart = function() { } }; + var allDisabled = function(data) { + return data.every(function(series) { + return series.disabled; + }); + } + function chart(selection) { selection.each(function(data) { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight1 = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom - (focusEnable ? focusHeight : 0) , + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight1 = nv.utils.availableHeight(height, container, margin) + - (focusEnable ? focusHeight : 0), availableHeight2 = focusHeight - margin2.top - margin2.bottom; chart.update = function() { container.transition().duration(transitionDuration).call(chart); }; @@ -5390,18 +6589,7 @@ nv.models.linePlusBarChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight1 / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -5469,7 +6657,10 @@ nv.models.linePlusBarChart = function() { //------------------------------------------------------------ if (showLegend) { - legend.width( availableWidth / 2 ); + var legendWidth = legend.align() ? availableWidth / 2 : availableWidth; + var legendXPosition = legend.align() ? legendWidth : 0; + + legend.width(legendWidth); g.select('.nv-legendWrap') .datum(data.map(function(series) { @@ -5481,12 +6672,12 @@ nv.models.linePlusBarChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight1 = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom - focusHeight; + // FIXME: shouldn't this be "- (focusEnabled ? focusHeight : 0)"? + availableHeight1 = nv.utils.availableHeight(height, container, margin) - focusHeight; } g.select('.nv-legendWrap') - .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')'); + .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')'); } wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -5519,10 +6710,12 @@ nv.models.linePlusBarChart = function() { .datum(dataBars.length ? dataBars : [ {values: []} ]); - var lines2Wrap = g.select('.nv-context .nv-linesWrap') - .datum(!dataLines[0].disabled ? dataLines : [ - {values: []} - ]); + var lines2Wrap = g.select('.nv-context .nv-linesWrap') + .datum(allDisabled(dataLines) ? + [{values: []}] : + dataLines.filter(function(dataLine) { + return !dataLine.disabled; + })); g.select('.nv-context') .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')'); @@ -5533,7 +6726,7 @@ nv.models.linePlusBarChart = function() { // context (focus chart) axis controls if (focusShowAxisX) { x2Axis - .ticks(nv.utils.calcTicksX(availableWidth / 100, data)) + ._ticks( nv.utils.calcTicksX(availableWidth / 100, data)) .tickSize(-availableHeight2, 0); g.select('.nv-context .nv-x.nv-axis') .attr('transform', 'translate(0,' + y3.range()[0] + ')'); @@ -5544,11 +6737,11 @@ nv.models.linePlusBarChart = function() { if (focusShowAxisY) { y3Axis .scale(y3) - .ticks( availableHeight2 / 36 ) + ._ticks( availableHeight2 / 36 ) .tickSize( -availableWidth, 0); y4Axis .scale(y4) - .ticks( availableHeight2 / 36 ) + ._ticks( availableHeight2 / 36 ) .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none g.select('.nv-context .nv-y3.nv-axis') @@ -5605,10 +6798,6 @@ nv.models.linePlusBarChart = function() { chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { if (typeof e.disabled !== 'undefined') { @@ -5692,10 +6881,13 @@ nv.models.linePlusBarChart = function() { ); var focusLinesWrap = g.select('.nv-focus .nv-linesWrap') - .datum(dataLines[0].disabled ? [{values:[]}] : - dataLines - .map(function(d,i) { + .datum(allDisabled(dataLines) ? [{values:[]}] : + dataLines + .filter(function(dataLine) { return !dataLine.disabled; }) + .map(function(d,i) { return { + area: d.area, + fillOpacity: d.fillOpacity, key: d.key, values: d.values.filter(function(d,i) { return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; @@ -5713,7 +6905,7 @@ nv.models.linePlusBarChart = function() { xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight1, 0); xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]); @@ -5731,17 +6923,17 @@ nv.models.linePlusBarChart = function() { y1Axis .scale(y1) - .ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) .tickSize(-availableWidth, 0); y2Axis .scale(y2) - .ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none g.select('.nv-focus .nv-y1.nv-axis') .style('opacity', dataBars.length ? 1 : 0); g.select('.nv-focus .nv-y2.nv-axis') - .style('opacity', dataLines.length && !dataLines[0].disabled ? 1 : 0) + .style('opacity', dataLines.length && !allDisabled(dataLines) ? 1 : 0) .attr('transform', 'translate(' + x.range()[1] + ',0)'); g.select('.nv-focus .nv-y1.nv-axis').transition().duration(transitionDuration) @@ -5761,26 +6953,41 @@ nv.models.linePlusBarChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - lines.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + lines.dispatch.on('elementMouseover.tooltip', function(evt) { + tooltip + .duration(100) + .valueFormatter(function(d, i) { + return y2Axis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); }); - lines.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + lines.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) }); - bars.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + bars.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.value = chart.x()(evt.data); + evt['series'] = { + value: chart.y()(evt.data), + color: evt.color + }; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return y1Axis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); }); - bars.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + bars.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + bars.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -5803,6 +7010,7 @@ nv.models.linePlusBarChart = function() { chart.y2Axis = y2Axis; chart.y3Axis = y3Axis; chart.y4Axis = y4Axis; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -5811,8 +7019,6 @@ nv.models.linePlusBarChart = function() { width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}}, @@ -5829,6 +7035,12 @@ nv.models.linePlusBarChart = function() { margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; margin.left = _.left !== undefined ? _.left : margin.left; }}, + focusMargin: {get: function(){return margin2;}, set: function(_){ + margin2.top = _.top !== undefined ? _.top : margin2.top; + margin2.right = _.right !== undefined ? _.right : margin2.right; + margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom; + margin2.left = _.left !== undefined ? _.left : margin2.left; + }}, duration: {get: function(){return transitionDuration;}, set: function(_){ transitionDuration = _; }}, @@ -5872,6 +7084,8 @@ nv.models.lineWithFocusChart = function() { , y2Axis = nv.models.axis() , legend = nv.models.legend() , brush = d3.svg.brush() + , tooltip = nv.models.tooltip() + , interactiveLayer = nv.interactiveGuideline() ; var margin = {top: 30, right: 30, bottom: 30, left: 60} @@ -5879,60 +7093,40 @@ nv.models.lineWithFocusChart = function() { , color = nv.utils.defaultColor() , width = null , height = null - , height2 = 100 + , height2 = 50 + , useInteractiveGuideline = false , x , y , x2 , y2 , showLegend = true , brushExtent = null - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

' + key + '

' + - '

' + y + ' at ' + x + '

' - } - , noData = "No Data Available." - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush', 'stateChange', 'changeState') + , noData = null + , dispatch = d3.dispatch('brush', 'stateChange', 'changeState') , transitionDuration = 250 , state = nv.utils.state() , defaultState = null ; - lines - .clipEdge(true) - ; - lines2 - .interactive(false) - ; - xAxis - .orient('bottom') - .tickPadding(5) - ; - yAxis - .orient('left') - ; - x2Axis - .orient('bottom') - .tickPadding(5) - ; - y2Axis - .orient('left') - ; + lines.clipEdge(true).duration(0); + lines2.interactive(false); + // We don't want any points emitted for the focus chart's scatter graph. + lines2.pointActive(function(d) { return false }); + xAxis.orient('bottom').tickPadding(5); + yAxis.orient('left'); + x2Axis.orient('bottom').tickPadding(5); + y2Axis.orient('left'); + + tooltip.valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, null, null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -5955,10 +7149,8 @@ nv.models.lineWithFocusChart = function() { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight1 = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom - height2, + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight1 = nv.utils.availableHeight(height, container, margin) - height2, availableHeight2 = height2 - margin2.top - margin2.bottom; chart.update = function() { container.transition().duration(transitionDuration).call(chart) }; @@ -5985,18 +7177,7 @@ nv.models.lineWithFocusChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight1 / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -6019,6 +7200,7 @@ nv.models.lineWithFocusChart = function() { focusEnter.append('g').attr('class', 'nv-x nv-axis'); focusEnter.append('g').attr('class', 'nv-y nv-axis'); focusEnter.append('g').attr('class', 'nv-linesWrap'); + focusEnter.append('g').attr('class', 'nv-interactive'); var contextEnter = gEnter.append('g').attr('class', 'nv-context'); contextEnter.append('g').attr('class', 'nv-x nv-axis'); @@ -6037,8 +7219,7 @@ nv.models.lineWithFocusChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight1 = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom - height2; + availableHeight1 = nv.utils.availableHeight(height, container, margin) - height2; } g.select('.nv-legendWrap') @@ -6047,6 +7228,18 @@ nv.models.lineWithFocusChart = function() { wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + //Set up interactive layer + if (useInteractiveGuideline) { + interactiveLayer + .width(availableWidth) + .height(availableHeight1) + .margin({left:margin.left, top:margin.top}) + .svgContainer(container) + .xScale(x); + wrap.select(".nv-interactive").call(interactiveLayer); + } + // Main Chart Component(s) lines .width(availableWidth) @@ -6086,12 +7279,12 @@ nv.models.lineWithFocusChart = function() { // Setup Main (Focus) Axes xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight1, 0); yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-focus .nv-x.nv-axis') @@ -6101,11 +7294,7 @@ nv.models.lineWithFocusChart = function() { brush .x(x2) .on('brush', function() { - //When brushing, turn off transitions because chart needs to change immediately. - var oldTransition = chart.duration(); - chart.duration(0); onBrush(); - chart.duration(oldTransition); }); if (brushExtent) brush.extent(brushExtent); @@ -6131,7 +7320,6 @@ nv.models.lineWithFocusChart = function() { var gBrush = g.select('.nv-x.nv-brush') .call(brush); gBrush.selectAll('rect') - //.attr('y', -5) .attr('height', availableHeight2); gBrush.selectAll('.resize').append('path').attr('d', resizePath); @@ -6140,7 +7328,7 @@ nv.models.lineWithFocusChart = function() { // Setup Secondary (Context) Axes x2Axis .scale(x2) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight2, 0); g.select('.nv-context .nv-x.nv-axis') @@ -6150,7 +7338,7 @@ nv.models.lineWithFocusChart = function() { y2Axis .scale(y2) - .ticks( nv.utils.calcTicksY(availableHeight2/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight2/36, data) ) .tickSize( -availableWidth, 0); d3.transition(g.select('.nv-context .nv-y.nv-axis')) @@ -6170,8 +7358,63 @@ nv.models.lineWithFocusChart = function() { chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); + interactiveLayer.dispatch.on('elementMousemove', function(e) { + lines.clearHighlights(); + var singlePoint, pointIndex, pointXLocation, allData = []; + data + .filter(function(series, i) { + series.seriesIndex = i; + return !series.disabled; + }) + .forEach(function(series,i) { + var extent = brush.empty() ? x2.domain() : brush.extent(); + var currentValues = series.values.filter(function(d,i) { + return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; + }); + + pointIndex = nv.interactiveBisect(currentValues, e.pointXValue, lines.x()); + var point = currentValues[pointIndex]; + var pointYValue = chart.y()(point, pointIndex); + if (pointYValue != null) { + lines.highlightPoint(i, pointIndex, true); + } + if (point === undefined) return; + if (singlePoint === undefined) singlePoint = point; + if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + allData.push({ + key: series.key, + value: chart.y()(point, pointIndex), + color: color(series,series.seriesIndex) + }); + }); + //Highlight the tooltip entry based on which point the mouse is closest to. + if (allData.length > 2) { + var yValue = chart.yScale().invert(e.mouseY); + var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]); + var threshold = 0.03 * domainExtent; + var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold); + if (indexToHighlight !== null) + allData[indexToHighlight].highlight = true; + } + + var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); + interactiveLayer.tooltip + .chartContainer(that.parentNode) + .valueFormatter(function(d,i) { + return d == null ? "N/A" : yAxis.tickFormat()(d); + }) + .data({ + value: xValue, + index: pointIndex, + series: allData + })(); + + interactiveLayer.renderGuideLine(pointXLocation); + + }); + + interactiveLayer.dispatch.on("elementMouseout",function(e) { + lines.clearHighlights(); }); dispatch.on('changeState', function(e) { @@ -6210,7 +7453,7 @@ nv.models.lineWithFocusChart = function() { .data([brush.empty() ? x2.domain() : brushExtent]) .each(function(d,i) { var leftWidth = x2(d[0]) - x.range()[0], - rightWidth = x.range()[1] - x2(d[1]); + rightWidth = availableWidth - x2(d[1]); d3.select(this).select('.left') .attr('width', leftWidth < 0 ? 0 : leftWidth); @@ -6244,6 +7487,7 @@ nv.models.lineWithFocusChart = function() { return { key: d.key, area: d.area, + classed: d.classed, values: d.values.filter(function(d,i) { return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; }) @@ -6268,17 +7512,12 @@ nv.models.lineWithFocusChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - lines.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + lines.dispatch.on('elementMouseover.tooltip', function(evt) { + tooltip.data(evt).hidden(false); }); - lines.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + lines.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) }); //============================================================ @@ -6294,6 +7533,8 @@ nv.models.lineWithFocusChart = function() { chart.yAxis = yAxis; chart.x2Axis = x2Axis; chart.y2Axis = y2Axis; + chart.interactiveLayer = interactiveLayer; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -6304,8 +7545,6 @@ nv.models.lineWithFocusChart = function() { focusHeight: {get: function(){return height2;}, set: function(_){height2=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, @@ -6316,6 +7555,12 @@ nv.models.lineWithFocusChart = function() { margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; margin.left = _.left !== undefined ? _.left : margin.left; }}, + focusMargin: {get: function(){return margin2;}, set: function(_){ + margin2.top = _.top !== undefined ? _.top : margin2.top; + margin2.right = _.right !== undefined ? _.right : margin2.right; + margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom; + margin2.left = _.left !== undefined ? _.left : margin2.left; + }}, color: {get: function(){return color;}, set: function(_){ color = nv.utils.getColor(_); legend.color(color); @@ -6325,18 +7570,20 @@ nv.models.lineWithFocusChart = function() { lines.interpolate(_); lines2.interpolate(_); }}, - xTickFormat: {get: function(){return xAxis.xTickFormat();}, set: function(_){ - xAxis.xTickFormat(_); - x2Axis.xTickFormat(_); + xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){ + xAxis.tickFormat(_); + x2Axis.tickFormat(_); }}, - yTickFormat: {get: function(){return yAxis.yTickFormat();}, set: function(_){ - yAxis.yTickFormat(_); - y2Axis.yTickFormat(_); + yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){ + yAxis.tickFormat(_); + y2Axis.tickFormat(_); }}, duration: {get: function(){return transitionDuration;}, set: function(_){ transitionDuration=_; yAxis.duration(transitionDuration); + y2Axis.duration(transitionDuration); xAxis.duration(transitionDuration); + x2Axis.duration(transitionDuration); }}, x: {get: function(){return lines.x();}, set: function(_){ lines.x(_); @@ -6345,6 +7592,13 @@ nv.models.lineWithFocusChart = function() { y: {get: function(){return lines.y();}, set: function(_){ lines.y(_); lines2.y(_); + }}, + useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ + useInteractiveGuideline = _; + if (useInteractiveGuideline) { + lines.interactive(false); + lines.useVoronoi(false); + } }} }); @@ -6367,6 +7621,7 @@ nv.models.multiBar = function() { , x = d3.scale.ordinal() , y = d3.scale.linear() , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null , getX = function(d) { return d.x } , getY = function(d) { return d.y } , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove @@ -6383,7 +7638,7 @@ nv.models.multiBar = function() { , xRange , yRange , groupSpacing = 0.1 - , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') ; //============================================================ @@ -6400,10 +7655,15 @@ nv.models.multiBar = function() { renderWatch.reset(); selection.each(function(data) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); - nv.utils.initSVG(container); + availableHeight = height - margin.top - margin.bottom; + //EDIT + if (availableWidth < 0) availableWidth = 0; + if (availableHeight < 0) availableHeight = 0; + //END EDIT + container = d3.select(this); + nv.utils.initSVG(container); + var nonStackableCount = 0; // This function defines the requirements for render complete var endFn = function(d, i) { if (d.series === data.length - 1 && i === data[0].values.length - 1) @@ -6421,53 +7681,84 @@ nv.models.multiBar = function() { };} )}]; - if (stacked) - data = d3.layout.stack() + if (stacked) { + var parsed = d3.layout.stack() .offset(stackOffset) .values(function(d){ return d.values }) .y(getY) (!data.length && hideable ? hideable : data); - - //add series index to each data point for reference + parsed.forEach(function(series, i){ + // if series is non-stackable, use un-parsed data + if (series.nonStackable) { + data[i].nonStackableSeries = nonStackableCount++; + parsed[i] = data[i]; + } else { + // don't stack this seires on top of the nonStackable seriees + if (i > 0 && parsed[i - 1].nonStackable){ + parsed[i].values.map(function(d,j){ + d.y0 -= parsed[i - 1].values[j].y; + d.y1 = d.y0 + d.y; + }); + } + } + }); + data = parsed; + } + //add series index and key to each data point for reference data.forEach(function(series, i) { series.values.forEach(function(point) { point.series = i; + point.key = series.key; }); }); // HACK for negative value stacking - if (stacked) + if (stacked) { data[0].values.map(function(d,i) { var posBase = 0, negBase = 0; - data.map(function(d) { - var f = d.values[i] - f.size = Math.abs(f.y); - if (f.y<0) { - f.y1 = negBase; - negBase = negBase - f.size; - } else - { - f.y1 = f.size + posBase; - posBase = posBase + f.size; + data.map(function(d, idx) { + if (!data[idx].nonStackable) { + var f = d.values[i] + f.size = Math.abs(f.y); + if (f.y<0) { + f.y1 = negBase; + negBase = negBase - f.size; + } else + { + f.y1 = f.size + posBase; + posBase = posBase + f.size; + } } + }); }); - + } // Setup Scales // remap and flatten the data for use in calculating the scales' domains var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate - data.map(function(d) { + data.map(function(d, idx) { return d.values.map(function(d,i) { - return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 } + return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1, idx:idx } }) }); x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x })) .rangeBands(xRange || [0, availableWidth], groupSpacing); - y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 : d.y1 + d.y ) : d.y }).concat(forceY))) - .range(yRange || [availableHeight, 0]); + y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { + var domain = d.y; + // increase the domain range if this series is stackable + if (stacked && !data[d.idx].nonStackable) { + if (d.y > 0){ + domain = d.y1 + } else { + domain = d.y1 + d.y + } + } + return domain; + }).concat(forceY))) + .range(yRange || [availableHeight, 0]); // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point if (x.domain()[0] === x.domain()[1]) @@ -6488,7 +7779,7 @@ nv.models.multiBar = function() { var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibar'); var defsEnter = wrapEnter.append('defs'); var gEnter = wrapEnter.append('g'); - var g = wrap.select('g') + var g = wrap.select('g'); gEnter.append('g').attr('class', 'nv-groups'); wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -6497,8 +7788,8 @@ nv.models.multiBar = function() { .attr('id', 'nv-edge-clip-' + id) .append('rect'); wrap.select('#nv-edge-clip-' + id + ' rect') - .attr('width', availableWidth > 0 ? availableWidth : 0) - .attr('height', availableHeight > 0 ? availableHeight : 0); + .attr('width', availableWidth) + .attr('height', availableHeight); g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : ''); @@ -6510,7 +7801,15 @@ nv.models.multiBar = function() { var exitTransition = renderWatch .transition(groups.exit().selectAll('rect.nv-bar'), 'multibarExit', Math.min(100, duration)) - .attr('y', function(d) { return (stacked ? y0(d.y0) : y0(0)) || 0 }) + .attr('y', function(d, i, j) { + var yVal = y0(0) || 0; + if (stacked) { + if (data[d.series] && !data[d.series].nonStackable) { + yVal = y0(d.y0); + } + } + return yVal; + }) .attr('height', 0) .remove(); if (exitTransition.delay) @@ -6534,11 +7833,11 @@ nv.models.multiBar = function() { var barsEnter = bars.enter().append('rect') .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'}) .attr('x', function(d,i,j) { - return stacked ? 0 : (j * x.rangeBand() / data.length ) + return stacked && !data[j].nonStackable ? 0 : (j * x.rangeBand() / data.length ) }) - .attr('y', function(d) { return y0(stacked ? d.y0 : 0) || 0 }) + .attr('y', function(d,i,j) { return y0(stacked && !data[j].nonStackable ? d.y0 : 0) || 0 }) .attr('height', 0) - .attr('width', x.rangeBand() / (stacked ? 1 : data.length) ) + .attr('width', function(d,i,j) { return x.rangeBand() / (stacked && !data[j].nonStackable ? 1 : data.length) }) .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; }) ; bars @@ -6547,47 +7846,39 @@ nv.models.multiBar = function() { .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here d3.select(this).classed('hover', true); dispatch.elementMouseover({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('mouseout', function(d,i) { d3.select(this).classed('hover', false); dispatch.elementMouseout({ - value: getY(d,i), - point: d, - series: data[d.series], - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('click', function(d,i) { dispatch.elementClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }) .on('dblclick', function(d,i) { dispatch.elementDblClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }); @@ -6607,22 +7898,62 @@ nv.models.multiBar = function() { .delay(function(d,i) { return i * duration / data[0].values.length; }); - if (stacked) + if (stacked){ barSelection - .attr('y', function(d,i) { - return y((stacked ? d.y1 : 0)); + .attr('y', function(d,i,j) { + var yVal = 0; + // if stackable, stack it on top of the previous series + if (!data[j].nonStackable) { + yVal = y(d.y1); + } else { + if (getY(d,i) < 0){ + yVal = y(0); + } else { + if (y(0) - y(getY(d,i)) < -1){ + yVal = y(0) - 1; + } else { + yVal = y(getY(d, i)) || 0; + } + } + } + return yVal; }) - .attr('height', function(d,i) { - return Math.max(Math.abs(y(d.y + (stacked ? d.y0 : 0)) - y((stacked ? d.y0 : 0))),1); + .attr('height', function(d,i,j) { + if (!data[j].nonStackable) { + return Math.max(Math.abs(y(d.y+d.y0) - y(d.y0)), 0); + } else { + return Math.max(Math.abs(y(getY(d,i)) - y(0)), 0) || 0; + } }) - .attr('x', function(d,i) { - return stacked ? 0 : (d.series * x.rangeBand() / data.length ) + .attr('x', function(d,i,j) { + var width = 0; + if (data[j].nonStackable) { + width = d.series * x.rangeBand() / data.length; + if (data.length !== nonStackableCount){ + width = data[j].nonStackableSeries * x.rangeBand()/(nonStackableCount*2); + } + } + return width; }) - .attr('width', x.rangeBand() / (stacked ? 1 : data.length) ); - else + .attr('width', function(d,i,j){ + if (!data[j].nonStackable) { + return x.rangeBand(); + } else { + // if all series are nonStacable, take the full width + var width = (x.rangeBand() / nonStackableCount); + // otherwise, nonStackable graph will be only taking the half-width + // of the x rangeBand + if (data.length !== nonStackableCount) { + width = x.rangeBand()/(nonStackableCount*2); + } + return width; + } + }); + } + else { barSelection .attr('x', function(d,i) { - return d.series * x.rangeBand() / data.length + return d.series * x.rangeBand() / data.length; }) .attr('width', x.rangeBand() / data.length) .attr('y', function(d,i) { @@ -6635,6 +7966,7 @@ nv.models.multiBar = function() { .attr('height', function(d,i) { return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0; }); + } //store old scales for use in transitions on update x0 = x.copy(); @@ -6696,7 +8028,7 @@ nv.models.multiBar = function() { color = nv.utils.getColor(_); }}, barColor: {get: function(){return barColor;}, set: function(_){ - barColor = nv.utils.getColor(_); + barColor = _ ? nv.utils.getColor(_) : null; }} }); @@ -6704,7 +8036,6 @@ nv.models.multiBar = function() { return chart; }; - nv.models.multiBarChart = function() { "use strict"; @@ -6717,6 +8048,7 @@ nv.models.multiBarChart = function() { , yAxis = nv.models.axis() , legend = nv.models.legend() , controls = nv.models.legend() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 20, bottom: 50, left: 60} @@ -6731,31 +8063,24 @@ nv.models.multiBarChart = function() { , rightAlignYAxis = false , reduceXTicks = true // if false a tick will show for every data point , staggerLabels = false + , wrapLabels = false , rotateLabels = 0 - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

' + key + '

' + - '

' + y + ' on ' + x + '

' - } , x //can be accessed via chart.xScale() , y //can be accessed via chart.yScale() , state = nv.utils.state() , defaultState = null - , noData = "No Data Available." - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , noData = null + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd') , controlWidth = function() { return showControls ? 180 : 0 } , duration = 250 ; state.stacked = false // DEPRECATED Maintained for backward compatibility - multibar - .stacked(false) - ; + multibar.stacked(false); xAxis .orient('bottom') .tickPadding(7) - .highlightZero(true) .showMaxMin(false) .tickFormat(function(d) { return d }) ; @@ -6764,6 +8089,15 @@ nv.models.multiBarChart = function() { .tickFormat(d3.format(',.1f')) ; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + controls.updateState(false); //============================================================ @@ -6773,16 +8107,6 @@ nv.models.multiBarChart = function() { var renderWatch = nv.utils.renderWatch(dispatch); var stacked = false; - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(multibar.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(multibar.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -6813,10 +8137,8 @@ nv.models.multiBarChart = function() { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { if (duration === 0) @@ -6849,18 +8171,7 @@ nv.models.multiBarChart = function() { // Display noData message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -6885,19 +8196,13 @@ nv.models.multiBarChart = function() { if (showLegend) { legend.width(availableWidth - controlWidth()); - if (multibar.barColor()) - data.forEach(function(series,i) { - series.color = d3.rgb('#ccc').darker(i * 1.5).toString(); - }); - g.select('.nv-legendWrap') .datum(data) .call(legend); if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.nv-legendWrap') @@ -6943,7 +8248,7 @@ nv.models.multiBarChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight, 0); g.select('.nv-x.nv-axis') @@ -6977,6 +8282,11 @@ nv.models.multiBarChart = function() { }); } + if (wrapLabels) { + g.selectAll('.tick text') + .call(nv.utils.wrapTicks, chart.xAxis.rangeBand()) + } + if (reduceXTicks) xTicks .filter(function(d,i) { @@ -6998,7 +8308,7 @@ nv.models.multiBarChart = function() { if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis') @@ -7026,40 +8336,33 @@ nv.models.multiBarChart = function() { switch (d.key) { case 'Grouped': + case controlLabels.grouped: multibar.stacked(false); break; case 'Stacked': + case controlLabels.stacked: multibar.stacked(true); break; } state.stacked = multibar.stacked(); dispatch.stateChange(state); - chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode) - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined') { data.forEach(function(series,i) { series.disabled = e.disabled[i]; }); - state.disabled = e.disabled; } - if (typeof e.stacked !== 'undefined') { multibar.stacked(e.stacked); state.stacked = e.stacked; stacked = e.stacked; } - chart.update(); }); }); @@ -7072,16 +8375,22 @@ nv.models.multiBarChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - multibar.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + multibar.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.value = chart.x()(evt.data); + evt['series'] = { + key: evt.data.key, + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - multibar.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + multibar.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + + multibar.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -7092,9 +8401,11 @@ nv.models.multiBarChart = function() { chart.dispatch = dispatch; chart.multibar = multibar; chart.legend = legend; + chart.controls = controls; chart.xAxis = xAxis; chart.yAxis = yAxis; chart.state = state; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -7107,13 +8418,12 @@ nv.models.multiBarChart = function() { controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, reduceXTicks: {get: function(){return reduceXTicks;}, set: function(_){reduceXTicks=_;}}, rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + wrapLabels: {get: function(){return wrapLabels;}, set: function(_){wrapLabels=!!_;}}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ @@ -7136,6 +8446,10 @@ nv.models.multiBarChart = function() { rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ rightAlignYAxis = _; yAxis.orient( rightAlignYAxis ? 'right' : 'left'); + }}, + barColor: {get: function(){return multibar.barColor;}, set: function(_){ + multibar.barColor(_); + legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();}) }} }); @@ -7156,6 +8470,7 @@ nv.models.multiBarHorizontal = function() { , width = 960 , height = 500 , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null , x = d3.scale.ordinal() , y = d3.scale.linear() , getX = function(d) { return d.x } @@ -7169,6 +8484,7 @@ nv.models.multiBarHorizontal = function() { , showValues = false , showBarLabels = false , valuePadding = 60 + , groupSpacing = 0.1 , valueFormat = d3.format(',.2f') , delay = 1200 , xDomain @@ -7176,7 +8492,7 @@ nv.models.multiBarHorizontal = function() { , xRange , yRange , duration = 250 - , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout','renderEnd') + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') ; //============================================================ @@ -7190,8 +8506,9 @@ nv.models.multiBarHorizontal = function() { renderWatch.reset(); selection.each(function(data) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); nv.utils.initSVG(container); if (stacked) @@ -7201,10 +8518,11 @@ nv.models.multiBarHorizontal = function() { .y(getY) (data); - //add series index to each data point for reference + //add series index and key to each data point for reference data.forEach(function(series, i) { series.values.forEach(function(point) { point.series = i; + point.key = series.key; }); }); @@ -7236,7 +8554,7 @@ nv.models.multiBarHorizontal = function() { }); x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x })) - .rangeBands(xRange || [0, availableHeight], .1); + .rangeBands(xRange || [0, availableHeight], groupSpacing); y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 + d.y : d.y1 ) : d.y }).concat(forceY))) @@ -7293,47 +8611,46 @@ nv.models.multiBarHorizontal = function() { .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here d3.select(this).classed('hover', true); dispatch.elementMouseover({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [ y(getY(d,i) + (stacked ? d.y0 : 0)), x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length) ], - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('mouseout', function(d,i) { d3.select(this).classed('hover', false); dispatch.elementMouseout({ - value: getY(d,i), - point: d, - series: data[d.series], - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mouseout', function(d,i) { + dispatch.elementMouseout({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('click', function(d,i) { dispatch.elementClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }) .on('dblclick', function(d,i) { dispatch.elementDblClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }); @@ -7364,13 +8681,13 @@ nv.models.multiBarHorizontal = function() { .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' }) .attr('y', x.rangeBand() / (data.length * 2)) .attr('dy', '.32em') - .html(function(d,i) { + .text(function(d,i) { var t = valueFormat(getY(d,i)) , yerr = getYerr(d,i); if (yerr === undefined) return t; if (!yerr.length) - return t + '±' + valueFormat(Math.abs(yerr)); + return t + '±' + valueFormat(Math.abs(yerr)); return t + '+' + valueFormat(Math.abs(yerr[1])) + '-' + valueFormat(Math.abs(yerr[0])); }); bars.watchTransition(renderWatch, 'multibarhorizontal: bars') @@ -7412,7 +8729,7 @@ nv.models.multiBarHorizontal = function() { }) .select('rect') .attr('width', function(d,i) { - return Math.abs(y(getY(d,i) + d.y0) - y(d.y0)) + return Math.abs(y(getY(d,i) + d.y0) - y(d.y0)) || 0 }) .attr('height', x.rangeBand() ); else @@ -7430,7 +8747,7 @@ nv.models.multiBarHorizontal = function() { .select('rect') .attr('height', x.rangeBand() / data.length ) .attr('width', function(d,i) { - return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) + return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0 }); //store old scales for use in transitions on update @@ -7473,6 +8790,7 @@ nv.models.multiBarHorizontal = function() { id: {get: function(){return id;}, set: function(_){id=_;}}, valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}}, valuePadding: {get: function(){return valuePadding;}, set: function(_){valuePadding=_;}}, + groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ @@ -7488,8 +8806,8 @@ nv.models.multiBarHorizontal = function() { color: {get: function(){return color;}, set: function(_){ color = nv.utils.getColor(_); }}, - barColor: {get: function(){return color;}, set: function(_){ - barColor = nv.utils.getColor(_); + barColor: {get: function(){return barColor;}, set: function(_){ + barColor = _ ? nv.utils.getColor(_) : null; }} }); @@ -7497,6 +8815,7 @@ nv.models.multiBarHorizontal = function() { return chart; }; + nv.models.multiBarHorizontalChart = function() { "use strict"; @@ -7509,6 +8828,7 @@ nv.models.multiBarHorizontalChart = function() { , yAxis = nv.models.axis() , legend = nv.models.legend().height(30) , controls = nv.models.legend().height(30) + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 20, bottom: 50, left: 60} @@ -7520,31 +8840,24 @@ nv.models.multiBarHorizontalChart = function() { , showLegend = true , showXAxis = true , showYAxis = true - , stacked = true - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

' + key + ' - ' + x + '

' + - '

' + y + '

' - } + , stacked = false , x //can be accessed via chart.xScale() , y //can be accessed via chart.yScale() , state = nv.utils.state() , defaultState = null - , noData = 'No Data Available.' - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd') + , noData = null + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') , controlWidth = function() { return showControls ? 180 : 0 } , duration = 250 ; state.stacked = false; // DEPRECATED Maintained for backward compatibility - multibar - .stacked(stacked) - ; + multibar.stacked(stacked); + xAxis .orient('left') .tickPadding(5) - .highlightZero(false) .showMaxMin(false) .tickFormat(function(d) { return d }) ; @@ -7553,22 +8866,21 @@ nv.models.multiBarHorizontalChart = function() { .tickFormat(d3.format(',.1f')) ; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + controls.updateState(false); //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(multibar.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(multibar.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'e' : 'w', null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -7601,10 +8913,8 @@ nv.models.multiBarHorizontalChart = function() { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { container.transition().duration(duration).call(chart) }; chart.container = this; @@ -7632,18 +8942,7 @@ nv.models.multiBarHorizontalChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -7670,20 +8969,13 @@ nv.models.multiBarHorizontalChart = function() { if (showLegend) { legend.width(availableWidth - controlWidth()); - //COMMENTED - /*if (multibar.barColor()) - data.forEach(function(series,i) { - series.color = d3.rgb('#ccc').darker(i * 1.5).toString(); - });*/ - g.select('.nv-legendWrap') .datum(data) .call(legend); if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.nv-legendWrap') @@ -7724,50 +9016,21 @@ nv.models.multiBarHorizontalChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( nv.utils.calcTicksY(availableHeight/24, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/24, data) ) .tickSize(-availableWidth, 0); - //based on 'wrapping long labels' by mike bostock - //http://bl.ocks.org/mbostock/7555321 - //console.log('x axis'); - - g.select('.nv-x.nv-axis').call(xAxis).selectAll('.tick text').call(function(selection) { - selection.each(function() { - var text = d3.select(this), - words = text.text().split(/\s+/).reverse(), - word, - line = [], - lineNumber = 0, - lineHeight = 1.1, // ems - y = text.attr("y"), - dy = parseFloat(text.attr("dy")), - tspan = text.text(null).append("tspan").attr("x", -5).attr("y", 0).attr("dy", dy + "em"); - while (word = words.pop()) { - line.push(word); - tspan.text(line.join(" ")); - if (tspan.node().getComputedTextLength() > margin.right) { - line.pop(); - tspan.text(line.join(" ")); - line = [word]; - tspan = text.append("tspan").attr("x", -5).attr("y", 0).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word); - } - } - //offset is height / 4 since position is already displaced by height / 2 - //lineNumber * 1.25em * 16px / 4 == lineNumber * 5 - if (lineNumber) { - text.attr('transform', 'translate(0, -' + lineNumber * 5 + ')'); - } - }); - }); + g.select('.nv-x.nv-axis').call(xAxis); + + var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); - //var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); - //xTicks.selectAll('line, text'); + xTicks + .selectAll('line, text'); } if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize( -availableHeight, 0); g.select('.nv-y.nv-axis') @@ -7818,10 +9081,6 @@ nv.models.multiBarHorizontalChart = function() { chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { @@ -7850,16 +9109,22 @@ nv.models.multiBarHorizontalChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - multibar.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + multibar.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.value = chart.x()(evt.data); + evt['series'] = { + key: evt.data.key, + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - multibar.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + multibar.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + + multibar.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -7870,9 +9135,11 @@ nv.models.multiBarHorizontalChart = function() { chart.dispatch = dispatch; chart.multibar = multibar; chart.legend = legend; + chart.controls = controls; chart.xAxis = xAxis; chart.yAxis = yAxis; chart.state = state; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -7885,8 +9152,6 @@ nv.models.multiBarHorizontalChart = function() { controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, @@ -7907,6 +9172,10 @@ nv.models.multiBarHorizontalChart = function() { color: {get: function(){return color;}, set: function(_){ color = nv.utils.getColor(_); legend.color(color); + }}, + barColor: {get: function(){return multibar.barColor;}, set: function(_){ + multibar.barColor(_); + legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();}) }} }); @@ -7927,19 +9196,13 @@ nv.models.multiChart = function() { width = null, height = null, showLegend = true, - tooltips = true, - tooltip = function(key, x, y, e, graph) { - return '

' + key + '

' + - '

' + y + ' at ' + x + '

' - }, - x, - y, - noData = 'No Data Available.', + noData = null, yDomain1, yDomain2, getX = function(d) { return d.x }, getY = function(d) { return d.y}, - interpolate = 'monotone' + interpolate = 'monotone', + useVoronoi = true ; //============================================================ @@ -7953,6 +9216,9 @@ nv.models.multiChart = function() { lines1 = nv.models.line().yScale(yScale1), lines2 = nv.models.line().yScale(yScale2), + scatters1 = nv.models.scatter().yScale(yScale1), + scatters2 = nv.models.scatter().yScale(yScale2), + bars1 = nv.models.multiBar().stacked(false).yScale(yScale1), bars2 = nv.models.multiBar().stacked(false).yScale(yScale2), @@ -7964,17 +9230,8 @@ nv.models.multiChart = function() { yAxis2 = nv.models.axis().scale(yScale2).orient('right'), legend = nv.models.legend().height(30), - dispatch = d3.dispatch('tooltipShow', 'tooltipHide'); - - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(lines1.x()(e.point, e.pointIndex)), - y = ((e.series.yAxis == 2) ? yAxis2 : yAxis1).tickFormat()(lines1.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, undefined, undefined, offsetElement.offsetParent); - }; + tooltip = nv.models.tooltip(), + dispatch = d3.dispatch(); function chart(selection) { selection.each(function(data) { @@ -7985,13 +9242,13 @@ nv.models.multiChart = function() { chart.update = function() { container.transition().call(chart); }; chart.container = this; - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); var dataLines1 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 1}); var dataLines2 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 2}); + var dataScatters1 = data.filter(function(d) {return d.type == 'scatter' && d.yAxis == 1}); + var dataScatters2 = data.filter(function(d) {return d.type == 'scatter' && d.yAxis == 2}); var dataBars1 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 1}); var dataBars2 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 2}); var dataStack1 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 1}); @@ -7999,18 +9256,7 @@ nv.models.multiChart = function() { // Display noData message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container); return chart; } else { container.selectAll('.nv-noData').remove(); @@ -8019,28 +9265,30 @@ nv.models.multiChart = function() { var series1 = data.filter(function(d) {return !d.disabled && d.yAxis == 1}) .map(function(d) { return d.values.map(function(d,i) { - return { x: d.x, y: d.y } + return { x: getX(d), y: getY(d) } }) }); var series2 = data.filter(function(d) {return !d.disabled && d.yAxis == 2}) .map(function(d) { return d.values.map(function(d,i) { - return { x: d.x, y: d.y } + return { x: getX(d), y: getY(d) } }) }); - x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } )) + x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return getX(d) })) .range([0, availableWidth]); var wrap = container.selectAll('g.wrap.multiChart').data([data]); var gEnter = wrap.enter().append('g').attr('class', 'wrap nvd3 multiChart').append('g'); - gEnter.append('g').attr('class', 'x axis'); - gEnter.append('g').attr('class', 'y1 axis'); - gEnter.append('g').attr('class', 'y2 axis'); + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y1 nv-axis'); + gEnter.append('g').attr('class', 'nv-y2 nv-axis'); gEnter.append('g').attr('class', 'lines1Wrap'); gEnter.append('g').attr('class', 'lines2Wrap'); + gEnter.append('g').attr('class', 'scatters1Wrap'); + gEnter.append('g').attr('class', 'scatters2Wrap'); gEnter.append('g').attr('class', 'bars1Wrap'); gEnter.append('g').attr('class', 'bars2Wrap'); gEnter.append('g').attr('class', 'stack1Wrap'); @@ -8054,8 +9302,11 @@ nv.models.multiChart = function() { }); if (showLegend) { + var legendWidth = legend.align() ? availableWidth / 2 : availableWidth; + var legendXPosition = legend.align() ? legendWidth : 0; + + legend.width(legendWidth); legend.color(color_array); - legend.width( availableWidth / 2 ); g.select('.legendWrap') .datum(data.map(function(series) { @@ -8067,12 +9318,11 @@ nv.models.multiChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.legendWrap') - .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')'); + .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')'); } lines1 @@ -8085,6 +9335,14 @@ nv.models.multiChart = function() { .height(availableHeight) .interpolate(interpolate) .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'line'})); + scatters1 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'scatter'})); + scatters2 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'scatter'})); bars1 .width(availableWidth) .height(availableHeight) @@ -8105,51 +9363,44 @@ nv.models.multiChart = function() { g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); var lines1Wrap = g.select('.lines1Wrap') - .datum( - dataLines1.filter(function(d){return !d.disabled}) - ); + .datum(dataLines1.filter(function(d){return !d.disabled})); + var scatters1Wrap = g.select('.scatters1Wrap') + .datum(dataScatters1.filter(function(d){return !d.disabled})); var bars1Wrap = g.select('.bars1Wrap') - .datum( - dataBars1.filter(function(d){return !d.disabled}) - ); + .datum(dataBars1.filter(function(d){return !d.disabled})); var stack1Wrap = g.select('.stack1Wrap') - .datum( - dataStack1.filter(function(d){return !d.disabled}) - ); - + .datum(dataStack1.filter(function(d){return !d.disabled})); var lines2Wrap = g.select('.lines2Wrap') - .datum( - dataLines2.filter(function(d){return !d.disabled}) - ); + .datum(dataLines2.filter(function(d){return !d.disabled})); + var scatters2Wrap = g.select('.scatters2Wrap') + .datum(dataScatters2.filter(function(d){return !d.disabled})); var bars2Wrap = g.select('.bars2Wrap') - .datum( - dataBars2.filter(function(d){return !d.disabled}) - ); + .datum(dataBars2.filter(function(d){return !d.disabled})); var stack2Wrap = g.select('.stack2Wrap') - .datum( - dataStack2.filter(function(d){return !d.disabled}) - ); + .datum(dataStack2.filter(function(d){return !d.disabled})); var extraValue1 = dataStack1.length ? dataStack1.map(function(a){return a.values}).reduce(function(a,b){ return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}}) - }).concat([{x:0, y:0}]) : [] + }).concat([{x:0, y:0}]) : []; var extraValue2 = dataStack2.length ? dataStack2.map(function(a){return a.values}).reduce(function(a,b){ return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}}) - }).concat([{x:0, y:0}]) : [] + }).concat([{x:0, y:0}]) : []; yScale1 .domain(yDomain1 || d3.extent(d3.merge(series1).concat(extraValue1), function(d) { return d.y } )) - .range([0, availableHeight]) + .range([0, availableHeight]); yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(extraValue2), function(d) { return d.y } )) - .range([0, availableHeight]) + .range([0, availableHeight]); - lines1.yDomain(yScale1.domain()) - bars1.yDomain(yScale1.domain()) - stack1.yDomain(yScale1.domain()) + lines1.yDomain(yScale1.domain()); + scatters1.yDomain(yScale1.domain()); + bars1.yDomain(yScale1.domain()); + stack1.yDomain(yScale1.domain()); - lines2.yDomain(yScale2.domain()) - bars2.yDomain(yScale2.domain()) - stack2.yDomain(yScale2.domain()) + lines2.yDomain(yScale2.domain()); + scatters2.yDomain(yScale2.domain()); + bars2.yDomain(yScale2.domain()); + stack2.yDomain(yScale2.domain()); if(dataStack1.length){d3.transition(stack1Wrap).call(stack1);} if(dataStack2.length){d3.transition(stack2Wrap).call(stack2);} @@ -8160,35 +9411,38 @@ nv.models.multiChart = function() { if(dataLines1.length){d3.transition(lines1Wrap).call(lines1);} if(dataLines2.length){d3.transition(lines2Wrap).call(lines2);} + if(dataScatters1.length){d3.transition(scatters1Wrap).call(scatters1);} + if(dataScatters2.length){d3.transition(scatters2Wrap).call(scatters2);} + xAxis - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight, 0); - g.select('.x.axis') + g.select('.nv-x.nv-axis') .attr('transform', 'translate(0,' + availableHeight + ')'); - d3.transition(g.select('.x.axis')) + d3.transition(g.select('.nv-x.nv-axis')) .call(xAxis); yAxis1 - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); - d3.transition(g.select('.y1.axis')) + d3.transition(g.select('.nv-y1.nv-axis')) .call(yAxis1); yAxis2 - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); - d3.transition(g.select('.y2.axis')) + d3.transition(g.select('.nv-y2.nv-axis')) .call(yAxis2); - g.select('.y1.axis') + g.select('.nv-y1.nv-axis') .classed('nv-disabled', series1.length ? false : true) .attr('transform', 'translate(' + x.range()[0] + ',0)'); - g.select('.y2.axis') + g.select('.nv-y2.nv-axis') .classed('nv-disabled', series2.length ? false : true) .attr('transform', 'translate(' + x.range()[1] + ',0)'); @@ -8196,116 +9450,133 @@ nv.models.multiChart = function() { chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - - }); - - return chart; - } - - //============================================================ - // Event Handling/Dispatching (out of chart's scope) - //------------------------------------------------------------ - - lines1.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - lines1.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - - lines2.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - lines2.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - - bars1.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - bars1.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - - bars2.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - bars2.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); + //============================================================ + // Event Handling/Dispatching + //------------------------------------------------------------ - stack1.dispatch.on('tooltipShow', function(e) { - //disable tooltips when value ~= 0 - //// TODO: consider removing points from voronoi that have 0 value instead of this hack - if (!Math.round(stack1.y()(e.point) * 100)) { // 100 will not be good for very small numbers... will have to think about making this valu dynamic, based on data range - setTimeout(function() { d3.selectAll('.point.hover').classed('hover', false) }, 0); - return false; - } + function mouseover_line(evt) { + var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1; + evt.value = evt.point.x; + evt.series = { + value: evt.point.y, + color: evt.point.color, + key: evt.series.key + }; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top], - dispatch.tooltipShow(e); - }); + function mouseover_scatter(evt) { + var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1; + evt.value = evt.point.x; + evt.series = { + value: evt.point.y, + color: evt.point.color, + key: evt.series.key + }; + tooltip + .duration(100) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } + + function mouseover_stack(evt) { + var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1; + evt.point['x'] = stack1.x()(evt.point); + evt.point['y'] = stack1.y()(evt.point); + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } - stack1.dispatch.on('tooltipHide', function(e) { - dispatch.tooltipHide(e); - }); + function mouseover_bar(evt) { + var yaxis = data[evt.data.series].yAxis === 2 ? yAxis2 : yAxis1; - stack2.dispatch.on('tooltipShow', function(e) { - //disable tooltips when value ~= 0 - //// TODO: consider removing points from voronoi that have 0 value instead of this hack - if (!Math.round(stack2.y()(e.point) * 100)) { // 100 will not be good for very small numbers... will have to think about making this valu dynamic, based on data range - setTimeout(function() { d3.selectAll('.point.hover').classed('hover', false) }, 0); - return false; - } + evt.value = bars1.x()(evt.data); + evt['series'] = { + value: bars1.y()(evt.data), + color: evt.color, + key: evt.data.key + }; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top], - dispatch.tooltipShow(e); - }); + lines1.dispatch.on('elementMouseover.tooltip', mouseover_line); + lines2.dispatch.on('elementMouseover.tooltip', mouseover_line); + lines1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + lines2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); - stack2.dispatch.on('tooltipHide', function(e) { - dispatch.tooltipHide(e); - }); + scatters1.dispatch.on('elementMouseover.tooltip', mouseover_scatter); + scatters2.dispatch.on('elementMouseover.tooltip', mouseover_scatter); + scatters1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + scatters2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); - lines1.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); + stack1.dispatch.on('elementMouseover.tooltip', mouseover_stack); + stack2.dispatch.on('elementMouseover.tooltip', mouseover_stack); + stack1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + stack2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); - lines1.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); + bars1.dispatch.on('elementMouseover.tooltip', mouseover_bar); + bars2.dispatch.on('elementMouseover.tooltip', mouseover_bar); - lines2.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); + bars1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + bars2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + bars1.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + bars2.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); - lines2.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); + }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); - }); + return chart; + } //============================================================ // Global getters and setters //------------------------------------------------------------ chart.dispatch = dispatch; + chart.legend = legend; chart.lines1 = lines1; chart.lines2 = lines2; + chart.scatters1 = scatters1; + chart.scatters2 = scatters2; chart.bars1 = bars1; chart.bars2 = bars2; chart.stack1 = stack1; @@ -8313,6 +9584,7 @@ nv.models.multiChart = function() { chart.xAxis = xAxis; chart.yAxis1 = yAxis1; chart.yAxis2 = yAxis2; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -8323,8 +9595,6 @@ nv.models.multiChart = function() { showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, yDomain1: {get: function(){return yDomain1;}, set: function(_){yDomain1=_;}}, yDomain2: {get: function(){return yDomain2;}, set: function(_){yDomain2=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}}, @@ -8341,12 +9611,31 @@ nv.models.multiChart = function() { x: {get: function(){return getX;}, set: function(_){ getX = _; lines1.x(_); + lines2.x(_); + scatters1.x(_); + scatters2.x(_); bars1.x(_); + bars2.x(_); + stack1.x(_); + stack2.x(_); }}, y: {get: function(){return getY;}, set: function(_){ getY = _; lines1.y(_); + lines2.y(_); + scatters1.y(_); + scatters2.y(_); + stack1.y(_); + stack2.y(_); bars1.y(_); + bars2.y(_); + }}, + useVoronoi: {get: function(){return useVoronoi;}, set: function(_){ + useVoronoi=_; + lines1.useVoronoi(_); + lines2.useVoronoi(_); + stack1.useVoronoi(_); + stack2.useVoronoi(_); }} }); @@ -8355,7 +9644,6 @@ nv.models.multiChart = function() { return chart; }; - nv.models.ohlcBar = function() { "use strict"; @@ -8367,6 +9655,7 @@ nv.models.ohlcBar = function() { , width = null , height = null , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null , x = d3.scale.linear() , y = d3.scale.linear() , getX = function(d) { return d.x } @@ -8385,7 +9674,7 @@ nv.models.ohlcBar = function() { , yDomain , xRange , yRange - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout') + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove') ; //============================================================ @@ -8394,21 +9683,22 @@ nv.models.ohlcBar = function() { function chart(selection) { selection.each(function(data) { - var container = d3.select(this); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right; - var availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); nv.utils.initSVG(container); + // ohlc bar width. + var w = (availableWidth / data[0].values.length) * .9; + // Setup Scales x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) )); if (padData) x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); else - x.range(xRange || [0, availableWidth]); + x.range(xRange || [5 + w/2, availableWidth - w/2 - 5]); y.domain(yDomain || [ d3.min(data[0].values.map(getLow).concat(forceY)), @@ -8462,10 +9752,9 @@ nv.models.ohlcBar = function() { .data(function(d) { return d }); ticks.exit().remove(); - var ticksEnter = ticks.enter().append('path') + ticks.enter().append('path') .attr('class', function(d,i,j) { return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i }) .attr('d', function(d,i) { - var w = (availableWidth / data[0].values.length) * .9; return 'm0,0l0,' + (y(getOpen(d,i)) - y(getHigh(d,i))) @@ -8528,13 +9817,13 @@ nv.models.ohlcBar = function() { //Create methods to allow outside functions to highlight a specific bar. chart.highlightPoint = function(pointIndex, isHoverOver) { chart.clearHighlights(); - d3.select(".nv-ohlcBar .nv-tick-0-" + pointIndex) + container.select(".nv-ohlcBar .nv-tick-0-" + pointIndex) .classed("hover", isHoverOver) ; }; chart.clearHighlights = function() { - d3.select(".nv-ohlcBar .nv-tick.hover") + container.select(".nv-ohlcBar .nv-tick.hover") .classed("hover", false) ; }; @@ -8585,10 +9874,8 @@ nv.models.ohlcBar = function() { nv.utils.initOptions(chart); return chart; }; - // Code adapted from Jason Davies' "Parallel Coordinates" // http://bl.ocks.org/jasondavies/1341281 - nv.models.parallelCoordinates = function() { "use strict"; @@ -8596,16 +9883,19 @@ nv.models.parallelCoordinates = function() { // Public Variables with Default Settings //------------------------------------------------------------ - var margin = {top: 30, right: 10, bottom: 10, left: 10} + var margin = {top: 30, right: 0, bottom: 10, left: 0} , width = null , height = null , x = d3.scale.ordinal() , y = {} - , dimensions = [] + , dimensionNames = [] + , dimensionFormats = [] , color = nv.utils.defaultColor() , filters = [] , active = [] - , dispatch = d3.dispatch('brush') + , dragging = [] + , lineTension = 1 + , dispatch = d3.dispatch('brush', 'elementMouseover', 'elementMouseout') ; //============================================================ @@ -8615,26 +9905,38 @@ nv.models.parallelCoordinates = function() { function chart(selection) { selection.each(function(data) { var container = d3.select(this); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right; - var availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); nv.utils.initSVG(container); active = data; //set all active before first brush call - //This is a placeholder until this chart is made resizeable - chart.update = function() { }; - // Setup Scales - x.rangePoints([0, availableWidth], 1).domain(dimensions); + x.rangePoints([0, availableWidth], 1).domain(dimensionNames); + //Set as true if all values on an axis are missing. + var onlyNanValues = {}; // Extract the list of dimensions and create a scale for each. - dimensions.forEach(function(d) { + dimensionNames.forEach(function(d) { + var extent = d3.extent(data, function(p) { return +p[d]; }); + onlyNanValues[d] = false; + //If there is no values to display on an axis, set the extent to 0 + if (extent[0] === undefined) { + onlyNanValues[d] = true; + extent[0] = 0; + extent[1] = 0; + } + //Scale axis if there is only one value + if (extent[0] === extent[1]) { + extent[0] = extent[0] - 1; + extent[1] = extent[1] + 1; + } + //Use 90% of (availableHeight - 12) for the axis range, 12 reprensenting the space necessary to display "undefined values" text. + //The remaining 10% are used to display the missingValue line. y[d] = d3.scale.linear() - .domain(d3.extent(data, function(p) { return +p[d]; })) - .range([availableHeight, 0]); + .domain(extent) + .range([(availableHeight - 12) * 0.9, 0]); y[d].brush = d3.svg.brush().y(y[d]).on('brush', brush); @@ -8647,65 +9949,150 @@ nv.models.parallelCoordinates = function() { var gEnter = wrapEnter.append('g'); var g = wrap.select('g'); - gEnter.append('g').attr('class', 'nv-parallelCoordinatesWrap'); + gEnter.append('g').attr('class', 'nv-parallelCoordinates background'); + gEnter.append('g').attr('class', 'nv-parallelCoordinates foreground'); + gEnter.append('g').attr('class', 'nv-parallelCoordinates missingValuesline'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - var line = d3.svg.line(), + var line = d3.svg.line().interpolate('cardinal').tension(lineTension), axis = d3.svg.axis().orient('left'), - background, - foreground; + axisDrag = d3.behavior.drag() + .on('dragstart', dragStart) + .on('drag', dragMove) + .on('dragend', dragEnd); + + //Add missing value line at the bottom of the chart + var missingValuesline, missingValueslineText; + var step = x.range()[1] - x.range()[0]; + var axisWithMissingValues = []; + var lineData = [0 + step / 2, availableHeight - 12, availableWidth - step / 2, availableHeight - 12]; + missingValuesline = wrap.select('.missingValuesline').selectAll('line').data([lineData]); + missingValuesline.enter().append('line'); + missingValuesline.exit().remove(); + missingValuesline.attr("x1", function(d) { return d[0]; }) + .attr("y1", function(d) { return d[1]; }) + .attr("x2", function(d) { return d[2]; }) + .attr("y2", function(d) { return d[3]; }); + + //Add the text "undefined values" under the missing value line + missingValueslineText = wrap.select('.missingValuesline').selectAll('text').data(["undefined values"]); + missingValueslineText.append('text').data(["undefined values"]); + missingValueslineText.enter().append('text'); + missingValueslineText.exit().remove(); + missingValueslineText.attr("y", availableHeight) + //To have the text right align with the missingValues line, substract 92 representing the text size. + .attr("x", availableWidth - 92 - step / 2) + .text(function(d) { return d; }); // Add grey background lines for context. - background = gEnter.append('g') - .attr('class', 'background') - .selectAll('path') - .data(data) - .enter().append('path') - .attr('d', path) - ; + var background = wrap.select('.background').selectAll('path').data(data); + background.enter().append('path'); + background.exit().remove(); + background.attr('d', path); // Add blue foreground lines for focus. - foreground = gEnter.append('g') - .attr('class', 'foreground') - .selectAll('path') - .data(data) - .enter().append('path') - .attr('d', path) - .attr('stroke', color) - ; + var foreground = wrap.select('.foreground').selectAll('path').data(data); + foreground.enter().append('path') + foreground.exit().remove(); + foreground.attr('d', path).attr('stroke', color); + foreground.on("mouseover", function (d, i) { + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + label: d.name, + data: d.data, + index: i, + pos: [d3.mouse(this.parentNode)[0], d3.mouse(this.parentNode)[1]] + }); + + }); + foreground.on("mouseout", function (d, i) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + label: d.name, + data: d.data, + index: i + }); + }); // Add a group element for each dimension. - var dimension = g.selectAll('.dimension') - .data(dimensions) - .enter().append('g') - .attr('class', 'dimension') - .attr('transform', function(d) { return 'translate(' + x(d) + ',0)'; }); + var dimensions = g.selectAll('.dimension').data(dimensionNames); + var dimensionsEnter = dimensions.enter().append('g').attr('class', 'nv-parallelCoordinates dimension'); + dimensionsEnter.append('g').attr('class', 'nv-parallelCoordinates nv-axis'); + dimensionsEnter.append('g').attr('class', 'nv-parallelCoordinates-brush'); + dimensionsEnter.append('text').attr('class', 'nv-parallelCoordinates nv-label'); + + dimensions.attr('transform', function(d) { return 'translate(' + x(d) + ',0)'; }); + dimensions.exit().remove(); // Add an axis and title. - dimension.append('g') - .attr('class', 'axis') - .each(function(d) { d3.select(this).call(axis.scale(y[d])); }) - .append('text') + dimensions.select('.nv-label') + .style("cursor", "move") + .attr('dy', '-1em') .attr('text-anchor', 'middle') - .attr('y', -9) - .text(String); + .text(String) + .on("mouseover", function(d, i) { + dispatch.elementMouseover({ + dim: d, + pos: [d3.mouse(this.parentNode.parentNode)[0], d3.mouse(this.parentNode.parentNode)[1]] + }); + }) + .on("mouseout", function(d, i) { + dispatch.elementMouseout({ + dim: d + }); + }) + .call(axisDrag); + + dimensions.select('.nv-axis') + .each(function (d, i) { + d3.select(this).call(axis.scale(y[d]).tickFormat(d3.format(dimensionFormats[i]))); + }); - // Add and store a brush for each axis. - dimension.append('g') - .attr('class', 'brush') - .each(function(d) { d3.select(this).call(y[d].brush); }) + dimensions.select('.nv-parallelCoordinates-brush') + .each(function (d) { + d3.select(this).call(y[d].brush); + }) .selectAll('rect') .attr('x', -8) .attr('width', 16); // Returns the path for a given data point. function path(d) { - return line(dimensions.map(function(p) { return [x(p), y[p](d[p])]; })); + return line(dimensionNames.map(function (p) { + //If value if missing, put the value on the missing value line + if(isNaN(d[p]) || isNaN(parseFloat(d[p]))) { + var domain = y[p].domain(); + var range = y[p].range(); + var min = domain[0] - (domain[1] - domain[0]) / 9; + + //If it's not already the case, allow brush to select undefined values + if(axisWithMissingValues.indexOf(p) < 0) { + + var newscale = d3.scale.linear().domain([min, domain[1]]).range([availableHeight - 12, range[1]]); + y[p].brush.y(newscale); + axisWithMissingValues.push(p); + } + + return [x(p), y[p](min)]; + } + + //If parallelCoordinate contain missing values show the missing values line otherwise, hide it. + if(axisWithMissingValues.length > 0) { + missingValuesline.style("display", "inline"); + missingValueslineText.style("display", "inline"); + } else { + missingValuesline.style("display", "none"); + missingValueslineText.style("display", "none"); + } + + return [x(p), y[p](d[p])]; + })); } // Handles a brush event, toggling the display of foreground lines. function brush() { - var actives = dimensions.filter(function(p) { return !y[p].brush.empty(); }), + var actives = dimensionNames.filter(function(p) { return !y[p].brush.empty(); }), extents = actives.map(function(p) { return y[p].brush.extent(); }); filters = []; //erase current filters @@ -8719,6 +10106,7 @@ nv.models.parallelCoordinates = function() { active = []; //erase current active list foreground.style('display', function(d) { var isActive = actives.every(function(p, i) { + if(isNaN(d[p]) && extents[i][0] == y[p].brush.y().domain()[0]) return true; return extents[i][0] <= d[p] && d[p] <= extents[i][1]; }); if (isActive) active.push(d); @@ -8730,6 +10118,37 @@ nv.models.parallelCoordinates = function() { active: active }); } + + function dragStart(d, i) { + dragging[d] = this.parentNode.__origin__ = x(d); + background.attr("visibility", "hidden"); + + } + + function dragMove(d, i) { + dragging[d] = Math.min(availableWidth, Math.max(0, this.parentNode.__origin__ += d3.event.x)); + foreground.attr("d", path); + dimensionNames.sort(function (a, b) { return position(a) - position(b); }); + x.domain(dimensionNames); + dimensions.attr("transform", function(d) { return "translate(" + position(d) + ")"; }); + } + + function dragEnd(d, i) { + delete this.parentNode.__origin__; + delete dragging[d]; + d3.select(this.parentNode).attr("transform", "translate(" + x(d) + ")"); + foreground + .attr("d", path); + background + .attr("d", path) + .attr("visibility", null); + + } + + function position(d) { + var v = dragging[d]; + return v == null ? x(d) : v; + } }); return chart; @@ -8744,16 +10163,25 @@ nv.models.parallelCoordinates = function() { chart._options = Object.create({}, { // simple options, just get/set the necessary values - width: {get: function(){return width;}, set: function(_){width=_;}}, - height: {get: function(){return height;}, set: function(_){height=_;}}, - dimensions: {get: function(){return dimensions;}, set: function(_){dimensions=_;}}, + width: {get: function(){return width;}, set: function(_){width= _;}}, + height: {get: function(){return height;}, set: function(_){height= _;}}, + dimensionNames: {get: function() { return dimensionNames;}, set: function(_){dimensionNames= _;}}, + dimensionFormats : {get: function(){return dimensionFormats;}, set: function (_){dimensionFormats=_;}}, + lineTension: {get: function(){return lineTension;}, set: function(_){lineTension = _;}}, + + // deprecated options + dimensions: {get: function (){return dimensionNames;}, set: function(_){ + // deprecated after 1.8.1 + nv.deprecated('dimensions', 'use dimensionNames instead'); + dimensionNames = _; + }}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ - margin.top = typeof _.top != 'undefined' ? _.top : margin.top; - margin.right = typeof _.right != 'undefined' ? _.right : margin.right; - margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom; - margin.left = typeof _.left != 'undefined' ? _.left : margin.left; + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; }}, color: {get: function(){return color;}, set: function(_){ color = nv.utils.getColor(_); @@ -8776,12 +10204,11 @@ nv.models.pie = function() { , getX = function(d) { return d.x } , getY = function(d) { return d.y } , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null , color = nv.utils.defaultColor() , valueFormat = d3.format(',.2f') - , labelFormat = d3.format('%') , showLabels = true - , pieLabelsOutside = true - , donutLabelsOutside = false + , labelsOutside = false , labelType = "key" , labelThreshold = .02 //if slice percentage is under this, don't show label , donut = false @@ -8794,10 +10221,12 @@ nv.models.pie = function() { , endAngle = false , cornerRadius = 0 , donutRatio = 0.5 - , duration = 250 - , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + , arcsRadius = [] + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') ; + var arcs = []; + var arcsOver = []; //============================================================ // chart function @@ -8809,11 +10238,25 @@ nv.models.pie = function() { renderWatch.reset(); selection.each(function(data) { var availableWidth = width - margin.left - margin.right - ,availableHeight = height - margin.top - margin.bottom - ,radius = Math.min(availableWidth, availableHeight) / 2 - ,arcRadius = radius-(radius / 5) - ,container = d3.select(this) + , availableHeight = height - margin.top - margin.bottom + , radius = Math.min(availableWidth, availableHeight) / 2 + , arcsRadiusOuter = [] + , arcsRadiusInner = [] ; + + container = d3.select(this) + if (arcsRadius.length === 0) { + var outer = radius - radius / 5; + var inner = donutRatio * radius; + for (var i = 0; i < data[0].length; i++) { + arcsRadiusOuter.push(outer); + arcsRadiusInner.push(inner); + } + } else { + arcsRadiusOuter = arcsRadius.map(function (d) { return (d.outer - d.outer / 5) * radius; }); + arcsRadiusInner = arcsRadius.map(function (d) { return (d.inner - d.inner / 5) * radius; }); + donutRatio = d3.min(arcsRadius.map(function (d) { return (d.inner - d.inner / 5); })); + } nv.utils.initSVG(container); // Setup containers and skeleton of chart @@ -8838,21 +10281,33 @@ nv.models.pie = function() { }); }); + arcs = []; + arcsOver = []; + for (var i = 0; i < data[0].length; i++) { - var arc = d3.svg.arc().outerRadius(arcRadius); - var arcOver = d3.svg.arc().outerRadius(arcRadius + 5); + var arc = d3.svg.arc().outerRadius(arcsRadiusOuter[i]); + var arcOver = d3.svg.arc().outerRadius(arcsRadiusOuter[i] + 5); - if (startAngle) { - arc.startAngle(startAngle); - arcOver.startAngle(startAngle); - } - if (endAngle) { - arc.endAngle(endAngle); - arcOver.endAngle(endAngle); - } - if (donut) { - arc.innerRadius(radius * donutRatio); - arcOver.innerRadius(radius * donutRatio); + if (startAngle !== false) { + arc.startAngle(startAngle); + arcOver.startAngle(startAngle); + } + if (endAngle !== false) { + arc.endAngle(endAngle); + arcOver.endAngle(endAngle); + } + if (donut) { + arc.innerRadius(arcsRadiusInner[i]); + arcOver.innerRadius(arcsRadiusInner[i]); + } + + if (arc.cornerRadius && cornerRadius) { + arc.cornerRadius(cornerRadius); + arcOver.cornerRadius(cornerRadius); + } + + arcs.push(arc); + arcsOver.push(arcOver); } // Setup the Pie chart and choose the data element @@ -8865,21 +10320,16 @@ nv.models.pie = function() { pie.padAngle(padAngle); } - if (arc.cornerRadius && cornerRadius) { - arc.cornerRadius(cornerRadius); - arcOver.cornerRadius(cornerRadius); - } - // if title is specified and donut, put it in the middle if (donut && title) { - var title_g = g_pie.append('g').attr('class', 'nv-pie'); + g_pie.append("text").attr('class', 'nv-pie-title'); - title_g.append("text") + wrap.select('.nv-pie-title') .style("text-anchor", "middle") - .attr('class', 'nv-pie-title') .text(function (d) { return title; }) + .style("font-size", (Math.min(availableWidth, availableHeight)) * donutRatio * 2 / (title.length + 2) + "px") .attr("dy", "0.35em") // trick to vertically center text .attr('transform', function(d, i) { return 'translate(0, '+ titleOffset + ')'; @@ -8892,105 +10342,95 @@ nv.models.pie = function() { slices.exit().remove(); pieLabels.exit().remove(); - var ae = slices.enter().append('g') - ae.attr('class', 'nv-slice') - ae.on('mouseover', function(d,i){ + var ae = slices.enter().append('g'); + ae.attr('class', 'nv-slice'); + ae.on('mouseover', function(d, i) { d3.select(this).classed('hover', true); if (growOnHover) { d3.select(this).select("path").transition() .duration(70) - .attr("d", arcOver); + .attr("d", arcsOver[i]); } dispatch.elementMouseover({ - label: getX(d.data), - value: getY(d.data), - point: d.data, - pointIndex: i, - pos: [d3.event.pageX, d3.event.pageY], - id: id, + data: d.data, + index: i, color: d3.select(this).style("fill") }); }); - ae.on('mouseout', function(d,i){ + ae.on('mouseout', function(d, i) { d3.select(this).classed('hover', false); if (growOnHover) { d3.select(this).select("path").transition() .duration(50) - .attr("d", arc); + .attr("d", arcs[i]); } - dispatch.elementMouseout({ - label: getX(d.data), - value: getY(d.data), - point: d.data, - index: i, - id: id - }); + dispatch.elementMouseout({data: d.data, index: i}); }); - - slices.attr('fill', function(d,i) { return color(d, i); }) - slices.attr('stroke', function(d,i) { return color(d, i); }); - - var paths = ae.append('path').each(function(d) { - this._current = d; + ae.on('mousemove', function(d, i) { + dispatch.elementMousemove({data: d.data, index: i}); }); - - paths.on('click', function(d,i) { + ae.on('click', function(d, i) { dispatch.elementClick({ - label: getX(d.data), - value: getY(d.data), - point: d.data, + data: d.data, index: i, - pos: d3.event, - id: id + color: d3.select(this).style("fill") }); - d3.event.stopPropagation(); }); - paths.on('dblclick', function(d,i) { + ae.on('dblclick', function(d, i) { dispatch.elementDblClick({ - label: getX(d.data), - value: getY(d.data), - point: d.data, + data: d.data, index: i, - pos: d3.event, - id: id + color: d3.select(this).style("fill") }); - d3.event.stopPropagation(); }); + + slices.attr('fill', function(d,i) { return color(d.data, i); }); + slices.attr('stroke', function(d,i) { return color(d.data, i); }); + + var paths = ae.append('path').each(function(d) { + this._current = d; + }); + slices.select('path') .transition() - .attr('d', arc) + .attr('d', function (d, i) { return arcs[i](d); }) .attrTween('d', arcTween); if (showLabels) { // This does the normal label - var labelsArc = d3.svg.arc().innerRadius(0); - - if (pieLabelsOutside){ - var labelsArc = arc; - } - - if (donutLabelsOutside) { - labelsArc = d3.svg.arc().outerRadius(arc.outerRadius()); + var labelsArc = []; + for (var i = 0; i < data[0].length; i++) { + labelsArc.push(arcs[i]); + + if (labelsOutside) { + if (donut) { + labelsArc[i] = d3.svg.arc().outerRadius(arcs[i].outerRadius()); + if (startAngle !== false) labelsArc[i].startAngle(startAngle); + if (endAngle !== false) labelsArc[i].endAngle(endAngle); + } + } else if (!donut) { + labelsArc[i].innerRadius(0); + } } pieLabels.enter().append("g").classed("nv-label",true).each(function(d,i) { var group = d3.select(this); - group.attr('transform', function(d) { + group.attr('transform', function (d, i) { if (labelSunbeamLayout) { - d.outerRadius = arcRadius + 10; // Set Outer Coordinate - d.innerRadius = arcRadius + 15; // Set Inner Coordinate + d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate + d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI); - if ((d.startAngle+d.endAngle)/2 < Math.PI) { + if ((d.startAngle + d.endAngle) / 2 < Math.PI) { rotateAngle -= 90; } else { rotateAngle += 90; } - return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')'; + return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')'; } else { d.outerRadius = radius + 10; // Set Outer Coordinate d.innerRadius = radius + 15; // Set Inner Coordinate - return 'translate(' + labelsArc.centroid(d) + ')' + return 'translate(' + labelsArc[i].centroid(d) + ')' } }); @@ -9003,7 +10443,6 @@ nv.models.pie = function() { group.append('text') .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned .style('fill', '#000') - }); var labelLocationHash = {}; @@ -9013,28 +10452,28 @@ nv.models.pie = function() { return Math.floor(coordinates[0]/avgWidth) * avgWidth + ',' + Math.floor(coordinates[1]/avgHeight) * avgHeight; }; - pieLabels.watchTransition(renderWatch,'pie labels').attr('transform', function(d) { + pieLabels.watchTransition(renderWatch, 'pie labels').attr('transform', function (d, i) { if (labelSunbeamLayout) { - d.outerRadius = arcRadius + 10; // Set Outer Coordinate - d.innerRadius = arcRadius + 15; // Set Inner Coordinate + d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate + d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI); - if ((d.startAngle+d.endAngle)/2 < Math.PI) { + if ((d.startAngle + d.endAngle) / 2 < Math.PI) { rotateAngle -= 90; } else { rotateAngle += 90; } - return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')'; + return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')'; } else { d.outerRadius = radius + 10; // Set Outer Coordinate d.innerRadius = radius + 15; // Set Inner Coordinate /* - Overlapping pie labels are not good. What this attempts to do is, prevent overlapping. - Each label location is hashed, and if a hash collision occurs, we assume an overlap. - Adjust the label's y-position to remove the overlap. - */ - var center = labelsArc.centroid(d); - if(d.value){ + Overlapping pie labels are not good. What this attempts to do is, prevent overlapping. + Each label location is hashed, and if a hash collision occurs, we assume an overlap. + Adjust the label's y-position to remove the overlap. + */ + var center = labelsArc[i].centroid(d); + if (d.value) { var hashKey = createHashKey(center); if (labelLocationHash[hashKey]) { center[1] -= avgHeight; @@ -9046,15 +10485,35 @@ nv.models.pie = function() { }); pieLabels.select(".nv-label text") - .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned + .style('text-anchor', function(d,i) { + //center the text on it's origin or begin/end if orthogonal aligned + return labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle'; + }) .text(function(d, i) { var percent = (d.endAngle - d.startAngle) / (2 * Math.PI); - var labelTypes = { - "key" : getX(d.data), - "value": getY(d.data), - "percent": labelFormat(percent) - }; - return (d.value && percent > labelThreshold) ? labelTypes[labelType] : ''; + var label = ''; + if (!d.value || percent < labelThreshold) return ''; + + if(typeof labelType === 'function') { + label = labelType(d, i, { + 'key': getX(d.data), + 'value': getY(d.data), + 'percent': valueFormat(percent) + }); + } else { + switch (labelType) { + case 'key': + label = getX(d.data); + break; + case 'value': + label = valueFormat(getY(d.data)); + break; + case 'percent': + label = d3.format('%')(percent); + break; + } + } + return label; }) ; } @@ -9066,14 +10525,14 @@ nv.models.pie = function() { return a > 90 ? a - 180 : a; } - function arcTween(a) { + function arcTween(a, idx) { a.endAngle = isNaN(a.endAngle) ? 0 : a.endAngle; a.startAngle = isNaN(a.startAngle) ? 0 : a.startAngle; if (!donut) a.innerRadius = 0; var i = d3.interpolate(this._current, a); this._current = i(0); - return function(t) { - return arc(i(t)); + return function (t) { + return arcs[idx](i(t)); }; } }); @@ -9091,13 +10550,13 @@ nv.models.pie = function() { chart._options = Object.create({}, { // simple options, just get/set the necessary values + arcsRadius: { get: function () { return arcsRadius; }, set: function (_) { arcsRadius = _; } }, width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, showLabels: {get: function(){return showLabels;}, set: function(_){showLabels=_;}}, title: {get: function(){return title;}, set: function(_){title=_;}}, titleOffset: {get: function(){return titleOffset;}, set: function(_){titleOffset=_;}}, labelThreshold: {get: function(){return labelThreshold;}, set: function(_){labelThreshold=_;}}, - labelFormat: {get: function(){return labelFormat;}, set: function(_){labelFormat=_;}}, valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}}, x: {get: function(){return getX;}, set: function(_){getX=_;}}, id: {get: function(){return id;}, set: function(_){id=_;}}, @@ -9106,12 +10565,27 @@ nv.models.pie = function() { padAngle: {get: function(){return padAngle;}, set: function(_){padAngle=_;}}, cornerRadius: {get: function(){return cornerRadius;}, set: function(_){cornerRadius=_;}}, donutRatio: {get: function(){return donutRatio;}, set: function(_){donutRatio=_;}}, - pieLabelsOutside: {get: function(){return pieLabelsOutside;}, set: function(_){pieLabelsOutside=_;}}, - donutLabelsOutside: {get: function(){return donutLabelsOutside;}, set: function(_){donutLabelsOutside=_;}}, + labelsOutside: {get: function(){return labelsOutside;}, set: function(_){labelsOutside=_;}}, labelSunbeamLayout: {get: function(){return labelSunbeamLayout;}, set: function(_){labelSunbeamLayout=_;}}, donut: {get: function(){return donut;}, set: function(_){donut=_;}}, growOnHover: {get: function(){return growOnHover;}, set: function(_){growOnHover=_;}}, + // depreciated after 1.7.1 + pieLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){ + labelsOutside=_; + nv.deprecated('pieLabelsOutside', 'use labelsOutside instead'); + }}, + // depreciated after 1.7.1 + donutLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){ + labelsOutside=_; + nv.deprecated('donutLabelsOutside', 'use labelsOutside instead'); + }}, + // deprecated after 1.7.1 + labelFormat: {get: function(){ return valueFormat;}, set: function(_) { + valueFormat=_; + nv.deprecated('labelFormat','use valueFormat instead'); + }}, + // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ margin.top = typeof _.top != 'undefined' ? _.top : margin.top; @@ -9142,39 +10616,32 @@ nv.models.pieChart = function() { var pie = nv.models.pie(); var legend = nv.models.legend(); + var tooltip = nv.models.tooltip(); var margin = {top: 30, right: 20, bottom: 20, left: 20} , width = null , height = null , showLegend = true + , legendPosition = "top" , color = nv.utils.defaultColor() - , tooltips = true - , tooltip = function(key, y, e, graph) { - return '

' + key + '

' - + '

' + y + '

'; - } , state = nv.utils.state() , defaultState = null - , noData = "No Data Available." + , noData = null , duration = 250 - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd') + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') ; + tooltip + .duration(0) + .headerEnabled(false) + .valueFormatter(function(d, i) { + return pie.valueFormat()(d, i); + }); + //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - var tooltipLabel = pie.x()(e.point); - var left = e.pos[0] + ( (offsetElement && offsetElement.offsetLeft) || 0 ), - top = e.pos[1] + ( (offsetElement && offsetElement.offsetTop) || 0), - y = pie.valueFormat()(pie.y()(e.point)), - content = tooltip(tooltipLabel, y, e, chart) - ; - nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var renderWatch = nv.utils.renderWatch(dispatch); var stateGetter = function(data) { @@ -9208,11 +10675,8 @@ nv.models.pieChart = function() { nv.utils.initSVG(container); var that = this; - var availableWidth = (width || parseInt(container.style('width'), 10) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height'), 10) || 400) - - margin.top - margin.bottom - ; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { container.transition().call(chart); }; chart.container = this; @@ -9237,18 +10701,7 @@ nv.models.pieChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container); return chart; } else { container.selectAll('.nv-noData').remove(); @@ -9264,20 +10717,34 @@ nv.models.pieChart = function() { // Legend if (showLegend) { - legend.width( availableWidth ).key(pie.x()); + if (legendPosition === "top") { + legend.width( availableWidth ).key(pie.x()); - wrap.select('.nv-legendWrap') - .datum(data) - .call(legend); + wrap.select('.nv-legendWrap') + .datum(data) + .call(legend); - if ( margin.top != legend.height()) { - margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; - } + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } - wrap.select('.nv-legendWrap') - .attr('transform', 'translate(0,' + (-margin.top) +')'); + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')'); + } else if (legendPosition === "right") { + var legendWidth = nv.models.legend().width(); + if (availableWidth / 2 < legendWidth) { + legendWidth = (availableWidth / 2) + } + legend.height(availableHeight).key(pie.x()); + legend.width(legendWidth); + availableWidth -= legend.width(); + + wrap.select('.nv-legendWrap') + .datum(data) + .call(legend) + .attr('transform', 'translate(' + (availableWidth) +',0)'); + } } wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -9286,7 +10753,10 @@ nv.models.pieChart = function() { var pieWrap = g.select('.nv-pieWrap').datum([data]); d3.transition(pieWrap).call(pie); + //============================================================ // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + legend.dispatch.on('stateChange', function(newState) { for (var key in newState) { state[key] = newState[key]; @@ -9295,10 +10765,6 @@ nv.models.pieChart = function() { chart.update(); }); - pie.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { if (typeof e.disabled !== 'undefined') { @@ -9309,7 +10775,6 @@ nv.models.pieChart = function() { } chart.update(); }); - }); renderWatch.renderEnd('pieChart immediate'); @@ -9320,17 +10785,21 @@ nv.models.pieChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - pie.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + pie.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: chart.x()(evt.data), + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e); + pie.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + pie.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -9341,16 +10810,17 @@ nv.models.pieChart = function() { chart.legend = legend; chart.dispatch = dispatch; chart.pie = pie; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); // use Object get/set functionality to map between vars and chart functions chart._options = Object.create({}, { // simple options, just get/set the necessary values noData: {get: function(){return noData;}, set: function(_){noData=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + // options that require extra logic in the setter color: {get: function(){return color;}, set: function(_){ color = _; @@ -9360,6 +10830,12 @@ nv.models.pieChart = function() { duration: {get: function(){return duration;}, set: function(_){ duration = _; renderWatch.reset(duration); + }}, + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; }} }); nv.utils.inheritOptions(chart, pie); @@ -9379,6 +10855,7 @@ nv.models.scatter = function() { , height = null , color = nv.utils.defaultColor() // chooses color , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one + , container = null , x = d3.scale.linear() , y = d3.scale.linear() , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area @@ -9395,6 +10872,7 @@ nv.models.scatter = function() { , padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding , clipEdge = false // if true, masks points within x and y scale , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance + , showVoronoi = false // display the voronoi areas , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips , xDomain = null // Override x domain (skips the calculation from data) , yDomain = null // Override y domain @@ -9417,16 +10895,15 @@ nv.models.scatter = function() { , timeoutID , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips , renderWatch = nv.utils.renderWatch(dispatch, duration) + , _sizeRange_def = [16, 256] ; function chart(selection) { renderWatch.reset(); selection.each(function(data) { - var container = d3.select(this); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right; - var availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); nv.utils.initSVG(container); @@ -9460,10 +10937,11 @@ nv.models.scatter = function() { .range(yRange || [availableHeight, 0]); z .domain(sizeDomain || d3.extent(seriesData.map(function(d) { return d.size }).concat(forceSize))) - .range(sizeRange || [16, 256]); + .range(sizeRange || _sizeRange_def); // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point - if (x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]) singlePoint = true; + singlePoint = x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]; + if (x.domain()[0] === x.domain()[1]) x.domain()[0] ? x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) @@ -9488,13 +10966,15 @@ nv.models.scatter = function() { // Setup containers and skeleton of chart var wrap = container.selectAll('g.nv-wrap.nv-scatter').data([data]); - var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id + (singlePoint ? ' nv-single-point' : '')); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id); var defsEnter = wrapEnter.append('defs'); var gEnter = wrapEnter.append('g'); var g = wrap.select('g'); + wrap.classed('nv-single-point', singlePoint); gEnter.append('g').attr('class', 'nv-groups'); gEnter.append('g').attr('class', 'nv-point-paths'); + wrapEnter.append('g').attr('class', 'nv-point-clips'); wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -9503,42 +10983,43 @@ nv.models.scatter = function() { .append('rect'); wrap.select('#nv-edge-clip-' + id + ' rect') - .attr('width', availableWidth > 0 ? availableWidth : 0) + .attr('width', availableWidth) .attr('height', (availableHeight > 0) ? availableHeight : 0); g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : ''); function updateInteractiveLayer() { + // Always clear needs-update flag regardless of whether or not + // we will actually do anything (avoids needless invocations). + needsUpdate = false; if (!interactive) return false; - var eventElements; - - var vertices = d3.merge(data.map(function(group, groupIndex) { - return group.values - .map(function(point, pointIndex) { - // *Adding noise to make duplicates very unlikely - // *Injecting series and point index for reference - /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi. - */ - var pX = getX(point,pointIndex); - var pY = getY(point,pointIndex); - - return [x(pX)+ Math.random() * 1e-7, - y(pY)+ Math.random() * 1e-7, - groupIndex, - pointIndex, point]; //temp hack to add noise untill I think of a better way so there are no duplicates - }) - .filter(function(pointArray, pointIndex) { - return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct! - }) - }) - ); - - //inject series and point index for reference into voronoi + // inject series and point index for reference into voronoi if (useVoronoi === true) { + var vertices = d3.merge(data.map(function(group, groupIndex) { + return group.values + .map(function(point, pointIndex) { + // *Adding noise to make duplicates very unlikely + // *Injecting series and point index for reference + /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi. + */ + var pX = getX(point,pointIndex); + var pY = getY(point,pointIndex); + + return [x(pX)+ Math.random() * 1e-4, + y(pY)+ Math.random() * 1e-4, + groupIndex, + pointIndex, point]; //temp hack to add noise until I think of a better way so there are no duplicates + }) + .filter(function(pointArray, pointIndex) { + return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct! + }) + }) + ); - if(vertices.length < 3) { + if (vertices.length == 0) return false; // No active points, we're done + if (vertices.length < 3) { // Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]); vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]); @@ -9566,7 +11047,7 @@ nv.models.scatter = function() { // nuke all voronoi paths on reload and recreate them wrap.select('.nv-point-paths').selectAll('path').remove(); var pointPaths = wrap.select('.nv-point-paths').selectAll('path').data(voronoi); - pointPaths + var vPointPaths = pointPaths .enter().append("svg:path") .attr("d", function(d) { if (!d || !d.data || d.data.length === 0) @@ -9576,38 +11057,58 @@ nv.models.scatter = function() { }) .attr("id", function(d,i) { return "nv-path-"+i; }) - .attr("clip-path", function(d,i) { return "url(#nv-clip-"+i+")"; }) + .attr("clip-path", function(d,i) { return "url(#nv-clip-"+id+"-"+i+")"; }) ; - // chain these to above to see the voronoi elements (good for debugging) - //.style("fill", d3.rgb(230, 230, 230)) - //.style('fill-opacity', 0.4) - //.style('stroke-opacity', 1) - //.style("stroke", d3.rgb(200,200,200)); + + // good for debugging point hover issues + if (showVoronoi) { + vPointPaths.style("fill", d3.rgb(230, 230, 230)) + .style('fill-opacity', 0.4) + .style('stroke-opacity', 1) + .style("stroke", d3.rgb(200,200,200)); + } if (clipVoronoi) { // voronoi sections are already set to clip, // just create the circles with the IDs they expect - var clips = wrap.append("svg:g").attr("id", "nv-point-clips"); - clips.selectAll("clipPath") - .data(vertices) + wrap.select('.nv-point-clips').selectAll('*').remove(); // must do * since it has sub-dom + var pointClips = wrap.select('.nv-point-clips').selectAll('clipPath').data(vertices); + var vPointClips = pointClips .enter().append("svg:clipPath") - .attr("id", function(d, i) { return "nv-clip-"+i;}) + .attr("id", function(d, i) { return "nv-clip-"+id+"-"+i;}) .append("svg:circle") .attr('cx', function(d) { return d[0]; }) .attr('cy', function(d) { return d[1]; }) .attr('r', clipRadius); } - var mouseEventCallback = function(d,mDispatch) { + var mouseEventCallback = function(d, mDispatch) { if (needsUpdate) return 0; var series = data[d.series]; - if (typeof series === 'undefined') return; + if (series === undefined) return; var point = series.values[d.point]; + point['color'] = color(series, d.series); + + // standardize attributes for tooltip. + point['x'] = getX(point); + point['y'] = getY(point); + + // can't just get box of event node since it's actually a voronoi polygon + var box = container.node().getBoundingClientRect(); + var scrollTop = /*window.pageYOffset ||*/ document.documentElement.scrollTop; + var scrollLeft = /*window.pageXOffset ||*/ document.documentElement.scrollLeft; + + var pos = { + left: x(getX(point, d.point)) + box.left + scrollLeft + margin.left + 10, + top: y(getY(point, d.point)) + box.top + scrollTop + margin.top + 10 + }; + /*console.log(pos);*/ mDispatch({ point: point, series: series, - pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top], + pos: pos, + relativePos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top], seriesIndex: d.series, pointIndex: d.point }); @@ -9628,17 +11129,6 @@ nv.models.scatter = function() { }); } else { - /* - // bring data in form needed for click handlers - var dataWithPoints = vertices.map(function(d, i) { - return { - 'data': d, - 'series': vertices[i][2], - 'point': vertices[i][3] - } - }); - */ - // add event handlers to points instead voronoi paths wrap.select('.nv-groups').selectAll('.nv-group') .selectAll('.nv-point') @@ -9653,7 +11143,22 @@ nv.models.scatter = function() { dispatch.elementClick({ point: point, series: series, - pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], //TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + seriesIndex: d.series, + pointIndex: i + }); + }) + .on('dblclick', function(d,i) { + if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point + var series = data[d.series], + point = series.values[i]; + + dispatch.elementDblClick({ + point: point, + series: series, + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], seriesIndex: d.series, pointIndex: i }); @@ -9666,9 +11171,11 @@ nv.models.scatter = function() { dispatch.elementMouseover({ point: point, series: series, - pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], seriesIndex: d.series, - pointIndex: i + pointIndex: i, + color: color(d, i) }); }) .on('mouseout', function(d,i) { @@ -9679,13 +11186,14 @@ nv.models.scatter = function() { dispatch.elementMouseout({ point: point, series: series, + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], seriesIndex: d.series, - pointIndex: i + pointIndex: i, + color: color(d, i) }); }); } - - needsUpdate = false; } needsUpdate = true; @@ -9705,44 +11213,53 @@ nv.models.scatter = function() { .style('stroke-opacity', 1) .style('fill-opacity', .5); - // create the points + // create the points, maintaining their IDs from the original data set var points = groups.selectAll('path.nv-point') - .data(function(d) { return d.values }); + .data(function(d) { + return d.values.map( + function (point, pointIndex) { + return [point, pointIndex] + }).filter( + function(pointArray, pointIndex) { + return pointActive(pointArray[0], pointIndex) + }) + }); points.enter().append('path') - .style('fill', function (d,i) { return d.color }) - .style('stroke', function (d,i) { return d.color }) - .attr('transform', function(d,i) { - return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')' + .style('fill', function (d) { return d.color }) + .style('stroke', function (d) { return d.color }) + .attr('transform', function(d) { + return 'translate(' + x0(getX(d[0],d[1])) + ',' + y0(getY(d[0],d[1])) + ')' }) .attr('d', nv.utils.symbol() - .type(getShape) - .size(function(d,i) { return z(getSize(d,i)) }) + .type(function(d) { return getShape(d[0]); }) + .size(function(d) { return z(getSize(d[0],d[1])) }) ); points.exit().remove(); groups.exit().selectAll('path.nv-point') .watchTransition(renderWatch, 'scatter exit') - .attr('transform', function(d,i) { - return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')' + .attr('transform', function(d) { + return 'translate(' + x(getX(d[0],d[1])) + ',' + y(getY(d[0],d[1])) + ')' }) .remove(); - points.each(function(d,i) { + points.each(function(d) { d3.select(this) .classed('nv-point', true) - .classed('nv-point-' + i, true) + .classed('nv-point-' + d[1], true) + .classed('nv-noninteractive', !interactive) .classed('hover',false) ; }); points .watchTransition(renderWatch, 'scatter points') - .attr('transform', function(d,i) { - //nv.log(d,i,getX(d,i), x(getX(d,i))); - return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')' + .attr('transform', function(d) { + //nv.log(d, getX(d[0],d[1]), x(getX(d[0],d[1]))); + return 'translate(' + x(getX(d[0],d[1])) + ',' + y(getY(d[0],d[1])) + ')' }) .attr('d', nv.utils.symbol() - .type(getShape) - .size(function(d,i) { return z(getSize(d,i)) }) + .type(function(d) { return getShape(d[0]); }) + .size(function(d) { return z(getSize(d[0],d[1])) }) ); // Delay updating the invisible interactive layer for smoother animation @@ -9770,12 +11287,18 @@ nv.models.scatter = function() { // utility function calls provided by this chart chart._calls = new function() { this.clearHighlights = function () { - d3.selectAll(".nv-chart-" + id + " .nv-point.hover").classed("hover", false); + nv.dom.write(function() { + container.selectAll(".nv-point.hover").classed("hover", false); + }); return null; }; this.highlightPoint = function (seriesIndex, pointIndex, isHoverOver) { - d3.select(".nv-chart-" + id + " .nv-series-" + seriesIndex + " .nv-point-" + pointIndex) - .classed("hover", isHoverOver); + nv.dom.write(function() { + container.select('.nv-groups') + .selectAll(".nv-series-" + seriesIndex) + .selectAll(".nv-point-" + pointIndex) + .classed("hover", isHoverOver); + }); }; }; @@ -9811,6 +11334,7 @@ nv.models.scatter = function() { clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, clipVoronoi: {get: function(){return clipVoronoi;}, set: function(_){clipVoronoi=_;}}, clipRadius: {get: function(){return clipRadius;}, set: function(_){clipRadius=_;}}, + showVoronoi: {get: function(){return showVoronoi;}, set: function(_){showVoronoi=_;}}, id: {get: function(){return id;}, set: function(_){id=_;}}, @@ -9859,11 +11383,13 @@ nv.models.scatterChart = function() { , legend = nv.models.legend() , distX = nv.models.distribution() , distY = nv.models.distribution() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 20, bottom: 50, left: 75} , width = null , height = null + , container = null , color = nv.utils.defaultColor() , x = scatter.xScale() , y = scatter.yScale() @@ -9873,36 +11399,28 @@ nv.models.scatterChart = function() { , showXAxis = true , showYAxis = true , rightAlignYAxis = false - , tooltips = true - , tooltipX = function(key, x, y) { return '' + x + '' } - , tooltipY = function(key, x, y) { return '' + y + '' } - , tooltip = function(key, x, y, date) { return '

' + key + '

' - + '

' + date + '

' } , state = nv.utils.state() , defaultState = null - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') - , noData = "No Data Available." + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd') + , noData = null , duration = 250 ; - scatter - .xScale(x) - .yScale(y) - ; - xAxis - .orient('bottom') - .tickPadding(10) - ; + scatter.xScale(x).yScale(y); + xAxis.orient('bottom').tickPadding(10); yAxis .orient((rightAlignYAxis) ? 'right' : 'left') .tickPadding(10) ; - distX - .axis('x') - ; - distY - .axis('y') - ; + distX.axis('x'); + distY.axis('y'); + tooltip + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }); //============================================================ // Private Variables @@ -9911,25 +11429,6 @@ nv.models.scatterChart = function() { var x0, y0 , renderWatch = nv.utils.renderWatch(dispatch, duration); - var showTooltip = function(e, offsetElement) { - //TODO: make tooltip style an option between single or dual on axes (maybe on all charts with axes? - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - leftX = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - topX = y.range()[0] + margin.top + ( offsetElement.offsetTop || 0), - leftY = x.range()[0] + margin.left + ( offsetElement.offsetLeft || 0 ), - topY = e.pos[1] + ( offsetElement.offsetTop || 0), - xVal = xAxis.tickFormat()(scatter.x()(e.point, e.pointIndex)), - yVal = yAxis.tickFormat()(scatter.y()(e.point, e.pointIndex)); - - if( tooltipX != null ) - nv.tooltip.show([leftX, topX], tooltipX(e.series.key, xVal, yVal, e, chart), 'n', 1, offsetElement, 'x-nvtooltip'); - if( tooltipY != null ) - nv.tooltip.show([leftY, topY], tooltipY(e.series.key, xVal, yVal, e, chart), 'e', 1, offsetElement, 'y-nvtooltip'); - if( tooltip != null ) - nv.tooltip.show([left, top], tooltip(e.series.key, xVal, yVal, e.point.tooltip, e, chart), e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -9956,14 +11455,13 @@ nv.models.scatterChart = function() { if (showDistY) renderWatch.models(distY); selection.each(function(data) { - var container = d3.select(this), - that = this; + var that = this; + + container = d3.select(this); nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { if (duration === 0) @@ -9994,20 +11492,8 @@ nv.models.scatterChart = function() { // Display noData message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container); renderWatch.renderEnd('scatter immediate'); - return chart; } else { container.selectAll('.nv-noData').remove(); @@ -10033,8 +11519,6 @@ nv.models.scatterChart = function() { gEnter.append('g').attr('class', 'nv-distWrap'); gEnter.append('g').attr('class', 'nv-legendWrap'); - wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - if (rightAlignYAxis) { g.select(".nv-y.nv-axis") .attr("transform", "translate(" + availableWidth + ",0)"); @@ -10042,7 +11526,8 @@ nv.models.scatterChart = function() { // Legend if (showLegend) { - legend.width( availableWidth / 2 ); + var legendWidth = availableWidth; + legend.width(legendWidth); wrap.select('.nv-legendWrap') .datum(data) @@ -10050,20 +11535,22 @@ nv.models.scatterChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } wrap.select('.nv-legendWrap') - .attr('transform', 'translate(' + (availableWidth / 2) + ',' + (-margin.top) +')'); + .attr('transform', 'translate(0' + ',' + (-margin.top) +')'); } + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + // Main Chart Component(s) scatter .width(availableWidth) .height(availableHeight) .color(data.map(function(d,i) { - return d.color || color(d, i); + d.color = d.color || color(d, i); + return d.color; }).filter(function(d,i) { return !data[i].disabled })); wrap.select('.nv-scatterWrap') @@ -10114,7 +11601,7 @@ nv.models.scatterChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( xAxis.ticks() ? xAxis.ticks() : nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize( -availableHeight , 0); g.select('.nv-x.nv-axis') @@ -10125,14 +11612,14 @@ nv.models.scatterChart = function() { if (showYAxis) { yAxis .scale(y) - .ticks( yAxis.ticks() ? yAxis.ticks() : nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis') .call(yAxis); } - + // Setup Distribution if (showDistX) { distX .getData(scatter.x()) @@ -10176,35 +11663,34 @@ nv.models.scatterChart = function() { chart.update(); }); - - scatter.dispatch.on('elementMouseover.tooltip', function(e) { - d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-distx-' + e.pointIndex) - .attr('y1', e.pos[1] - availableHeight); - d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-disty-' + e.pointIndex) - .attr('x2', e.pos[0] + distX.size()); - - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined') { data.forEach(function(series,i) { series.disabled = e.disabled[i]; }); - state.disabled = e.disabled; } - chart.update(); }); + // mouseover needs availableHeight so we just keep scatter mouse events inside the chart block + scatter.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex) + .attr('y1', 0); + container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex) + .attr('x2', distY.size()); + }); + + scatter.dispatch.on('elementMouseover.tooltip', function(evt) { + container.select('.nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex) + .attr('y1', evt.relativePos[1] - availableHeight); + container.select('.nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex) + .attr('x2', evt.relativePos[0] + distX.size()); + tooltip.data(evt).hidden(false); + }); + //store old scales for use in transitions on update x0 = x.copy(); y0 = y.copy(); @@ -10215,22 +11701,6 @@ nv.models.scatterChart = function() { return chart; } - //============================================================ - // Event Handling/Dispatching (out of chart's scope) - //------------------------------------------------------------ - - scatter.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - - d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-distx-' + e.pointIndex) - .attr('y1', 0); - d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-disty-' + e.pointIndex) - .attr('x2', distY.size()); - }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); - }); - //============================================================ // Expose Public Variables //------------------------------------------------------------ @@ -10243,20 +11713,19 @@ nv.models.scatterChart = function() { chart.yAxis = yAxis; chart.distX = distX; chart.distY = distY; + chart.tooltip = tooltip; + chart.options = nv.utils.optionsFunc.bind(chart); chart._options = Object.create({}, { // simple options, just get/set the necessary values width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, + container: {get: function(){return container;}, set: function(_){container=_;}}, showDistX: {get: function(){return showDistX;}, set: function(_){showDistX=_;}}, showDistY: {get: function(){return showDistY;}, set: function(_){showDistY=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, - tooltipXContent: {get: function(){return tooltipX;}, set: function(_){tooltipX=_;}}, - tooltipYContent: {get: function(){return tooltipY;}, set: function(_){tooltipY=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, duration: {get: function(){return duration;}, set: function(_){duration=_;}}, @@ -10295,6 +11764,7 @@ nv.models.sparkline = function() { var margin = {top: 2, right: 0, bottom: 2, left: 0} , width = 400 , height = 32 + , container = null , animate = true , x = d3.scale.linear() , y = d3.scale.linear() @@ -10310,8 +11780,9 @@ nv.models.sparkline = function() { function chart(selection) { selection.each(function(data) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); nv.utils.initSVG(container); // Setup Scales @@ -10429,10 +11900,10 @@ nv.models.sparklinePlus = function() { , paused = false , xTickFormat = d3.format(',r') , yTickFormat = d3.format(',.2f') - , showValue = true + , showLastValue = true , alignValue = true , rightAlignValue = false - , noData = "No Data Available." + , noData = null ; function chart(selection) { @@ -10440,28 +11911,15 @@ nv.models.sparklinePlus = function() { var container = d3.select(this); nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); - chart.update = function() { chart(selection) }; + chart.update = function() { container.call(chart); }; chart.container = this; // Display No Data message if there's nothing to show. if (!data || !data.length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -10491,20 +11949,24 @@ nv.models.sparklinePlus = function() { sparkline.width(availableWidth).height(availableHeight); sparklineWrap.call(sparkline); - var valueWrap = g.select('.nv-valueWrap'); - var value = valueWrap.selectAll('.nv-currentValue') - .data([currentValue]); + if (showLastValue) { + var valueWrap = g.select('.nv-valueWrap'); + var value = valueWrap.selectAll('.nv-currentValue') + .data([currentValue]); - value.enter().append('text').attr('class', 'nv-currentValue') - .attr('dx', rightAlignValue ? -8 : 8) - .attr('dy', '.9em') - .style('text-anchor', rightAlignValue ? 'end' : 'start'); + value.enter().append('text').attr('class', 'nv-currentValue') + .attr('dx', rightAlignValue ? -8 : 8) + .attr('dy', '.9em') + .style('text-anchor', rightAlignValue ? 'end' : 'start'); - value - .attr('x', availableWidth + (rightAlignValue ? margin.right : 0)) - .attr('y', alignValue ? function(d) { return y(d) } : 0) - .style('fill', sparkline.color()(data[data.length-1], data.length-1)) - .text(yTickFormat(currentValue)); + value + .attr('x', availableWidth + (rightAlignValue ? margin.right : 0)) + .attr('y', alignValue ? function (d) { + return y(d) + } : 0) + .style('fill', sparkline.color()(data[data.length - 1], data.length - 1)) + .text(yTickFormat(currentValue)); + } gEnter.select('.nv-hoverArea').append('rect') .on('mousemove', sparklineHover) @@ -10520,7 +11982,7 @@ nv.models.sparklinePlus = function() { function updateValueLine() { if (paused) return; - var hoverValue = g.selectAll('.nv-hoverValue').data(index) + var hoverValue = g.selectAll('.nv-hoverValue').data(index); var hoverEnter = hoverValue.enter() .append('g').attr('class', 'nv-hoverValue') @@ -10551,7 +12013,7 @@ nv.models.sparklinePlus = function() { .attr('x', -6) .attr('y', -margin.top) .attr('text-anchor', 'end') - .attr('dy', '.9em') + .attr('dy', '.9em'); g.select('.nv-hoverValue .nv-xValue') .text(xTickFormat(sparkline.x()(data[index[0]], index[0]))); @@ -10560,7 +12022,7 @@ nv.models.sparklinePlus = function() { .attr('x', 6) .attr('y', -margin.top) .attr('text-anchor', 'start') - .attr('dy', '.9em') + .attr('dy', '.9em'); g.select('.nv-hoverValue .nv-yValue') .text(yTickFormat(sparkline.y()(data[index[0]], index[0]))); @@ -10607,7 +12069,7 @@ nv.models.sparklinePlus = function() { height: {get: function(){return height;}, set: function(_){height=_;}}, xTickFormat: {get: function(){return xTickFormat;}, set: function(_){xTickFormat=_;}}, yTickFormat: {get: function(){return yTickFormat;}, set: function(_){yTickFormat=_;}}, - showValue: {get: function(){return showValue;}, set: function(_){showValue=_;}}, + showLastValue: {get: function(){return showLastValue;}, set: function(_){showLastValue=_;}}, alignValue: {get: function(){return alignValue;}, set: function(_){alignValue=_;}}, rightAlignValue: {get: function(){return rightAlignValue;}, set: function(_){rightAlignValue=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, @@ -10639,6 +12101,7 @@ nv.models.stackedArea = function() { , height = 500 , color = nv.utils.defaultColor() // a function that computes the color , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one + , container = null , getX = function(d) { return d.x } // accessor to get the x value from a data point , getY = function(d) { return d.y } // accessor to get the y value from a data point , style = 'stack' @@ -10650,12 +12113,9 @@ nv.models.stackedArea = function() { , y //can be accessed via chart.yScale() , scatter = nv.models.scatter() , duration = 250 - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'areaClick', 'areaMouseover', 'areaMouseout','renderEnd') + , dispatch = d3.dispatch('areaClick', 'areaMouseover', 'areaMouseout','renderEnd', 'elementClick', 'elementMouseover', 'elementMouseout') ; - // scatter is interactive by default, but this chart isn't so must disable - scatter.interactive(false); - scatter .pointSize(2.2) // default size .pointDomain([2.2, 2.2]) // all the same size by default @@ -10680,8 +12140,9 @@ nv.models.stackedArea = function() { renderWatch.models(scatter); selection.each(function(data) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); nv.utils.initSVG(container); // Setup Scales @@ -10710,9 +12171,8 @@ nv.models.stackedArea = function() { .x(getX) .y(getY) .out(function(d, y0, y) { - var yHeight = (getY(d) === 0) ? 0 : y; d.display = { - y: yHeight, + y: y, y0: y0 }; }) @@ -10729,12 +12189,20 @@ nv.models.stackedArea = function() { gEnter.append('g').attr('class', 'nv-scatterWrap'); wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - + + // If the user has not specified forceY, make sure 0 is included in the domain + // Otherwise, use user-specified values for forceY + if (scatter.forceY().length == 0) { + scatter.forceY().push(0); + } + scatter .width(availableWidth) .height(availableHeight) .x(getX) - .y(function(d) { return d.display.y + d.display.y0 }) + .y(function(d) { + if (d.display !== undefined) { return d.display.y + d.display.y0; } + }) .forceY([0]) .color(data.map(function(d,i) { return d.color || color(d, d.seriesIndex); @@ -10830,22 +12298,21 @@ nv.models.stackedArea = function() { chart.d3_stackedOffset_stackPercent = function(stackData) { var n = stackData.length, //How many series m = stackData[0].length, //how many points per series - k = 1 / n, i, j, o, y0 = []; for (j = 0; j < m; ++j) { //Looping through all points - for (i = 0, o = 0; i < dataRaw.length; i++) { //looping through series' - o += getY(dataRaw[i].values[j]); //total value of all points at a certian point in time. + for (i = 0, o = 0; i < dataRaw.length; i++) { //looping through all series + o += getY(dataRaw[i].values[j]); //total y value of all series at a certian point in time. } - if (o) for (i = 0; i < n; i++) { + if (o) for (i = 0; i < n; i++) { //(total y value of all series at point in time i) != 0 stackData[i][j][1] /= o; - } else { + } else { //(total y value of all series at point in time i) == 0 for (i = 0; i < n; i++) { - stackData[i][j][1] = k; + stackData[i][j][1] = 0; } } } @@ -10859,22 +12326,6 @@ nv.models.stackedArea = function() { return chart; } - - //============================================================ - // Event Handling/Dispatching (out of chart's scope) - //------------------------------------------------------------ - - scatter.dispatch.on('elementClick.area', function(e) { - dispatch.areaClick(e); - }); - scatter.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top], - dispatch.tooltipShow(e); - }); - scatter.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - //============================================================ // Global getters and setters //------------------------------------------------------------ @@ -10882,6 +12333,10 @@ nv.models.stackedArea = function() { chart.dispatch = dispatch; chart.scatter = scatter; + scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); }); + scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); }); + scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); }); + chart.interpolate = function(_) { if (!arguments.length) return interpolate; interpolate = _; @@ -10897,6 +12352,7 @@ nv.models.stackedArea = function() { }; chart.dispatch = dispatch; + chart.scatter = scatter; chart.options = nv.utils.optionsFunc.bind(chart); chart._options = Object.create({}, { @@ -10973,6 +12429,7 @@ nv.models.stackedAreaChart = function() { , legend = nv.models.legend() , controls = nv.models.legend() , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 25, bottom: 50, left: 60} @@ -10985,20 +12442,16 @@ nv.models.stackedAreaChart = function() { , showYAxis = true , rightAlignYAxis = false , useInteractiveGuideline = false - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

' + key + '

' + - '

' + y + ' on ' + x + '

' - } + , showTotalInTooltip = true + , totalLabel = 'TOTAL' , x //can be accessed via chart.xScale() , y //can be accessed via chart.yScale() - , yAxisTickFormat = d3.format(',.2f') , state = nv.utils.state() , defaultState = null - , noData = 'No Data Available.' - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd') + , noData = null + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') , controlWidth = 250 - , cData = ['Stacked','Stream','Expanded'] + , controlOptions = ['Stacked','Stream','Expanded'] , controlLabels = {} , duration = 250 ; @@ -11007,6 +12460,25 @@ nv.models.stackedAreaChart = function() { xAxis.orient('bottom').tickPadding(7); yAxis.orient((rightAlignYAxis) ? 'right' : 'left'); + tooltip + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }); + + interactiveLayer.tooltip + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }); + + var oldYTickFormat = null, + oldValueFormatter = null; + controls.updateState(false); //============================================================ @@ -11016,16 +12488,6 @@ nv.models.stackedAreaChart = function() { var renderWatch = nv.utils.renderWatch(dispatch); var style = stacked.style(); - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(stacked.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(stacked.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -11046,6 +12508,8 @@ nv.models.stackedAreaChart = function() { } }; + var percentFormatter = d3.format('%'); + function chart(selection) { renderWatch.reset(); renderWatch.models(stacked); @@ -11057,10 +12521,8 @@ nv.models.stackedAreaChart = function() { that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { container.transition().duration(duration).call(chart); }; chart.container = this; @@ -11084,20 +12546,9 @@ nv.models.stackedAreaChart = function() { } } - // Display No Data message if there's nothing to show. - if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + // Display No Data message if there's nothing to show. + if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -11131,8 +12582,7 @@ nv.models.stackedAreaChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.nv-legendWrap') @@ -11168,9 +12618,9 @@ nv.models.stackedAreaChart = function() { } ]; - controlWidth = (cData.length/3) * 260; + controlWidth = (controlOptions.length/3) * 260; controlsData = controlsData.filter(function(d) { - return cData.indexOf(d.metaKey) !== -1; + return controlOptions.indexOf(d.metaKey) !== -1; }); controls @@ -11183,8 +12633,7 @@ nv.models.stackedAreaChart = function() { if ( margin.top != Math.max(controls.height(), legend.height()) ) { margin.top = Math.max(controls.height(), legend.height()); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.nv-controlsWrap') @@ -11221,7 +12670,7 @@ nv.models.stackedAreaChart = function() { // Setup Axes if (showXAxis) { xAxis.scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize( -availableHeight, 0); g.select('.nv-x.nv-axis') @@ -11233,11 +12682,32 @@ nv.models.stackedAreaChart = function() { } if (showYAxis) { + var ticks; + if (stacked.offset() === 'wiggle') { + ticks = 0; + } + else { + ticks = nv.utils.calcTicksY(availableHeight/36, data); + } yAxis.scale(y) - .ticks(stacked.offset() == 'wiggle' ? 0 : nv.utils.calcTicksY(availableHeight/36, data) ) - .tickSize(-availableWidth, 0) - .setTickFormat( (stacked.style() == 'expand' || stacked.style() == 'stack_percent') - ? d3.format('%') : yAxisTickFormat); + ._ticks(ticks) + .tickSize(-availableWidth, 0); + + if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') { + var currentFormat = yAxis.tickFormat(); + + if ( !oldYTickFormat || currentFormat !== percentFormatter ) + oldYTickFormat = currentFormat; + + //Forces the yAxis to use percentage in 'expand' mode. + yAxis.tickFormat(percentFormatter); + } + else { + if (oldYTickFormat) { + yAxis.tickFormat(oldYTickFormat); + oldYTickFormat = null; + } + } g.select('.nv-y.nv-axis') .transition().duration(0) @@ -11291,7 +12761,7 @@ nv.models.stackedAreaChart = function() { interactiveLayer.dispatch.on('elementMousemove', function(e) { stacked.clearHighlights(); - var singlePoint, pointIndex, pointXLocation, allData = []; + var singlePoint, pointIndex, pointXLocation, allData = [], valueSum = 0; data .filter(function(series, i) { series.seriesIndex = i; @@ -11299,8 +12769,11 @@ nv.models.stackedAreaChart = function() { }) .forEach(function(series,i) { pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); - stacked.highlightPoint(i, pointIndex, true); var point = series.values[pointIndex]; + var pointYValue = chart.y()(point, pointIndex); + if (pointYValue != null) { + stacked.highlightPoint(i, pointIndex, true); + } if (typeof point === 'undefined') return; if (typeof singlePoint === 'undefined') singlePoint = point; if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); @@ -11313,6 +12786,10 @@ nv.models.stackedAreaChart = function() { color: color(series,series.seriesIndex), stackedValue: point.display }); + + if (showTotalInTooltip && stacked.style() != 'expand') { + valueSum += tooltipValue; + }; }); allData.reverse(); @@ -11338,16 +12815,35 @@ nv.models.stackedAreaChart = function() { allData[indexToHighlight].highlight = true; } + //If we are not in 'expand' mode, add a 'Total' row to the tooltip. + if (showTotalInTooltip && stacked.style() != 'expand' && allData.length >= 2) { + allData.push({ + key: totalLabel, + value: valueSum, + total: true + }); + } + var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); - //If we are in 'expand' mode, force the format to be a percentage. - var valueFormatter = (stacked.style() == 'expand') ? - function(d,i) {return d3.format(".1%")(d);} : - function(d,i) {return yAxis.tickFormat()(d); }; + var valueFormatter = interactiveLayer.tooltip.valueFormatter(); + // Keeps track of the tooltip valueFormatter if the chart changes to expanded view + if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') { + if ( !oldValueFormatter ) { + oldValueFormatter = valueFormatter; + } + //Forces the tooltip to use percentage in 'expand' mode. + valueFormatter = d3.format(".1%"); + } + else { + if (oldValueFormatter) { + valueFormatter = oldValueFormatter; + oldValueFormatter = null; + } + } + interactiveLayer.tooltip - .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) .chartContainer(that.parentNode) - .enabled(tooltips) .valueFormatter(valueFormatter) .data( { @@ -11361,15 +12857,9 @@ nv.models.stackedAreaChart = function() { }); interactiveLayer.dispatch.on("elementMouseout",function(e) { - dispatch.tooltipHide(); stacked.clearHighlights(); }); - - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { @@ -11399,17 +12889,14 @@ nv.models.stackedAreaChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - stacked.dispatch.on('tooltipShow', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - stacked.dispatch.on('tooltipHide', function(e) { - dispatch.tooltipHide(e); + stacked.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.point['x'] = stacked.x()(evt.point); + evt.point['y'] = stacked.y()(evt.point); + tooltip.data(evt).hidden(false); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + stacked.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) }); //============================================================ @@ -11424,8 +12911,7 @@ nv.models.stackedAreaChart = function() { chart.xAxis = xAxis; chart.yAxis = yAxis; chart.interactiveLayer = interactiveLayer; - - yAxis.setTickFormat = yAxis.tickFormat; + chart.tooltip = tooltip; chart.dispatch = dispatch; chart.options = nv.utils.optionsFunc.bind(chart); @@ -11437,13 +12923,13 @@ nv.models.stackedAreaChart = function() { showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, - yAxisTickFormat: {get: function(){return yAxisTickFormat;}, set: function(_){yAxisTickFormat=_;}}, + controlOptions: {get: function(){return controlOptions;}, set: function(_){controlOptions=_;}}, + showTotalInTooltip: {get: function(){return showTotalInTooltip;}, set: function(_){showTotalInTooltip=_;}}, + totalLabel: {get: function(){return totalLabel;}, set: function(_){totalLabel=_;}}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ @@ -11470,10 +12956,9 @@ nv.models.stackedAreaChart = function() { }}, useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ useInteractiveGuideline = !!_; - if (_) { - chart.interactive(false); - chart.useVoronoi(false); - } + chart.interactive(!_); + chart.useVoronoi(!_); + stacked.scatter.interactive(!_); }} }); @@ -11482,6 +12967,355 @@ nv.models.stackedAreaChart = function() { return chart; }; +// based on http://bl.ocks.org/kerryrodden/477c1bfb081b783f80ad +nv.models.sunburst = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , mode = "count" + , modes = {count: function(d) { return 1; }, size: function(d) { return d.size }} + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null + , color = nv.utils.defaultColor() + , duration = 500 + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMousemove', 'elementMouseover', 'elementMouseout', 'renderEnd') + ; + + var x = d3.scale.linear().range([0, 2 * Math.PI]); + var y = d3.scale.sqrt(); + + var partition = d3.layout.partition() + .sort(null) + .value(function(d) { return 1; }); + + var arc = d3.svg.arc() + .startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); }) + .endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); }) + .innerRadius(function(d) { return Math.max(0, y(d.y)); }) + .outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); }); + + // Keep track of the current and previous node being displayed as the root. + var node, prevNode; + // Keep track of the root node + var rootNode; + + //============================================================ + // chart function + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin); + var availableHeight = nv.utils.availableHeight(height, container, margin); + var radius = Math.min(availableWidth, availableHeight) / 2; + var path; + + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('.nv-wrap.nv-sunburst').data(data); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sunburst nv-chart-' + id); + + var g = wrapEnter.selectAll('nv-sunburst'); + + wrap.attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')'); + + container.on('click', function (d, i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + y.range([0, radius]); + + node = node || data; + rootNode = data[0]; + partition.value(modes[mode] || modes["count"]); + path = g.data(partition.nodes).enter() + .append("path") + .attr("d", arc) + .style("fill", function (d) { + return color((d.children ? d : d.parent).name); + }) + .style("stroke", "#FFF") + .on("click", function(d) { + if (prevNode !== node && node !== d) prevNode = node; + node = d; + path.transition() + .duration(duration) + .attrTween("d", arcTweenZoom(d)); + }) + .each(stash) + .on("dblclick", function(d) { + if (prevNode.parent == d) { + path.transition() + .duration(duration) + .attrTween("d", arcTweenZoom(rootNode)); + } + }) + .each(stash) + .on('mouseover', function(d,i){ + d3.select(this).classed('hover', true).style('opacity', 0.8); + dispatch.elementMouseover({ + data: d, + color: d3.select(this).style("fill") + }); + }) + .on('mouseout', function(d,i){ + d3.select(this).classed('hover', false).style('opacity', 1); + dispatch.elementMouseout({ + data: d + }); + }) + .on('mousemove', function(d,i){ + dispatch.elementMousemove({ + data: d + }); + }); + + + + // Setup for switching data: stash the old values for transition. + function stash(d) { + d.x0 = d.x; + d.dx0 = d.dx; + } + + // When switching data: interpolate the arcs in data space. + function arcTweenData(a, i) { + var oi = d3.interpolate({x: a.x0, dx: a.dx0}, a); + + function tween(t) { + var b = oi(t); + a.x0 = b.x; + a.dx0 = b.dx; + return arc(b); + } + + if (i == 0) { + // If we are on the first arc, adjust the x domain to match the root node + // at the current zoom level. (We only need to do this once.) + var xd = d3.interpolate(x.domain(), [node.x, node.x + node.dx]); + return function (t) { + x.domain(xd(t)); + return tween(t); + }; + } else { + return tween; + } + } + + // When zooming: interpolate the scales. + function arcTweenZoom(d) { + var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]), + yd = d3.interpolate(y.domain(), [d.y, 1]), + yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]); + return function (d, i) { + return i + ? function (t) { + return arc(d); + } + : function (t) { + x.domain(xd(t)); + y.domain(yd(t)).range(yr(t)); + return arc(d); + }; + }; + } + + }); + + renderWatch.renderEnd('sunburst immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + mode: {get: function(){return mode;}, set: function(_){mode=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + duration: {get: function(){return duration;}, set: function(_){duration=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top != undefined ? _.top : margin.top; + margin.right = _.right != undefined ? _.right : margin.right; + margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom; + margin.left = _.left != undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color=nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; +nv.models.sunburstChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var sunburst = nv.models.sunburst(); + var tooltip = nv.models.tooltip(); + + var margin = {top: 30, right: 20, bottom: 20, left: 20} + , width = null + , height = null + , color = nv.utils.defaultColor() + , id = Math.round(Math.random() * 100000) + , defaultState = null + , noData = null + , duration = 250 + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') + ; + + tooltip.duration(0); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + tooltip + .headerEnabled(false) + .valueFormatter(function(d, i) { + return d; + }); + + //============================================================ + // Chart function + //------------------------------------------------------------ + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(sunburst); + + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var that = this; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { + if (duration === 0) + container.call(chart); + else + container.transition().duration(duration).call(chart) + }; + chart.container = this; + + // Display No Data message if there's nothing to show. + if (!data || !data.length) { + nv.utils.noData(chart, container); + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-sunburstChart').data(data); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sunburstChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-sunburstWrap'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + sunburst.width(availableWidth).height(availableHeight); + var sunWrap = g.select('.nv-sunburstWrap').datum(data); + d3.transition(sunWrap).call(sunburst); + + }); + + renderWatch.renderEnd('sunburstChart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + sunburst.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: evt.data.name, + value: evt.data.size, + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + sunburst.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + sunburst.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.sunburst = sunburst; + chart.tooltip = tooltip; + chart.options = nv.utils.optionsFunc.bind(chart); + + // use Object get/set functionality to map between vars and chart functions + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + + // options that require extra logic in the setter + color: {get: function(){return color;}, set: function(_){ + color = _; + sunburst.color(color); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + sunburst.duration(duration); + }}, + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }} + }); + nv.utils.inheritOptions(chart, sunburst); + nv.utils.initOptions(chart); + return chart; +}; -nv.version = "1.7.1"; +nv.version = "1.8.1-dev"; })(); \ No newline at end of file diff --git a/build/nv.d3.min.css b/build/nv.d3.min.css index 3c9aed028..7d63faf94 100644 --- a/build/nv.d3.min.css +++ b/build/nv.d3.min.css @@ -1 +1,2 @@ -svg{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;display:block;width:100%;height:100%}svg.nvd3-svg{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none;display:block}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nvtooltip{position:absolute;background-color:rgba(255,255,255,1);padding:1px;border:1px solid rgba(0,0,0,.2);z-index:10000;font-family:Arial;font-size:13px;text-align:left;pointer-events:none;white-space:nowrap;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;-moz-transition:opacity 50ms linear;-webkit-transition:opacity 50ms linear;transition-delay:200ms;-moz-transition-delay:200ms;-webkit-transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{margin:0;padding:4px 14px;line-height:18px;font-weight:400;background-color:rgba(247,247,247,.75);text-align:center;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:1px 5px 0 0}.nvtooltip p{margin:0;padding:5px 14px;text-align:center}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key{font-weight:400}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{width:8px;height:8px;vertical-align:middle}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{position:absolute;pointer-events:none}.nvd3 text{font:400 12px Arial}.nvd3 .title{font:700 14px Arial}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125;shape-rendering:crispEdges}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.axis{opacity:1}.axis.nv-disabled{opacity:0}.nvd3 .nv-axis{pointer-events:none}.nvd3 .nv-axis path{fill:none;stroke:#000;stroke-opacity:.75;shape-rendering:crispEdges}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{fill:none;stroke:#e5e5e5;shape-rendering:crispEdges}.nvd3 .nv-axis .zero line,.nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-bars .negative rect{zfill:brown}.nvd3 .nv-bars rect{zfill:#4682b4;fill-opacity:.75;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:rgba(0,0,0,0)}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect,.nvd3 .nv-discretebar .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:rgba(0,0,0,0)}.nvd3.nv-pie path{stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{stroke:#fff;stroke-width:1px;stroke-opacity:1}.nvd3.nv-pie .hover path{fill-opacity:.7}.nvd3.nv-pie .nv-label{pointer-events:none}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups path.nv-line{fill:none;stroke-width:1.5px}.nvd3 .nv-groups path.nv-line.nv-thin-line{stroke-width:1px}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3 .nv-line.hover path{stroke-width:6px}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-scatter .nv-groups .nv-point.hover,.nvd3 .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}.nvd3 .nv-distribution{pointer-events:none}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3.nv-historicalStockChart .nv-axis .nv-axislabel{font-weight:700}.nvd3.nv-historicalStockChart .nv-dragTarget{fill-opacity:0;stroke:none;cursor:move}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4;shape-rendering:crispEdges}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .brush .extent{fill-opacity:.3;stroke:#fff;shape-rendering:crispEdges}.nvd3 .axis line,.axis path{fill:none;stroke:#000;shape-rendering:crispEdges}.nvd3 .axis text{text-shadow:0 1px 0 #fff}.nvd3 .nv-interactiveGuideLine{pointer-events:none}.nvd3 line.nv-guideline{stroke:#ccc} \ No newline at end of file +.nvd3 .nv-axis line,.nvd3 .nv-axis path{fill:none;shape-rendering:crispEdges}.nv-brush .extent,.nvd3 .background path,.nvd3 .nv-axis line,.nvd3 .nv-axis path{shape-rendering:crispEdges}.nv-distx,.nv-disty,.nv-noninteractive,.nvd3 .nv-axis,.nvd3.nv-pie .nv-label,.nvd3.nv-sparklineplus g.nv-hoverValue{pointer-events:none}.nvtooltip,svg.nvd3-svg{display:block;-webkit-touch-callout:none;-khtml-user-select:none}.nvd3 .nv-axis{opacity:1}.nvd3 .nv-axis.nv-disabled,.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check{opacity:0}.nvd3 .nv-axis path{stroke:#000;stroke-opacity:.75}.nvd3 .nv-axis path.domain{stroke-opacity:.75}.nvd3 .nv-axis.nv-x path.domain{stroke-opacity:0}.nvd3 .nv-axis line{stroke:#e5e5e5}.nvd3 .nv-axis .zero line, .nvd3 .nv-axis line.zero{stroke-opacity:.75}.nvd3 .nv-axis .nv-axisMaxMin text{font-weight:700}.nvd3 .x .nv-axis .nv-axisMaxMin text,.nvd3 .x2 .nv-axis .nv-axisMaxMin text,.nvd3 .x3 .nv-axis .nv-axisMaxMin text{text-anchor:middle}.nvd3 .nv-bars rect{fill-opacity:.75;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-bars rect.hover{fill-opacity:1}.nvd3 .nv-bars .hover rect{fill:#add8e6}.nvd3 .nv-bars text{fill:transparent}.nvd3 .nv-bars .hover text{fill:rgba(0,0,0,1)}.nvd3 .nv-discretebar .nv-groups rect,.nvd3 .nv-multibar .nv-groups rect,.nvd3 .nv-multibarHorizontal .nv-groups rect{stroke-opacity:0;transition:fill-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear}.nvd3 .nv-candlestickBar .nv-ticks rect:hover,.nvd3 .nv-discretebar .nv-groups rect:hover,.nvd3 .nv-multibar .nv-groups rect:hover,.nvd3 .nv-multibarHorizontal .nv-groups rect:hover{fill-opacity:1}.nvd3 .nv-discretebar .nv-groups text,.nvd3 .nv-multibarHorizontal .nv-groups text{font-weight:700;fill:rgba(0,0,0,1);stroke:transparent}.nvd3 .nv-boxplot circle{fill-opacity:.5}.nvd3 .nv-boxplot circle:hover,.nvd3 .nv-boxplot rect:hover{fill-opacity:1}.nvd3 line.nv-boxplot-median{stroke:#000}.nv-boxplot-tick:hover{stroke-width:2.5px}.nvd3.nv-bullet{font:10px sans-serif}.nvd3.nv-bullet .nv-measure{fill-opacity:.8}.nvd3.nv-bullet .nv-measure:hover{fill-opacity:1}.nvd3.nv-bullet .nv-marker{stroke:#000;stroke-width:2px}.nvd3.nv-bullet .nv-markerTriangle{stroke:#000;fill:#fff;stroke-width:1.5px}.nvd3.nv-bullet .nv-tick line{stroke:#666;stroke-width:.5px}.nvd3.nv-bullet .nv-range.nv-s0{fill:#eee}.nvd3.nv-bullet .nv-range.nv-s1{fill:#ddd}.nvd3.nv-bullet .nv-range.nv-s2{fill:#ccc}.nvd3.nv-bullet .nv-title{font-size:14px;font-weight:700}.nvd3.nv-bullet .nv-subtitle{fill:#999}.nvd3.nv-bullet .nv-range{fill:#bababa;fill-opacity:.4}.nvd3.nv-bullet .nv-range:hover{fill-opacity:.7}.nvd3.nv-candlestickBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect{stroke:#d62728;fill:#d62728}.with-transitions .nv-candlestickBar .nv-ticks .nv-tick{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-candlestickBar .nv-ticks line{stroke:#333}.nvd3 .nv-check-box .nv-box{fill-opacity:0;stroke-width:2}.nvd3 .nv-check-box .nv-check{fill-opacity:0;stroke-width:4}.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check{fill-opacity:0;stroke-opacity:0}.nvd3.nv-linePlusBar .nv-bar rect{fill-opacity:.75}.nvd3.nv-linePlusBar .nv-bar rect:hover{fill-opacity:1}.nvd3 .nv-groups path.nv-line{fill:none}.nvd3 .nv-groups path.nv-area{stroke:none}.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point{fill-opacity:0;stroke-opacity:0}.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point{fill-opacity:.5!important;stroke-opacity:.5!important}.with-transitions .nvd3 .nv-groups .nv-point{transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:stroke-width 250ms linear,stroke-opacity 250ms linear}.nvd3 .nv-groups .nv-point.hover,.nvd3.nv-scatter .nv-groups .nv-point.hover{stroke-width:7px;fill-opacity:.95!important;stroke-opacity:.95!important}.nvd3 .nv-point-paths path{stroke:#aaa;stroke-opacity:0;fill:#eee;fill-opacity:0}.nvd3 .nv-indexLine{cursor:ew-resize}svg.nvd3-svg{-webkit-user-select:none;-ms-user-select:none;-moz-user-select:none;user-select:none;width:100%;height:100%}.nvtooltip.with-3d-shadow,.with-3d-shadow .nvtooltip{-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nvd3 text{font:400 12px Arial}.nvd3 .title{font:700 14px Arial}.nvd3 .nv-background{fill:#fff;fill-opacity:0}.nvd3.nv-noData{font-size:18px;font-weight:700}.nv-brush .extent{fill-opacity:.125}.nv-brush .resize path{fill:#eee;stroke:#666}.nvd3 .nv-legend .nv-series{cursor:pointer}.nvd3 .nv-legend .nv-disabled circle{fill-opacity:0}.nvd3 .nv-brush .extent{fill-opacity:0!important}.nvd3 .nv-brushBackground rect{stroke:#000;stroke-width:.4;fill:#fff;fill-opacity:.7}.nvd3.nv-ohlcBar .nv-ticks .nv-tick{stroke-width:1px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover{stroke-width:2px}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive{stroke:#2ca02c}.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative{stroke:#d62728}.nvd3 .background path{fill:none;stroke:#EEE;stroke-opacity:.4}.nvd3 .foreground path{fill:none;stroke-opacity:.7}.nvd3 .nv-parallelCoordinates-brush .extent{fill:#fff;fill-opacity:.6;stroke:gray;shape-rendering:crispEdges}.nvd3 .nv-parallelCoordinates .hover{fill-opacity:1;stroke-width:3px}.nvd3 .missingValuesline line{fill:none;stroke:#000;stroke-width:1;stroke-opacity:1;stroke-dasharray:5,5}.nvd3.nv-pie .nv-pie-title{font-size:24px;fill:rgba(19,196,249,.59)}.nvd3.nv-pie .nv-slice text{stroke:#000;stroke-width:0}.nvd3.nv-pie path{transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-width 250ms linear,stroke-opacity 250ms linear;stroke:#fff;stroke-width:1px;stroke-opacity:1}.nvd3.nv-pie .hover path{fill-opacity:.7}.nvd3.nv-pie .nv-label rect{fill-opacity:0;stroke-opacity:0}.nvd3 .nv-groups .nv-point.hover{stroke-width:20px;stroke-opacity:.5}.nvd3 .nv-scatter .nv-point.hover{fill-opacity:1}.nvd3.nv-sparkline path{fill:none}.nvd3.nv-sparklineplus .nv-hoverValue line{stroke:#333;stroke-width:1.5px}.nvd3.nv-sparklineplus,.nvd3.nv-sparklineplus g{pointer-events:all}.nvd3 .nv-interactiveGuideLine,.nvtooltip{pointer-events:none}.nvd3 .nv-hoverArea{fill-opacity:0;stroke-opacity:0}.nvd3.nv-sparklineplus .nv-xValue,.nvd3.nv-sparklineplus .nv-yValue{stroke-width:0;font-size:.9em;font-weight:400}.nvd3.nv-sparklineplus .nv-yValue{stroke:#f66}.nvd3.nv-sparklineplus .nv-maxValue{stroke:#2ca02c;fill:#2ca02c}.nvd3.nv-sparklineplus .nv-minValue{stroke:#d62728;fill:#d62728}.nvd3.nv-sparklineplus .nv-currentValue{font-weight:700;font-size:1.1em}.nvtooltip h3,.nvtooltip table td.key{font-weight:400}.nvd3.nv-stackedarea path.nv-area{fill-opacity:.7;stroke-opacity:0;transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-moz-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear;-webkit-transition:fill-opacity 250ms linear,stroke-opacity 250ms linear}.nvd3.nv-stackedarea path.nv-area.hover{fill-opacity:.9}.nvd3.nv-stackedarea .nv-groups .nv-point{stroke-opacity:0;fill-opacity:0}.nvtooltip{position:absolute;color:rgba(0,0,0,1);padding:1px;z-index:10000;font-family:Arial;font-size:13px;text-align:left;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background:rgba(255,255,255,.8);border:1px solid rgba(0,0,0,.5);border-radius:4px}.nvtooltip h3,.nvtooltip p{margin:0;text-align:center}.nvtooltip.with-transitions,.with-transitions .nvtooltip{transition:opacity 50ms linear;-moz-transition:opacity 50ms linear;-webkit-transition:opacity 50ms linear;transition-delay:200ms;-moz-transition-delay:200ms;-webkit-transition-delay:200ms}.nvtooltip.x-nvtooltip,.nvtooltip.y-nvtooltip{padding:8px}.nvtooltip h3{padding:4px 14px;line-height:18px;background-color:rgba(247,247,247,.75);color:rgba(0,0,0,1);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}.nvtooltip p{padding:5px 14px}.nvtooltip span{display:inline-block;margin:2px 0}.nvtooltip table{margin:6px;border-spacing:0}.nvtooltip table td{padding:2px 9px 2px 0;vertical-align:middle}.nvtooltip table td.key.total{font-weight:700}.nvtooltip table td.value{text-align:right;font-weight:700}.nvtooltip table tr.highlight td{padding:1px 9px 1px 0;border-bottom-style:solid;border-bottom-width:1px;border-top-style:solid;border-top-width:1px}.nvtooltip table td.legend-color-guide div{vertical-align:middle;width:12px;height:12px;border:1px solid #999}.nvtooltip .footer{padding:3px;text-align:center}.nvtooltip-pending-removal{pointer-events:none;display:none}.nvd3 line.nv-guideline{stroke:#ccc} +/*# sourceMappingURL=nv.d3.min.css.map */ \ No newline at end of file diff --git a/build/nv.d3.min.css.map b/build/nv.d3.min.css.map new file mode 100644 index 000000000..5a66f42d7 --- /dev/null +++ b/build/nv.d3.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["build/nv.d3.css"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/build/nv.d3.min.js b/build/nv.d3.min.js index a904981f0..7d62e7b31 100644 --- a/build/nv.d3.min.js +++ b/build/nv.d3.min.js @@ -1,6 +1,9 @@ -!function(){var a=window.nv||{};window.nv=a,a.dev=!1,a.tooltip=a.tooltip||{},a.utils=a.utils||{},a.models=a.models||{},a.charts={},a.graphs=[],a.logs={},a.dispatch=d3.dispatch("render_start","render_end"),Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d&&a?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),a.dev&&(a.dispatch.on("render_start",function(b){a.logs.startTime=+new Date}),a.dispatch.on("render_end",function(b){a.logs.endTime=+new Date,a.logs.totalTime=a.logs.endTime-a.logs.startTime,a.log("total",a.logs.totalTime)})),a.log=function(){if(a.dev&&window.console&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(a.dev&&window.console&&"function"==typeof console.log&&Function.prototype.bind){var b=Function.prototype.bind.call(console.log,console);b.apply(console,arguments)}return arguments[arguments.length-1]},a.deprecated=function(b){a.dev&&console&&console.warn&&console.warn("`"+b+"` has been deprecated.")},a.render=function(b){b=b||1,a.render.active=!0,a.dispatch.render_start(),setTimeout(function(){for(var c,d,e=0;b>e&&(d=a.render.queue[e]);e++)c=d.generate(),typeof d.callback==typeof Function&&d.callback(c),a.graphs.push(c);a.render.queue.splice(0,e),a.render.queue.length?setTimeout(arguments.callee,0):(a.dispatch.render_end(),a.render.active=!1)},0)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},a.interactiveGuideline=function(){"use strict";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],i=!0,j=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,"svg"!==d3.event.target.tagName&&(i=!1),d3.event.target.className.baseVal.match("nv-legend")&&(j=!0)),i&&(d-=f.left,e-=f.top),0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||j){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&d3.event.relatedTarget.className.match(c.nvPointerEventsClass))return;return h.elementMouseout({mouseX:d,mouseY:e}),void b.renderGuideLine(null)}var l=g.invert(d);h.elementMousemove({mouseX:d,mouseY:e,pointXValue:l}),"dblclick"===d3.event.type&&h.elementDblclick({mouseX:d,mouseY:e,pointXValue:l}),"click"===d3.event.type&&h.elementClick({mouseX:d,mouseY:e,pointXValue:l})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([l]),r=q.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");r.append("g").attr("class","nv-interactiveGuideLine"),j&&(j.on("mousemove",m,!0).on("mouseout",m,!0).on("dblclick",m).on("click",m),b.renderGuideLine=function(b){if(i){var c=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=b?[a.utils.NaNtoZero(b)]:[],String);c.enter().append("line").attr("class","nv-guideline").attr("x1",function(a){return a}).attr("x2",function(a){return a}).attr("y1",p).attr("y2",0),c.exit().remove()}})})}var c=a.models.tooltip(),d=null,e=null,f={left:0,top:0},g=d3.scale.linear(),h=(d3.scale.linear(),d3.dispatch("elementMousemove","elementMouseout","elementClick","elementDblclick")),i=!0,j=null,k="ActiveXObject"in window;return b.dispatch=h,b.tooltip=c,b.margin=function(a){return arguments.length?(f.top="undefined"!=typeof a.top?a.top:f.top,f.left="undefined"!=typeof a.left?a.left:f.left,b):f},b.width=function(a){return arguments.length?(d=a,b):d},b.height=function(a){return arguments.length?(e=a,b):e},b.xScale=function(a){return arguments.length?(g=a,b):g},b.showGuideLine=function(a){return arguments.length?(i=a,b):i},b.svgContainer=function(a){return arguments.length?(j=a,b):j},b},a.interactiveBisect=function(a,b,c){"use strict";if(!(a instanceof Array))return null;"function"!=typeof c&&(c=function(a,b){return a.x});var d=d3.bisector(c).left,e=d3.max([0,d(a,b)-1]),f=c(a[e],e);if("undefined"==typeof f&&(f=e),f===b)return e;var g=d3.min([e+1,a.length-1]),h=c(a[g],g);return"undefined"==typeof h&&(h=g),Math.abs(h-b)>=Math.abs(f-b)?e:g},a.nearestValueIndex=function(a,b,c){"use strict";var d=1/0,e=null;return a.forEach(function(a,f){var g=Math.abs(b-a);d>=g&&c>g&&(d=g,e=f)}),e},function(){"use strict";window.nv.tooltip={},window.nv.models.tooltip=function(){function b(){if(l){var a=d3.select(l);"svg"!==a.node().tagName&&(a=a.select("svg"));var b=a.node()?a.attr("viewBox"):null;if(b){b=b.split(" ");var c=parseInt(a.style("width"))/b[2];n.left=n.left*c,n.top=n.top*c}}}function c(a){var b;b=d3.select(l?l:"body");var c=b.select(".nvtooltip");return null===c.node()&&(c=b.append("div").attr("class","nvtooltip "+(k?k:"xy-tooltip")).attr("id",p)),c.node().innerHTML=a,c.style("top",0).style("left",0).style("opacity",0),c.selectAll("div, table, td, tr").classed(q,!0),c.classed(q,!0),c.node()}function d(){if(o&&u(f)){b();var e=n.left,k=null!=j?j:n.top,p=c(t(f));if(m=p,l){var q=l.getElementsByTagName("svg")[0],r=(q?q.getBoundingClientRect():l.getBoundingClientRect(),{left:0,top:0});if(q){var s=q.getBoundingClientRect(),v=l.getBoundingClientRect(),w=s.top;if(0>w){var x=l.getBoundingClientRect();w=Math.abs(w)>x.height?0:w}r.top=Math.abs(w-v.top),r.left=Math.abs(s.left-v.left)}e+=l.offsetLeft+r.left-2*l.scrollLeft,k+=l.offsetTop+r.top-2*l.scrollTop}return i&&i>0&&(k=Math.floor(k/i)*i),a.tooltip.calcTooltipPosition([e,k],g,h,p),d}}var e=null,f=null,g="w",h=50,i=25,j=null,k=null,l=null,m=null,n={left:null,top:null},o=!0,p="nvtooltip-"+Math.floor(1e5*Math.random()),q="nv-pointer-events-none",r=function(a,b){return a},s=function(a){return a},t=function(a){if(null!=e)return e;if(null==a)return"";var b=d3.select(document.createElement("table")),c=b.selectAll("thead").data([a]).enter().append("thead");c.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(s(a.value));var d=b.selectAll("tbody").data([a]).enter().append("tbody"),f=d.selectAll("tr").data(function(a){return a.series}).enter().append("tr").classed("highlight",function(a){return a.highlight});if(f.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(a){return a.color}),f.append("td").classed("key",!0).html(function(a){return a.key}),f.append("td").classed("value",!0).html(function(a,b){return r(a.value,b)}),f.selectAll("td").each(function(a){if(a.highlight){var b=d3.scale.linear().domain([0,1]).range(["#fff",a.color]),c=.6;d3.select(this).style("border-bottom-color",b(c)).style("border-top-color",b(c))}}),a.postMarkerTooltip){var g=d.selectAll("tfoot").data([a]).enter().append("tfoot");g.append("tr").append("td").attr("colspan",3).append("strong").html(function(a){return a.postMarkerTooltip.label}),g.append("tr").append("td").attr("colspan",3).html(function(a){return d3.time.format("%x %I %p")(a.postMarkerTooltip.postDate)})}var h=b.node().outerHTML;return void 0!==a.footer&&(h+=""),h},u=function(a){return a&&a.series&&a.series.length>0?!0:!1};return d.nvPointerEventsClass=q,d.content=function(a){return arguments.length?(e=a,d):e},d.tooltipElem=function(){return m},d.contentGenerator=function(a){return arguments.length?("function"==typeof a&&(t=a),d):t},d.data=function(a){return arguments.length?(f=a,d):f},d.gravity=function(a){return arguments.length?(g=a,d):g},d.distance=function(a){return arguments.length?(h=a,d):h},d.snapDistance=function(a){return arguments.length?(i=a,d):i},d.classes=function(a){return arguments.length?(k=a,d):k},d.chartContainer=function(a){return arguments.length?(l=a,d):l},d.position=function(a){return arguments.length?(n.left="undefined"!=typeof a.left?a.left:n.left,n.top="undefined"!=typeof a.top?a.top:n.top,d):n},d.fixedTop=function(a){return arguments.length?(j=a,d):j},d.enabled=function(a){return arguments.length?(o=a,d):o},d.valueFormatter=function(a){return arguments.length?("function"==typeof a&&(r=a),d):r},d.headerFormatter=function(a){return arguments.length?("function"==typeof a&&(s=a),d):s},d.id=function(){return p},d},a.tooltip.show=function(b,c,d,e,f,g){var h=document.createElement("div");h.className="nvtooltip "+(g?g:"xy-tooltip");var i=f;(!f||f.tagName.match(/g|svg/i))&&(i=document.getElementsByTagName("body")[0]),h.style.left=0,h.style.top=0,h.style.opacity=0,"string"!=typeof c?h.appendChild(c):h.innerHTML=c,i.appendChild(h),f&&(b[0]=b[0]-f.scrollLeft,b[1]=b[1]-f.scrollTop),a.tooltip.calcTooltipPosition(b,d,e,h)},a.tooltip.findFirstNonSVGParent=function(a){for(;null!==a.tagName.match(/^g|svg$/i);)a=a.parentNode;return a},a.tooltip.findTotalOffsetTop=function(a,b){var c=b;do isNaN(a.offsetTop)||(c+=a.offsetTop);while(a=a.offsetParent);return c},a.tooltip.findTotalOffsetLeft=function(a,b){var c=b;do isNaN(a.offsetLeft)||(c+=a.offsetLeft);while(a=a.offsetParent);return c},a.tooltip.calcTooltipPosition=function(b,c,d,e){var f,g,h=parseInt(e.offsetHeight),i=parseInt(e.offsetWidth),j=a.utils.windowSize().width,k=a.utils.windowSize().height,l=window.pageYOffset,m=window.pageXOffset;k=window.innerWidth>=document.body.scrollWidth?k:k-16,j=window.innerHeight>=document.body.scrollHeight?j:j-16,c=c||"s",d=d||20;var n=function(b){return a.tooltip.findTotalOffsetTop(b,g)},o=function(b){return a.tooltip.findTotalOffsetLeft(b,f)};switch(c){case"e":f=b[0]-i-d,g=b[1]-h/2;var p=o(e),q=n(e);m>p&&(f=b[0]+d>m?b[0]+d:m-p+f),l>q&&(g=l-q+g),q+h>l+k&&(g=l+k-q+g-h);break;case"w":f=b[0]+d,g=b[1]-h/2;var p=o(e),q=n(e);p+i>j&&(f=b[0]-i-d),l>q&&(g=l+5),q+h>l+k&&(g=l+k-q+g-h);break;case"n":f=b[0]-i/2-5,g=b[1]+d;var p=o(e),q=n(e);m>p&&(f=m+5),p+i>j&&(f=f-i/2+5),q+h>l+k&&(g=l+k-q+g-h);break;case"s":f=b[0]-i/2,g=b[1]-h-d;var p=o(e),q=n(e);m>p&&(f=m+5),p+i>j&&(f=f-i/2+5),l>q&&(g=l);break;case"none":f=b[0],g=b[1]-d;var p=o(e),q=n(e)}return e.style.left=f+"px",e.style.top=g+"px",e.style.opacity=1,e.style.position="absolute",e},a.tooltip.cleanup=function(){for(var a=document.getElementsByClassName("nvtooltip"),b=[];a.length;)b.push(a[0]),a[0].style.transitionDelay="0 !important",a[0].style.opacity=0,a[0].className="nvtooltip-pending-removal";setTimeout(function(){for(;b.length;){var a=b.pop();a.parentNode.removeChild(a)}},500)}}(),a.utils.windowSize=function(){var a={width:640,height:480};return document.body&&document.body.offsetWidth&&(a.width=document.body.offsetWidth,a.height=document.body.offsetHeight),"CSS1Compat"==document.compatMode&&document.documentElement&&document.documentElement.offsetWidth&&(a.width=document.documentElement.offsetWidth,a.height=document.documentElement.offsetHeight),window.innerWidth&&window.innerHeight&&(a.width=window.innerWidth,a.height=window.innerHeight),a},a.utils.windowResize=function(b){return window.addEventListener?window.addEventListener("resize",b):a.log("ERROR: Failed to bind to window.resize with: ",b),{callback:b,clear:function(){window.removeEventListener("resize",b)}}},a.utils.getColor=function(b){return arguments.length?b instanceof Array?function(a,c){return a.color||b[c%b.length]}:b:a.utils.defaultColor()},a.utils.defaultColor=function(){var a=d3.scale.category20().range();return function(b,c){return b.color||a[c%a.length]}},a.utils.customTheme=function(a,b,c){b=b||function(a){return a.key},c=c||d3.scale.category20().range();var d=c.length;return function(e,f){var g=b(e);return"function"==typeof a[g]?a[g]():void 0!==a[g]?a[g]:(d||(d=c.length),d-=1,c[d])}},a.utils.pjax=function(b,c){var d=function(d){d3.html(d,function(d){var e=d3.select(c).node();e.parentNode.replaceChild(d3.select(d).select(c).node(),e),a.utils.pjax(b,c)})};d3.selectAll(b).on("click",function(){history.pushState(this.href,this.textContent,this.href),d(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&d(d3.event.state)})},a.utils.calcApproxTextWidth=function(a){if("function"==typeof a.style&&"function"==typeof a.text){var b=parseInt(a.style("font-size").replace("px","")),c=a.text().length;return c*b*.5}return 0},a.utils.NaNtoZero=function(a){return"number"!=typeof a||isNaN(a)||null===a||a===1/0||a===-(1/0)?0:a},d3.selection.prototype.watchTransition=function(a){var b=[this].concat([].slice.call(arguments,1));return a.transition.apply(a,b)},a.utils.renderWatch=function(b,c){if(!(this instanceof a.utils.renderWatch))return new a.utils.renderWatch(b,c);var d=void 0!==c?c:250,e=[],f=this;this.models=function(a){return a=[].slice.call(arguments,0),a.forEach(function(a){a.__rendered=!1,function(a){a.dispatch.on("renderEnd",function(b){a.__rendered=!0,f.renderEnd("model")})}(a),e.indexOf(a)<0&&e.push(a)}),this},this.reset=function(a){void 0!==a&&(d=a),e=[]},this.transition=function(a,b,c){if(b=arguments.length>1?[].slice.call(arguments,1):[],c=b.length>1?b.pop():void 0!==d?d:250,a.__rendered=!1,e.indexOf(a)<0&&e.push(a),0===c)return a.__rendered=!0,a.delay=function(){return this},a.duration=function(){return this},a;0===a.length?a.__rendered=!0:a.every(function(a){return!a.length})?a.__rendered=!0:a.__rendered=!1;var g=0;return a.transition().duration(c).each(function(){++g}).each("end",function(c,d){0===--g&&(a.__rendered=!0,f.renderEnd.apply(this,b))})},this.renderEnd=function(){e.every(function(a){return a.__rendered})&&(e.forEach(function(a){a.__rendered=!1}),b.renderEnd.apply(this,arguments))}},a.utils.deepExtend=function(b){var c=arguments.length>1?[].slice.call(arguments,1):[];c.forEach(function(c){for(key in c){var d=b[key]instanceof Array,e="object"==typeof b[key],f="object"==typeof c[key];e&&!d&&f?a.utils.deepExtend(b[key],c[key]):b[key]=c[key]}})},a.utils.state=function(){if(!(this instanceof a.utils.state))return new a.utils.state;var b={},c=function(){},d=function(){return{}},e=null,f=null;this.dispatch=d3.dispatch("change","set"),this.dispatch.on("set",function(a){c(a,!0)}),this.getter=function(a){return d=a,this},this.setter=function(a,b){return b||(b=function(){}),c=function(c,d){a(c),d&&b()},this},this.init=function(b){e=e||{},a.utils.deepExtend(e,b)};var g=function(){var a=d();if(JSON.stringify(a)===JSON.stringify(b))return!1;for(var c in a)void 0===b[c]&&(b[c]={}),b[c]=a[c],f=!0;return!0};this.update=function(){e&&(c(e,!1),e=null),g.call(this)&&this.dispatch.change(b)}},a.utils.optionsFunc=function(b){return a.deprecated("nv.utils.optionsFunc"),b&&d3.map(b).forEach(function(a,b){"function"==typeof this[a]&&this[a](b)}.bind(this)),this},a.utils.calcTicksX=function(b,c){var d=1,e=0;for(e;ed?f:d}return a.log("Requested number of ticks: ",b),a.log("Calculated max values to be: ",d),b=b>d?b=d-1:b,b=1>b?1:b,b=Math.floor(b),a.log("Calculating tick count as: ",b),b},a.utils.calcTicksY=function(b,c){return a.utils.calcTicksX(b,c)},a.utils.initOption=function(a,b){a._calls&&a._calls[b]?a[b]=a._calls[b]:a[b]=function(c){return arguments.length?(a._options[b]=c,a):a._options[b]}},a.utils.initOptions=function(b){var c=Object.getOwnPropertyNames(b._options||{}),d=Object.getOwnPropertyNames(b._calls||{});c=c.concat(d);for(var e in c)a.utils.initOption(b,c[e])},a.utils.inheritOptionsD3=function(a,b,c){a._d3options=c.concat(a._d3options||[]),c.unshift(b),c.unshift(a),d3.rebind.apply(this,c)},a.utils.arrayUnique=function(a){return a.sort().filter(function(b,c){return!c||b!=a[c-1]})},a.utils.symbolMap=d3.map(),a.utils.symbol=function(){function b(b,e){var f=c.call(this,b,e),g=d.call(this,b,e);return-1!==d3.svg.symbolTypes.indexOf(f)?d3.svg.symbol().type(f).size(g)():a.utils.symbolMap.get(f)(g)}var c,d=64;return b.type=function(a){return arguments.length?(c=d3.functor(a),b):c},b.size=function(a){return arguments.length?(d=d3.functor(a),b):d},b},a.utils.inheritOptions=function(b,c){var d=Object.getOwnPropertyNames(c._options||{}),e=Object.getOwnPropertyNames(c._calls||{}),f=c._inherited||[],g=c._d3options||[],h=d.concat(e).concat(f).concat(g);h.unshift(c),h.unshift(b),d3.rebind.apply(this,h),b._inherited=a.utils.arrayUnique(d.concat(e).concat(f).concat(d).concat(b._inherited||[])),b._d3options=a.utils.arrayUnique(g.concat(b._d3options||[]))},a.utils.initSVG=function(a){a.classed({"nvd3-svg":!0})},a.models.axis=function(){"use strict";function b(g){return t.reset(),g.each(function(b){var g=d3.select(this);a.utils.initSVG(g);var q=g.selectAll("g.nv-wrap.nv-axis").data([b]),r=q.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),u=(r.append("g"),q.select("g"));null!==o?c.ticks(o):("top"==c.orient()||"bottom"==c.orient())&&c.ticks(Math.abs(d.range()[1]-d.range()[0])/100),u.watchTransition(t,"axis").call(c),s=s||c.scale();var v=c.tickFormat();null==v&&(v=s.tickFormat());var w=u.selectAll("text.nv-axislabel").data([h||null]);switch(w.exit().remove(),c.orient()){case"top":w.enter().append("text").attr("class","nv-axislabel");var x;if(x=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),w.attr("text-anchor","middle").attr("y",0).attr("x",x/2),i){var y=q.selectAll("g.nv-axisMaxMin").data(d.domain());y.enter().append("g").attr("class","nv-axisMaxMin").append("text"),y.exit().remove(),y.attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b))+",0)"}).select("text").attr("dy","-0.5em").attr("y",-c.tickPadding()).attr("text-anchor","middle").text(function(a,b){var c=v(a);return(""+c).match("NaN")?"":c}),y.watchTransition(t,"min-max top").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d.range()[c])+",0)"})}break;case"bottom":var z=p+36,A=30,B=u.selectAll("g").select("text");if(k%360){B.each(function(a,b){var c=this.getBoundingClientRect().width;c>A&&(A=c)});var C=Math.abs(Math.sin(k*Math.PI/180)),z=(C?C*A:A)+30;B.attr("transform",function(a,b,c){return"rotate("+k+" 0,0)"}).style("text-anchor",k%360>0?"start":"end")}w.enter().append("text").attr("class","nv-axislabel");var x;if(x=d.range().length<2?0:2===d.range().length?d.range()[1]:d.range()[d.range().length-1]+(d.range()[1]-d.range()[0]),w.attr("text-anchor","middle").attr("y",z).attr("x",x/2),i){var y=q.selectAll("g.nv-axisMaxMin").data([d.domain()[0],d.domain()[d.domain().length-1]]);y.enter().append("g").attr("class","nv-axisMaxMin").append("text"),y.exit().remove(),y.attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b)+(n?d.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",c.tickPadding()).attr("transform",function(a,b,c){return"rotate("+k+" 0,0)"}).style("text-anchor",k?k%360>0?"start":"end":"middle").text(function(a,b){var c=v(a);return(""+c).match("NaN")?"":c}),y.watchTransition(t,"min-max bottom").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b)+(n?d.rangeBand()/2:0))+",0)"})}m&&B.attr("transform",function(a,b){return"translate(0,"+(b%2==0?"0":"12")+")"});break;case"right":if(w.enter().append("text").attr("class","nv-axislabel"),w.style("text-anchor",l?"middle":"begin").attr("transform",l?"rotate(90)":"").attr("y",l?-Math.max(e.right,f)+12:-10).attr("x",l?d.range()[0]/2:c.tickPadding()),i){var y=q.selectAll("g.nv-axisMaxMin").data(d.domain());y.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),y.exit().remove(),y.attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",c.tickPadding()).style("text-anchor","start").text(function(a,b){var c=v(a);return(""+c).match("NaN")?"":c}),y.watchTransition(t,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1)}break;case"left":if(w.enter().append("text").attr("class","nv-axislabel"),w.style("text-anchor",l?"middle":"end").attr("transform",l?"rotate(-90)":"").attr("y",l?-Math.max(e.left,f)+25-(p||0):-10).attr("x",l?-d.range()[0]/2:-c.tickPadding()),i){var y=q.selectAll("g.nv-axisMaxMin").data(d.domain());y.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),y.exit().remove(),y.attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(s(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-c.tickPadding()).attr("text-anchor","end").text(function(a,b){var c=v(a);return(""+c).match("NaN")?"":c}),y.watchTransition(t,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1)}}if(w.text(function(a){return a}),!i||"left"!==c.orient()&&"right"!==c.orient()||(u.selectAll("g").each(function(a,b){d3.select(this).select("text").attr("opacity",1),(d(a)d.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),d.domain()[0]==d.domain()[1]&&0==d.domain()[0]&&q.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===c.orient()||"bottom"===c.orient())){var D=[];q.selectAll("g.nv-axisMaxMin").each(function(a,b){try{D.push(b?d(a)-this.getBoundingClientRect().width-4:d(a)+this.getBoundingClientRect().width+4)}catch(c){D.push(b?d(a)-4:d(a)+4)}}),u.selectAll("g").each(function(a,b){(d(a)D[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}j&&u.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*this.__data__)/1e6)&&void 0!==this.__data__}).classed("zero",!0),s=d.copy()}),t.renderEnd("axis immediate"),b}var c=d3.svg.axis(),d=d3.scale.linear(),e={top:0,right:0,bottom:0,left:0},f=75,g=60,h=null,i=!0,j=!0,k=0,l=!0,m=!1,n=!1,o=null,p=0,q=250,r=d3.dispatch("renderEnd");c.scale(d).orient("bottom").tickFormat(function(a){return a});var s,t=a.utils.renderWatch(r,q);return b.axis=c,b.dispatch=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{axisLabelDistance:{get:function(){return p},set:function(a){p=a}},staggerLabels:{get:function(){return m},set:function(a){m=a}},rotateLabels:{get:function(){return k},set:function(a){k=a}},rotateYLabel:{get:function(){return l},set:function(a){l=a}},highlightZero:{get:function(){return j},set:function(a){j=a}},showMaxMin:{get:function(){return i},set:function(a){i=a}},axisLabel:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return g},set:function(a){g=a}},ticks:{get:function(){return o},set:function(a){o=a}},width:{get:function(){return f},set:function(a){f=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},duration:{get:function(){return q},set:function(a){q=a,t.reset(q)}},scale:{get:function(){return d},set:function(e){d=e,c.scale(d),n="function"==typeof d.rangeBands,a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"])}}}),a.utils.initOptions(b),a.utils.inheritOptionsD3(b,c,["orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"]),a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"]),b},a.models.bullet=function(){"use strict";function b(d){return d.each(function(b,d){var o=m-c.left-c.right,r=n-c.top-c.bottom,s=d3.select(this);a.utils.initSVG(s);{var t=f.call(this,b,d).slice().sort(d3.descending),u=g.call(this,b,d).slice().sort(d3.descending),v=h.call(this,b,d).slice().sort(d3.descending),w=i.call(this,b,d).slice(),x=j.call(this,b,d).slice(),y=k.call(this,b,d).slice(),z=d3.scale.linear().domain(d3.extent(d3.merge([l,t]))).range(e?[o,0]:[0,o]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range())}this.__chart__=z;var A=d3.min(t),B=d3.max(t),C=t[1],D=s.selectAll("g.nv-wrap.nv-bullet").data([b]),E=D.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),F=E.append("g"),G=D.select("g");F.append("rect").attr("class","nv-range nv-rangeMax"),F.append("rect").attr("class","nv-range nv-rangeAvg"),F.append("rect").attr("class","nv-range nv-rangeMin"),F.append("rect").attr("class","nv-measure"),F.append("path").attr("class","nv-markerTriangle"),D.attr("transform","translate("+c.left+","+c.top+")");var H=function(a){return Math.abs(z(a)-z(0))},I=function(a){return z(0>a?a:0)};G.select("rect.nv-rangeMax").attr("height",r).attr("width",H(B>0?B:A)).attr("x",I(B>0?B:A)).datum(B>0?B:A),G.select("rect.nv-rangeAvg").attr("height",r).attr("width",H(C)).attr("x",I(C)).datum(C),G.select("rect.nv-rangeMin").attr("height",r).attr("width",H(B)).attr("x",I(B)).attr("width",H(B>0?A:B)).attr("x",I(B>0?A:B)).datum(B>0?A:B),G.select("rect.nv-measure").style("fill",p).attr("height",r/3).attr("y",r/3).attr("width",0>v?z(0)-z(v[0]):z(v[0])-z(0)).attr("x",I(v)).on("mouseover",function(){q.elementMouseover({value:v[0],label:y[0]||"Current",pos:[z(v[0]),r/2]})}).on("mouseout",function(){q.elementMouseout({value:v[0],label:y[0]||"Current"})});var J=r/6;u[0]?G.selectAll("path.nv-markerTriangle").attr("transform",function(a){return"translate("+z(u[0])+","+r/2+")"}).attr("d","M0,"+J+"L"+J+","+-J+" "+-J+","+-J+"Z").on("mouseover",function(){q.elementMouseover({value:u[0],label:x[0]||"Previous",pos:[z(u[0]),r/2]})}).on("mouseout",function(){q.elementMouseout({value:u[0],label:x[0]||"Previous"})}):G.selectAll("path.nv-markerTriangle").remove(),D.selectAll(".nv-range").on("mouseover",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");q.elementMouseover({value:a,label:c,pos:[z(a),r/2]})}).on("mouseout",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");q.elementMouseout({value:a,label:c})})}),b}var c={top:0,right:0,bottom:0,left:0},d="left",e=!1,f=function(a){return a.ranges},g=function(a){return a.markers?a.markers:[0]},h=function(a){return a.measures},i=function(a){return a.rangeLabels?a.rangeLabels:[]},j=function(a){return a.markerLabels?a.markerLabels:[]},k=function(a){return a.measureLabels?a.measureLabels:[]},l=[0],m=380,n=30,o=null,p=a.utils.getColor(["#1f77b4"]),q=d3.dispatch("elementMouseover","elementMouseout");return b.dispatch=q,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return f},set:function(a){f=a}},markers:{get:function(){return g},set:function(a){g=a}},measures:{get:function(){return h},set:function(a){h=a}},forceX:{get:function(){return l},set:function(a){l=a}},width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},tickFormat:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},orient:{get:function(){return d},set:function(a){d=a,e="right"==d||"bottom"==d}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.bulletChart=function(){"use strict";function b(d){return d.each(function(n,r){var s=d3.select(this);a.utils.initSVG(s);var t=(j||parseInt(s.style("width"))||960)-f.left-f.right,u=k-f.top-f.bottom,v=this;if(b.update=function(){b(d)},b.container=this,!n||!g.call(this,n,r)){var w=s.selectAll(".nv-noData").data([o]);return w.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),w.attr("x",f.left+t/2).attr("y",18+f.top+u/2).text(function(a){return a}),b}s.selectAll(".nv-noData").remove();var x=g.call(this,n,r).slice().sort(d3.descending),y=h.call(this,n,r).slice().sort(d3.descending),z=i.call(this,n,r).slice().sort(d3.descending),A=s.selectAll("g.nv-wrap.nv-bulletChart").data([n]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),C=B.append("g"),D=A.select("g");C.append("g").attr("class","nv-bulletWrap"),C.append("g").attr("class","nv-titles"),A.attr("transform","translate("+f.left+","+f.top+")");var E=d3.scale.linear().domain([0,Math.max(x[0],y[0],z[0])]).range(e?[t,0]:[0,t]),F=this.__chart__||d3.scale.linear().domain([0,1/0]).range(E.range());this.__chart__=E;var G=C.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(k-f.top-f.bottom)/2+")");G.append("text").attr("class","nv-title").text(function(a){return a.title}),G.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),c.width(t).height(u);var H=D.select(".nv-bulletWrap");d3.transition(H).call(c);var I=l||E.tickFormat(t/100),J=D.selectAll("g.nv-tick").data(E.ticks(t/50),function(a){return this.textContent||I(a)}),K=J.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+F(a)+",0)"}).style("opacity",1e-6);K.append("line").attr("y1",u).attr("y2",7*u/6),K.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*u/6).text(I);var L=d3.transition(J).attr("transform",function(a){return"translate("+E(a)+",0)"}).style("opacity",1);L.select("line").attr("y1",u).attr("y2",7*u/6),L.select("text").attr("y",7*u/6),d3.transition(J.exit()).attr("transform",function(a){return"translate("+E(a)+",0)"}).style("opacity",1e-6).remove(),p.on("tooltipShow",function(a){a.key=n.title,m&&q(a,v.parentNode)})}),d3.timer.flush(),b}var c=a.models.bullet(),d="left",e=!1,f={top:5,right:40,bottom:20,left:120},g=function(a){return a.ranges},h=function(a){return a.markers?a.markers:[0]},i=function(a){return a.measures},j=null,k=55,l=null,m=!0,n=function(a,b,c,d,e){return"

"+b+"

"+c+"

"},o="No Data Available.",p=d3.dispatch("tooltipShow","tooltipHide"),q=function(c,d){var e=c.pos[0]+(d.offsetLeft||0)+f.left,g=c.pos[1]+(d.offsetTop||0)+f.top,h=n(c.key,c.label,c.value,c,b);a.tooltip.show([e,g],h,c.value<0?"e":"w",null,d)};return c.dispatch.on("elementMouseover.tooltip",function(a){p.tooltipShow(a)}),c.dispatch.on("elementMouseout.tooltip",function(a){p.tooltipHide(a)}),p.on("tooltipHide",function(){m&&a.tooltip.cleanup()}),b.bullet=c,b.dispatch=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return g},set:function(a){g=a}},markers:{get:function(){return h},set:function(a){h=a}},measures:{get:function(){return i},set:function(a){i=a}},width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},tickFormat:{get:function(){return l},set:function(a){l=a}},tooltips:{get:function(){return m},set:function(a){m=a}},tooltipContent:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},orient:{get:function(){return d},set:function(a){d=a,e="right"==d||"bottom"==d}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){"use strict";function b(x){return I.reset(),I.models(f),q&&I.models(g),r&&I.models(h),x.each(function(x){function F(a,c){d3.select(b.container).style("cursor","ew-resize")}function I(a,b){H.x=d3.event.x,H.i=Math.round(G.invert(H.x)),N()}function M(a,c){d3.select(b.container).style("cursor","auto"),z.index=H.i,D.stateChange(z)}function N(){fa.data([H]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var O=d3.select(this);a.utils.initSVG(O),O.classed("nv-chart-"+y,!0);var P=this,Q=(n||parseInt(O.style("width"))||960)-l.left-l.right,R=(o||parseInt(O.style("height"))||400)-l.top-l.bottom;if(b.update=function(){0===E?O.call(b):O.transition().duration(E).call(b)},b.container=this,z.setter(L(x),b.update).getter(K(x)).update(),z.disabled=x.map(function(a){return!!a.disabled}),!A){var S;A={};for(S in z)z[S]instanceof Array?A[S]=z[S].slice(0):A[S]=z[S]}var T=d3.behavior.drag().on("dragstart",F).on("drag",I).on("dragend",M);if(!(x&&x.length&&x.filter(function(a){return a.values.length}).length)){var U=O.selectAll(".nv-noData").data([B]);return U.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"), -U.attr("x",l.left+Q/2).attr("y",l.top+R/2).text(function(a){return a}),b}if(O.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),w)f.yDomain(null);else{var V=x.filter(function(a){return!a.disabled}).map(function(a,b){var c=d3.extent(a.values,f.y());return c[0]<-.95&&(c[0]=-.95),[(c[0]-c[1])/(1+c[1]),(c[1]-c[0])/(1+c[0])]}),W=[d3.min(V,function(a){return a[0]}),d3.max(V,function(a){return a[1]})];f.yDomain(W)}G.domain([0,x[0].values.length-1]).range([0,Q]).clamp(!0);var x=c(H.i,x),X=v?"none":"all",Y=O.selectAll("g.nv-wrap.nv-cumulativeLine").data([x]),Z=Y.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),$=Y.select("g");if(Z.append("g").attr("class","nv-interactive"),Z.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),Z.append("g").attr("class","nv-y nv-axis"),Z.append("g").attr("class","nv-background"),Z.append("g").attr("class","nv-linesWrap").style("pointer-events",X),Z.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),Z.append("g").attr("class","nv-legendWrap"),Z.append("g").attr("class","nv-controlsWrap"),p&&(i.width(Q),$.select(".nv-legendWrap").datum(x).call(i),l.top!=i.height()&&(l.top=i.height(),R=(o||parseInt(O.style("height"))||400)-l.top-l.bottom),$.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")),u){var _=[{key:"Re-scale y-axis",disabled:!w}];j.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),$.select(".nv-controlsWrap").datum(_).attr("transform","translate(0,"+-l.top+")").call(j)}Y.attr("transform","translate("+l.left+","+l.top+")"),s&&$.select(".nv-y.nv-axis").attr("transform","translate("+Q+",0)");var aa=x.filter(function(a){return a.tempDisabled});Y.select(".tempDisabled").remove(),aa.length&&Y.append("text").attr("class","tempDisabled").attr("x",Q/2).attr("y","-.71em").style("text-anchor","end").text(aa.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),v&&(k.width(Q).height(R).margin({left:l.left,top:l.top}).svgContainer(O).xScale(d),Y.select(".nv-interactive").call(k)),Z.select(".nv-background").append("rect"),$.select(".nv-background rect").attr("width",Q).attr("height",R),f.y(function(a){return a.display.y}).width(Q).height(R).color(x.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!x[b].disabled&&!x[b].tempDisabled}));var ba=$.select(".nv-linesWrap").datum(x.filter(function(a){return!a.disabled&&!a.tempDisabled}));ba.call(f),x.forEach(function(a,b){a.seriesIndex=b});var ca=x.filter(function(a){return!a.disabled&&!!C(a)}),da=$.select(".nv-avgLinesWrap").selectAll("line").data(ca,function(a){return a.key}),ea=function(a){var b=e(C(a));return 0>b?0:b>R?R:b};da.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a,b){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",Q).attr("y1",ea).attr("y2",ea),da.style("stroke-opacity",function(a){var b=e(C(a));return 0>b||b>R?0:1}).attr("x1",0).attr("x2",Q).attr("y1",ea).attr("y2",ea),da.exit().remove();var fa=ba.selectAll(".nv-indexLine").data([H]);fa.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(T),fa.attr("transform",function(a){return"translate("+G(a.i)+",0)"}).attr("height",R),q&&(g.scale(d).ticks(a.utils.calcTicksX(Q/70,x)).tickSize(-R,0),$.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),$.select(".nv-x.nv-axis").call(g)),r&&(h.scale(e).ticks(a.utils.calcTicksY(R/36,x)).tickSize(-Q,0),$.select(".nv-y.nv-axis").call(h)),$.select(".nv-background rect").on("click",function(){H.x=d3.mouse(this)[0],H.i=Math.round(G.invert(H.x)),z.index=H.i,D.stateChange(z),N()}),f.dispatch.on("elementClick",function(a){H.i=a.pointIndex,H.x=G(H.i),z.index=H.i,D.stateChange(z),N()}),j.dispatch.on("legendClick",function(a,c){a.disabled=!a.disabled,w=!a.disabled,z.rescaleY=w,D.stateChange(z),b.update()}),i.dispatch.on("stateChange",function(a){for(var c in a)z[c]=a[c];D.stateChange(z),b.update()}),k.dispatch.on("elementMousemove",function(c){f.clearHighlights();var d,e,i,j=[];if(x.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:m(g,g.seriesIndex)}))}),j.length>2){var n=b.yScale().invert(c.mouseY),o=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),p=.03*o,q=a.nearestValueIndex(j.map(function(a){return a.value}),n,p);null!==q&&(j[q].highlight=!0)}var r=g.tickFormat()(b.x()(d,e),e);k.tooltip.position({left:i+l.left,top:c.mouseY+l.top}).chartContainer(P.parentNode).enabled(t).valueFormatter(function(a,b){return h.tickFormat()(a)}).data({value:r,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(a){D.tooltipHide(),f.clearHighlights()}),D.on("tooltipShow",function(a){t&&J(a,P.parentNode)}),D.on("changeState",function(a){"undefined"!=typeof a.disabled&&(x.forEach(function(b,c){b.disabled=a.disabled[c]}),z.disabled=a.disabled),"undefined"!=typeof a.index&&(H.i=a.index,H.x=G(H.i),z.index=a.index,fa.data([H])),"undefined"!=typeof a.rescaleY&&(w=a.rescaleY),b.update()})}),I.renderEnd("cumulativeLineChart immediate"),b}function c(a,b){return M||(M=f.y()),b.map(function(b,c){if(!b.values)return b;var d=b.values[a];if(null==d)return b;var e=M(d,a);return-.95>e&&!F?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(M(a,b)-e)/(1+e)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l={top:30,right:30,bottom:50,left:60},m=a.utils.defaultColor(),n=null,o=null,p=!0,q=!0,r=!0,s=!1,t=!0,u=!0,v=!1,w=!0,x=function(a,b,c,d,e){return"

"+a+"

"+c+" at "+b+"

"},y=f.id(),z=a.utils.state(),A=null,B="No Data Available.",C=function(a){return a.average},D=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),E=250,F=!1;z.index=0,z.rescaleY=w,g.orient("bottom").tickPadding(7),h.orient(s?"right":"left"),j.updateState(!1);var G=d3.scale.linear(),H={i:0,x:0},I=a.utils.renderWatch(D,E),J=function(c,d){var e=c.pos[0]+(d.offsetLeft||0),i=c.pos[1]+(d.offsetTop||0),j=g.tickFormat()(f.x()(c.point,c.pointIndex)),k=h.tickFormat()(f.y()(c.point,c.pointIndex)),l=x(c.series.key,j,k,c,b);a.tooltip.show([e,i],l,null,null,d)},K=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:H.i,rescaleY:w}}},L=function(a){return function(b){void 0!==b.index&&(H.i=b.index),void 0!==b.rescaleY&&(w=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+l.left,a.pos[1]+l.top],D.tooltipShow(a)}),f.dispatch.on("elementMouseout.tooltip",function(a){D.tooltipHide(a)}),D.on("tooltipHide",function(){t&&a.tooltip.cleanup()});var M=null;return b.dispatch=D,b.lines=f,b.legend=i,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return n},set:function(a){n=a}},height:{get:function(){return o},set:function(a){o=a}},rescaleY:{get:function(){return w},set:function(a){w=a}},showControls:{get:function(){return u},set:function(a){u=a}},showLegend:{get:function(){return p},set:function(a){p=a}},average:{get:function(){return C},set:function(a){C=a}},tooltips:{get:function(){return t},set:function(a){t=a}},tooltipContent:{get:function(){return x},set:function(a){x=a}},defaultState:{get:function(){return A},set:function(a){A=a}},noData:{get:function(){return B},set:function(a){B=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},noErrorCheck:{get:function(){return F},set:function(a){F=a}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),i.color(m)}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,h.orient(a?"right":"left")}},duration:{get:function(){return E},set:function(a){E=a,f.duration(E),g.duration(E),h.duration(E),I.reset(E)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){"use strict";function b(l){return x.reset(),l.each(function(b){var l=j-i.left-i.right,w=k-i.top-i.bottom,y=d3.select(this);a.utils.initSVG(y),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=c&&d?[]:b.map(function(a){return a.values.map(function(a,b){return{x:o(a,b),y:p(a,b),y0:a.y0}})});m.domain(c||d3.merge(z).map(function(a){return a.x})).rangeBands(e||[0,l],.1),n.domain(d||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(q))),n.range(s?f||[w-(n.domain()[0]<0?12:0),n.domain()[1]>0?12:0]:f||[w,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);{var A=y.selectAll("g.nv-wrap.nv-discretebar").data([b]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),C=B.append("g");A.select("g")}C.append("g").attr("class","nv-groups"),A.attr("transform","translate("+i.left+","+i.top+")");var D=A.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().watchTransition(x,"discreteBar: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),D.watchTransition(x,"discreteBar: groups").style("stroke-opacity",1).style("fill-opacity",.75);var E=D.selectAll("g.nv-bar").data(function(a){return a.values});E.exit().remove();var F=E.enter().append("g").attr("transform",function(a,b,c){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", "+n(0)+")"}).on("mouseover",function(a,c){d3.select(this).classed("hover",!0),u.elementMouseover({value:p(a,c),point:a,series:b[a.series],pos:[m(o(a,c))+m.rangeBand()*(a.series+.5)/b.length,n(p(a,c))],pointIndex:c,seriesIndex:a.series,e:d3.event})}).on("mouseout",function(a,c){d3.select(this).classed("hover",!1),u.elementMouseout({value:p(a,c),point:a,series:b[a.series],pointIndex:c,seriesIndex:a.series,e:d3.event})}).on("click",function(a,c){u.elementClick({value:p(a,c),point:a,series:b[a.series],pos:[m(o(a,c))+m.rangeBand()*(a.series+.5)/b.length,n(p(a,c))],pointIndex:c,seriesIndex:a.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(a,c){u.elementDblClick({value:p(a,c),point:a,series:b[a.series],pos:[m(o(a,c))+m.rangeBand()*(a.series+.5)/b.length,n(p(a,c))],pointIndex:c,seriesIndex:a.series,e:d3.event}),d3.event.stopPropagation()});F.append("rect").attr("height",0).attr("width",.9*m.rangeBand()/b.length),s?(F.append("text").attr("text-anchor","middle"),E.select("text").text(function(a,b){return t(p(a,b))}).watchTransition(x,"discreteBar: bars text").attr("x",.9*m.rangeBand()/2).attr("y",function(a,b){return p(a,b)<0?n(p(a,b))-n(0)+12:-4})):E.selectAll("text").remove(),E.attr("class",function(a,b){return p(a,b)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(a,b){return a.color||r(a,b)}).style("stroke",function(a,b){return a.color||r(a,b)}).select("rect").attr("class",v).watchTransition(x,"discreteBar: bars rect").attr("width",.9*m.rangeBand()/b.length),E.watchTransition(x,"discreteBar: bars").attr("transform",function(a,b){var c=m(o(a,b))+.05*m.rangeBand(),d=p(a,b)<0?n(0):n(0)-n(p(a,b))<1?n(0)-1:n(p(a,b));return"translate("+c+", "+d+")"}).select("rect").attr("height",function(a,b){return Math.max(Math.abs(n(p(a,b))-n(d&&d[0]||0))||1)}),g=m.copy(),h=n.copy()}),x.renderEnd("discreteBar immediate"),b}var c,d,e,f,g,h,i={top:0,right:0,bottom:0,left:0},j=960,k=500,l=Math.floor(1e4*Math.random()),m=d3.scale.ordinal(),n=d3.scale.linear(),o=function(a){return a.x},p=function(a){return a.y},q=[0],r=a.utils.defaultColor(),s=!1,t=d3.format(",.2f"),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),v="discreteBar",w=250,x=a.utils.renderWatch(u,w);return b.dispatch=u,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},forceY:{get:function(){return q},set:function(a){q=a}},showValues:{get:function(){return s},set:function(a){s=a}},x:{get:function(){return o},set:function(a){o=a}},y:{get:function(){return p},set:function(a){p=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},valueFormat:{get:function(){return t},set:function(a){t=a}},id:{get:function(){return l},set:function(a){l=a}},rectClass:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},color:{get:function(){return r},set:function(b){r=a.utils.getColor(b)}},duration:{get:function(){return w},set:function(a){w=a,x.reset(w)}}}),a.utils.initOptions(b),b},a.models.discreteBarChart=function(){"use strict";function b(k){return v.reset(),v.models(e),l&&v.models(f),m&&v.models(g),k.each(function(k){var q=d3.select(this),v=this;a.utils.initSVG(q);var w=(i||parseInt(q.style("width"))||960)-h.left-h.right,x=(j||parseInt(q.style("height"))||400)-h.top-h.bottom;if(b.update=function(){s.beforeUpdate(),q.transition().duration(t).call(b)},b.container=this,!(k&&k.length&&k.filter(function(a){return a.values.length}).length)){var y=q.selectAll(".nv-noData").data([r]);return y.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),y.attr("x",h.left+w/2).attr("y",h.top+x/2).text(function(a){return a}),b}q.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var z=q.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([k]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),B=A.append("defs"),C=z.select("g");A.append("g").attr("class","nv-x nv-axis"),A.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),A.append("g").attr("class","nv-barsWrap"),C.attr("transform","translate("+h.left+","+h.top+")"),n&&C.select(".nv-y.nv-axis").attr("transform","translate("+w+",0)"),e.width(w).height(x);var D=C.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));if(D.transition().call(e),B.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),C.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(o?2:1)).attr("height",16).attr("x",-c.rangeBand()/(o?1:2)),l){f.scale(c).ticks(a.utils.calcTicksX(w/100,k)).tickSize(-x,0),C.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),C.select(".nv-x.nv-axis").call(f);var E=C.select(".nv-x.nv-axis").selectAll("g");o&&E.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}m&&(g.scale(d).ticks(a.utils.calcTicksY(x/36,k)).tickSize(-w,0),C.select(".nv-y.nv-axis").call(g)),C.select(".nv-zeroLine line").attr("x1",0).attr("x2",w).attr("y1",d(0)).attr("y2",d(0)),s.on("tooltipShow",function(a){p&&u(a,v.parentNode)})}),v.renderEnd("discreteBar chart immediate"),b}var c,d,e=a.models.discreteBar(),f=a.models.axis(),g=a.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=a.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=!0,q=function(a,b,c,d,e){return"

"+b+"

"+c+"

"},r="No Data Available.",s=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate","renderEnd"),t=250;f.orient("bottom").highlightZero(!1).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(n?"right":"left").tickFormat(d3.format(",.1f"));var u=function(c,d){var h=c.pos[0]+(d.offsetLeft||0),i=c.pos[1]+(d.offsetTop||0),j=f.tickFormat()(e.x()(c.point,c.pointIndex)),k=g.tickFormat()(e.y()(c.point,c.pointIndex)),l=q(c.series.key,j,k,c,b);a.tooltip.show([h,i],l,c.value<0?"n":"s",null,d)},v=a.utils.renderWatch(s,t);return e.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+h.left,a.pos[1]+h.top],s.tooltipShow(a)}),e.dispatch.on("elementMouseout.tooltip",function(a){s.tooltipHide(a)}),s.on("tooltipHide",function(){p&&a.tooltip.cleanup()}),b.dispatch=s,b.discretebar=e,b.xAxis=f,b.yAxis=g,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},staggerLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return l},set:function(a){l=a}},showYAxis:{get:function(){return m},set:function(a){m=a}},tooltips:{get:function(){return p},set:function(a){p=a}},tooltipContent:{get:function(){return q},set:function(a){q=a}},noData:{get:function(){return r},set:function(a){r=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!==a.top?a.top:h.top,h.right=void 0!==a.right?a.right:h.right,h.bottom=void 0!==a.bottom?a.bottom:h.bottom,h.left=void 0!==a.left?a.left:h.left}},duration:{get:function(){return t},set:function(a){t=a,v.reset(t),e.duration(t),f.duration(t),g.duration(t)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}},rightAlignYAxis:{get:function(){return n},set:function(a){n=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.distribution=function(){"use strict";function b(k){return m.reset(),k.each(function(b){var k=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),l=d3.select(this);a.utils.initSVG(l),c=c||j;var n=l.selectAll("g.nv-distribution").data([b]),o=n.enter().append("g").attr("class","nvd3 nv-distribution"),p=(o.append("g"),n.select("g"));n.attr("transform","translate("+d.left+","+d.top+")");var q=p.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});q.enter().append("g"),q.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var r=q.selectAll("line.nv-dist"+g).data(function(a){return a.values});r.enter().append("line").attr(g+"1",function(a,b){return c(h(a,b))}).attr(g+"2",function(a,b){return c(h(a,b))}),m.transition(q.exit().selectAll("line.nv-dist"+g),"dist exit").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}).style("stroke-opacity",0).remove(),r.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(k+"1",0).attr(k+"2",f),m.transition(r,"dist").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),c=j.copy()}),m.renderEnd("distribution immediate"),b}var c,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=a.utils.defaultColor(),j=d3.scale.linear(),k=250,l=d3.dispatch("renderEnd"),m=a.utils.renderWatch(l,k);return b.options=a.utils.optionsFunc.bind(b),b.dispatch=l,b.margin=function(a){return arguments.length?(d.top="undefined"!=typeof a.top?a.top:d.top,d.right="undefined"!=typeof a.right?a.right:d.right,d.bottom="undefined"!=typeof a.bottom?a.bottom:d.bottom,d.left="undefined"!=typeof a.left?a.left:d.left,b):d},b.width=function(a){return arguments.length?(e=a,b):e},b.axis=function(a){return arguments.length?(g=a,b):g},b.size=function(a){return arguments.length?(f=a,b):f},b.getData=function(a){return arguments.length?(h=d3.functor(a),b):h},b.scale=function(a){return arguments.length?(j=a,b):j},b.color=function(c){return arguments.length?(i=a.utils.getColor(c),b):i},b.duration=function(a){return arguments.length?(k=a,m.reset(k),b):k},b},a.models.historicalBar=function(){"use strict";function b(w){return w.each(function(b){v.reset();var w=d3.select(this),x=(h||parseInt(w.style("width"))||960)-g.left-g.right,y=(i||parseInt(w.style("height"))||400)-g.top-g.bottom;a.utils.initSVG(w),k.domain(c||d3.extent(b[0].values.map(m).concat(o))),k.range(q?e||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:e||[0,x]),l.domain(d||d3.extent(b[0].values.map(n).concat(p))).range(f||[y,0]),k.domain()[0]===k.domain()[1]&&k.domain(k.domain()[0]?[k.domain()[0]-.01*k.domain()[0],k.domain()[1]+.01*k.domain()[1]]:[-1,1]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]+.01*l.domain()[0],l.domain()[1]-.01*l.domain()[1]]:[-1,1]);var z=w.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([b[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),B=A.append("defs"),C=A.append("g"),D=z.select("g");C.append("g").attr("class","nv-bars"),z.attr("transform","translate("+g.left+","+g.top+")"),w.on("click",function(a,b){t.chartClick({data:a,index:b,pos:d3.event,id:j})}),B.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),z.select("#nv-chart-clip-path-"+j+" rect").attr("width",x).attr("height",y),D.attr("clip-path",r?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return m(a,b)});E.exit().remove();E.enter().append("rect").attr("x",0).attr("y",function(b,c){return a.utils.NaNtoZero(l(Math.max(0,n(b,c))))}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.abs(l(n(b,c))-l(0)))}).attr("transform",function(a,c){return"translate("+(k(m(a,c))-x/b[0].values.length*.45)+",0)"}).on("mouseover",function(a,c){u&&(d3.select(this).classed("hover",!0),t.elementMouseover({point:a,series:b[0],pos:[k(m(a,c)),l(n(a,c))],pointIndex:c,seriesIndex:0,e:d3.event}))}).on("mouseout",function(a,c){u&&(d3.select(this).classed("hover",!1),t.elementMouseout({point:a,series:b[0],pointIndex:c,seriesIndex:0,e:d3.event}))}).on("click",function(a,b){u&&(t.elementClick({value:n(a,b),data:a,index:b,pos:[k(m(a,b)),l(n(a,b))],e:d3.event,id:j}),d3.event.stopPropagation())}).on("dblclick",function(a,b){u&&(t.elementDblClick({value:n(a,b),data:a,index:b,pos:[k(m(a,b)),l(n(a,b))],e:d3.event,id:j}),d3.event.stopPropagation())});E.attr("fill",function(a,b){return s(a,b)}).attr("class",function(a,b,c){return(n(a,b)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+c+"-"+b}).watchTransition(v,"bars").attr("transform",function(a,c){return"translate("+(k(m(a,c))-x/b[0].values.length*.45)+",0)"}).attr("width",x/b[0].values.length*.9),E.watchTransition(v,"bars").attr("y",function(b,c){var d=n(b,c)<0?l(0):l(0)-l(n(b,c))<1?l(0)-1:l(n(b,c));return a.utils.NaNtoZero(d)}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.max(Math.abs(l(n(b,c))-l(0)),1))})}),v.renderEnd("historicalBar immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=d3.scale.linear(),l=d3.scale.linear(),m=function(a){return a.x},n=function(a){return a.y},o=[],p=[0],q=!1,r=!0,s=a.utils.defaultColor(),t=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),u=!0,v=a.utils.renderWatch(t,0);return b.highlightPoint=function(a,b){d3.select(".nv-historicalBar-"+j).select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},b.clearHighlights=function(){d3.select(".nv-historicalBar-"+j).select(".nv-bars .nv-bar.hover").classed("hover",!1)},b.dispatch=t,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},forceX:{get:function(){return o},set:function(a){o=a}},forceY:{get:function(){return p},set:function(a){p=a}},padData:{get:function(){return q},set:function(a){q=a}},x:{get:function(){return m},set:function(a){m=a}},y:{get:function(){return n},set:function(a){n=a}},xScale:{get:function(){return k},set:function(a){k=a}},yScale:{get:function(){return l},set:function(a){l=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},clipEdge:{get:function(){return r},set:function(a){r=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return u},set:function(a){u=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBarChart=function(b){"use strict";function c(b){return b.each(function(u){B.reset(),B.models(f),p&&B.models(g),q&&B.models(h);var C=d3.select(this),D=this;a.utils.initSVG(C);var E=(m||parseInt(C.style("width"))||960)-k.left-k.right,F=(n||parseInt(C.style("height"))||400)-k.top-k.bottom;if(c.update=function(){C.transition().duration(z).call(c)},c.container=this,v.disabled=u.map(function(a){return!!a.disabled}),!w){var G;w={};for(G in v)v[G]instanceof Array?w[G]=v[G].slice(0):w[G]=v[G]}if(!(u&&u.length&&u.filter(function(a){return a.values.length}).length)){var H=C.selectAll(".nv-noData").data([x]);return H.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),H.attr("x",k.left+E/2).attr("y",k.top+F/2).text(function(a){return a}),c}C.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale();var I=C.selectAll("g.nv-wrap.nv-historicalBarChart").data([u]),J=I.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),K=I.select("g");J.append("g").attr("class","nv-x nv-axis"),J.append("g").attr("class","nv-y nv-axis"),J.append("g").attr("class","nv-barsWrap"),J.append("g").attr("class","nv-legendWrap"),J.append("g").attr("class","nv-interactive"),o&&(i.width(E),K.select(".nv-legendWrap").datum(u).call(i),k.top!=i.height()&&(k.top=i.height(),F=(n||parseInt(C.style("height"))||400)-k.top-k.bottom),I.select(".nv-legendWrap").attr("transform","translate(0,"+-k.top+")")),I.attr("transform","translate("+k.left+","+k.top+")"),r&&K.select(".nv-y.nv-axis").attr("transform","translate("+E+",0)"),s&&(j.width(E).height(F).margin({left:k.left,top:k.top}).svgContainer(C).xScale(d),I.select(".nv-interactive").call(j)),f.width(E).height(F).color(u.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!u[b].disabled}));var L=K.select(".nv-barsWrap").datum(u.filter(function(a){return!a.disabled}));L.transition().call(f),p&&(g.scale(d).tickSize(-F,0),K.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),K.select(".nv-x.nv-axis").transition().call(g)),q&&(h.scale(e).ticks(a.utils.calcTicksY(F/36,u)).tickSize(-E,0),K.select(".nv-y.nv-axis").transition().call(h)),j.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,m=[];u.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,b.pointXValue,c.x()),f.highlightPoint(e,!0);var j=g.values[e];"undefined"!=typeof j&&("undefined"==typeof d&&(d=j),"undefined"==typeof i&&(i=c.xScale()(c.x()(j,e))),m.push({key:g.key,value:c.y()(j,e),color:l(g,g.seriesIndex),data:g.values[e]}))});var n=g.tickFormat()(c.x()(d,e));j.tooltip.position({left:i+k.left,top:b.mouseY+k.top}).chartContainer(D.parentNode).enabled(t).valueFormatter(function(a,b){return h.tickFormat()(a)}).data({value:n,series:m})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(a){y.tooltipHide(),f.clearHighlights()}),i.dispatch.on("legendClick",function(a,d){a.disabled=!a.disabled,u.filter(function(a){return!a.disabled}).length||u.map(function(a){return a.disabled=!1,I.selectAll(".nv-series").classed("disabled",!1),a}),v.disabled=u.map(function(a){return!!a.disabled}),y.stateChange(v),b.transition().call(c)}),i.dispatch.on("legendDblclick",function(a){u.forEach(function(a){a.disabled=!0}),a.disabled=!1,v.disabled=u.map(function(a){return!!a.disabled}),y.stateChange(v),c.update()}),y.on("tooltipShow",function(a){t&&A(a,D.parentNode)}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(u.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),c.update()})}),B.renderEnd("historicalBarChart immediate"),c}var d,e,f=b||a.models.historicalBar(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.interactiveGuideline(),k={top:30,right:90,bottom:50,left:90},l=a.utils.defaultColor(),m=null,n=null,o=!1,p=!0,q=!0,r=!1,s=!1,t=!0,u=function(a,b,c,d,e){return"

"+a+"

"+c+" at "+b+"

"},v={},w=null,x="No Data Available.",y=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),z=250;g.orient("bottom").tickPadding(7),h.orient(r?"right":"left");var A=function(b,d){if(d){var e=d3.select(d).select("svg"),i=e.node()?e.attr("viewBox"):null;if(i){i=i.split(" ");var j=parseInt(e.style("width"))/i[2];b.pos[0]=b.pos[0]*j,b.pos[1]=b.pos[1]*j}}var k=b.pos[0]+(d.offsetLeft||0),l=b.pos[1]+(d.offsetTop||0),m=g.tickFormat()(f.x()(b.point,b.pointIndex)),n=h.tickFormat()(f.y()(b.point,b.pointIndex)),o=u(b.series.key,m,n,b,c);a.tooltip.show([k,l],o,null,null,d)},B=a.utils.renderWatch(y,0);return f.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+k.left,a.pos[1]+k.top],y.tooltipShow(a)}),f.dispatch.on("elementMouseout.tooltip",function(a){y.tooltipHide(a)}),y.on("tooltipHide",function(){t&&a.tooltip.cleanup()}),c.dispatch=y,c.bars=f,c.legend=i,c.xAxis=g,c.yAxis=h,c.interactiveLayer=j,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return p},set:function(a){p=a}},showYAxis:{get:function(){return q},set:function(a){q=a}},tooltips:{get:function(){return t},set:function(a){t=a}},tooltipContent:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),i.color(l),f.color(l)}},duration:{get:function(){return z},set:function(a){z=a,B.reset(z),h.duration(z),g.duration(z)}},rightAlignYAxis:{get:function(){return r},set:function(a){r=a,h.orient(a?"right":"left")}},useInteractiveGuideline:{get:function(){return s},set:function(a){s=a,a===!0&&c.interactive(!1)}}}),a.utils.inheritOptions(c,f),a.utils.initOptions(c),c},a.models.ohlcBarChart=function(){var b=a.models.historicalBarChart(a.models.ohlcBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
open:"+b.yAxis.tickFormat()(c.open)+"
close:"+b.yAxis.tickFormat()(c.close)+"
high"+b.yAxis.tickFormat()(c.high)+"
low:"+b.yAxis.tickFormat()(c.low)+"
"}),b},a.models.legend=function(){"use strict";function b(m){return m.each(function(b){var m=d-c.left-c.right,n=d3.select(this);a.utils.initSVG(n);var o=n.selectAll("g.nv-legend").data([b]),p=(o.enter().append("g").attr("class","nvd3 nv-legend").append("g"), -o.select("g"));o.attr("transform","translate("+c.left+","+c.top+")");var q=p.selectAll(".nv-series").data(function(a){return a}),r=q.enter().append("g").attr("class","nv-series").on("mouseover",function(a,b){l.legendMouseover(a,b)}).on("mouseout",function(a,b){l.legendMouseout(a,b)}).on("click",function(a,c){l.legendClick(a,c),j&&(k?(b.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,b.every(function(a){return a.disabled})&&b.forEach(function(a){a.disabled=!1})),l.stateChange({disabled:b.map(function(a){return!!a.disabled})}))}).on("dblclick",function(a,c){l.legendDblclick(a,c),j&&(b.forEach(function(a){a.disabled=!0}),a.disabled=!1,l.stateChange({disabled:b.map(function(a){return!!a.disabled})}))});if(r.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),r.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8"),q.classed("nv-disabled",function(a){return a.disabled}),q.exit().remove(),q.select("circle").style("fill",function(a,b){return a.color||g(a,b)}).style("stroke",function(a,b){return a.color||g(a,b)}),q.select("text").text(f),h){var s=[];q.each(function(b,c){var d,e=d3.select(this).select("text");try{if(d=e.node().getComputedTextLength(),0>=d)throw Error()}catch(f){d=a.utils.calcApproxTextWidth(e)}s.push(d+28)});for(var t=0,u=0,v=[];m>u&&tm&&t>1;){v=[],t--;for(var w=0;w(v[w%t]||0)&&(v[w%t]=s[w]);u=v.reduce(function(a,b,c,d){return a+b})}for(var x=[],y=0,z=0;t>y;y++)x[y]=z,z+=v[y];q.attr("transform",function(a,b){return"translate("+x[b%t]+","+(5+20*Math.floor(b/t))+")"});{p.insert("rect","g").attr("height",e).attr("width",u>0?u:0).attr("transform","translate(-10,-5)").style("fill","#eee")}e=d3.select(this.parentNode.parentNode.parentNode).attr("height"),i?p.attr("transform","translate("+(d-c.right-u)+","+(e-50)+")"):p.attr("transform","translate(0,"+(e-50)+")"),e=c.top+c.bottom+20*Math.ceil(s.length/t)}else{var A,B=5,C=5,D=0;q.attr("transform",function(a,b){var e=d3.select(this).select("text").node().getComputedTextLength()+28;return A=C,dD&&(D=C),"translate("+A+","+B+")"}),p.attr("transform","translate("+(d-c.right-D)+","+c.top+")"),e=c.top+c.bottom+B+15}}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.defaultColor(),h=!0,i=!0,j=!0,k=!1,l=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange");return b.dispatch=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return i},set:function(a){i=a}},updateState:{get:function(){return j},set:function(a){j=a}},radioButtonMode:{get:function(){return k},set:function(a){k=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.line=function(){"use strict";function b(p){return t.reset(),t.models(e),p.each(function(b){var p=g-f.left-f.right,q=h-f.top-f.bottom,u=d3.select(this);a.utils.initSVG(u),c=e.xScale(),d=e.yScale(),r=r||c,s=s||d;var v=u.selectAll("g.nv-wrap.nv-line").data([b]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),x=w.append("defs"),y=w.append("g"),z=v.select("g");y.append("g").attr("class","nv-groups"),y.append("g").attr("class","nv-scatterWrap"),v.attr("transform","translate("+f.left+","+f.top+")"),e.width(p).height(q);var A=v.select(".nv-scatterWrap");A.call(e),x.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),v.select("#nv-edge-clip-"+e.id()+" rect").attr("width",p>0?p:0).attr("height",q>0?q:0),z.attr("clip-path",n?"url(#nv-edge-clip-"+e.id()+")":""),A.attr("clip-path",n?"url(#nv-edge-clip-"+e.id()+")":"");var B=v.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});B.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),B.exit().remove(),B.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return i(a,b)}).style("stroke",function(a,b){return i(a,b)}),B.watchTransition(t,"line: groups").style("stroke-opacity",1).style("fill-opacity",.5);var C=B.selectAll("path.nv-area").data(function(a){return m(a)?[a]:[]});C.enter().append("path").attr("class","nv-area").attr("d",function(b){return d3.svg.area().interpolate(o).defined(l).x(function(b,c){return a.utils.NaNtoZero(r(j(b,c)))}).y0(function(b,c){return a.utils.NaNtoZero(s(k(b,c)))}).y1(function(a,b){return s(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])}),B.exit().selectAll("path.nv-area").remove(),C.watchTransition(t,"line: areaPaths").attr("d",function(b){return d3.svg.area().interpolate(o).defined(l).x(function(b,d){return a.utils.NaNtoZero(c(j(b,d)))}).y0(function(b,c){return a.utils.NaNtoZero(d(k(b,c)))}).y1(function(a,b){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])});var D=B.selectAll("path.nv-line").data(function(a){return[a.values]});D.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(o).defined(l).x(function(b,c){return a.utils.NaNtoZero(r(j(b,c)))}).y(function(b,c){return a.utils.NaNtoZero(s(k(b,c)))})),D.watchTransition(t,"line: linePaths").attr("d",d3.svg.line().interpolate(o).defined(l).x(function(b,d){return a.utils.NaNtoZero(c(j(b,d)))}).y(function(b,c){return a.utils.NaNtoZero(d(k(b,c)))})),r=c.copy(),s=d.copy()}),t.renderEnd("line immediate"),b}var c,d,e=a.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=a.utils.defaultColor(),j=function(a){return a.x},k=function(a){return a.y},l=function(a,b){return!isNaN(k(a,b))&&null!==k(a,b)},m=function(a){return a.area},n=!1,o="linear",p=250,q=d3.dispatch("elementClick","elementMouseover","elementMouseout","renderEnd");e.pointSize(16).pointDomain([16,256]);var r,s,t=a.utils.renderWatch(q,p);return b.dispatch=q,b.scatter=e,e.dispatch.on("elementClick",function(){q.elementClick.apply(this,arguments)}),e.dispatch.on("elementMouseover",function(){q.elementMouseover.apply(this,arguments)}),e.dispatch.on("elementMouseout",function(){q.elementMouseout.apply(this,arguments)}),b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},defined:{get:function(){return l},set:function(a){l=a}},interpolate:{get:function(){return o},set:function(a){o=a}},clipEdge:{get:function(){return n},set:function(a){n=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},duration:{get:function(){return p},set:function(a){p=a,t.reset(p),e.duration(p)}},isArea:{get:function(){return m},set:function(a){m=d3.functor(a)}},x:{get:function(){return j},set:function(a){j=a,e.x(a)}},y:{get:function(){return k},set:function(a){k=a,e.y(a)}},color:{get:function(){return i},set:function(b){i=a.utils.getColor(b),e.color(i)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineChart=function(){"use strict";function b(t){return A.reset(),A.models(e),o&&A.models(f),p&&A.models(g),t.each(function(t){var A=d3.select(this),D=this;a.utils.initSVG(A);var E=(l||parseInt(A.style("width"))||960)-j.left-j.right,F=(m||parseInt(A.style("height"))||400)-j.top-j.bottom;if(b.update=function(){0===y?A.call(b):A.transition().duration(y).call(b)},b.container=this,u.setter(C(t),b.update).getter(B(t)).update(),u.disabled=t.map(function(a){return!!a.disabled}),!v){var G;v={};for(G in u)u[G]instanceof Array?v[G]=u[G].slice(0):v[G]=u[G]}if(!(t&&t.length&&t.filter(function(a){return a.values.length}).length)){var H=A.selectAll(".nv-noData").data([w]);return H.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),H.attr("x",j.left+E/2).attr("y",j.top+F/2).text(function(a){return a}),b}A.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var I=A.selectAll("g.nv-wrap.nv-lineChart").data([t]),J=I.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),K=I.select("g");J.append("rect").style("opacity",0),J.append("g").attr("class","nv-x nv-axis"),J.append("g").attr("class","nv-y nv-axis"),J.append("g").attr("class","nv-linesWrap"),J.append("g").attr("class","nv-legendWrap"),J.append("g").attr("class","nv-interactive"),J.append("g").attr("class","en-postMarkers"),K.select("rect").attr("width",E>0?E:0).attr("height",F>0?F:0);var L;t.some(function(a,b){return"Post Markers"==a.key?(L=t.splice(b,1)[0],!0):void 0}),n&&(h.width(E),K.select(".nv-legendWrap").datum(t).call(h),j.top!=h.height()&&(j.top=h.height(),F=(m||parseInt(A.style("height"))||400)-j.top-j.bottom),I.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")),I.attr("transform","translate("+j.left+","+j.top+")"),q&&K.select(".nv-y.nv-axis").attr("transform","translate("+E+",0)"),r&&(i.width(E).height(F).margin({left:j.left,top:j.top}).svgContainer(A).xScale(c),I.select(".nv-interactive").call(i)),e.width(E).height(F).color(t.map(function(a,b){return a.color||k(a,b)}).filter(function(a,b){return!t[b].disabled}));var M=K.select(".nv-linesWrap").datum(t.filter(function(a){return!a.disabled}));if(M.call(e),L){var N;d3.select(".en-postMarkers").size()?(N=d3.select(".en-postMarkers"),N.selectAll("*").remove()):N=J.append("g").attr("class","en-postMarkers").attr("width",E).attr("height",F>0?F:0);var O=F-16,P=0;L.values.forEach(function(a,b){var e;if(t.some(function(b){(b.postURLs.indexOf(a.postURL)>-1||b.postURLs.indexOf("all")>-1)&&b.disabled&&(e=!0)}),!e){a.x=new Date(a.x);var f=Math.round(c(a.x)-8>=P?c(a.x)-8:P),g=Math.round(d(a.y)-8<=O?d(a.y)-8:O);a.markerX=f,a.markerY=g;{var h="translate("+f+","+g+")";N.append("g").attr("class","marker").attr("transform",h).append("svg:image").attr("height",16).attr("width",16).attr("xlink:href","/admin/images/icons16/"+a.network.toLowerCase()+".png")}}}),t.push(L)}o&&(f.scale(c).ticks(a.utils.calcTicksX(E/100,t)).tickSize(-F,0),K.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),K.select(".nv-x.nv-axis").call(f)),p&&(g.scale(d).ticks(a.utils.calcTicksY(F/36,t)).tickSize(-E,0),K.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)u[c]=a[c];x.stateChange(u),b.update()}),i.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,h,l,m=[];if(t.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=a.interactiveBisect(f.values,c.pointXValue,b.x()),e.highlightPoint(g,h,!0);var i=f.values[h];"undefined"!=typeof i&&("undefined"==typeof d&&(d=i),"undefined"==typeof l&&(l=b.xScale()(b.x()(i,h))),m.push({key:f.key,value:b.y()(i,h),color:k(f,f.seriesIndex)}))}),m.length>2){var n=b.yScale().invert(c.mouseY),o=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),p=.03*o,q=a.nearestValueIndex(m.map(function(a){return a.value}),n,p);null!==q&&(m[q].highlight=!0)}var r;L.values.forEach(function(a){c.mouseX>=a.markerX&&c.mouseX<=a.markerX+16&&c.mouseY>=a.markerY&&c.mouseY<=a.markerY+16&&(r={label:a.label,postDate:a.x})});var u=f.tickFormat()(b.x()(d,h));i.tooltip.position({left:l+j.left,top:c.mouseY+j.top}).chartContainer(D.parentNode).enabled(s).valueFormatter(function(a,b){return g.tickFormat()(a)}).data({value:u,series:m,postMarkerTooltip:r})(),i.renderGuideLine(l)}),i.dispatch.on("elementClick",function(c){var d,f=[];t.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if("undefined"!=typeof h){"undefined"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on("elementMouseout",function(a){x.tooltipHide(),e.clearHighlights()}),x.on("tooltipShow",function(a){s&&z(a,D.parentNode)}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&t.length===a.disabled.length&&(t.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),b.update()})}),A.renderEnd("lineChart immediate"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j={top:30,right:20,bottom:50,left:60},k=a.utils.defaultColor(),l=null,m=null,n=!0,o=!0,p=!0,q=!1,r=!1,s=!0,t=function(a,b,c,d,e){return"

"+a+"

"+c+" at "+b+"

"},u=a.utils.state(),v=null,w="No Data Available.",x=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),y=250;f.orient("bottom").tickPadding(7),g.orient(q?"right":"left");var z=function(c,d){var h=c.pos[0]+(d.offsetLeft||0),i=c.pos[1]+(d.offsetTop||0),j=f.tickFormat()(e.x()(c.point,c.pointIndex)),k=g.tickFormat()(e.y()(c.point,c.pointIndex)),l=t(c.series.key,j,k,c,b);a.tooltip.show([h,i],l,null,null,d)},A=a.utils.renderWatch(x,y),B=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},C=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+j.left,a.pos[1]+j.top],x.tooltipShow(a)}),e.dispatch.on("elementMouseout.tooltip",function(a){x.tooltipHide(a)}),x.on("tooltipHide",function(){s&&a.tooltip.cleanup()}),b.dispatch=x,b.lines=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.interactiveLayer=i,b.dispatch=x,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return n},set:function(a){n=a}},showXAxis:{get:function(){return o},set:function(a){o=a}},showYAxis:{get:function(){return p},set:function(a){p=a}},tooltips:{get:function(){return s},set:function(a){s=a}},tooltipContent:{get:function(){return t},set:function(a){t=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return y},set:function(a){y=a,A.reset(y),e.duration(y),f.duration(y),g.duration(y)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),h.color(k),e.color(k)}},rightAlignYAxis:{get:function(){return q},set:function(a){q=a,g.orient(q?"right":"left")}},useInteractiveGuideline:{get:function(){return r},set:function(a){r=a,r&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.linePlusBarChart=function(){"use strict";function b(J){return J.each(function(J){function U(a){var b=+("e"==a),c=b?1:-1,d=_/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function V(){u.empty()||u.extent(H),na.data([u.empty()?e.domain():H]).each(function(a,b){var c=e(a[0])-e.range()[0],d=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>c?0:c),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>d?0:d)})}function W(){H=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),L.brush({extent:c,brush:u}),V(),l.width(Z).height($).color(J.map(function(a,b){return a.color||B(a,b)}).filter(function(a,b){return!J[b].disabled&&J[b].bar})),j.width(Z).height($).color(J.map(function(a,b){return a.color||B(a,b)}).filter(function(a,b){return!J[b].disabled&&!J[b].bar}));var b=ia.select(".nv-focus .nv-barsWrap").datum(ca.length?ca.map(function(a,b){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=ia.select(".nv-focus .nv-linesWrap").datum(da[0].disabled?[{values:[]}]:da.map(function(a,b){return{key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=ca.length?l.xScale():j.xScale(),n.scale(d).ticks(a.utils.calcTicksX(Z/100,J)).tickSize(-$,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),ia.select(".nv-x.nv-axis").transition().duration(M).call(n),b.transition().duration(M).call(l),h.transition().duration(M).call(j),ia.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f).ticks(a.utils.calcTicksY($/36,J)).tickSize(-Z,0),q.scale(g).ticks(a.utils.calcTicksY($/36,J)).tickSize(ca.length?0:-Z,0),ia.select(".nv-focus .nv-y1.nv-axis").style("opacity",ca.length?1:0),ia.select(".nv-focus .nv-y2.nv-axis").style("opacity",da.length&&!da[0].disabled?1:0).attr("transform","translate("+d.range()[1]+",0)"),ia.select(".nv-focus .nv-y1.nv-axis").transition().duration(M).call(p),ia.select(".nv-focus .nv-y2.nv-axis").transition().duration(M).call(q)}var X=d3.select(this),Y=this;a.utils.initSVG(X);var Z=(x||parseInt(X.style("width"))||960)-v.left-v.right,$=(y||parseInt(X.style("height"))||400)-v.top-v.bottom-(D?G:0),_=G-w.top-w.bottom;if(b.update=function(){X.transition().duration(M).call(b)},b.container=this,N.setter(T(J),b.update).getter(S(J)).update(),N.disabled=J.map(function(a){return!!a.disabled}),!O){var aa;O={};for(aa in N)N[aa]instanceof Array?O[aa]=N[aa].slice(0):O[aa]=N[aa]}if(!(J&&J.length&&J.filter(function(a){return a.values.length}).length)){var ba=X.selectAll(".nv-noData").data([K]);return ba.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),ba.attr("x",v.left+Z/2).attr("y",v.top+$/2).text(function(a){return a}),b}X.selectAll(".nv-noData").remove();var ca=J.filter(function(a){return!a.disabled&&a.bar}),da=J.filter(function(a){return!a.bar});d=l.xScale(),e=o.scale(),f=l.yScale(),g=j.yScale(),h=m.yScale(),i=k.yScale();var ea=J.filter(function(a){return!a.disabled&&a.bar}).map(function(a){return a.values.map(function(a,b){return{x:z(a,b),y:A(a,b)}})}),fa=J.filter(function(a){return!a.disabled&&!a.bar}).map(function(a){return a.values.map(function(a,b){return{x:z(a,b),y:A(a,b)}})});d.range([0,Z]),e.domain(d3.extent(d3.merge(ea.concat(fa)),function(a){return a.x})).range([0,Z]);var ga=X.selectAll("g.nv-wrap.nv-linePlusBar").data([J]),ha=ga.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),ia=ga.select("g");ha.append("g").attr("class","nv-legendWrap");var ja=ha.append("g").attr("class","nv-focus");ja.append("g").attr("class","nv-x nv-axis"),ja.append("g").attr("class","nv-y1 nv-axis"),ja.append("g").attr("class","nv-y2 nv-axis"),ja.append("g").attr("class","nv-barsWrap"),ja.append("g").attr("class","nv-linesWrap");var ka=ha.append("g").attr("class","nv-context");ka.append("g").attr("class","nv-x nv-axis"),ka.append("g").attr("class","nv-y1 nv-axis"),ka.append("g").attr("class","nv-y2 nv-axis"),ka.append("g").attr("class","nv-barsWrap"),ka.append("g").attr("class","nv-linesWrap"),ka.append("g").attr("class","nv-brushBackground"),ka.append("g").attr("class","nv-x nv-brush"),C&&(t.width(Z/2),ia.select(".nv-legendWrap").datum(J.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?P:Q),a})).call(t),v.top!=t.height()&&(v.top=t.height(),$=(y||parseInt(X.style("height"))||400)-v.top-v.bottom-G),ia.select(".nv-legendWrap").attr("transform","translate("+Z/2+","+-v.top+")")),ga.attr("transform","translate("+v.left+","+v.top+")"),ia.select(".nv-context").style("display",D?"initial":"none"),m.width(Z).height(_).color(J.map(function(a,b){return a.color||B(a,b)}).filter(function(a,b){return!J[b].disabled&&J[b].bar})),k.width(Z).height(_).color(J.map(function(a,b){return a.color||B(a,b)}).filter(function(a,b){return!J[b].disabled&&!J[b].bar}));var la=ia.select(".nv-context .nv-barsWrap").datum(ca.length?ca:[{values:[]}]),ma=ia.select(".nv-context .nv-linesWrap").datum(da[0].disabled?[{values:[]}]:da);ia.select(".nv-context").attr("transform","translate(0,"+($+v.bottom+w.top)+")"),la.transition().call(m),ma.transition().call(k),F&&(o.ticks(a.utils.calcTicksX(Z/100,J)).tickSize(-_,0),ia.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),ia.select(".nv-context .nv-x.nv-axis").transition().call(o)),E&&(r.scale(h).ticks(_/36).tickSize(-Z,0),s.scale(i).ticks(_/36).tickSize(ca.length?0:-Z,0),ia.select(".nv-context .nv-y3.nv-axis").style("opacity",ca.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),ia.select(".nv-context .nv-y2.nv-axis").style("opacity",da.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),ia.select(".nv-context .nv-y1.nv-axis").transition().call(r),ia.select(".nv-context .nv-y2.nv-axis").transition().call(s)),u.x(e).on("brush",W),H&&u.extent(H);var na=ia.select(".nv-brushBackground").selectAll("g").data([H||u.extent()]),oa=na.enter().append("g");oa.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",_),oa.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",_);var pa=ia.select(".nv-x.nv-brush").call(u);pa.selectAll("rect").attr("height",_),pa.selectAll(".resize").append("path").attr("d",U),t.dispatch.on("stateChange",function(a){for(var c in a)N[c]=a[c];L.stateChange(N),b.update()}),L.on("tooltipShow",function(a){I&&R(a,Y.parentNode)}),L.on("changeState",function(a){"undefined"!=typeof a.disabled&&(J.forEach(function(b,c){b.disabled=a.disabled[c]}),N.disabled=a.disabled),b.update()}),W()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v={top:30,right:30,bottom:30,left:60},w={top:0,right:30,bottom:20,left:60},x=null,y=null,z=function(a){return a.x},A=function(a){return a.y},B=a.utils.defaultColor(),C=!0,D=!0,E=!1,F=!0,G=50,H=null,I=!0,J=function(a,b,c,d,e){return"

"+a+"

"+c+" at "+b+"

"},K="No Data Available.",L=d3.dispatch("tooltipShow","tooltipHide","brush","stateChange","changeState"),M=0,N=a.utils.state(),O=null,P=" (left axis)",Q=" (right axis)";j.clipEdge(!0),k.interactive(!1),n.orient("bottom").tickPadding(5),p.orient("left"),q.orient("right"),o.orient("bottom").tickPadding(5),r.orient("left"),s.orient("right");var R=function(d,e){c&&(d.pointIndex+=Math.ceil(c[0]));var f=d.pos[0]+(e.offsetLeft||0),g=d.pos[1]+(e.offsetTop||0),h=n.tickFormat()(j.x()(d.point,d.pointIndex)),i=(d.series.bar?p:q).tickFormat()(j.y()(d.point,d.pointIndex)),k=J(d.series.key,h,i,d,b);a.tooltip.show([f,g],k,d.value<0?"n":"s",null,e)},S=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},T=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return j.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+v.left,a.pos[1]+v.top],L.tooltipShow(a)}),j.dispatch.on("elementMouseout.tooltip",function(a){L.tooltipHide(a)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+v.left,a.pos[1]+v.top],L.tooltipShow(a)}),l.dispatch.on("elementMouseout.tooltip",function(a){L.tooltipHide(a)}),L.on("tooltipHide",function(){I&&a.tooltip.cleanup()}),b.dispatch=L,b.legend=t,b.lines=j,b.lines2=k,b.bars=l,b.bars2=m,b.xAxis=n,b.x2Axis=o,b.y1Axis=p,b.y2Axis=q,b.y3Axis=r,b.y4Axis=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return x},set:function(a){x=a}},height:{get:function(){return y},set:function(a){y=a}},showLegend:{get:function(){return C},set:function(a){C=a}},tooltips:{get:function(){return I},set:function(a){I=a}},tooltipContent:{get:function(){return J},set:function(a){J=a}},brushExtent:{get:function(){return H},set:function(a){H=a}},noData:{get:function(){return K},set:function(a){K=a}},focusEnable:{get:function(){return D},set:function(a){D=a}},focusHeight:{get:function(){return G},set:function(a){G=a}},focusShowAxisX:{get:function(){return F},set:function(a){F=a}},focusShowAxisY:{get:function(){return E},set:function(a){E=a}},legendLeftAxisHint:{get:function(){return P},set:function(a){P=a}},legendRightAxisHint:{get:function(){return Q},set:function(a){Q=a}},margin:{get:function(){return v},set:function(a){v.top=void 0!==a.top?a.top:v.top,v.right=void 0!==a.right?a.right:v.right,v.bottom=void 0!==a.bottom?a.bottom:v.bottom,v.left=void 0!==a.left?a.left:v.left}},duration:{get:function(){return M},set:function(a){M=a}},color:{get:function(){return B},set:function(b){B=a.utils.getColor(b),t.color(B)}},x:{get:function(){return z},set:function(a){z=a,j.x(a),k.x(a),l.x(a),m.x(a)}},y:{get:function(){return A},set:function(a){A=a,j.y(a),k.y(a),l.y(a),m.y(a)}}}),a.utils.inheritOptions(b,j),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){"use strict";function b(x){return x.each(function(x){function G(a){var b=+("e"==a),c=b?1:-1,d=N/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function H(){n.empty()||n.extent(v),W.data([n.empty()?e.domain():v]).each(function(a,b){var d=e(a[0])-c.range()[0],f=c.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>d?0:d),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>f?0:f)})}function I(){v=n.empty()?null:n.extent();var a=n.empty()?e.domain():n.extent();if(!(Math.abs(a[0]-a[1])<=1)){z.brush({extent:a,brush:n}),H();var b=S.select(".nv-focus .nv-linesWrap").datum(x.filter(function(a){return!a.disabled}).map(function(b,c){return{key:b.key,area:b.area,values:b.values.filter(function(b,c){return g.x()(b,c)>=a[0]&&g.x()(b,c)<=a[1]})}}));b.transition().duration(A).call(g),S.select(".nv-focus .nv-x.nv-axis").transition().duration(A).call(i),S.select(".nv-focus .nv-y.nv-axis").transition().duration(A).call(j)}}var J=d3.select(this),K=this;a.utils.initSVG(J);var L=(r||parseInt(J.style("width"))||960)-o.left-o.right,M=(s||parseInt(J.style("height"))||400)-o.top-o.bottom-t,N=t-p.top-p.bottom;if(b.update=function(){J.transition().duration(A).call(b)},b.container=this,B.setter(F(x),b.update).getter(E(x)).update(),B.disabled=x.map(function(a){return!!a.disabled}),!C){var O;C={};for(O in B)B[O]instanceof Array?C[O]=B[O].slice(0):C[O]=B[O]}if(!(x&&x.length&&x.filter(function(a){return a.values.length}).length)){var P=J.selectAll(".nv-noData").data([y]);return P.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),P.attr("x",o.left+L/2).attr("y",o.top+M/2).text(function(a){return a}),b}J.selectAll(".nv-noData").remove(),c=g.xScale(),d=g.yScale(),e=h.xScale(),f=h.yScale();var Q=J.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([x]),R=Q.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),S=Q.select("g");R.append("g").attr("class","nv-legendWrap");var T=R.append("g").attr("class","nv-focus");T.append("g").attr("class","nv-x nv-axis"),T.append("g").attr("class","nv-y nv-axis"),T.append("g").attr("class","nv-linesWrap");var U=R.append("g").attr("class","nv-context");U.append("g").attr("class","nv-x nv-axis"),U.append("g").attr("class","nv-y nv-axis"),U.append("g").attr("class","nv-linesWrap"),U.append("g").attr("class","nv-brushBackground"),U.append("g").attr("class","nv-x nv-brush"),u&&(m.width(L),S.select(".nv-legendWrap").datum(x).call(m),o.top!=m.height()&&(o.top=m.height(),M=(s||parseInt(J.style("height"))||400)-o.top-o.bottom-t),S.select(".nv-legendWrap").attr("transform","translate(0,"+-o.top+")")),Q.attr("transform","translate("+o.left+","+o.top+")"),g.width(L).height(M).color(x.map(function(a,b){return a.color||q(a,b)}).filter(function(a,b){return!x[b].disabled})),h.defined(g.defined()).width(L).height(N).color(x.map(function(a,b){return a.color||q(a,b)}).filter(function(a,b){return!x[b].disabled})),S.select(".nv-context").attr("transform","translate(0,"+(M+o.bottom+p.top)+")");var V=S.select(".nv-context .nv-linesWrap").datum(x.filter(function(a){return!a.disabled}));d3.transition(V).call(h),i.scale(c).ticks(a.utils.calcTicksX(L/100,x)).tickSize(-M,0),j.scale(d).ticks(a.utils.calcTicksY(M/36,x)).tickSize(-L,0),S.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+M+")"),n.x(e).on("brush",function(){var a=b.duration();b.duration(0),I(),b.duration(a)}),v&&n.extent(v);var W=S.select(".nv-brushBackground").selectAll("g").data([v||n.extent()]),X=W.enter().append("g");X.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",N),X.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",N);var Y=S.select(".nv-x.nv-brush").call(n);Y.selectAll("rect").attr("height",N),Y.selectAll(".resize").append("path").attr("d",G),I(),k.scale(e).ticks(a.utils.calcTicksX(L/100,x)).tickSize(-N,0),S.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),d3.transition(S.select(".nv-context .nv-x.nv-axis")).call(k),l.scale(f).ticks(a.utils.calcTicksY(N/36,x)).tickSize(-L,0),d3.transition(S.select(".nv-context .nv-y.nv-axis")).call(l),S.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),m.dispatch.on("stateChange",function(a){for(var c in a)B[c]=a[c];z.stateChange(B),b.update()}),z.on("tooltipShow",function(a){w&&D(a,K.parentNode)}),z.on("changeState",function(a){"undefined"!=typeof a.disabled&&x.forEach(function(b,c){b.disabled=a.disabled[c]}),b.update()})}),b}var c,d,e,f,g=a.models.line(),h=a.models.line(),i=a.models.axis(),j=a.models.axis(),k=a.models.axis(),l=a.models.axis(),m=a.models.legend(),n=d3.svg.brush(),o={top:30,right:30,bottom:30,left:60},p={top:0,right:30,bottom:20,left:60},q=a.utils.defaultColor(),r=null,s=null,t=100,u=!0,v=null,w=!0,x=function(a,b,c,d,e){return"

"+a+"

"+c+" at "+b+"

"},y="No Data Available.",z=d3.dispatch("tooltipShow","tooltipHide","brush","stateChange","changeState"),A=250,B=a.utils.state(),C=null;g.clipEdge(!0),h.interactive(!1),i.orient("bottom").tickPadding(5),j.orient("left"),k.orient("bottom").tickPadding(5),l.orient("left");var D=function(c,d){var e=c.pos[0]+(d.offsetLeft||0),f=c.pos[1]+(d.offsetTop||0),h=i.tickFormat()(g.x()(c.point,c.pointIndex)),k=j.tickFormat()(g.y()(c.point,c.pointIndex)),l=x(c.series.key,h,k,c,b);a.tooltip.show([e,f],l,null,null,d)},E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return g.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+o.left,a.pos[1]+o.top],z.tooltipShow(a)}),g.dispatch.on("elementMouseout.tooltip",function(a){z.tooltipHide(a)}),z.on("tooltipHide",function(){w&&a.tooltip.cleanup()}),b.dispatch=z,b.legend=m,b.lines=g,b.lines2=h,b.xAxis=i,b.yAxis=j,b.x2Axis=k,b.y2Axis=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return r},set:function(a){r=a}},height:{get:function(){return s},set:function(a){s=a}},focusHeight:{get:function(){return t},set:function(a){t=a}},showLegend:{get:function(){return u},set:function(a){u=a}},brushExtent:{get:function(){return v},set:function(a){v=a}},tooltips:{get:function(){return w},set:function(a){w=a}},tooltipContent:{get:function(){return x},set:function(a){x=a}},defaultState:{get:function(){return C},set:function(a){C=a}},noData:{get:function(){return y},set:function(a){y=a}},margin:{get:function(){return o},set:function(a){ -o.top=void 0!==a.top?a.top:o.top,o.right=void 0!==a.right?a.right:o.right,o.bottom=void 0!==a.bottom?a.bottom:o.bottom,o.left=void 0!==a.left?a.left:o.left}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b),m.color(q)}},interpolate:{get:function(){return g.interpolate()},set:function(a){g.interpolate(a),h.interpolate(a)}},xTickFormat:{get:function(){return i.xTickFormat()},set:function(a){i.xTickFormat(a),k.xTickFormat(a)}},yTickFormat:{get:function(){return j.yTickFormat()},set:function(a){j.yTickFormat(a),l.yTickFormat(a)}},duration:{get:function(){return A},set:function(a){A=a,j.duration(A),i.duration(A)}},x:{get:function(){return g.x()},set:function(a){g.x(a),h.x(a)}},y:{get:function(){return g.y()},set:function(a){g.y(a),h.y(a)}}}),a.utils.inheritOptions(b,g),a.utils.initOptions(b),b},a.models.multiBar=function(){"use strict";function b(D){return B.reset(),D.each(function(b){var D=k-j.left-j.right,E=l-j.top-j.bottom,F=d3.select(this);a.utils.initSVG(F);w&&b.length&&(w=[{values:b[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),t&&(b=d3.layout.stack().offset(u).values(function(a){return a.values}).y(q)(!b.length&&w?w:b)),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})}),t&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e,e-=b.size):(b.y1=b.size+d,d+=b.size)})});var G=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0,y1:a.y1}})});m.domain(d||d3.merge(G).map(function(a){return a.x})).rangeBands(f||[0,D],z),n.domain(e||d3.extent(d3.merge(G).map(function(a){return t?a.y>0?a.y1:a.y1+a.y:a.y}).concat(r))).range(g||[E,0]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]:[-1,1]),h=h||m,i=i||n;var H=F.selectAll("g.nv-wrap.nv-multibar").data([b]),I=H.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),J=I.append("defs"),K=I.append("g"),L=H.select("g");K.append("g").attr("class","nv-groups"),H.attr("transform","translate("+j.left+","+j.top+")"),J.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),H.select("#nv-edge-clip-"+o+" rect").attr("width",D>0?D:0).attr("height",E>0?E:0),L.attr("clip-path",s?"url(#nv-edge-clip-"+o+")":"");var M=H.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});M.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);var N=B.transition(M.exit().selectAll("rect.nv-bar"),"multibarExit",Math.min(100,y)).attr("y",function(a){return i(t?a.y0:0)||0}).attr("height",0).remove();N.delay&&N.delay(function(a,b){var c=b*(y/(C+1))-b;return c}),M.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return v(a,b)}).style("stroke",function(a,b){return v(a,b)}),M.style("stroke-opacity",1).style("fill-opacity",.75);var O=M.selectAll("rect.nv-bar").data(function(a){return w&&!b.length?w.values:a.values});O.exit().remove();O.enter().append("rect").attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(a,c,d){return t?0:d*m.rangeBand()/b.length}).attr("y",function(a){return i(t?a.y0:0)||0}).attr("height",0).attr("width",m.rangeBand()/(t?1:b.length)).attr("transform",function(a,b){return"translate("+m(p(a,b))+",0)"});O.style("fill",function(a,b,c){return v(a,c,b)}).style("stroke",function(a,b,c){return v(a,c,b)}).on("mouseover",function(a,c){d3.select(this).classed("hover",!0),A.elementMouseover({value:q(a,c),point:a,series:b[a.series],pos:[m(p(a,c))+m.rangeBand()*(t?b.length/2:a.series+.5)/b.length,n(q(a,c)+(t?a.y0:0))],pointIndex:c,seriesIndex:a.series,e:d3.event})}).on("mouseout",function(a,c){d3.select(this).classed("hover",!1),A.elementMouseout({value:q(a,c),point:a,series:b[a.series],pointIndex:c,seriesIndex:a.series,e:d3.event})}).on("click",function(a,c){A.elementClick({value:q(a,c),point:a,series:b[a.series],pos:[m(p(a,c))+m.rangeBand()*(t?b.length/2:a.series+.5)/b.length,n(q(a,c)+(t?a.y0:0))],pointIndex:c,seriesIndex:a.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(a,c){A.elementDblClick({value:q(a,c),point:a,series:b[a.series],pos:[m(p(a,c))+m.rangeBand()*(t?b.length/2:a.series+.5)/b.length,n(q(a,c)+(t?a.y0:0))],pointIndex:c,seriesIndex:a.series,e:d3.event}),d3.event.stopPropagation()}),O.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(a,b){return"translate("+m(p(a,b))+",0)"}),x&&(c||(c=b.map(function(){return!0})),O.style("fill",function(a,b,d){return d3.rgb(x(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(x(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}));var P=O.watchTransition(B,"multibar",Math.min(250,y)).delay(function(a,c){return c*y/b[0].values.length});t?P.attr("y",function(a,b){return n(t?a.y1:0)}).attr("height",function(a,b){return Math.max(Math.abs(n(a.y+(t?a.y0:0))-n(t?a.y0:0)),1)}).attr("x",function(a,c){return t?0:a.series*m.rangeBand()/b.length}).attr("width",m.rangeBand()/(t?1:b.length)):P.attr("x",function(a,c){return a.series*m.rangeBand()/b.length}).attr("width",m.rangeBand()/b.length).attr("y",function(a,b){return q(a,b)<0?n(0):n(0)-n(q(a,b))<1?n(0)-1:n(q(a,b))||0}).attr("height",function(a,b){return Math.max(Math.abs(n(q(a,b))-n(0)),1)||0}),h=m.copy(),i=n.copy(),b[0]&&b[0].values&&(C=b[0].values.length)}),B.renderEnd("multibar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=d3.scale.ordinal(),n=d3.scale.linear(),o=Math.floor(1e4*Math.random()),p=function(a){return a.x},q=function(a){return a.y},r=[0],s=!0,t=!1,u="zero",v=a.utils.defaultColor(),w=!1,x=null,y=500,z=.1,A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),B=a.utils.renderWatch(A,y),C=0;return b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return r},set:function(a){r=a}},stacked:{get:function(){return t},set:function(a){t=a}},stackOffset:{get:function(){return u},set:function(a){u=a}},clipEdge:{get:function(){return s},set:function(a){s=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return o},set:function(a){o=a}},hideable:{get:function(){return w},set:function(a){w=a}},groupSpacing:{get:function(){return z},set:function(a){z=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return y},set:function(a){y=a,B.reset(y)}},color:{get:function(){return v},set:function(b){v=a.utils.getColor(b)}},barColor:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.multiBarChart=function(){"use strict";function b(x){return E.reset(),E.models(e),q&&E.models(f),r&&E.models(g),x.each(function(x){var E=d3.select(this),J=this;a.utils.initSVG(E);var K=(k||parseInt(E.style("width"))||960)-j.left-j.right,L=(l||parseInt(E.style("height"))||400)-j.top-j.bottom;if(b.update=function(){0===D?E.call(b):E.transition().duration(D).call(b)},b.container=this,y.setter(I(x),b.update).getter(H(x)).update(),y.disabled=x.map(function(a){return!!a.disabled}),!z){var M;z={};for(M in y)y[M]instanceof Array?z[M]=y[M].slice(0):z[M]=y[M]}if(!(x&&x.length&&x.filter(function(a){return a.values.length}).length)){var N=E.selectAll(".nv-noData").data([A]);return N.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),N.attr("x",j.left+K/2).attr("y",j.top+L/2).text(function(a){return a}),b}E.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var O=E.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([x]),P=O.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),Q=O.select("g");if(P.append("g").attr("class","nv-x nv-axis"),P.append("g").attr("class","nv-y nv-axis"),P.append("g").attr("class","nv-barsWrap"),P.append("g").attr("class","nv-legendWrap"),P.append("g").attr("class","nv-controlsWrap"),p&&(h.width(K-C()),e.barColor()&&x.forEach(function(a,b){a.color=d3.rgb("#ccc").darker(1.5*b).toString()}),Q.select(".nv-legendWrap").datum(x).call(h),j.top!=h.height()&&(j.top=h.height(),L=(l||parseInt(E.style("height"))||400)-j.top-j.bottom),Q.select(".nv-legendWrap").attr("transform","translate("+C()+","+-j.top+")")),n){var R=[{key:o.grouped||"Grouped",disabled:e.stacked()},{key:o.stacked||"Stacked",disabled:!e.stacked()}];i.width(C()).color(["#444","#444","#444"]),Q.select(".nv-controlsWrap").datum(R).attr("transform","translate(0,"+-j.top+")").call(i)}O.attr("transform","translate("+j.left+","+j.top+")"),s&&Q.select(".nv-y.nv-axis").attr("transform","translate("+K+",0)"),e.disabled(x.map(function(a){return a.disabled})).width(K).height(L).color(x.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!x[b].disabled}));var S=Q.select(".nv-barsWrap").datum(x.filter(function(a){return!a.disabled}));if(S.call(e),q){f.scale(c).ticks(a.utils.calcTicksX(K/100,x)).tickSize(-L,0),Q.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),Q.select(".nv-x.nv-axis").call(f);var T=Q.select(".nv-x.nv-axis > g").selectAll("g");if(T.selectAll("line, text").style("opacity",1),u){var U=function(a,b){return"translate("+a+","+b+")"},V=5,W=17;T.selectAll("text").attr("transform",function(a,b,c){return U(0,c%2==0?V:W)});var X=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;Q.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return U(0,0===b||X%2!==0?W:V)})}t&&T.filter(function(a,b){return b%Math.ceil(x[0].values.length/(K/100))!==0}).selectAll("text, line").style("opacity",0),v&&T.selectAll(".tick text").attr("transform","rotate("+v+" 0,0)").style("text-anchor",v>0?"start":"end"),Q.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}r&&(g.scale(d).ticks(a.utils.calcTicksY(L/36,x)).tickSize(-K,0),Q.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];B.stateChange(y),b.update()}),i.dispatch.on("legendClick",function(a,c){if(a.disabled){switch(R=R.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}y.stacked=e.stacked(),B.stateChange(y),b.update()}}),B.on("tooltipShow",function(a){w&&G(a,J.parentNode)}),B.on("changeState",function(a){"undefined"!=typeof a.disabled&&(x.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),y.stacked=a.stacked,F=a.stacked),b.update()})}),E.renderEnd("multibarchart immediate"),b}var c,d,e=a.models.multiBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j={top:30,right:20,bottom:50,left:60},k=null,l=null,m=a.utils.defaultColor(),n=!0,o={},p=!0,q=!0,r=!0,s=!1,t=!0,u=!1,v=0,w=!0,x=function(a,b,c,d,e){return"

"+a+"

"+c+" on "+b+"

"},y=a.utils.state(),z=null,A="No Data Available.",B=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),C=function(){return n?180:0},D=250;y.stacked=!1,e.stacked(!1),f.orient("bottom").tickPadding(7).highlightZero(!0).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(s?"right":"left").tickFormat(d3.format(",.1f")),i.updateState(!1);var E=a.utils.renderWatch(B),F=!1,G=function(c,d){var h=c.pos[0]+(d.offsetLeft||0),i=c.pos[1]+(d.offsetTop||0),j=f.tickFormat()(e.x()(c.point,c.pointIndex)),k=g.tickFormat()(e.y()(c.point,c.pointIndex)),l=x(c.series.key,j,k,c,b);a.tooltip.show([h,i],l,c.value<0?"n":"s",null,d)},H=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:F}}},I=function(a){return function(b){void 0!==b.stacked&&(F=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+j.left,a.pos[1]+j.top],B.tooltipShow(a)}),e.dispatch.on("elementMouseout.tooltip",function(a){B.tooltipHide(a)}),B.on("tooltipHide",function(){w&&a.tooltip.cleanup()}),b.dispatch=B,b.multibar=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.state=y,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showControls:{get:function(){return n},set:function(a){n=a}},controlLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},tooltips:{get:function(){return w},set:function(a){w=a}},tooltipContent:{get:function(){return x},set:function(a){x=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return A},set:function(a){A=a}},reduceXTicks:{get:function(){return t},set:function(a){t=a}},rotateLabels:{get:function(){return v},set:function(a){v=a}},staggerLabels:{get:function(){return u},set:function(a){u=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return D},set:function(a){D=a,e.duration(D),f.duration(D),g.duration(D),E.reset(D)}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),h.color(m)}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,g.orient(s?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiBarHorizontal=function(){"use strict";function b(m){return C.reset(),m.each(function(b){var m=k-j.left-j.right,A=l-j.top-j.bottom,D=d3.select(this);a.utils.initSVG(D),v&&(b=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(q)(b)),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})}),v&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e-b.size,e-=b.size):(b.y1=d,d+=b.size)})});var E=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0,y1:a.y1}})});n.domain(d||d3.merge(E).map(function(a){return a.x})).rangeBands(f||[0,A],.1),o.domain(e||d3.extent(d3.merge(E).map(function(a){return v?a.y>0?a.y1+a.y:a.y1:a.y}).concat(s))),o.range(w&&!v?g||[o.domain()[0]<0?y:0,m-(o.domain()[1]>0?y:0)]:g||[0,m]),h=h||n,i=i||d3.scale.linear().domain(o.domain()).range([o(0),o(0)]);{var F=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([b]),G=F.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),H=(G.append("defs"),G.append("g"));F.select("g")}H.append("g").attr("class","nv-groups"),F.attr("transform","translate("+j.left+","+j.top+")");var I=F.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});I.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),I.exit().watchTransition(C,"multibarhorizontal: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),I.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return t(a,b)}).style("stroke",function(a,b){return t(a,b)}),I.watchTransition(C,"multibarhorizontal: groups").style("stroke-opacity",1).style("fill-opacity",.75);var J=I.selectAll("g.nv-bar").data(function(a){return a.values});J.exit().remove();var K=J.enter().append("g").attr("transform",function(a,c,d){return"translate("+i(v?a.y0:0)+","+(v?0:d*n.rangeBand()/b.length+n(p(a,c)))+")"});K.append("rect").attr("width",0).attr("height",n.rangeBand()/(v?1:b.length)),J.on("mouseover",function(a,c){d3.select(this).classed("hover",!0),B.elementMouseover({value:q(a,c),point:a,series:b[a.series],pos:[o(q(a,c)+(v?a.y0:0)),n(p(a,c))+n.rangeBand()*(v?b.length/2:a.series+.5)/b.length],pointIndex:c,seriesIndex:a.series,e:d3.event})}).on("mouseout",function(a,c){d3.select(this).classed("hover",!1),B.elementMouseout({value:q(a,c),point:a,series:b[a.series],pointIndex:c,seriesIndex:a.series,e:d3.event})}).on("click",function(a,c){B.elementClick({value:q(a,c),point:a,series:b[a.series],pos:[n(p(a,c))+n.rangeBand()*(v?b.length/2:a.series+.5)/b.length,o(q(a,c)+(v?a.y0:0))],pointIndex:c,seriesIndex:a.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(a,c){B.elementDblClick({value:q(a,c),point:a,series:b[a.series],pos:[n(p(a,c))+n.rangeBand()*(v?b.length/2:a.series+.5)/b.length,o(q(a,c)+(v?a.y0:0))],pointIndex:c,seriesIndex:a.series,e:d3.event}),d3.event.stopPropagation()}),r(b[0],0)&&(K.append("polyline"),J.select("polyline").attr("fill","none").attr("points",function(a,c){var d=r(a,c),e=.8*n.rangeBand()/(2*(v?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return o(a)-o(0)});var f=[[d[0],-e],[d[0],e],[d[0],0],[d[1],0],[d[1],-e],[d[1],e]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=n.rangeBand()/(2*(v?1:b.length));return"translate("+(q(a,c)<0?0:o(q(a,c))-o(0))+", "+d+")"})),K.append("text"),w&&!v?(J.select("text").attr("text-anchor",function(a,b){return q(a,b)<0?"end":"start"}).attr("y",n.rangeBand()/(2*b.length)).attr("dy",".32em").html(function(a,b){var c=z(q(a,b)),d=r(a,b);return void 0===d?c:d.length?c+"+"+z(Math.abs(d[1]))+"-"+z(Math.abs(d[0])):c+"±"+z(Math.abs(d))}),J.watchTransition(C,"multibarhorizontal: bars").select("text").attr("x",function(a,b){return q(a,b)<0?-4:o(q(a,b))-o(0)+4})):J.selectAll("text").text(""),x&&!v?(K.append("text").classed("nv-bar-label",!0),J.select("text.nv-bar-label").attr("text-anchor",function(a,b){return q(a,b)<0?"start":"end"}).attr("y",n.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){return p(a,b)}),J.watchTransition(C,"multibarhorizontal: bars").select("text.nv-bar-label").attr("x",function(a,b){return q(a,b)<0?o(0)-o(q(a,b))+4:-4})):J.selectAll("text.nv-bar-label").text(""),J.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}),u&&(c||(c=b.map(function(){return!0})),J.style("fill",function(a,b,d){return d3.rgb(u(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(u(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()})),v?J.watchTransition(C,"multibarhorizontal: bars").attr("transform",function(a,b){return"translate("+o(a.y1)+","+n(p(a,b))+")"}).select("rect").attr("width",function(a,b){return Math.abs(o(q(a,b)+a.y0)-o(a.y0))}).attr("height",n.rangeBand()):J.watchTransition(C,"multibarhorizontal: bars").attr("transform",function(a,c){return"translate("+o(q(a,c)<0?q(a,c):0)+","+(a.series*n.rangeBand()/b.length+n(p(a,c)))+")"}).select("rect").attr("height",n.rangeBand()/b.length).attr("width",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(0)),1)}),h=n.copy(),i=o.copy()}),C.renderEnd("multibarHorizontal immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=d3.scale.ordinal(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=function(a){return a.yErr},s=[0],t=a.utils.defaultColor(),u=null,v=!1,w=!1,x=!1,y=60,z=d3.format(",.2f"),A=250,B=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),C=a.utils.renderWatch(B,A);return b.dispatch=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},yErr:{get:function(){return r},set:function(a){r=a}},xScale:{get:function(){return n},set:function(a){n=a}},yScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return s},set:function(a){s=a}},stacked:{get:function(){return v},set:function(a){v=a}},showValues:{get:function(){return w},set:function(a){w=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return m},set:function(a){m=a}},valueFormat:{get:function(){return z},set:function(a){z=a}},valuePadding:{get:function(){return y},set:function(a){y=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return A},set:function(a){A=a,C.reset(A)}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}},barColor:{get:function(){return t},set:function(b){u=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.multiBarHorizontalChart=function(){"use strict";function b(u){return E.reset(),E.models(e),q&&E.models(f),r&&E.models(g),u.each(function(u){var E=d3.select(this),F=this;a.utils.initSVG(E);var G=(k||parseInt(E.style("width"))||960)-j.left-j.right,H=(l||parseInt(E.style("height"))||400)-j.top-j.bottom;if(b.update=function(){E.transition().duration(A).call(b)},b.container=this,s=e.stacked(),v.setter(D(u),b.update).getter(C(u)).update(),v.disabled=u.map(function(a){return!!a.disabled}),!w){var I;w={};for(I in v)v[I]instanceof Array?w[I]=v[I].slice(0):w[I]=v[I]}if(!(u&&u.length&&u.filter(function(a){return a.values.length}).length)){var J=E.selectAll(".nv-noData").data([x]);return J.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),J.attr("x",j.left+G/2).attr("y",j.top+H/2).text(function(a){return a}),b}E.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var K=E.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([u]),L=K.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),M=K.select("g");if(L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),L.append("g").attr("class","nv-barsWrap"),L.append("g").attr("class","nv-legendWrap"),L.append("g").attr("class","nv-controlsWrap"),p&&(h.width(G-z()),M.select(".nv-legendWrap").datum(u).call(h),j.top!=h.height()&&(j.top=h.height(),H=(l||parseInt(E.style("height"))||400)-j.top-j.bottom),M.select(".nv-legendWrap").attr("transform","translate("+z()+","+-j.top+")")),n){var N=[{key:o.grouped||"Grouped",disabled:e.stacked()},{key:o.stacked||"Stacked",disabled:!e.stacked()}];i.width(z()).color(["#444","#444","#444"]),M.select(".nv-controlsWrap").datum(N).attr("transform","translate(0,"+-j.top+")").call(i)}K.attr("transform","translate("+j.left+","+j.top+")"),e.disabled(u.map(function(a){return a.disabled})).width(G).height(H).color(u.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!u[b].disabled}));var O=M.select(".nv-barsWrap").datum(u.filter(function(a){return!a.disabled}));O.transition().call(e),q&&(f.scale(c).ticks(a.utils.calcTicksY(H/24,u)).tickSize(-G,0),M.select(".nv-x.nv-axis").call(f).selectAll(".tick text").call(function(a){a.each(function(){for(var a,b=d3.select(this),c=b.text().split(/\s+/).reverse(),d=[],e=0,f=1.1,g=(b.attr("y"),parseFloat(b.attr("dy"))),h=b.text(null).append("tspan").attr("x",-5).attr("y",0).attr("dy",g+"em");a=c.pop();)d.push(a),h.text(d.join(" ")),h.node().getComputedTextLength()>j.right&&(d.pop(),h.text(d.join(" ")),d=[a],h=b.append("tspan").attr("x",-5).attr("y",0).attr("dy",++e*f+g+"em").text(a));e&&b.attr("transform","translate(0, -"+5*e+")")})})),r&&(g.scale(d).ticks(a.utils.calcTicksX(G/100,u)).tickSize(-H,0),M.select(".nv-y.nv-axis").attr("transform","translate(0,"+H+")"),M.select(".nv-y.nv-axis").call(g)),M.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-H),h.dispatch.on("stateChange",function(a){for(var c in a)v[c]=a[c];y.stateChange(v),b.update()}),i.dispatch.on("legendClick",function(a,c){if(a.disabled){switch(N=N.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}v.stacked=e.stacked(),y.stateChange(v),s=e.stacked(),b.update()}}),y.on("tooltipShow",function(a){t&&B(a,F.parentNode)}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(u.forEach(function(b,c){b.disabled=a.disabled[c]}),v.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),v.stacked=a.stacked,s=a.stacked),b.update()})}),E.renderEnd("multibar horizontal chart immediate"),b}var c,d,e=a.models.multiBarHorizontal(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend().height(30),i=a.models.legend().height(30),j={top:30,right:20,bottom:50,left:60},k=null,l=null,m=a.utils.defaultColor(),n=!0,o={},p=!0,q=!0,r=!0,s=!0,t=!0,u=function(a,b,c,d,e){return"

"+a+" - "+b+"

"+c+"

"},v=a.utils.state(),w=null,x="No Data Available.",y=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),z=function(){return n?180:0},A=250;v.stacked=!1,e.stacked(s),f.orient("left").tickPadding(5).highlightZero(!1).showMaxMin(!1).tickFormat(function(a){return a}),g.orient("bottom").tickFormat(d3.format(",.1f")),i.updateState(!1);var B=function(c,d){var h=c.pos[0]+(d.offsetLeft||0),i=c.pos[1]+(d.offsetTop||0),j=f.tickFormat()(e.x()(c.point,c.pointIndex)),k=g.tickFormat()(e.y()(c.point,c.pointIndex)),l=u(c.series.key,j,k,c,b);a.tooltip.show([h,i],l,c.value<0?"e":"w",null,d)},C=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:s}}},D=function(a){return function(b){void 0!==b.stacked&&(s=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},E=a.utils.renderWatch(y,A);return e.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+j.left,a.pos[1]+j.top],y.tooltipShow(a)}),e.dispatch.on("elementMouseout.tooltip",function(a){y.tooltipHide(a)}),y.on("tooltipHide",function(){t&&a.tooltip.cleanup()}),b.dispatch=y,b.multibar=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.state=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showControls:{get:function(){return n},set:function(a){n=a}},controlLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},tooltips:{get:function(){return t},set:function(a){t=a}},tooltipContent:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return w},set:function(a){w=a}},noData:{get:function(){return x},set:function(a){x=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return A},set:function(a){A=a,E.reset(A),e.duration(A),f.duration(A),g.duration(A)}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),h.color(m)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiChart=function(){"use strict";function b(l){return l.each(function(l){var n=d3.select(this),o=this;a.utils.initSVG(n),b.update=function(){n.transition().call(b)},b.container=this;var E=(h||parseInt(n.style("width"))||960)-f.left-f.right,F=(i||parseInt(n.style("height"))||400)-f.top-f.bottom,G=l.filter(function(a){return"line"==a.type&&1==a.yAxis}),H=l.filter(function(a){return"line"==a.type&&2==a.yAxis}),I=l.filter(function(a){return"bar"==a.type&&1==a.yAxis}),J=l.filter(function(a){return"bar"==a.type&&2==a.yAxis}),K=l.filter(function(a){return"area"==a.type&&1==a.yAxis}),L=l.filter(function(a){return"area"==a.type&&2==a.yAxis});if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length)){var M=n.selectAll(".nv-noData").data([m]);return M.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),M.attr("x",f.left+E/2).attr("y",f.top+F/2).text(function(a){return a}),b}n.selectAll(".nv-noData").remove();var N=l.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a,b){return{x:a.x,y:a.y}})}),O=l.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a,b){return{x:a.x,y:a.y}})});c.domain(d3.extent(d3.merge(N.concat(O)),function(a){return a.x})).range([0,E]);var P=n.selectAll("g.wrap.multiChart").data([l]),Q=P.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");Q.append("g").attr("class","x axis"),Q.append("g").attr("class","y1 axis"),Q.append("g").attr("class","y2 axis"),Q.append("g").attr("class","lines1Wrap"),Q.append("g").attr("class","lines2Wrap"),Q.append("g").attr("class","bars1Wrap"),Q.append("g").attr("class","bars2Wrap"),Q.append("g").attr("class","stack1Wrap"),Q.append("g").attr("class","stack2Wrap"),Q.append("g").attr("class","legendWrap");var R=P.select("g"),S=l.map(function(a,b){return l[b].color||g(a,b)});j&&(B.color(S),B.width(E/2),R.select(".legendWrap").datum(l.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(1==a.yAxis?"":" (right axis)"),a})).call(B),f.top!=B.height()&&(f.top=B.height(),F=(i||parseInt(n.style("height"))||400)-f.top-f.bottom),R.select(".legendWrap").attr("transform","translate("+E/2+","+-f.top+")")),s.width(E).height(F).interpolate(p).color(S.filter(function(a,b){return!l[b].disabled&&1==l[b].yAxis&&"line"==l[b].type})),t.width(E).height(F).interpolate(p).color(S.filter(function(a,b){return!l[b].disabled&&2==l[b].yAxis&&"line"==l[b].type})),u.width(E).height(F).color(S.filter(function(a,b){return!l[b].disabled&&1==l[b].yAxis&&"bar"==l[b].type})),v.width(E).height(F).color(S.filter(function(a,b){return!l[b].disabled&&2==l[b].yAxis&&"bar"==l[b].type})),w.width(E).height(F).color(S.filter(function(a,b){return!l[b].disabled&&1==l[b].yAxis&&"area"==l[b].type})),x.width(E).height(F).color(S.filter(function(a,b){return!l[b].disabled&&2==l[b].yAxis&&"area"==l[b].type})),R.attr("transform","translate("+f.left+","+f.top+")");var T=R.select(".lines1Wrap").datum(G.filter(function(a){return!a.disabled})),U=R.select(".bars1Wrap").datum(I.filter(function(a){return!a.disabled})),V=R.select(".stack1Wrap").datum(K.filter(function(a){return!a.disabled})),W=R.select(".lines2Wrap").datum(H.filter(function(a){return!a.disabled})),X=R.select(".bars2Wrap").datum(J.filter(function(a){return!a.disabled})),Y=R.select(".stack2Wrap").datum(L.filter(function(a){return!a.disabled})),Z=K.length?K.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[],$=L.length?L.map(function(a){ -return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[];q.domain(d||d3.extent(d3.merge(N).concat(Z),function(a){return a.y})).range([0,F]),r.domain(e||d3.extent(d3.merge(O).concat($),function(a){return a.y})).range([0,F]),s.yDomain(q.domain()),u.yDomain(q.domain()),w.yDomain(q.domain()),t.yDomain(r.domain()),v.yDomain(r.domain()),x.yDomain(r.domain()),K.length&&d3.transition(V).call(w),L.length&&d3.transition(Y).call(x),I.length&&d3.transition(U).call(u),J.length&&d3.transition(X).call(v),G.length&&d3.transition(T).call(s),H.length&&d3.transition(W).call(t),y.ticks(a.utils.calcTicksX(E/100,l)).tickSize(-F,0),R.select(".x.axis").attr("transform","translate(0,"+F+")"),d3.transition(R.select(".x.axis")).call(y),z.ticks(a.utils.calcTicksY(F/36,l)).tickSize(-E,0),d3.transition(R.select(".y1.axis")).call(z),A.ticks(a.utils.calcTicksY(F/36,l)).tickSize(-E,0),d3.transition(R.select(".y2.axis")).call(A),R.select(".y1.axis").classed("nv-disabled",N.length?!1:!0).attr("transform","translate("+c.range()[0]+",0)"),R.select(".y2.axis").classed("nv-disabled",O.length?!1:!0).attr("transform","translate("+c.range()[1]+",0)"),B.dispatch.on("stateChange",function(a){b.update()}),C.on("tooltipShow",function(a){k&&D(a,o.parentNode)})}),b}var c,d,e,f={top:30,right:20,bottom:50,left:60},g=a.utils.defaultColor(),h=null,i=null,j=!0,k=!0,l=function(a,b,c,d,e){return"

"+a+"

"+c+" at "+b+"

"},m="No Data Available.",n=function(a){return a.x},o=function(a){return a.y},p="monotone",c=d3.scale.linear(),q=d3.scale.linear(),r=d3.scale.linear(),s=a.models.line().yScale(q),t=a.models.line().yScale(r),u=a.models.multiBar().stacked(!1).yScale(q),v=a.models.multiBar().stacked(!1).yScale(r),w=a.models.stackedArea().yScale(q),x=a.models.stackedArea().yScale(r),y=a.models.axis().scale(c).orient("bottom").tickPadding(5),z=a.models.axis().scale(q).orient("left"),A=a.models.axis().scale(r).orient("right"),B=a.models.legend().height(30),C=d3.dispatch("tooltipShow","tooltipHide"),D=function(c,d){var e=c.pos[0]+(d.offsetLeft||0),f=c.pos[1]+(d.offsetTop||0),g=y.tickFormat()(s.x()(c.point,c.pointIndex)),h=(2==c.series.yAxis?A:z).tickFormat()(s.y()(c.point,c.pointIndex)),i=l(c.series.key,g,h,c,b);a.tooltip.show([e,f],i,void 0,void 0,d.offsetParent)};return s.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],C.tooltipShow(a)}),s.dispatch.on("elementMouseout.tooltip",function(a){C.tooltipHide(a)}),t.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],C.tooltipShow(a)}),t.dispatch.on("elementMouseout.tooltip",function(a){C.tooltipHide(a)}),u.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],C.tooltipShow(a)}),u.dispatch.on("elementMouseout.tooltip",function(a){C.tooltipHide(a)}),v.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],C.tooltipShow(a)}),v.dispatch.on("elementMouseout.tooltip",function(a){C.tooltipHide(a)}),w.dispatch.on("tooltipShow",function(a){return Math.round(100*w.y()(a.point))?(a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],void C.tooltipShow(a)):(setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1)}),w.dispatch.on("tooltipHide",function(a){C.tooltipHide(a)}),x.dispatch.on("tooltipShow",function(a){return Math.round(100*x.y()(a.point))?(a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],void C.tooltipShow(a)):(setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1)}),x.dispatch.on("tooltipHide",function(a){C.tooltipHide(a)}),s.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],C.tooltipShow(a)}),s.dispatch.on("elementMouseout.tooltip",function(a){C.tooltipHide(a)}),t.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],C.tooltipShow(a)}),t.dispatch.on("elementMouseout.tooltip",function(a){C.tooltipHide(a)}),C.on("tooltipHide",function(){k&&a.tooltip.cleanup()}),b.dispatch=C,b.lines1=s,b.lines2=t,b.bars1=u,b.bars2=v,b.stack1=w,b.stack2=x,b.xAxis=y,b.yAxis1=z,b.yAxis2=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},showLegend:{get:function(){return j},set:function(a){j=a}},yDomain1:{get:function(){return d},set:function(a){d=a}},yDomain2:{get:function(){return e},set:function(a){e=a}},tooltips:{get:function(){return k},set:function(a){k=a}},tooltipContent:{get:function(){return l},set:function(a){l=a}},noData:{get:function(){return m},set:function(a){m=a}},interpolate:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}},x:{get:function(){return n},set:function(a){n=a,s.x(a),u.x(a)}},y:{get:function(){return o},set:function(a){o=a,s.y(a),u.y(a)}}}),a.utils.initOptions(b),b},a.models.ohlcBar=function(){"use strict";function b(x){return x.each(function(b){var x=d3.select(this),z=(h||parseInt(x.style("width"))||960)-g.left-g.right,A=(i||parseInt(x.style("height"))||400)-g.top-g.bottom;a.utils.initSVG(x),k.domain(c||d3.extent(b[0].values.map(m).concat(s))),k.range(u?e||[.5*z/b[0].values.length,z*(b[0].values.length-.5)/b[0].values.length]:e||[0,z]),l.domain(d||[d3.min(b[0].values.map(r).concat(t)),d3.max(b[0].values.map(q).concat(t))]).range(f||[A,0]),k.domain()[0]===k.domain()[1]&&k.domain(k.domain()[0]?[k.domain()[0]-.01*k.domain()[0],k.domain()[1]+.01*k.domain()[1]]:[-1,1]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]+.01*l.domain()[0],l.domain()[1]-.01*l.domain()[1]]:[-1,1]);var B=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([b[0].values]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),D=C.append("defs"),E=C.append("g"),F=B.select("g");E.append("g").attr("class","nv-ticks"),B.attr("transform","translate("+g.left+","+g.top+")"),x.on("click",function(a,b){y.chartClick({data:a,index:b,pos:d3.event,id:j})}),D.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),B.select("#nv-chart-clip-path-"+j+" rect").attr("width",z).attr("height",A),F.attr("clip-path",v?"url(#nv-chart-clip-path-"+j+")":"");var G=B.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});G.exit().remove();G.enter().append("path").attr("class",function(a,b,c){return(o(a,b)>p(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}).attr("d",function(a,c){var d=z/b[0].values.length*.9;return"m0,0l0,"+(l(o(a,c))-l(q(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(l(r(a,c))-l(o(a,c)))+"l0,"+(l(p(a,c))-l(r(a,c)))+"l"+d/2+",0l"+-d/2+",0z"}).attr("transform",function(a,b){return"translate("+k(m(a,b))+","+l(q(a,b))+")"}).attr("fill",function(a,b){return w[0]}).attr("stroke",function(a,b){return w[0]}).attr("x",0).attr("y",function(a,b){return l(Math.max(0,n(a,b)))}).attr("height",function(a,b){return Math.abs(l(n(a,b))-l(0))});G.attr("class",function(a,b,c){return(o(a,b)>p(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(G).attr("transform",function(a,b){return"translate("+k(m(a,b))+","+l(q(a,b))+")"}).attr("d",function(a,c){var d=z/b[0].values.length*.9;return"m0,0l0,"+(l(o(a,c))-l(q(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(l(r(a,c))-l(o(a,c)))+"l0,"+(l(p(a,c))-l(r(a,c)))+"l"+d/2+",0l"+-d/2+",0z"})}),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=d3.scale.linear(),l=d3.scale.linear(),m=function(a){return a.x},n=function(a){return a.y},o=function(a){return a.open},p=function(a){return a.close},q=function(a){return a.high},r=function(a){return a.low},s=[],t=[],u=!1,v=!0,w=a.utils.defaultColor(),x=!1,y=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return b.highlightPoint=function(a,c){b.clearHighlights(),d3.select(".nv-ohlcBar .nv-tick-0-"+a).classed("hover",c)},b.clearHighlights=function(){d3.select(".nv-ohlcBar .nv-tick.hover").classed("hover",!1)},b.dispatch=y,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return k},set:function(a){k=a}},yScale:{get:function(){return l},set:function(a){l=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},forceX:{get:function(){return s},set:function(a){s=a}},forceY:{get:function(){return t},set:function(a){t=a}},padData:{get:function(){return u},set:function(a){u=a}},clipEdge:{get:function(){return v},set:function(a){v=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return x},set:function(a){x=a}},x:{get:function(){return m},set:function(a){m=a}},y:{get:function(){return n},set:function(a){n=a}},open:{get:function(){return o()},set:function(a){o=a}},close:{get:function(){return p()},set:function(a){p=a}},high:{get:function(){return q},set:function(a){q=a}},low:{get:function(){return r},set:function(a){r=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!=a.top?a.top:g.top,g.right=void 0!=a.right?a.right:g.right,g.bottom=void 0!=a.bottom?a.bottom:g.bottom,g.left=void 0!=a.left?a.left:g.left}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinates=function(){"use strict";function b(m){return m.each(function(m){function n(a){return y(h.map(function(b){return[f(b),g[b](a[b])]}))}function o(){var a=h.filter(function(a){return!g[a].brush.empty()}),b=a.map(function(a){return g[a].brush.extent()});j=[],a.forEach(function(a,c){j[c]={dimension:a,extent:b[c]}}),k=[],x.style("display",function(c){var d=a.every(function(a,d){return b[d][0]<=c[a]&&c[a]<=b[d][1]});return d&&k.push(c),d?null:"none"}),l.brush({filters:j,active:k})}var p=d3.select(this),q=(d||parseInt(p.style("width"))||960)-c.left-c.right,r=(e||parseInt(p.style("height"))||400)-c.top-c.bottom;a.utils.initSVG(p),k=m,b.update=function(){},f.rangePoints([0,q],1).domain(h),h.forEach(function(a){return g[a]=d3.scale.linear().domain(d3.extent(m,function(b){return+b[a]})).range([r,0]),g[a].brush=d3.svg.brush().y(g[a]).on("brush",o),"name"!=a});var s=p.selectAll("g.nv-wrap.nv-parallelCoordinates").data([m]),t=s.enter().append("g").attr("class","nvd3 nv-wrap nv-parallelCoordinates"),u=t.append("g"),v=s.select("g");u.append("g").attr("class","nv-parallelCoordinatesWrap"),s.attr("transform","translate("+c.left+","+c.top+")");var w,x,y=d3.svg.line(),z=d3.svg.axis().orient("left");w=u.append("g").attr("class","background").selectAll("path").data(m).enter().append("path").attr("d",n),x=u.append("g").attr("class","foreground").selectAll("path").data(m).enter().append("path").attr("d",n).attr("stroke",i);var A=v.selectAll(".dimension").data(h).enter().append("g").attr("class","dimension").attr("transform",function(a){return"translate("+f(a)+",0)"});A.append("g").attr("class","axis").each(function(a){d3.select(this).call(z.scale(g[a]))}).append("text").attr("text-anchor","middle").attr("y",-9).text(String),A.append("g").attr("class","brush").each(function(a){d3.select(this).call(g[a].brush)}).selectAll("rect").attr("x",-8).attr("width",16)}),b}var c={top:30,right:10,bottom:10,left:10},d=null,e=null,f=d3.scale.ordinal(),g={},h=[],i=a.utils.defaultColor(),j=[],k=[],l=d3.dispatch("brush");return b.dispatch=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},dimensions:{get:function(){return h},set:function(a){h=a}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},color:{get:function(){return i},set:function(b){i=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.pie=function(){"use strict";function b(k){return C.reset(),k.each(function(b){function k(a){a.endAngle=isNaN(a.endAngle)?0:a.endAngle,a.startAngle=isNaN(a.startAngle)?0:a.startAngle,r||(a.innerRadius=0);var b=d3.interpolate(this._current,a);return this._current=b(0),function(a){return N(b(a))}}var D=e-c.left-c.right,E=f-c.top-c.bottom,F=Math.min(D,E)/2,G=F-F/5,H=d3.select(this);a.utils.initSVG(H);var I=H.selectAll(".nv-wrap.nv-pie").data(b),J=I.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+i),K=J.append("g"),L=I.select("g"),M=K.append("g").attr("class","nv-pie");K.append("g").attr("class","nv-pieLabels"),I.attr("transform","translate("+c.left+","+c.top+")"),L.select(".nv-pie").attr("transform","translate("+D/2+","+E/2+")"),L.select(".nv-pieLabels").attr("transform","translate("+D/2+","+E/2+")"),H.on("click",function(a,b){B.chartClick({data:a,index:b,pos:d3.event,id:i})});var N=d3.svg.arc().outerRadius(G),O=d3.svg.arc().outerRadius(G+5);w&&(N.startAngle(w),O.startAngle(w)),y&&(N.endAngle(y),O.endAngle(y)),r&&(N.innerRadius(F*A),O.innerRadius(F*A));var P=d3.layout.pie().sort(null).value(function(a){return a.disabled?0:h(a)});if(P.padAngle&&x&&P.padAngle(x),N.cornerRadius&&z&&(N.cornerRadius(z),O.cornerRadius(z)),r&&s){var Q=M.append("g").attr("class","nv-pie");Q.append("text").style("text-anchor","middle").attr("class","nv-pie-title").text(function(a){return s}).attr("dy","0.35em").attr("transform",function(a,b){return"translate(0, "+u+")"})}var R=I.select(".nv-pie").selectAll(".nv-slice").data(P),S=I.select(".nv-pieLabels").selectAll(".nv-label").data(P);R.exit().remove(),S.exit().remove();var T=R.enter().append("g");T.attr("class","nv-slice"),T.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),t&&d3.select(this).select("path").transition().duration(70).attr("d",O),B.elementMouseover({label:g(a.data),value:h(a.data),point:a.data,pointIndex:b,pos:[d3.event.pageX,d3.event.pageY],id:i,color:d3.select(this).style("fill")})}),T.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),t&&d3.select(this).select("path").transition().duration(50).attr("d",N),B.elementMouseout({label:g(a.data),value:h(a.data),point:a.data,index:b,id:i})}),R.attr("fill",function(a,b){return j(a,b)}),R.attr("stroke",function(a,b){return j(a,b)});var U=T.append("path").each(function(a){this._current=a});if(U.on("click",function(a,b){B.elementClick({label:g(a.data),value:h(a.data),point:a.data,index:b,pos:d3.event,id:i}),d3.event.stopPropagation()}),U.on("dblclick",function(a,b){B.elementDblClick({label:g(a.data),value:h(a.data),point:a.data,index:b,pos:d3.event,id:i}),d3.event.stopPropagation()}),R.select("path").transition().attr("d",N).attrTween("d",k),m){var V=d3.svg.arc().innerRadius(0);if(n)var V=N;o&&(V=d3.svg.arc().outerRadius(N.outerRadius())),S.enter().append("g").classed("nv-label",!0).each(function(a,b){var c=d3.select(this);c.attr("transform",function(a){if(v){a.outerRadius=G+10,a.innerRadius=G+15;var b=(a.startAngle+a.endAngle)/2*(180/Math.PI);return(a.startAngle+a.endAngle)/2q?d[p]:""})}}),C.renderEnd("pie immediate"),b}var c={top:0,right:0,bottom:0,left:0},e=500,f=500,g=function(a){return a.x},h=function(a){return a.y},i=Math.floor(1e4*Math.random()),j=a.utils.defaultColor(),k=d3.format(",.2f"),l=d3.format("%"),m=!0,n=!0,o=!1,p="key",q=.02,r=!1,s=!1,t=!0,u=0,v=!1,w=!1,x=!1,y=!1,z=0,A=.5,B=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),C=a.utils.renderWatch(B);return b.dispatch=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return e},set:function(a){e=a}},height:{get:function(){return f},set:function(a){f=a}},showLabels:{get:function(){return m},set:function(a){m=a}},title:{get:function(){return s},set:function(a){s=a}},titleOffset:{get:function(){return u},set:function(a){u=a}},labelThreshold:{get:function(){return q},set:function(a){q=a}},labelFormat:{get:function(){return l},set:function(a){l=a}},valueFormat:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return g},set:function(a){g=a}},id:{get:function(){return i},set:function(a){i=a}},endAngle:{get:function(){return y},set:function(a){y=a}},startAngle:{get:function(){return w},set:function(a){w=a}},padAngle:{get:function(){return x},set:function(a){x=a}},cornerRadius:{get:function(){return z},set:function(a){z=a}},donutRatio:{get:function(){return A},set:function(a){A=a}},pieLabelsOutside:{get:function(){return n},set:function(a){n=a}},donutLabelsOutside:{get:function(){return o},set:function(a){o=a}},labelSunbeamLayout:{get:function(){return v},set:function(a){v=a}},donut:{get:function(){return r},set:function(a){r=a}},growOnHover:{get:function(){return t},set:function(a){t=a}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},y:{get:function(){return h},set:function(a){h=d3.functor(a)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},labelType:{get:function(){return p},set:function(a){p=a||"key"}}}),a.utils.initOptions(b),b},a.models.pieChart=function(){"use strict";function b(i){return r.reset(),r.models(c),i.each(function(i){var j=d3.select(this);a.utils.initSVG(j);var k=(f||parseInt(j.style("width"),10)||960)-e.left-e.right,o=(g||parseInt(j.style("height"),10)||400)-e.top-e.bottom;if(b.update=function(){j.transition().call(b)},b.container=this,l.setter(t(i),b.update).getter(s(i)).update(),l.disabled=i.map(function(a){return!!a.disabled}),!m){var q;m={};for(q in l)l[q]instanceof Array?m[q]=l[q].slice(0):m[q]=l[q]}if(!i||!i.length){var r=j.selectAll(".nv-noData").data([n]);return r.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),r.attr("x",e.left+k/2).attr("y",e.top+o/2).text(function(a){return a}),b}j.selectAll(".nv-noData").remove();var u=j.selectAll("g.nv-wrap.nv-pieChart").data([i]),v=u.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),w=u.select("g");v.append("g").attr("class","nv-pieWrap"),v.append("g").attr("class","nv-legendWrap"),h&&(d.width(k).key(c.x()),u.select(".nv-legendWrap").datum(i).call(d),e.top!=d.height()&&(e.top=d.height(),o=(g||parseInt(j.style("height"))||400)-e.top-e.bottom),u.select(".nv-legendWrap").attr("transform","translate(0,"+-e.top+")")),u.attr("transform","translate("+e.left+","+e.top+")"),c.width(k).height(o);var x=w.select(".nv-pieWrap").datum([i]);d3.transition(x).call(c),d.dispatch.on("stateChange",function(a){for(var c in a)l[c]=a[c];p.stateChange(l),b.update()}),c.dispatch.on("elementMouseout.tooltip",function(a){p.tooltipHide(a)}),p.on("changeState",function(a){"undefined"!=typeof a.disabled&&(i.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),r.renderEnd("pieChart immediate"),b}var c=a.models.pie(),d=a.models.legend(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=!0,i=a.utils.defaultColor(),j=!0,k=function(a,b,c,d){return'

'+a+"

"+b+"

"},l=a.utils.state(),m=null,n="No Data Available.",o=250,p=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),q=function(d,e){var f=c.x()(d.point),g=d.pos[0]+(e&&e.offsetLeft||0),h=d.pos[1]+(e&&e.offsetTop||0),i=c.valueFormat()(c.y()(d.point)),j=k(f,i,d,b);a.tooltip.show([g,h],j,d.value<0?"n":"s",null,e)},r=a.utils.renderWatch(p),s=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},t=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+e.left,a.pos[1]+e.top],p.tooltipShow(a)}),p.on("tooltipShow",function(a){j&&q(a)}),p.on("tooltipHide",function(){j&&a.tooltip.cleanup()}),b.legend=d,b.dispatch=p,b.pie=c,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return n},set:function(a){n=a}},tooltipContent:{get:function(){return k},set:function(a){k=a}},tooltips:{get:function(){return j},set:function(a){j=a}},showLegend:{get:function(){return h},set:function(a){h=a}},defaultState:{get:function(){return m},set:function(a){m=a}},color:{get:function(){return i},set:function(a){i=a,d.color(i),c.color(i)}},duration:{get:function(){return o},set:function(a){o=a,r.reset(o)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.scatter=function(){"use strict";function b(L){return N.reset(),L.each(function(b){function L(){if(!v)return!1;var a=d3.merge(b.map(function(a,b){return a.values.map(function(a,c){var d=o(a,c),e=p(a,c);return[l(d)+1e-7*Math.random(),m(e)+1e-7*Math.random(),b,c,a]}).filter(function(a,b){return w(a[4],b)})}));if(K===!0){a.length<3&&(a.push([l.range()[0]-20,m.range()[0]-20,null,null]),a.push([l.range()[1]+20,m.range()[1]+20,null,null]),a.push([l.range()[0]-20,m.range()[0]+20,null,null]),a.push([l.range()[1]+20,m.range()[1]-20,null,null]));var c=d3.geom.polygon([[-10,-10],[-10,i+10],[h+10,i+10],[h+10,-10]]),d=d3.geom.voronoi(a).map(function(b,d){return{data:c.clip(b),series:a[d][2],point:a[d][3]}});S.select(".nv-point-paths").selectAll("path").remove();var e=S.select(".nv-point-paths").selectAll("path").data(d);if(e.enter().append("svg:path").attr("d",function(a){return a&&a.data&&0!==a.data.length?"M"+a.data.join(",")+"Z":"M 0 0"}).attr("id",function(a,b){return"nv-path-"+b}).attr("clip-path",function(a,b){return"url(#nv-clip-"+b+")"}),A){var f=S.append("svg:g").attr("id","nv-point-clips");f.selectAll("clipPath").data(a).enter().append("svg:clipPath").attr("id",function(a,b){return"nv-clip-"+b}).append("svg:circle").attr("cx",function(a){return a[0]}).attr("cy",function(a){return a[1]}).attr("r",B)}var j=function(a,c){if(M)return 0;var d=b[a.series];if("undefined"!=typeof d){var e=d.values[a.point];c({point:e,series:d,pos:[l(o(e,a.point))+g.left,m(p(e,a.point))+g.top],seriesIndex:a.series,pointIndex:a.point})}};e.on("click",function(a){j(a,J.elementClick)}).on("dblclick",function(a){j(a,J.elementDblClick)}).on("mouseover",function(a){j(a,J.elementMouseover)}).on("mouseout",function(a,b){j(a,J.elementMouseout)})}else S.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(a,c){if(M||!b[a.series])return 0;var d=b[a.series],e=d.values[c];J.elementClick({point:e,series:d,pos:[l(o(e,c))+g.left,m(p(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("mouseover",function(a,c){if(M||!b[a.series])return 0;var d=b[a.series],e=d.values[c];J.elementMouseover({point:e,series:d,pos:[l(o(e,c))+g.left,m(p(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("mouseout",function(a,c){if(M||!b[a.series])return 0;var d=b[a.series],e=d.values[c];J.elementMouseout({point:e,series:d,seriesIndex:a.series,pointIndex:c})});M=!1}var O=d3.select(this),P=(h||parseInt(O.style("width"))||960)-g.left-g.right,Q=(i||parseInt(O.style("height"))||400)-g.top-g.bottom;a.utils.initSVG(O),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var R=C&&D&&G?[]:d3.merge(b.map(function(a){return a.values.map(function(a,b){return{x:o(a,b),y:p(a,b),size:q(a,b)}})}));l.domain(C||d3.extent(R.map(function(a){return a.x}).concat(s))),l.range(x&&b[0]?E||[(P*y+P)/(2*b[0].values.length),P-P*(1+y)/(2*b[0].values.length)]:E||[0,P]),m.domain(D||d3.extent(R.map(function(a){return a.y}).concat(t))).range(F||[Q,0]),n.domain(G||d3.extent(R.map(function(a){return a.size}).concat(u))).range(H||[16,256]),(l.domain()[0]===l.domain()[1]||m.domain()[0]===m.domain()[1])&&(I=!0),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),isNaN(l.domain()[0])&&l.domain([-1,1]),isNaN(m.domain()[0])&&m.domain([-1,1]),c=c||l,d=d||m,e=e||n;var S=O.selectAll("g.nv-wrap.nv-scatter").data([b]),T=S.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+k+(I?" nv-single-point":"")),U=T.append("defs"),V=T.append("g"),W=S.select("g");V.append("g").attr("class","nv-groups"),V.append("g").attr("class","nv-point-paths"),S.attr("transform","translate("+g.left+","+g.top+")"),U.append("clipPath").attr("id","nv-edge-clip-"+k).append("rect"),S.select("#nv-edge-clip-"+k+" rect").attr("width",P>0?P:0).attr("height",Q>0?Q:0),W.attr("clip-path",z?"url(#nv-edge-clip-"+k+")":""),M=!0;var X=S.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});X.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),X.exit().remove(),X.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),X.watchTransition(N,"scatter: groups").style("fill",function(a,b){return j(a,b)}).style("stroke",function(a,b){return j(a,b)}).style("stroke-opacity",1).style("fill-opacity",.5);var Y=X.selectAll("path.nv-point").data(function(a){return a.values});Y.enter().append("path").style("fill",function(a,b){return a.color}).style("stroke",function(a,b){return a.color}).attr("transform",function(a,b){return"translate("+c(o(a,b))+","+d(p(a,b))+")"}).attr("d",a.utils.symbol().type(r).size(function(a,b){return n(q(a,b))})),Y.exit().remove(),X.exit().selectAll("path.nv-point").watchTransition(N,"scatter exit").attr("transform",function(a,b){return"translate("+l(o(a,b))+","+m(p(a,b))+")"}).remove(),Y.each(function(a,b){d3.select(this).classed("nv-point",!0).classed("nv-point-"+b,!0).classed("hover",!1)}),Y.watchTransition(N,"scatter points").attr("transform",function(a,b){return"translate("+l(o(a,b))+","+m(p(a,b))+")"}).attr("d",a.utils.symbol().type(r).size(function(a,b){return n(q(a,b))})),clearTimeout(f),f=setTimeout(L,300),c=l.copy(),d=m.copy(),e=n.copy()}),N.renderEnd("scatter immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=a.utils.defaultColor(),k=Math.floor(1e5*Math.random()),l=d3.scale.linear(),m=d3.scale.linear(),n=d3.scale.linear(),o=function(a){return a.x},p=function(a){return a.y},q=function(a){return a.size||1},r=function(a){return a.shape||"circle"},s=[],t=[],u=[],v=!0,w=function(a){return!a.notActive},x=!1,y=.1,z=!1,A=!0,B=function(){return 25},C=null,D=null,E=null,F=null,G=null,H=null,I=!1,J=d3.dispatch("elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),K=!0,L=250,M=!1,N=a.utils.renderWatch(J,L);return b.dispatch=J,b.options=a.utils.optionsFunc.bind(b),b._calls=new function(){this.clearHighlights=function(){return d3.selectAll(".nv-chart-"+k+" .nv-point.hover").classed("hover",!1),null},this.highlightPoint=function(a,b,c){d3.select(".nv-chart-"+k+" .nv-series-"+a+" .nv-point-"+b).classed("hover",c)}},J.on("elementMouseover.point",function(a){v&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!0)}),J.on("elementMouseout.point",function(a){v&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!1)}),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},pointScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return C},set:function(a){C=a}},yDomain:{get:function(){return D},set:function(a){D=a}},pointDomain:{get:function(){return G},set:function(a){G=a}},xRange:{get:function(){return E},set:function(a){E=a}},yRange:{get:function(){return F},set:function(a){F=a}},pointRange:{get:function(){return H},set:function(a){H=a}},forceX:{get:function(){return s},set:function(a){s=a}},forceY:{get:function(){return t},set:function(a){t=a}},forcePoint:{get:function(){return u},set:function(a){u=a}},interactive:{get:function(){return v},set:function(a){v=a}},pointActive:{get:function(){return w},set:function(a){w=a}},padDataOuter:{get:function(){return y},set:function(a){y=a}},padData:{get:function(){return x},set:function(a){x=a}},clipEdge:{get:function(){return z},set:function(a){z=a}},clipVoronoi:{get:function(){return A},set:function(a){A=a}},clipRadius:{get:function(){return B},set:function(a){B=a}},id:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return o},set:function(a){o=d3.functor(a)}},y:{get:function(){return p},set:function(a){p=d3.functor(a)}},pointSize:{get:function(){return q},set:function(a){q=d3.functor(a)}},pointShape:{get:function(){return r},set:function(a){r=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},duration:{get:function(){return L},set:function(a){L=a,N.reset(L)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},useVoronoi:{get:function(){return K},set:function(a){K=a,K===!1&&(A=!1)}}}),a.utils.initOptions(b),b},a.models.scatterChart=function(){"use strict";function b(v){return F.reset(),F.models(c),r&&F.models(d),s&&F.models(e),o&&F.models(g),p&&F.models(h),v.each(function(v){var w=d3.select(this),x=this;a.utils.initSVG(w);var J=(j||parseInt(w.style("width"))||960)-i.left-i.right,K=(k||parseInt(w.style("height"))||400)-i.top-i.bottom;if(b.update=function(){0===C?w.call(b):w.transition().duration(C).call(b)},b.container=this,y.setter(I(v),b.update).getter(H(v)).update(),y.disabled=v.map(function(a){return!!a.disabled}),!z){var L;z={};for(L in y)y[L]instanceof Array?z[L]=y[L].slice(0):z[L]=y[L]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length)){var M=w.selectAll(".nv-noData").data([B]);return M.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),M.attr("x",i.left+J/2).attr("y",i.top+K/2).text(function(a){return a}),F.renderEnd("scatter immediate"),b}w.selectAll(".nv-noData").remove(),m=c.xScale(),n=c.yScale();var N=w.selectAll("g.nv-wrap.nv-scatterChart").data([v]),O=N.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+c.id()),P=O.append("g"),Q=N.select("g");P.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),P.append("g").attr("class","nv-x nv-axis"),P.append("g").attr("class","nv-y nv-axis"),P.append("g").attr("class","nv-scatterWrap"),P.append("g").attr("class","nv-regressionLinesWrap"), -P.append("g").attr("class","nv-distWrap"),P.append("g").attr("class","nv-legendWrap"),N.attr("transform","translate("+i.left+","+i.top+")"),t&&Q.select(".nv-y.nv-axis").attr("transform","translate("+J+",0)"),q&&(f.width(J/2),N.select(".nv-legendWrap").datum(v).call(f),i.top!=f.height()&&(i.top=f.height(),K=(k||parseInt(w.style("height"))||400)-i.top-i.bottom),N.select(".nv-legendWrap").attr("transform","translate("+J/2+","+-i.top+")")),c.width(J).height(K).color(v.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!v[b].disabled})),N.select(".nv-scatterWrap").datum(v.filter(function(a){return!a.disabled})).call(c),N.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+c.id()+")");var R=N.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});R.enter().append("g").attr("class","nv-regLines");var S=R.selectAll(".nv-regLine").data(function(a){return[a]});S.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),S.filter(function(a){return a.intercept&&a.slope}).watchTransition(F,"scatterPlusLineChart: regline").attr("x1",m.range()[0]).attr("x2",m.range()[1]).attr("y1",function(a,b){return n(m.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a,b){return n(m.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return l(a,c)}).style("stroke-opacity",function(a,b){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),r&&(d.scale(m).ticks(d.ticks()?d.ticks():a.utils.calcTicksX(J/100,v)).tickSize(-K,0),Q.select(".nv-x.nv-axis").attr("transform","translate(0,"+n.range()[0]+")").call(d)),s&&(e.scale(n).ticks(e.ticks()?e.ticks():a.utils.calcTicksY(K/36,v)).tickSize(-J,0),Q.select(".nv-y.nv-axis").call(e)),o&&(g.getData(c.x()).scale(m).width(J).color(v.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!v[b].disabled})),P.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),Q.select(".nv-distributionX").attr("transform","translate(0,"+n.range()[0]+")").datum(v.filter(function(a){return!a.disabled})).call(g)),p&&(h.getData(c.y()).scale(n).width(K).color(v.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!v[b].disabled})),P.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),Q.select(".nv-distributionY").attr("transform","translate("+(t?J:-h.size())+",0)").datum(v.filter(function(a){return!a.disabled})).call(h)),f.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];A.stateChange(y),b.update()}),c.dispatch.on("elementMouseover.tooltip",function(a){d3.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.pos[1]-K),d3.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.pos[0]+g.size()),a.pos=[a.pos[0]+i.left,a.pos[1]+i.top],A.tooltipShow(a)}),A.on("tooltipShow",function(a){u&&G(a,x.parentNode)}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),b.update()}),D=m.copy(),E=n.copy()}),F.renderEnd("scatter with line immediate"),b}var c=a.models.scatter(),d=a.models.axis(),e=a.models.axis(),f=a.models.legend(),g=a.models.distribution(),h=a.models.distribution(),i={top:30,right:20,bottom:50,left:75},j=null,k=null,l=a.utils.defaultColor(),m=c.xScale(),n=c.yScale(),o=!1,p=!1,q=!0,r=!0,s=!0,t=!1,u=!0,v=function(a,b,c){return""+b+""},w=function(a,b,c){return""+c+""},x=function(a,b,c,d){return"

"+a+"

"+d+"

"},y=a.utils.state(),z=null,A=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),B="No Data Available.",C=250;c.xScale(m).yScale(n),d.orient("bottom").tickPadding(10),e.orient(t?"right":"left").tickPadding(10),g.axis("x"),h.axis("y");var D,E,F=a.utils.renderWatch(A,C),G=function(f,g){var h=f.pos[0]+(g.offsetLeft||0),j=f.pos[1]+(g.offsetTop||0),k=f.pos[0]+(g.offsetLeft||0),l=n.range()[0]+i.top+(g.offsetTop||0),o=m.range()[0]+i.left+(g.offsetLeft||0),p=f.pos[1]+(g.offsetTop||0),q=d.tickFormat()(c.x()(f.point,f.pointIndex)),r=e.tickFormat()(c.y()(f.point,f.pointIndex));null!=v&&a.tooltip.show([k,l],v(f.series.key,q,r,f,b),"n",1,g,"x-nvtooltip"),null!=w&&a.tooltip.show([o,p],w(f.series.key,q,r,f,b),"e",1,g,"y-nvtooltip"),null!=x&&a.tooltip.show([h,j],x(f.series.key,q,r,f.point.tooltip,f,b),f.value<0?"n":"s",null,g)},H=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},I=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseout.tooltip",function(a){A.tooltipHide(a),d3.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),d3.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",h.size())}),A.on("tooltipHide",function(){u&&a.tooltip.cleanup()}),b.dispatch=A,b.scatter=c,b.legend=f,b.xAxis=d,b.yAxis=e,b.distX=g,b.distY=h,b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},showDistX:{get:function(){return o},set:function(a){o=a}},showDistY:{get:function(){return p},set:function(a){p=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},tooltips:{get:function(){return u},set:function(a){u=a}},tooltipContent:{get:function(){return x},set:function(a){x=a}},tooltipXContent:{get:function(){return v},set:function(a){v=a}},tooltipYContent:{get:function(){return w},set:function(a){w=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return B},set:function(a){B=a}},duration:{get:function(){return C},set:function(a){C=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,e.orient(a?"right":"left")}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),f.color(l),g.color(l),h.color(l)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sparkline=function(){"use strict";function b(j){return j.each(function(b){var j=h-g.left-g.right,p=i-g.top-g.bottom,q=d3.select(this);a.utils.initSVG(q),k.domain(c||d3.extent(b,m)).range(e||[0,j]),l.domain(d||d3.extent(b,n)).range(f||[p,0]);{var r=q.selectAll("g.nv-wrap.nv-sparkline").data([b]),s=r.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");s.append("g"),r.select("g")}r.attr("transform","translate("+g.left+","+g.top+")");var t=r.selectAll("path").data(function(a){return[a]});t.enter().append("path"),t.exit().remove(),t.style("stroke",function(a,b){return a.color||o(a,b)}).attr("d",d3.svg.line().x(function(a,b){return k(m(a,b))}).y(function(a,b){return l(n(a,b))}));var u=r.selectAll("circle.nv-point").data(function(a){function b(b){if(-1!=b){var c=a[b];return c.pointIndex=b,c}return null}var c=a.map(function(a,b){return n(a,b)}),d=b(c.lastIndexOf(l.domain()[1])),e=b(c.indexOf(l.domain()[0])),f=b(c.length-1);return[e,d,f].filter(function(a){return null!=a})});u.enter().append("circle"),u.exit().remove(),u.attr("cx",function(a,b){return k(m(a,a.pointIndex))}).attr("cy",function(a,b){return l(n(a,a.pointIndex))}).attr("r",2).attr("class",function(a,b){return m(a,a.pointIndex)==k.domain()[1]?"nv-point nv-currentValue":n(a,a.pointIndex)==l.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),b}var c,d,e,f,g={top:2,right:0,bottom:2,left:0},h=400,i=32,j=!0,k=d3.scale.linear(),l=d3.scale.linear(),m=function(a){return a.x},n=function(a){return a.y},o=a.utils.getColor(["#000"]);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},xScale:{get:function(){return k},set:function(a){k=a}},yScale:{get:function(){return l},set:function(a){l=a}},animate:{get:function(){return j},set:function(a){j=a}},x:{get:function(){return m},set:function(a){m=d3.functor(a)}},y:{get:function(){return n},set:function(a){n=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sparklinePlus=function(){"use strict";function b(m){return m.each(function(q){function r(){if(!j){var a=B.selectAll(".nv-hoverValue").data(i),b=a.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);a.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),a.attr("transform",function(a){return"translate("+c(e.x()(q[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(b.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",v),b.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),B.select(".nv-hoverValue .nv-xValue").text(k(e.x()(q[i[0]],i[0]))),b.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),B.select(".nv-hoverValue .nv-yValue").text(l(e.y()(q[i[0]],i[0]))))}}function s(){function a(a,b){for(var c=Math.abs(e.x()(a[0],0)-b),d=0,f=0;fc;++c){for(b=0,d=0;bb;b++)a[b][c][1]/=d;else for(b=0;e>b;b++)a[b][c][1]=g}for(c=0;f>c;++c)h[c]=0;return h}}),t.renderEnd("stackedArea immediate"),b}var c,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=a.utils.defaultColor(),i=Math.floor(1e5*Math.random()),j=function(a){return a.x},k=function(a){return a.y},l="stack",m="zero",n="default",o="linear",p=!1,q=a.models.scatter(),r=250,s=d3.dispatch("tooltipShow","tooltipHide","areaClick","areaMouseover","areaMouseout","renderEnd");q.interactive(!1),q.pointSize(2.2).pointDomain([2.2,2.2]);var t=a.utils.renderWatch(s,r);return q.dispatch.on("elementClick.area",function(a){s.areaClick(a)}),q.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+e.left,a.pos[1]+e.top],s.tooltipShow(a)}),q.dispatch.on("elementMouseout.tooltip",function(a){s.tooltipHide(a)}),b.dispatch=s,b.scatter=q,b.interpolate=function(a){return arguments.length?(o=a,b):o},b.duration=function(a){return arguments.length?(r=a,t.reset(r),q.duration(r),b):r},b.dispatch=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return f},set:function(a){f=a}},height:{get:function(){return g},set:function(a){g=a}},clipEdge:{get:function(){return p},set:function(a){p=a}},offset:{get:function(){return m},set:function(a){m=a}},order:{get:function(){return n},set:function(a){n=a}},interpolate:{get:function(){return o},set:function(a){o=a}},x:{get:function(){return j},set:function(a){j=d3.functor(a)}},y:{get:function(){return k},set:function(a){k=d3.functor(a)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},style:{get:function(){return l},set:function(a){switch(l=a){case"stack":b.offset("zero"),b.order("default");break;case"stream":b.offset("wiggle"),b.order("inside-out");break;case"stream-center":b.offset("silhouette"),b.order("inside-out");break;case"expand":b.offset("expand"),b.order("default");break;case"stack_percent":b.offset(b.d3_stackedOffset_stackPercent),b.order("default")}}},duration:{get:function(){return r},set:function(a){r=a,t.reset(r),q.duration(r)}}}),a.utils.inheritOptions(b,q),a.utils.initOptions(b),b},a.models.stackedAreaChart=function(){"use strict";function b(v){return F.reset(),F.models(e),q&&F.models(f),r&&F.models(g),v.each(function(v){var F=d3.select(this),K=this;a.utils.initSVG(F);var L=(l||parseInt(F.style("width"))||960)-k.left-k.right,M=(m||parseInt(F.style("height"))||400)-k.top-k.bottom;if(b.update=function(){F.transition().duration(E).call(b)},b.container=this,x.setter(J(v),b.update).getter(I(v)).update(),x.disabled=v.map(function(a){return!!a.disabled}),!y){var N;y={};for(N in x)x[N]instanceof Array?y[N]=x[N].slice(0):y[N]=x[N]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length)){var O=F.selectAll(".nv-noData").data([z]);return O.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),O.attr("x",k.left+L/2).attr("y",k.top+M/2).text(function(a){return a}),b}F.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var P=F.selectAll("g.nv-wrap.nv-stackedAreaChart").data([v]),Q=P.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),R=P.select("g");if(Q.append("rect").style("opacity",0),Q.append("g").attr("class","nv-x nv-axis"),Q.append("g").attr("class","nv-y nv-axis"),Q.append("g").attr("class","nv-stackedWrap"),Q.append("g").attr("class","nv-legendWrap"),Q.append("g").attr("class","nv-controlsWrap"),Q.append("g").attr("class","nv-interactive"),R.select("rect").attr("width",L).attr("height",M),p){var S=o?L-B:L;h.width(S),R.select(".nv-legendWrap").datum(v).call(h),k.top!=h.height()&&(k.top=h.height(),M=(m||parseInt(F.style("height"))||400)-k.top-k.bottom),R.select(".nv-legendWrap").attr("transform","translate("+(L-S)+","+-k.top+")")}if(o){var T=[{key:D.stacked||"Stacked",metaKey:"Stacked",disabled:"stack"!=e.style(),style:"stack"},{key:D.stream||"Stream",metaKey:"Stream",disabled:"stream"!=e.style(),style:"stream"},{key:D.expanded||"Expanded",metaKey:"Expanded",disabled:"expand"!=e.style(),style:"expand"},{key:D.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:"stack_percent"!=e.style(),style:"stack_percent"}];B=C.length/3*260,T=T.filter(function(a){return-1!==C.indexOf(a.metaKey)}),i.width(B).color(["#444","#444","#444"]),R.select(".nv-controlsWrap").datum(T).call(i),k.top!=Math.max(i.height(),h.height())&&(k.top=Math.max(i.height(),h.height()),M=(m||parseInt(F.style("height"))||400)-k.top-k.bottom),R.select(".nv-controlsWrap").attr("transform","translate(0,"+-k.top+")")}P.attr("transform","translate("+k.left+","+k.top+")"),s&&R.select(".nv-y.nv-axis").attr("transform","translate("+L+",0)"),t&&(j.width(L).height(M).margin({left:k.left,top:k.top}).svgContainer(F).xScale(c),P.select(".nv-interactive").call(j)),e.width(L).height(M);var U=R.select(".nv-stackedWrap").datum(v);U.transition().call(e),q&&(f.scale(c).ticks(a.utils.calcTicksX(L/100,v)).tickSize(-M,0),R.select(".nv-x.nv-axis").attr("transform","translate(0,"+M+")"),R.select(".nv-x.nv-axis").transition().duration(0).call(f)),r&&(g.scale(d).ticks("wiggle"==e.offset()?0:a.utils.calcTicksY(M/36,v)).tickSize(-L,0).setTickFormat("expand"==e.style()||"stack_percent"==e.style()?d3.format("%"):w),R.select(".nv-y.nv-axis").transition().duration(0).call(g)),e.dispatch.on("areaClick.toggle",function(a){v.forEach(1===v.filter(function(a){return!a.disabled}).length?function(a){a.disabled=!1}:function(b,c){b.disabled=c!=a.seriesIndex}),x.disabled=v.map(function(a){return!!a.disabled}),A.stateChange(x),b.update()}),h.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];A.stateChange(x),b.update()}),i.dispatch.on("legendClick",function(a,c){a.disabled&&(T=T.map(function(a){return a.disabled=!0,a}),a.disabled=!1,e.style(a.style),x.style=e.style(),A.stateChange(x),b.update())}),j.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,h,i,l=[];if(v.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=a.interactiveBisect(f.values,c.pointXValue,b.x()),e.highlightPoint(g,h,!0);var j=f.values[h];if("undefined"!=typeof j){"undefined"==typeof d&&(d=j),"undefined"==typeof i&&(i=b.xScale()(b.x()(j,h)));var k="expand"==e.style()?j.display.y:b.y()(j,h);l.push({key:f.key,value:k,color:n(f,f.seriesIndex),stackedValue:j.display})}}),l.reverse(),l.length>2){var m=b.yScale().invert(c.mouseY),o=null;l.forEach(function(a,b){m=Math.abs(m);var c=Math.abs(a.stackedValue.y0),d=Math.abs(a.stackedValue.y);return m>=c&&d+c>=m?void(o=b):void 0}),null!=o&&(l[o].highlight=!0)}var p=f.tickFormat()(b.x()(d,h)),q="expand"==e.style()?function(a,b){return d3.format(".1%")(a)}:function(a,b){return g.tickFormat()(a)};j.tooltip.position({left:i+k.left,top:c.mouseY+k.top}).chartContainer(K.parentNode).enabled(u).valueFormatter(q).data({value:p,series:l})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(a){A.tooltipHide(),e.clearHighlights()}),A.on("tooltipShow",function(a){u&&H(a,K.parentNode)}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&v.length===a.disabled.length&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),"undefined"!=typeof a.style&&(e.style(a.style),G=a.style),b.update()})}),F.renderEnd("stacked Area chart immediate"),b}var c,d,e=a.models.stackedArea(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.interactiveGuideline(),k={top:30,right:25,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p=!0,q=!0,r=!0,s=!1,t=!1,u=!0,v=function(a,b,c,d,e){return"

"+a+"

"+c+" on "+b+"

"},w=d3.format(",.2f"),x=a.utils.state(),y=null,z="No Data Available.",A=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),B=250,C=["Stacked","Stream","Expanded"],D={},E=250;x.style=e.style(),f.orient("bottom").tickPadding(7),g.orient(s?"right":"left"),i.updateState(!1);var F=a.utils.renderWatch(A),G=e.style(),H=function(c,d){var h=c.pos[0]+(d.offsetLeft||0),i=c.pos[1]+(d.offsetTop||0),j=f.tickFormat()(e.x()(c.point,c.pointIndex)),k=g.tickFormat()(e.y()(c.point,c.pointIndex)),l=v(c.series.key,j,k,c,b);a.tooltip.show([h,i],l,c.value<0?"n":"s",null,d)},I=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),style:e.style()}}},J=function(a){return function(b){void 0!==b.style&&(G=b.style),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("tooltipShow",function(a){a.pos=[a.pos[0]+k.left,a.pos[1]+k.top],A.tooltipShow(a)}),e.dispatch.on("tooltipHide",function(a){A.tooltipHide(a)}),A.on("tooltipHide",function(){u&&a.tooltip.cleanup()}),b.dispatch=A,b.stacked=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.interactiveLayer=j,g.setTickFormat=g.tickFormat,b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},tooltips:{get:function(){return u},set:function(a){u=a}},tooltipContent:{get:function(){return v},set:function(a){v=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return D},set:function(a){D=a}},yAxisTickFormat:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return E},set:function(a){E=a,F.reset(E),e.duration(E),f.duration(E),g.duration(E)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n),e.color(n)}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,g.orient(s?"right":"left")}},useInteractiveGuideline:{get:function(){return t},set:function(a){t=!!a,a&&(b.interactive(!1),b.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.version="1.7.1"}(); \ No newline at end of file +!function(){var a={};a.dev=!1,a.tooltip=a.tooltip||{},a.utils=a.utils||{},a.models=a.models||{},a.charts={},a.logs={},a.dom={},a.dispatch=d3.dispatch("render_start","render_end"),Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d&&a?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),a.dev&&(a.dispatch.on("render_start",function(b){a.logs.startTime=+new Date}),a.dispatch.on("render_end",function(b){a.logs.endTime=+new Date,a.logs.totalTime=a.logs.endTime-a.logs.startTime,a.log("total",a.logs.totalTime)})),a.log=function(){if(a.dev&&window.console&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(a.dev&&window.console&&"function"==typeof console.log&&Function.prototype.bind){var b=Function.prototype.bind.call(console.log,console);b.apply(console,arguments)}return arguments[arguments.length-1]},a.deprecated=function(a,b){console&&console.warn&&console.warn("nvd3 warning: `"+a+"` has been deprecated. ",b||"")},a.render=function(b){b=b||1,a.render.active=!0,a.dispatch.render_start();var c=function(){for(var d,e,f=0;b>f&&(e=a.render.queue[f]);f++)d=e.generate(),typeof e.callback==typeof Function&&e.callback(d);a.render.queue.splice(0,f),a.render.queue.length?setTimeout(c):(a.dispatch.render_end(),a.render.active=!1)};setTimeout(c)},a.render.active=!1,a.render.queue=[],a.addGraph=function(b){typeof arguments[0]==typeof Function&&(b={generate:arguments[0],callback:arguments[1]}),a.render.queue.push(b),a.render.active||a.render()},"undefined"!=typeof module&&"undefined"!=typeof exports&&(module.exports=a),"undefined"!=typeof window&&(window.nv=a),a.dom.write=function(a){return void 0!==window.fastdom?fastdom.write(a):a()},a.dom.read=function(a){return void 0!==window.fastdom?fastdom.read(a):a()},a.interactiveGuideline=function(){"use strict";function b(l){l.each(function(l){function m(){var a=d3.mouse(this),d=a[0],e=a[1],h=!0,i=!1;if(k&&(d=d3.event.offsetX,e=d3.event.offsetY,"svg"!==d3.event.target.tagName&&(h=!1),d3.event.target.className.baseVal.match("nv-legend")&&(i=!0)),h&&(d-=c.left,e-=c.top),0>d||0>e||d>o||e>p||d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement||i){if(k&&d3.event.relatedTarget&&void 0===d3.event.relatedTarget.ownerSVGElement&&(void 0===d3.event.relatedTarget.className||d3.event.relatedTarget.className.match(j.nvPointerEventsClass)))return;return g.elementMouseout({mouseX:d,mouseY:e}),b.renderGuideLine(null),void j.hidden(!0)}j.hidden(!1);var l=f.invert(d);g.elementMousemove({mouseX:d,mouseY:e,pointXValue:l}),"dblclick"===d3.event.type&&g.elementDblclick({mouseX:d,mouseY:e,pointXValue:l}),"click"===d3.event.type&&g.elementClick({mouseX:d,mouseY:e,pointXValue:l}),"mousedown"===d3.event.type&&g.elementMouseDown({mouseX:d,mouseY:e,pointXValue:l}),"mouseup"===d3.event.type&&g.elementMouseUp({mouseX:d,mouseY:e,pointXValue:l})}var n=d3.select(this),o=d||960,p=e||400,q=n.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([l]),r=q.enter().append("g").attr("class"," nv-wrap nv-interactiveLineLayer");r.append("g").attr("class","nv-interactiveGuideLine"),i&&(i.on("touchmove",m).on("mousemove",m,!0).on("mouseout",m,!0).on("mousedown",m,!0).on("mouseup",m,!0).on("dblclick",m).on("click",m),b.guideLine=null,b.renderGuideLine=function(c){h&&(b.guideLine&&b.guideLine.attr("x1")===c||a.dom.write(function(){var b=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=c?[a.utils.NaNtoZero(c)]:[],String);b.enter().append("line").attr("class","nv-guideline").attr("x1",function(a){return a}).attr("x2",function(a){return a}).attr("y1",p).attr("y2",0),b.exit().remove()}))})})}var c={left:0,top:0},d=null,e=null,f=d3.scale.linear(),g=d3.dispatch("elementMousemove","elementMouseout","elementClick","elementDblclick","elementMouseDown","elementMouseUp"),h=!0,i=null,j=a.models.tooltip(),k="ActiveXObject"in window;return j.duration(0).hideDelay(0).hidden(!1),b.dispatch=g,b.tooltip=j,b.margin=function(a){return arguments.length?(c.top="undefined"!=typeof a.top?a.top:c.top,c.left="undefined"!=typeof a.left?a.left:c.left,b):c},b.width=function(a){return arguments.length?(d=a,b):d},b.height=function(a){return arguments.length?(e=a,b):e},b.xScale=function(a){return arguments.length?(f=a,b):f},b.showGuideLine=function(a){return arguments.length?(h=a,b):h},b.svgContainer=function(a){return arguments.length?(i=a,b):i},b},a.interactiveBisect=function(a,b,c){"use strict";if(!(a instanceof Array))return null;var d;d="function"!=typeof c?function(a){return a.x}:c;var e=function(a,b){return d(a)-b},f=d3.bisector(e).left,g=d3.max([0,f(a,b)-1]),h=d(a[g]);if("undefined"==typeof h&&(h=g),h===b)return g;var i=d3.min([g+1,a.length-1]),j=d(a[i]);return"undefined"==typeof j&&(j=i),Math.abs(j-b)>=Math.abs(h-b)?g:i},a.nearestValueIndex=function(a,b,c){"use strict";var d=1/0,e=null;return a.forEach(function(a,f){var g=Math.abs(b-a);null!=a&&d>=g&&c>g&&(d=g,e=f)}),e},a.models.tooltip=function(){"use strict";function b(){if(!m){var a=j?j:document.body;m=d3.select(a).append("div").attr("class","nvtooltip "+(i?i:"xy-tooltip")).attr("id",d),m.style("top",0).style("left",0),m.style("opacity",0),m.style("position","absolute"),m.selectAll("div, table, td, tr").classed(r,!0),m.classed(r,!0)}}function c(){return o&&x(e)?(a.dom.write(function(){b();var a=w(e);a&&(m.node().innerHTML=a),z()}),c):void 0}var d="nvtooltip-"+Math.floor(1e5*Math.random()),e=null,f="w",g=25,h=0,i=null,j=null,k=!0,l=200,m=null,n={left:null,top:null},o=!0,p=100,q=!0,r="nv-pointer-events-none",s=function(){var a=j?j:document.body,b=a.getBoundingClientRect();return{left:d3.event.clientX-b.left,top:d3.event.clientY-b.top}},t=function(a,b){return a},u=function(a){return a},v=function(a,b){return a},w=function(a){if(null===a)return"";var b=d3.select(document.createElement("table"));if(q){var c=b.selectAll("thead").data([a]).enter().append("thead");c.append("tr").append("td").attr("colspan",3).append("strong").classed("x-value",!0).html(u(a.value))}var d=b.selectAll("tbody").data([a]).enter().append("tbody"),e=d.selectAll("tr").data(function(a){return a.series}).enter().append("tr").classed("highlight",function(a){return a.highlight});if(e.append("td").classed("legend-color-guide",!0).append("div").style("background-color",function(a){return a.color}),e.append("td").classed("key",!0).classed("total",function(a){return!!a.total}).html(function(a,b){return v(a.key,b)}),e.append("td").classed("value",!0).html(function(a,b){return t(a.value,b)}),e.selectAll("td").each(function(a){if(a.highlight){var b=d3.scale.linear().domain([0,1]).range(["#fff",a.color]),c=.6;d3.select(this).style("border-bottom-color",b(c)).style("border-top-color",b(c))}}),a.postMarkerTooltip){var f=d.selectAll("tfoot").data([a]).enter().append("tfoot");f.append("tr").append("td").attr("colspan",3).append("strong").html(function(a){return a.postMarkerTooltip.label}),f.append("tr").append("td").attr("colspan",3).html(function(a){return d3.time.format("%x %I %p")(a.postMarkerTooltip.postDate)})}var g=b.node().outerHTML;return void 0!==a.footer&&(g+=""),g},x=function(a){if(a&&a.series){if(a.series instanceof Array)return!!a.series.length;if(a.series instanceof Object)return a.series=[a.series],!0}return!1},y=function(a){var b,c,d,e=m.node().offsetHeight,h=m.node().offsetWidth,i=document.documentElement.clientWidth,j=document.documentElement.clientHeight;switch(f){case"e":b=-h-g,c=-(e/2),a.left+b<0&&(b=g),(d=a.top+c)<0&&(c-=d),(d=a.top+c+e)>j&&(c-=d-j);break;case"w":b=g,c=-(e/2),a.left+b+h>i&&(b=-h-g),(d=a.top+c)<0&&(c-=d),(d=a.top+c+e)>j&&(c-=d-j);break;case"n":b=-(h/2)-5,c=g,a.top+c+e>j&&(c=-e-g),(d=a.left+b)<0&&(b-=d),(d=a.left+b+h)>i&&(b-=d-i);break;case"s":b=-(h/2),c=-e-g,a.top+c<0&&(c=g),(d=a.left+b)<0&&(b-=d),(d=a.left+b+h)>i&&(b-=d-i);break;case"center":b=-(h/2),c=-(e/2);break;default:b=0,c=0}return{left:b,top:c}},z=function(){a.dom.read(function(){var a=s(),b=y(a),c=a.left+b.left,d=a.top+b.top;if(k)m.interrupt().transition().delay(l).duration(0).style("opacity",0);else{var e="translate("+n.left+"px, "+n.top+"px)",f="translate("+c+"px, "+d+"px)",g=d3.interpolateString(e,f),h=m.style("opacity")<.1;m.interrupt().transition().duration(h?0:p).styleTween("transform",function(a){return g},"important").styleTween("-webkit-transform",function(a){return g}).style("-ms-transform",f).style("opacity",1)}n.left=c,n.top=d})};return c.nvPointerEventsClass=r,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{duration:{get:function(){return p},set:function(a){p=a}},gravity:{get:function(){return f},set:function(a){f=a}},distance:{get:function(){return g},set:function(a){g=a}},snapDistance:{get:function(){return h},set:function(a){h=a}},classes:{get:function(){return i},set:function(a){i=a}},chartContainer:{get:function(){return j},set:function(a){j=a}},enabled:{get:function(){return o},set:function(a){o=a}},hideDelay:{get:function(){return l},set:function(a){l=a}},contentGenerator:{get:function(){return w},set:function(a){w=a}},valueFormatter:{get:function(){return t},set:function(a){t=a}},headerFormatter:{get:function(){return u},set:function(a){u=a}},keyFormatter:{get:function(){return v},set:function(a){v=a}},headerEnabled:{get:function(){return q},set:function(a){q=a}},position:{get:function(){return s},set:function(a){s=a}},hidden:{get:function(){return k},set:function(a){k!=a&&(k=!!a,c())}},data:{get:function(){return e},set:function(a){a.point&&(a.value=a.point.x,a.series=a.series||{},a.series.value=a.point.y,a.series.color=a.point.color||a.series.color),e=a}},node:{get:function(){return m.node()},set:function(a){}},id:{get:function(){return d},set:function(a){}}}),a.utils.initOptions(c),c},a.utils.windowSize=function(){var a={width:640,height:480};return window.innerWidth&&window.innerHeight?(a.width=window.innerWidth,a.height=window.innerHeight,a):"CSS1Compat"==document.compatMode&&document.documentElement&&document.documentElement.offsetWidth?(a.width=document.documentElement.offsetWidth,a.height=document.documentElement.offsetHeight,a):document.body&&document.body.offsetWidth?(a.width=document.body.offsetWidth,a.height=document.body.offsetHeight,a):a},a.utils.windowResize=function(b){return window.addEventListener?window.addEventListener("resize",b):a.log("ERROR: Failed to bind to window.resize with: ",b),{callback:b,clear:function(){window.removeEventListener("resize",b)}}},a.utils.getColor=function(b){if(void 0===b)return a.utils.defaultColor();if(Array.isArray(b)){var c=d3.scale.ordinal().range(b);return function(a,b){var d=void 0===b?a:b;return a.color||c(d)}}return b},a.utils.defaultColor=function(){return a.utils.getColor(d3.scale.category20().range())},a.utils.customTheme=function(a,b,c){b=b||function(a){return a.key},c=c||d3.scale.category20().range();var d=c.length;return function(e,f){var g=b(e);return"function"==typeof a[g]?a[g]():void 0!==a[g]?a[g]:(d||(d=c.length),d-=1,c[d])}},a.utils.pjax=function(b,c){var d=function(d){d3.html(d,function(d){var e=d3.select(c).node();e.parentNode.replaceChild(d3.select(d).select(c).node(),e),a.utils.pjax(b,c)})};d3.selectAll(b).on("click",function(){history.pushState(this.href,this.textContent,this.href),d(this.href),d3.event.preventDefault()}),d3.select(window).on("popstate",function(){d3.event.state&&d(d3.event.state)})},a.utils.calcApproxTextWidth=function(a){if("function"==typeof a.style&&"function"==typeof a.text){var b=parseInt(a.style("font-size").replace("px",""),10),c=a.text().length;return c*b*.5}return 0},a.utils.NaNtoZero=function(a){return"number"!=typeof a||isNaN(a)||null===a||a===1/0||a===-(1/0)?0:a},d3.selection.prototype.watchTransition=function(a){var b=[this].concat([].slice.call(arguments,1));return a.transition.apply(a,b)},a.utils.renderWatch=function(b,c){if(!(this instanceof a.utils.renderWatch))return new a.utils.renderWatch(b,c);var d=void 0!==c?c:250,e=[],f=this;this.models=function(a){return a=[].slice.call(arguments,0),a.forEach(function(a){a.__rendered=!1,function(a){a.dispatch.on("renderEnd",function(b){a.__rendered=!0,f.renderEnd("model")})}(a),e.indexOf(a)<0&&e.push(a)}),this},this.reset=function(a){void 0!==a&&(d=a),e=[]},this.transition=function(a,b,c){if(b=arguments.length>1?[].slice.call(arguments,1):[],c=b.length>1?b.pop():void 0!==d?d:250,a.__rendered=!1,e.indexOf(a)<0&&e.push(a),0===c)return a.__rendered=!0,a.delay=function(){return this},a.duration=function(){return this},a;0===a.length?a.__rendered=!0:a.every(function(a){return!a.length})?a.__rendered=!0:a.__rendered=!1;var g=0;return a.transition().duration(c).each(function(){++g}).each("end",function(c,d){0===--g&&(a.__rendered=!0,f.renderEnd.apply(this,b))})},this.renderEnd=function(){e.every(function(a){return a.__rendered})&&(e.forEach(function(a){a.__rendered=!1}),b.renderEnd.apply(this,arguments))}},a.utils.deepExtend=function(b){var c=arguments.length>1?[].slice.call(arguments,1):[];c.forEach(function(c){for(var d in c){var e=b[d]instanceof Array,f="object"==typeof b[d],g="object"==typeof c[d];f&&!e&&g?a.utils.deepExtend(b[d],c[d]):b[d]=c[d]}})},a.utils.state=function(){if(!(this instanceof a.utils.state))return new a.utils.state;var b={},c=function(){},d=function(){return{}},e=null,f=null;this.dispatch=d3.dispatch("change","set"),this.dispatch.on("set",function(a){c(a,!0)}),this.getter=function(a){return d=a,this},this.setter=function(a,b){return b||(b=function(){}),c=function(c,d){a(c),d&&b()},this},this.init=function(b){e=e||{},a.utils.deepExtend(e,b)};var g=function(){var a=d();if(JSON.stringify(a)===JSON.stringify(b))return!1;for(var c in a)void 0===b[c]&&(b[c]={}),b[c]=a[c],f=!0;return!0};this.update=function(){e&&(c(e,!1),e=null),g.call(this)&&this.dispatch.change(b)}},a.utils.optionsFunc=function(a){return a&&d3.map(a).forEach(function(a,b){"function"==typeof this[a]&&this[a](b)}.bind(this)),this},a.utils.calcTicksX=function(b,c){var d=1,e=0;for(e;ed?f:d}return a.log("Requested number of ticks: ",b),a.log("Calculated max values to be: ",d),b=b>d?b=d-1:b,b=1>b?1:b,b=Math.floor(b),a.log("Calculating tick count as: ",b),b},a.utils.calcTicksY=function(b,c){return a.utils.calcTicksX(b,c)},a.utils.initOption=function(a,b){a._calls&&a._calls[b]?a[b]=a._calls[b]:(a[b]=function(c){return arguments.length?(a._overrides[b]=!0,a._options[b]=c,a):a._options[b]},a["_"+b]=function(c){return arguments.length?(a._overrides[b]||(a._options[b]=c),a):a._options[b]})},a.utils.initOptions=function(b){b._overrides=b._overrides||{};var c=Object.getOwnPropertyNames(b._options||{}),d=Object.getOwnPropertyNames(b._calls||{});c=c.concat(d);for(var e in c)a.utils.initOption(b,c[e])},a.utils.inheritOptionsD3=function(a,b,c){a._d3options=c.concat(a._d3options||[]),c.unshift(b),c.unshift(a),d3.rebind.apply(this,c)},a.utils.arrayUnique=function(a){return a.sort().filter(function(b,c){return!c||b!=a[c-1]})},a.utils.symbolMap=d3.map(),a.utils.symbol=function(){function b(b,e){var f=c.call(this,b,e),g=d.call(this,b,e);return-1!==d3.svg.symbolTypes.indexOf(f)?d3.svg.symbol().type(f).size(g)():a.utils.symbolMap.get(f)(g)}var c,d=64;return b.type=function(a){return arguments.length?(c=d3.functor(a),b):c},b.size=function(a){return arguments.length?(d=d3.functor(a),b):d},b},a.utils.inheritOptions=function(b,c){var d=Object.getOwnPropertyNames(c._options||{}),e=Object.getOwnPropertyNames(c._calls||{}),f=c._inherited||[],g=c._d3options||[],h=d.concat(e).concat(f).concat(g);h.unshift(c),h.unshift(b),d3.rebind.apply(this,h),b._inherited=a.utils.arrayUnique(d.concat(e).concat(f).concat(d).concat(b._inherited||[])),b._d3options=a.utils.arrayUnique(g.concat(b._d3options||[]))},a.utils.initSVG=function(a){a.classed({"nvd3-svg":!0})},a.utils.sanitizeHeight=function(a,b){return a||parseInt(b.style("height"),10)||400},a.utils.sanitizeWidth=function(a,b){return a||parseInt(b.style("width"),10)||960},a.utils.availableHeight=function(b,c,d){return a.utils.sanitizeHeight(b,c)-d.top-d.bottom},a.utils.availableWidth=function(b,c,d){return a.utils.sanitizeWidth(b,c)-d.left-d.right},a.utils.noData=function(b,c){var d=b.options(),e=d.margin(),f=d.noData(),g=null==f?["No Data Available."]:[f],h=a.utils.availableHeight(null,c,e),i=a.utils.availableWidth(null,c,e),j=e.left+i/2,k=e.top+h/2;c.selectAll("g").remove();var l=c.selectAll(".nv-noData").data(g);l.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),l.attr("x",j).attr("y",k).text(function(a){return a})},a.utils.wrapTicks=function(a,b){a.each(function(){for(var a,c=d3.select(this),d=c.text().split(/\s+/).reverse(),e=[],f=0,g=1.1,h=c.attr("y"),i=parseFloat(c.attr("dy")),j=c.text(null).append("tspan").attr("x",0).attr("y",h).attr("dy",i+"em");a=d.pop();)e.push(a),j.text(e.join(" ")),j.node().getComputedTextLength()>b&&(e.pop(),j.text(e.join(" ")),e=[a],j=c.append("tspan").attr("x",0).attr("y",h).attr("dy",++f*g+i+"em").text(a))})},a.models.axis=function(){"use strict";function b(g){return s.reset(),g.each(function(b){var g=d3.select(this);a.utils.initSVG(g);var p=g.selectAll("g.nv-wrap.nv-axis").data([b]),q=p.enter().append("g").attr("class","nvd3 nv-wrap nv-axis"),t=(q.append("g"),p.select("g"));null!==n?c.ticks(n):("top"==c.orient()||"bottom"==c.orient())&&c.ticks(Math.abs(d.range()[1]-d.range()[0])/100),t.watchTransition(s,"axis").call(c),r=r||c.scale();var u=c.tickFormat();null==u&&(u=r.tickFormat());var v=t.selectAll("text.nv-axislabel").data([h||null]);v.exit().remove();var w,x,y;switch(c.orient()){case"top":v.enter().append("text").attr("class","nv-axislabel"),y=0,1===d.range().length?y=m?2*d.range()[0]+d.rangeBand():0:2===d.range().length?y=m?d.range()[0]+d.range()[1]+d.rangeBand():d.range()[1]:d.range().length>2&&(y=d.range()[d.range().length-1]+(d.range()[1]-d.range()[0])),v.attr("text-anchor","middle").attr("y",0).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b))+",0)"}).select("text").attr("dy","-0.5em").attr("y",-c.tickPadding()).attr("text-anchor","middle").text(function(a,b){var c=u(a);return(""+c).match("NaN")?"":c}),x.watchTransition(s,"min-max top").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d.range()[c])+",0)"}));break;case"bottom":w=o+36;var z=30,A=0,B=t.selectAll("g").select("text"),C="";if(j%360){B.each(function(a,b){var c=this.getBoundingClientRect(),d=c.width;A=c.height,d>z&&(z=d)}),C="rotate("+j+" 0,"+(A/2+c.tickPadding())+")";var D=Math.abs(Math.sin(j*Math.PI/180));w=(D?D*z:z)+30,B.attr("transform",C).style("text-anchor",j%360>0?"start":"end")}v.enter().append("text").attr("class","nv-axislabel"),y=0,1===d.range().length?y=m?2*d.range()[0]+d.rangeBand():0:2===d.range().length?y=m?d.range()[0]+d.range()[1]+d.rangeBand():d.range()[1]:d.range().length>2&&(y=d.range()[d.range().length-1]+(d.range()[1]-d.range()[0])),v.attr("text-anchor","middle").attr("y",w).attr("x",y/2),i&&(x=p.selectAll("g.nv-axisMaxMin").data([d.domain()[0],d.domain()[d.domain().length-1]]),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-x",0==b?"nv-axisMin-x":"nv-axisMax-x"].join(" ")}).append("text"),x.exit().remove(),x.attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",c.tickPadding()).attr("transform",C).style("text-anchor",j?j%360>0?"start":"end":"middle").text(function(a,b){var c=u(a);return(""+c).match("NaN")?"":c}),x.watchTransition(s,"min-max bottom").attr("transform",function(b,c){return"translate("+a.utils.NaNtoZero(d(b)+(m?d.rangeBand()/2:0))+",0)"})),l&&B.attr("transform",function(a,b){return"translate(0,"+(b%2==0?"0":"12")+")"});break;case"right":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"begin").attr("transform",k?"rotate(90)":"").attr("y",k?-Math.max(e.right,f)+12:-10).attr("x",k?d3.max(d.range())/2:c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",c.tickPadding()).style("text-anchor","start").text(function(a,b){var c=u(a);return(""+c).match("NaN")?"":c}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1));break;case"left":v.enter().append("text").attr("class","nv-axislabel"),v.style("text-anchor",k?"middle":"end").attr("transform",k?"rotate(-90)":"").attr("y",k?-Math.max(e.left,f)+25-(o||0):-10).attr("x",k?-d3.max(d.range())/2:-c.tickPadding()),i&&(x=p.selectAll("g.nv-axisMaxMin").data(d.domain()),x.enter().append("g").attr("class",function(a,b){return["nv-axisMaxMin","nv-axisMaxMin-y",0==b?"nv-axisMin-y":"nv-axisMax-y"].join(" ")}).append("text").style("opacity",0),x.exit().remove(),x.attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(r(b))+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-c.tickPadding()).attr("text-anchor","end").text(function(a,b){var c=u(a);return(""+c).match("NaN")?"":c}),x.watchTransition(s,"min-max right").attr("transform",function(b,c){return"translate(0,"+a.utils.NaNtoZero(d.range()[c])+")"}).select("text").style("opacity",1))}if(v.text(function(a){return a}),!i||"left"!==c.orient()&&"right"!==c.orient()||(t.selectAll("g").each(function(a,b){d3.select(this).select("text").attr("opacity",1),(d(a)d.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),d.domain()[0]==d.domain()[1]&&0==d.domain()[0]&&p.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===c.orient()||"bottom"===c.orient())){var E=[];p.selectAll("g.nv-axisMaxMin").each(function(a,b){try{E.push(b?d(a)-this.getBoundingClientRect().width-4:d(a)+this.getBoundingClientRect().width+4)}catch(c){E.push(b?d(a)-4:d(a)+4)}}),t.selectAll("g").each(function(a,b){(d(a)E[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}t.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*a)/1e6)&&void 0!==a}).classed("zero",!0),r=d.copy()}),s.renderEnd("axis immediate"),b}var c=d3.svg.axis(),d=d3.scale.linear(),e={top:0,right:0,bottom:0,left:0},f=75,g=60,h=null,i=!0,j=0,k=!0,l=!1,m=!1,n=null,o=0,p=250,q=d3.dispatch("renderEnd");c.scale(d).orient("bottom").tickFormat(function(a){return a});var r,s=a.utils.renderWatch(q,p);return b.axis=c,b.dispatch=q,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{axisLabelDistance:{get:function(){return o},set:function(a){o=a}},staggerLabels:{get:function(){return l},set:function(a){l=a}},rotateLabels:{get:function(){return j},set:function(a){j=a}},rotateYLabel:{get:function(){return k},set:function(a){k=a}},showMaxMin:{get:function(){return i},set:function(a){i=a}},axisLabel:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return g},set:function(a){g=a}},ticks:{get:function(){return n},set:function(a){n=a}},width:{get:function(){return f},set:function(a){f=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},duration:{get:function(){return p},set:function(a){p=a,s.reset(p)}},scale:{get:function(){return d},set:function(e){d=e,c.scale(d),m="function"==typeof d.rangeBands,a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"])}}}),a.utils.initOptions(b),a.utils.inheritOptionsD3(b,c,["orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"]),a.utils.inheritOptionsD3(b,d,["domain","range","rangeBand","rangeBands"]),b},a.models.boxPlot=function(){"use strict";function b(l){return v.reset(),l.each(function(b){var l=j-i.left-i.right,p=k-i.top-i.bottom;r=d3.select(this),a.utils.initSVG(r),m.domain(c||b.map(function(a,b){return o(a,b)})).rangeBands(e||[0,l],.1);var w=[];if(!d){var x=d3.min(b.map(function(a){var b=[];return b.push(a.values.Q1),a.values.hasOwnProperty("whisker_low")&&null!==a.values.whisker_low&&b.push(a.values.whisker_low),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.min(b)})),y=d3.max(b.map(function(a){var b=[];return b.push(a.values.Q3),a.values.hasOwnProperty("whisker_high")&&null!==a.values.whisker_high&&b.push(a.values.whisker_high),a.values.hasOwnProperty("outliers")&&null!==a.values.outliers&&(b=b.concat(a.values.outliers)),d3.max(b)}));w=[x,y]}n.domain(d||w),n.range(f||[p,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);{var z=r.selectAll("g.nv-wrap").data([b]);z.enter().append("g").attr("class","nvd3 nv-wrap")}z.attr("transform","translate("+i.left+","+i.top+")");var A=z.selectAll(".nv-boxplot").data(function(a){return a}),B=A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);A.attr("class","nv-boxplot").attr("transform",function(a,b,c){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}).classed("hover",function(a){return a.hover}),A.watchTransition(v,"nv-boxplot: boxplots").style("stroke-opacity",1).style("fill-opacity",.75).delay(function(a,c){return c*t/b.length}).attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", 0)"}),A.exit().remove(),B.each(function(a,b){var c=d3.select(this);["low","high"].forEach(function(d){a.values.hasOwnProperty("whisker_"+d)&&null!==a.values["whisker_"+d]&&(c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-whisker nv-boxplot-"+d),c.append("line").style("stroke",a.color?a.color:q(a,b)).attr("class","nv-boxplot-tick nv-boxplot-"+d))})});var C=A.selectAll(".nv-boxplot-outlier").data(function(a){return a.values.hasOwnProperty("outliers")&&null!==a.values.outliers?a.values.outliers:[]});C.enter().append("circle").style("fill",function(a,b,c){return q(a,c)}).style("stroke",function(a,b,c){return q(a,c)}).on("mouseover",function(a,b,c){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:a,color:q(a,c)},e:d3.event})}).on("mouseout",function(a,b,c){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:a,color:q(a,c)},e:d3.event})}).on("mousemove",function(a,b){s.elementMousemove({e:d3.event})}),C.attr("class","nv-boxplot-outlier"),C.watchTransition(v,"nv-boxplot: nv-boxplot-outlier").attr("cx",.45*m.rangeBand()).attr("cy",function(a,b,c){return n(a)}).attr("r","3"),C.exit().remove();var D=function(){return null===u?.9*m.rangeBand():Math.min(75,.9*m.rangeBand())},E=function(){return.45*m.rangeBand()-D()/2},F=function(){return.45*m.rangeBand()+D()/2};["low","high"].forEach(function(a){var b="low"===a?"Q1":"Q3";A.select("line.nv-boxplot-whisker.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",.45*m.rangeBand()).attr("y1",function(b,c){return n(b.values["whisker_"+a])}).attr("x2",.45*m.rangeBand()).attr("y2",function(a,c){return n(a.values[b])}),A.select("line.nv-boxplot-tick.nv-boxplot-"+a).watchTransition(v,"nv-boxplot: boxplots").attr("x1",E).attr("y1",function(b,c){return n(b.values["whisker_"+a])}).attr("x2",F).attr("y2",function(b,c){return n(b.values["whisker_"+a])})}),["low","high"].forEach(function(a){B.selectAll(".nv-boxplot-"+a).on("mouseover",function(b,c,d){d3.select(this).classed("hover",!0),s.elementMouseover({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mouseout",function(b,c,d){d3.select(this).classed("hover",!1),s.elementMouseout({series:{key:b.values["whisker_"+a],color:q(b,d)},e:d3.event})}).on("mousemove",function(a,b){s.elementMousemove({e:d3.event})})}),B.append("rect").attr("class","nv-boxplot-box").on("mouseover",function(a,b){d3.select(this).classed("hover",!0),s.elementMouseover({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),s.elementMouseout({key:a.label,value:a.label,series:[{key:"Q3",value:a.values.Q3,color:a.color||q(a,b)},{key:"Q2",value:a.values.Q2,color:a.color||q(a,b)},{key:"Q1",value:a.values.Q1,color:a.color||q(a,b)}],data:a,index:b,e:d3.event})}).on("mousemove",function(a,b){s.elementMousemove({e:d3.event})}),A.select("rect.nv-boxplot-box").watchTransition(v,"nv-boxplot: boxes").attr("y",function(a,b){return n(a.values.Q3)}).attr("width",D).attr("x",E).attr("height",function(a,b){return Math.abs(n(a.values.Q3)-n(a.values.Q1))||1}).style("fill",function(a,b){return a.color||q(a,b)}).style("stroke",function(a,b){return a.color||q(a,b)}),B.append("line").attr("class","nv-boxplot-median"),A.select("line.nv-boxplot-median").watchTransition(v,"nv-boxplot: boxplots line").attr("x1",E).attr("y1",function(a,b){return n(a.values.Q2)}).attr("x2",F).attr("y2",function(a,b){return n(a.values.Q2)}),g=m.copy(),h=n.copy()}),v.renderEnd("nv-boxplot immediate"),b}var c,d,e,f,g,h,i={top:0,right:0,bottom:0,left:0},j=960,k=500,l=Math.floor(1e4*Math.random()),m=d3.scale.ordinal(),n=d3.scale.linear(),o=function(a){return a.x},p=function(a){return a.y},q=a.utils.defaultColor(),r=null,s=d3.dispatch("elementMouseover","elementMouseout","elementMousemove","renderEnd"),t=250,u=null,v=a.utils.renderWatch(s,t);return b.dispatch=s,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},maxBoxWidth:{get:function(){return u},set:function(a){u=a}},x:{get:function(){return o},set:function(a){o=a}},y:{get:function(){return p},set:function(a){p=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return l},set:function(a){l=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}},duration:{get:function(){return t},set:function(a){t=a,v.reset(t)}}}),a.utils.initOptions(b),b},a.models.boxPlotChart=function(){"use strict";function b(k){return t.reset(),t.models(e),l&&t.models(f),m&&t.models(g),k.each(function(k){var p=d3.select(this);a.utils.initSVG(p);var t=(i||parseInt(p.style("width"))||960)-h.left-h.right,u=(j||parseInt(p.style("height"))||400)-h.top-h.bottom;if(b.update=function(){r.beforeUpdate(),p.transition().duration(s).call(b)},b.container=this,!(k&&k.length&&k.filter(function(a){return a.values.hasOwnProperty("Q1")&&a.values.hasOwnProperty("Q2")&&a.values.hasOwnProperty("Q3")}).length)){var v=p.selectAll(".nv-noData").data([q]);return v.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),v.attr("x",h.left+t/2).attr("y",h.top+u/2).text(function(a){return a}),b}p.selectAll(".nv-noData").remove(), +c=e.xScale(),d=e.yScale().clamp(!0);var w=p.selectAll("g.nv-wrap.nv-boxPlotWithAxes").data([k]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-boxPlotWithAxes").append("g"),y=x.append("defs"),z=w.select("g");x.append("g").attr("class","nv-x nv-axis"),x.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),x.append("g").attr("class","nv-barsWrap"),z.attr("transform","translate("+h.left+","+h.top+")"),n&&z.select(".nv-y.nv-axis").attr("transform","translate("+t+",0)"),e.width(t).height(u);var A=z.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));if(A.transition().call(e),y.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),z.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(o?2:1)).attr("height",16).attr("x",-c.rangeBand()/(o?1:2)),l){f.scale(c).ticks(a.utils.calcTicksX(t/100,k)).tickSize(-u,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),z.select(".nv-x.nv-axis").call(f);var B=z.select(".nv-x.nv-axis").selectAll("g");o&&B.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"})}m&&(g.scale(d).ticks(Math.floor(u/36)).tickSize(-t,0),z.select(".nv-y.nv-axis").call(g)),z.select(".nv-zeroLine line").attr("x1",0).attr("x2",t).attr("y1",d(0)).attr("y2",d(0))}),t.renderEnd("nv-boxplot chart immediate"),b}var c,d,e=a.models.boxPlot(),f=a.models.axis(),g=a.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=a.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=a.models.tooltip(),q="No Data Available.",r=d3.dispatch("beforeUpdate","renderEnd"),s=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(n?"right":"left").tickFormat(d3.format(",.1f")),p.duration(0);var t=a.utils.renderWatch(r,s);return e.dispatch.on("elementMouseover.tooltip",function(a){p.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){p.data(a).hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){p()}),b.dispatch=r,b.boxplot=e,b.xAxis=f,b.yAxis=g,b.tooltip=p,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},staggerLabels:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return l},set:function(a){l=a}},showYAxis:{get:function(){return m},set:function(a){m=a}},tooltipContent:{get:function(){return p},set:function(a){p=a}},noData:{get:function(){return q},set:function(a){q=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!==a.top?a.top:h.top,h.right=void 0!==a.right?a.right:h.right,h.bottom=void 0!==a.bottom?a.bottom:h.bottom,h.left=void 0!==a.left?a.left:h.left}},duration:{get:function(){return s},set:function(a){s=a,t.reset(s),e.duration(s),f.duration(s),g.duration(s)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}},rightAlignYAxis:{get:function(){return n},set:function(a){n=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.bullet=function(){"use strict";function b(d){return d.each(function(b,d){var p=m-c.left-c.right,s=n-c.top-c.bottom;o=d3.select(this),a.utils.initSVG(o);{var t=f.call(this,b,d).slice().sort(d3.descending),u=g.call(this,b,d).slice().sort(d3.descending),v=h.call(this,b,d).slice().sort(d3.descending),w=i.call(this,b,d).slice(),x=j.call(this,b,d).slice(),y=k.call(this,b,d).slice(),z=d3.scale.linear().domain(d3.extent(d3.merge([l,t]))).range(e?[p,0]:[0,p]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range())}this.__chart__=z;var A=d3.min(t),B=d3.max(t),C=t[1],D=o.selectAll("g.nv-wrap.nv-bullet").data([b]),E=D.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),F=E.append("g"),G=D.select("g");F.append("rect").attr("class","nv-range nv-rangeMax"),F.append("rect").attr("class","nv-range nv-rangeAvg"),F.append("rect").attr("class","nv-range nv-rangeMin"),F.append("rect").attr("class","nv-measure"),D.attr("transform","translate("+c.left+","+c.top+")");var H=function(a){return Math.abs(z(a)-z(0))},I=function(a){return z(0>a?a:0)};G.select("rect.nv-rangeMax").attr("height",s).attr("width",H(B>0?B:A)).attr("x",I(B>0?B:A)).datum(B>0?B:A),G.select("rect.nv-rangeAvg").attr("height",s).attr("width",H(C)).attr("x",I(C)).datum(C),G.select("rect.nv-rangeMin").attr("height",s).attr("width",H(B)).attr("x",I(B)).attr("width",H(B>0?A:B)).attr("x",I(B>0?A:B)).datum(B>0?A:B),G.select("rect.nv-measure").style("fill",q).attr("height",s/3).attr("y",s/3).attr("width",0>v?z(0)-z(v[0]):z(v[0])-z(0)).attr("x",I(v)).on("mouseover",function(){r.elementMouseover({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})}).on("mouseout",function(){r.elementMouseout({value:v[0],label:y[0]||"Current",color:d3.select(this).style("fill")})});var J=s/6,K=u.map(function(a,b){return{value:a,label:x[b]}});F.selectAll("path.nv-markerTriangle").data(K).enter().append("path").attr("class","nv-markerTriangle").attr("transform",function(a){return"translate("+z(a.value)+","+s/2+")"}).attr("d","M0,"+J+"L"+J+","+-J+" "+-J+","+-J+"Z").on("mouseover",function(a){r.elementMouseover({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill"),pos:[z(a.value),s/2]})}).on("mousemove",function(a){r.elementMousemove({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){r.elementMouseout({value:a.value,label:a.label||"Previous",color:d3.select(this).style("fill")})}),D.selectAll(".nv-range").on("mouseover",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseover({value:a,label:c,color:d3.select(this).style("fill")})}).on("mousemove",function(){r.elementMousemove({value:v[0],label:y[0]||"Previous",color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){var c=w[b]||(b?1==b?"Mean":"Minimum":"Maximum");r.elementMouseout({value:a,label:c,color:d3.select(this).style("fill")})})}),b}var c={top:0,right:0,bottom:0,left:0},d="left",e=!1,f=function(a){return a.ranges},g=function(a){return a.markers?a.markers:[0]},h=function(a){return a.measures},i=function(a){return a.rangeLabels?a.rangeLabels:[]},j=function(a){return a.markerLabels?a.markerLabels:[]},k=function(a){return a.measureLabels?a.measureLabels:[]},l=[0],m=380,n=30,o=null,p=null,q=a.utils.getColor(["#1f77b4"]),r=d3.dispatch("elementMouseover","elementMouseout","elementMousemove");return b.dispatch=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return f},set:function(a){f=a}},markers:{get:function(){return g},set:function(a){g=a}},measures:{get:function(){return h},set:function(a){h=a}},forceX:{get:function(){return l},set:function(a){l=a}},width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},tickFormat:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},orient:{get:function(){return d},set:function(a){d=a,e="right"==d||"bottom"==d}},color:{get:function(){return q},set:function(b){q=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.bulletChart=function(){"use strict";function b(d){return d.each(function(e,o){var p=d3.select(this);a.utils.initSVG(p);var q=a.utils.availableWidth(k,p,g),r=l-g.top-g.bottom;if(b.update=function(){b(d)},b.container=this,!e||!h.call(this,e,o))return a.utils.noData(b,p),b;p.selectAll(".nv-noData").remove();var s=h.call(this,e,o).slice().sort(d3.descending),t=i.call(this,e,o).slice().sort(d3.descending),u=j.call(this,e,o).slice().sort(d3.descending),v=p.selectAll("g.nv-wrap.nv-bulletChart").data([e]),w=v.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),x=w.append("g"),y=v.select("g");x.append("g").attr("class","nv-bulletWrap"),x.append("g").attr("class","nv-titles"),v.attr("transform","translate("+g.left+","+g.top+")");var z=d3.scale.linear().domain([0,Math.max(s[0],t[0],u[0])]).range(f?[q,0]:[0,q]),A=this.__chart__||d3.scale.linear().domain([0,1/0]).range(z.range());this.__chart__=z;var B=x.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(l-g.top-g.bottom)/2+")");B.append("text").attr("class","nv-title").text(function(a){return a.title}),B.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),c.width(q).height(r);var C=y.select(".nv-bulletWrap");d3.transition(C).call(c);var D=m||z.tickFormat(q/100),E=y.selectAll("g.nv-tick").data(z.ticks(n?n:q/50),function(a){return this.textContent||D(a)}),F=E.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+A(a)+",0)"}).style("opacity",1e-6);F.append("line").attr("y1",r).attr("y2",7*r/6),F.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*r/6).text(D);var G=d3.transition(E).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1);G.select("line").attr("y1",r).attr("y2",7*r/6),G.select("text").attr("y",7*r/6),d3.transition(E.exit()).attr("transform",function(a){return"translate("+z(a)+",0)"}).style("opacity",1e-6).remove()}),d3.timer.flush(),b}var c=a.models.bullet(),d=a.models.tooltip(),e="left",f=!1,g={top:5,right:40,bottom:20,left:120},h=function(a){return a.ranges},i=function(a){return a.markers?a.markers:[0]},j=function(a){return a.measures},k=null,l=55,m=null,n=null,o=null,p=d3.dispatch();return d.duration(0).headerEnabled(!1),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.label,value:a.value,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(a){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(a){d()}),b.bullet=c,b.dispatch=p,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{ranges:{get:function(){return h},set:function(a){h=a}},markers:{get:function(){return i},set:function(a){i=a}},measures:{get:function(){return j},set:function(a){j=a}},width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},tickFormat:{get:function(){return m},set:function(a){m=a}},ticks:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return o},set:function(a){o=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},orient:{get:function(){return e},set:function(a){e=a,f="right"==e||"bottom"==e}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.candlestickBar=function(){"use strict";function b(x){return x.each(function(b){c=d3.select(this);var x=a.utils.availableWidth(i,c,h),y=a.utils.availableHeight(j,c,h);a.utils.initSVG(c);var A=x/b[0].values.length*.45;l.domain(d||d3.extent(b[0].values.map(n).concat(t))),l.range(v?f||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:f||[5+A/2,x-A/2-5]),m.domain(e||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(g||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var B=d3.select(this).selectAll("g.nv-wrap.nv-candlestickBar").data([b[0].values]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-candlestickBar"),D=C.append("defs"),E=C.append("g"),F=B.select("g");E.append("g").attr("class","nv-ticks"),B.attr("transform","translate("+h.left+","+h.top+")"),c.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:k})}),D.append("clipPath").attr("id","nv-chart-clip-path-"+k).append("rect"),B.select("#nv-chart-clip-path-"+k+" rect").attr("width",x).attr("height",y),F.attr("clip-path",w?"url(#nv-chart-clip-path-"+k+")":"");var G=B.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});G.exit().remove();var H=G.enter().append("g");G.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b});H.append("line").attr("class","nv-candlestick-lines").attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),H.append("rect").attr("class","nv-candlestick-rects nv-bars").attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)});G.select(".nv-candlestick-lines").transition().attr("transform",function(a,b){return"translate("+l(n(a,b))+",0)"}).attr("x1",0).attr("y1",function(a,b){return m(r(a,b))}).attr("x2",0).attr("y2",function(a,b){return m(s(a,b))}),G.select(".nv-candlestick-rects").transition().attr("transform",function(a,b){return"translate("+(l(n(a,b))-A/2)+","+(m(o(a,b))-(p(a,b)>q(a,b)?m(q(a,b))-m(p(a,b)):0))+")"}).attr("x",0).attr("y",0).attr("width",A).attr("height",function(a,b){var c=p(a,b),d=q(a,b);return c>d?m(d)-m(c):m(c)-m(d)})}),b}var c,d,e,f,g,h={top:0,right:0,bottom:0,left:0},i=null,j=null,k=Math.floor(1e4*Math.random()),l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,d){b.clearHighlights(),c.select(".nv-candlestickBar .nv-tick-0-"+a).classed("hover",d)},b.clearHighlights=function(){c.select(".nv-candlestickBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return i},set:function(a){i=a}},height:{get:function(){return j},set:function(a){j=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return k},set:function(a){k=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return h},set:function(a){h.top=void 0!=a.top?a.top:h.top,h.right=void 0!=a.right?a.right:h.right,h.bottom=void 0!=a.bottom?a.bottom:h.bottom,h.left=void 0!=a.left?a.left:h.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.cumulativeLineChart=function(){"use strict";function b(l){return H.reset(),H.models(f),r&&H.models(g),s&&H.models(h),l.each(function(l){function A(a,c){d3.select(b.container).style("cursor","ew-resize")}function E(a,b){G.x=d3.event.x,G.i=Math.round(F.invert(G.x)),K()}function H(a,c){d3.select(b.container).style("cursor","auto"),y.index=G.i,C.stateChange(y)}function K(){ba.data([G]);var a=b.duration();b.duration(0),b.update(),b.duration(a)}var L=d3.select(this);a.utils.initSVG(L),L.classed("nv-chart-"+x,!0);var M=this,N=a.utils.availableWidth(o,L,m),O=a.utils.availableHeight(p,L,m);if(b.update=function(){0===D?L.call(b):L.transition().duration(D).call(b)},b.container=this,y.setter(J(l),b.update).getter(I(l)).update(),y.disabled=l.map(function(a){return!!a.disabled}),!z){var P;z={};for(P in y)y[P]instanceof Array?z[P]=y[P].slice(0):z[P]=y[P]}var Q=d3.behavior.drag().on("dragstart",A).on("drag",E).on("dragend",H);if(!(l&&l.length&&l.filter(function(a){return a.values.length}).length))return a.utils.noData(b,L),b;if(L.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),w)f.yDomain(null);else{var R=l.filter(function(a){return!a.disabled}).map(function(a,b){var c=d3.extent(a.values,f.y());return c[0]<-.95&&(c[0]=-.95),[(c[0]-c[1])/(1+c[1]),(c[1]-c[0])/(1+c[0])]}),S=[d3.min(R,function(a){return a[0]}),d3.max(R,function(a){return a[1]})];f.yDomain(S)}F.domain([0,l[0].values.length-1]).range([0,N]).clamp(!0);var l=c(G.i,l),T=v?"none":"all",U=L.selectAll("g.nv-wrap.nv-cumulativeLine").data([l]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),W=U.select("g");if(V.append("g").attr("class","nv-interactive"),V.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),V.append("g").attr("class","nv-y nv-axis"),V.append("g").attr("class","nv-background"),V.append("g").attr("class","nv-linesWrap").style("pointer-events",T),V.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),V.append("g").attr("class","nv-legendWrap"),V.append("g").attr("class","nv-controlsWrap"),q&&(i.width(N),W.select(".nv-legendWrap").datum(l).call(i),m.top!=i.height()&&(m.top=i.height(),O=a.utils.availableHeight(p,L,m)),W.select(".nv-legendWrap").attr("transform","translate(0,"+-m.top+")")),u){var X=[{key:"Re-scale y-axis",disabled:!w}];j.width(140).color(["#444","#444","#444"]).rightAlign(!1).margin({top:5,right:0,bottom:5,left:20}),W.select(".nv-controlsWrap").datum(X).attr("transform","translate(0,"+-m.top+")").call(j)}U.attr("transform","translate("+m.left+","+m.top+")"),t&&W.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)");var Y=l.filter(function(a){return a.tempDisabled});U.select(".tempDisabled").remove(),Y.length&&U.append("text").attr("class","tempDisabled").attr("x",N/2).attr("y","-.71em").style("text-anchor","end").text(Y.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),v&&(k.width(N).height(O).margin({left:m.left,top:m.top}).svgContainer(L).xScale(d),U.select(".nv-interactive").call(k)),V.select(".nv-background").append("rect"),W.select(".nv-background rect").attr("width",N).attr("height",O),f.y(function(a){return a.display.y}).width(N).height(O).color(l.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!l[b].disabled&&!l[b].tempDisabled}));var Z=W.select(".nv-linesWrap").datum(l.filter(function(a){return!a.disabled&&!a.tempDisabled}));Z.call(f),l.forEach(function(a,b){a.seriesIndex=b});var $=l.filter(function(a){return!a.disabled&&!!B(a)}),_=W.select(".nv-avgLinesWrap").selectAll("line").data($,function(a){return a.key}),aa=function(a){var b=e(B(a));return 0>b?0:b>O?O:b};_.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a,b){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",N).attr("y1",aa).attr("y2",aa),_.style("stroke-opacity",function(a){var b=e(B(a));return 0>b||b>O?0:1}).attr("x1",0).attr("x2",N).attr("y1",aa).attr("y2",aa),_.exit().remove();var ba=Z.selectAll(".nv-indexLine").data([G]);ba.enter().append("rect").attr("class","nv-indexLine").attr("width",3).attr("x",-2).attr("fill","red").attr("fill-opacity",.5).style("pointer-events","all").call(Q),ba.attr("transform",function(a){return"translate("+F(a.i)+",0)"}).attr("height",O),r&&(g.scale(d)._ticks(a.utils.calcTicksX(N/70,l)).tickSize(-O,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),W.select(".nv-x.nv-axis").call(g)),s&&(h.scale(e)._ticks(a.utils.calcTicksY(O/36,l)).tickSize(-N,0),W.select(".nv-y.nv-axis").call(h)),W.select(".nv-background rect").on("click",function(){G.x=d3.mouse(this)[0],G.i=Math.round(F.invert(G.x)),y.index=G.i,C.stateChange(y),K()}),f.dispatch.on("elementClick",function(a){G.i=a.pointIndex,G.x=F(G.i),y.index=G.i,C.stateChange(y),K()}),j.dispatch.on("legendClick",function(a,c){a.disabled=!a.disabled,w=!a.disabled,y.rescaleY=w,C.stateChange(y),b.update()}),i.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];C.stateChange(y),b.update()}),k.dispatch.on("elementMousemove",function(c){f.clearHighlights();var d,e,i,j=[];if(l.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,c.pointXValue,b.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=b.xScale()(b.x()(k,e))),j.push({key:g.key,value:b.y()(k,e),color:n(g,g.seriesIndex)}))}),j.length>2){var m=b.yScale().invert(c.mouseY),o=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),p=.03*o,q=a.nearestValueIndex(j.map(function(a){return a.value}),m,p);null!==q&&(j[q].highlight=!0)}var r=g.tickFormat()(b.x()(d,e),e);k.tooltip.chartContainer(M.parentNode).valueFormatter(function(a,b){return h.tickFormat()(a)}).data({value:r,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(a){f.clearHighlights()}),C.on("changeState",function(a){"undefined"!=typeof a.disabled&&(l.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),"undefined"!=typeof a.index&&(G.i=a.index,G.x=F(G.i),y.index=a.index,ba.data([G])),"undefined"!=typeof a.rescaleY&&(w=a.rescaleY),b.update()})}),H.renderEnd("cumulativeLineChart immediate"),b}function c(a,b){return K||(K=f.y()),b.map(function(b,c){if(!b.values)return b;var d=b.values[a];if(null==d)return b;var e=K(d,a);return-.95>e&&!E?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(K(a,b)-e)/(1+e)},a}),b)})}var d,e,f=a.models.line(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.models.legend(),k=a.interactiveGuideline(),l=a.models.tooltip(),m={top:30,right:30,bottom:50,left:60},n=a.utils.defaultColor(),o=null,p=null,q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=!0,x=f.id(),y=a.utils.state(),z=null,A=null,B=function(a){return a.average},C=d3.dispatch("stateChange","changeState","renderEnd"),D=250,E=!1;y.index=0,y.rescaleY=w,g.orient("bottom").tickPadding(7),h.orient(t?"right":"left"),l.valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)}),j.updateState(!1);var F=d3.scale.linear(),G={i:0,x:0},H=a.utils.renderWatch(C,D),I=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),index:G.i,rescaleY:w}}},J=function(a){return function(b){void 0!==b.index&&(G.i=b.index),void 0!==b.rescaleY&&(w=b.rescaleY),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};f.dispatch.on("elementMouseover.tooltip",function(a){var c={x:b.x()(a.point),y:b.y()(a.point),color:a.point.color};a.point=c,l.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(a){l.hidden(!0)});var K=null;return b.dispatch=C,b.lines=f,b.legend=i,b.controls=j,b.xAxis=g,b.yAxis=h,b.interactiveLayer=k,b.state=y,b.tooltip=l,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return o},set:function(a){o=a}},height:{get:function(){return p},set:function(a){p=a}},rescaleY:{get:function(){return w},set:function(a){w=a}},showControls:{get:function(){return u},set:function(a){u=a}},showLegend:{get:function(){return q},set:function(a){q=a}},average:{get:function(){return B},set:function(a){B=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return A},set:function(a){A=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},noErrorCheck:{get:function(){return E},set:function(a){E=a}},margin:{get:function(){return m},set:function(a){m.top=void 0!==a.top?a.top:m.top,m.right=void 0!==a.right?a.right:m.right,m.bottom=void 0!==a.bottom?a.bottom:m.bottom,m.left=void 0!==a.left?a.left:m.left}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),i.color(n)}},useInteractiveGuideline:{get:function(){return v},set:function(a){v=a,a===!0&&(b.interactive(!1),b.useVoronoi(!1))}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,h.orient(a?"right":"left")}},duration:{get:function(){return D},set:function(a){D=a,f.duration(D),g.duration(D),h.duration(D),H.reset(D)}}}),a.utils.inheritOptions(b,f),a.utils.initOptions(b),b},a.models.discreteBar=function(){"use strict";function b(m){return y.reset(),m.each(function(b){var m=k-j.left-j.right,x=l-j.top-j.bottom;c=d3.select(this),a.utils.initSVG(c),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var z=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),y0:a.y0}})});n.domain(d||d3.merge(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return a.y}).concat(r))),o.range(t?g||[x-(o.domain()[0]<0?12:0),o.domain()[1]>0?12:0]:g||[x,0]),h=h||n,i=i||o.copy().range([o(0),o(0)]);{var A=c.selectAll("g.nv-wrap.nv-discretebar").data([b]),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),C=B.append("g");A.select("g")}C.append("g").attr("class","nv-groups"),A.attr("transform","translate("+j.left+","+j.top+")");var D=A.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});D.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),D.exit().watchTransition(y,"discreteBar: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),D.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),D.watchTransition(y,"discreteBar: groups").style("stroke-opacity",1).style("fill-opacity",.75);var E=D.selectAll("g.nv-bar").data(function(a){return a.values});E.exit().remove();var F=E.enter().append("g").attr("transform",function(a,b,c){return"translate("+(n(p(a,b))+.05*n.rangeBand())+", "+o(0)+")"}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),v.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),v.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){v.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){v.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()});F.append("rect").attr("height",0).attr("width",.9*n.rangeBand()/b.length),t?(F.append("text").attr("text-anchor","middle"),E.select("text").text(function(a,b){return u(q(a,b))}).watchTransition(y,"discreteBar: bars text").attr("x",.9*n.rangeBand()/2).attr("y",function(a,b){return q(a,b)<0?o(q(a,b))-o(0)+12:-4})):E.selectAll("text").remove(),E.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).style("fill",function(a,b){return a.color||s(a,b)}).style("stroke",function(a,b){return a.color||s(a,b)}).select("rect").attr("class",w).watchTransition(y,"discreteBar: bars rect").attr("width",.9*n.rangeBand()/b.length),E.watchTransition(y,"discreteBar: bars").attr("transform",function(a,b){var c=n(p(a,b))+.05*n.rangeBand(),d=q(a,b)<0?o(0):o(0)-o(q(a,b))<1?o(0)-1:o(q(a,b));return"translate("+c+", "+d+")"}).select("rect").attr("height",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(e&&e[0]||0))||1)}),h=n.copy(),i=o.copy()}),y.renderEnd("discreteBar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=d3.scale.ordinal(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=[0],s=a.utils.defaultColor(),t=!1,u=d3.format(",.2f"),v=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),w="discreteBar",x=250,y=a.utils.renderWatch(v,x);return b.dispatch=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},forceY:{get:function(){return r},set:function(a){r=a}},showValues:{get:function(){return t},set:function(a){t=a}},x:{get:function(){return p},set:function(a){p=a}},y:{get:function(){return q},set:function(a){q=a}},xScale:{get:function(){return n},set:function(a){n=a}},yScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},valueFormat:{get:function(){return u},set:function(a){u=a}},id:{get:function(){return m},set:function(a){m=a}},rectClass:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b)}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x)}}}),a.utils.initOptions(b),b},a.models.discreteBarChart=function(){"use strict";function b(h){return v.reset(),v.models(e),m&&v.models(f),n&&v.models(g),h.each(function(h){var l=d3.select(this);a.utils.initSVG(l);var s=a.utils.availableWidth(j,l,i),v=a.utils.availableHeight(k,l,i);if(b.update=function(){t.beforeUpdate(),l.transition().duration(u).call(b)},b.container=this,!(h&&h.length&&h.filter(function(a){return a.values.length}).length))return a.utils.noData(b,l),b;l.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale().clamp(!0);var w=l.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([h]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),y=x.append("defs"),z=w.select("g");x.append("g").attr("class","nv-x nv-axis"),x.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),x.append("g").attr("class","nv-barsWrap"),z.attr("transform","translate("+i.left+","+i.top+")"),o&&z.select(".nv-y.nv-axis").attr("transform","translate("+s+",0)"),e.width(s).height(v);var A=z.select(".nv-barsWrap").datum(h.filter(function(a){return!a.disabled}));if(A.transition().call(e),y.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),z.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",c.rangeBand()*(p?2:1)).attr("height",16).attr("x",-c.rangeBand()/(p?1:2)),m){f.scale(c)._ticks(a.utils.calcTicksX(s/100,h)).tickSize(-v,0),z.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),z.select(".nv-x.nv-axis").call(f);var B=z.select(".nv-x.nv-axis").selectAll("g");p&&B.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(c%2==0?"5":"17")+")"}),r&&B.selectAll(".tick text").attr("transform","rotate("+r+" 0,0)").style("text-anchor",r>0?"start":"end"),q&&z.selectAll(".tick text").call(a.utils.wrapTicks,b.xAxis.rangeBand())}n&&(g.scale(d)._ticks(a.utils.calcTicksY(v/36,h)).tickSize(-s,0),z.select(".nv-y.nv-axis").call(g)),z.select(".nv-zeroLine line").attr("x1",0).attr("x2",s).attr("y1",d(0)).attr("y2",d(0))}),v.renderEnd("discreteBar chart immediate"),b}var c,d,e=a.models.discreteBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.tooltip(),i={ +top:15,right:10,bottom:50,left:60},j=null,k=null,l=a.utils.getColor(),m=!0,n=!0,o=!1,p=!1,q=!1,r=0,s=null,t=d3.dispatch("beforeUpdate","renderEnd"),u=250;f.orient("bottom").showMaxMin(!1).tickFormat(function(a){return a}),g.orient(o?"right":"left").tickFormat(d3.format(",.1f")),h.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).keyFormatter(function(a,b){return f.tickFormat()(a,b)});var v=a.utils.renderWatch(t,u);return e.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},h.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){h.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){h()}),b.dispatch=t,b.discretebar=e,b.xAxis=f,b.yAxis=g,b.tooltip=h,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return j},set:function(a){j=a}},height:{get:function(){return k},set:function(a){k=a}},staggerLabels:{get:function(){return p},set:function(a){p=a}},rotateLabels:{get:function(){return r},set:function(a){r=a}},wrapLabels:{get:function(){return q},set:function(a){q=!!a}},showXAxis:{get:function(){return m},set:function(a){m=a}},showYAxis:{get:function(){return n},set:function(a){n=a}},noData:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return i},set:function(a){i.top=void 0!==a.top?a.top:i.top,i.right=void 0!==a.right?a.right:i.right,i.bottom=void 0!==a.bottom?a.bottom:i.bottom,i.left=void 0!==a.left?a.left:i.left}},duration:{get:function(){return u},set:function(a){u=a,v.reset(u),e.duration(u),f.duration(u),g.duration(u)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),e.color(l)}},rightAlignYAxis:{get:function(){return o},set:function(a){o=a,g.orient(a?"right":"left")}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.distribution=function(){"use strict";function b(k){return m.reset(),k.each(function(b){var k=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),l=d3.select(this);a.utils.initSVG(l),c=c||j;var n=l.selectAll("g.nv-distribution").data([b]),o=n.enter().append("g").attr("class","nvd3 nv-distribution"),p=(o.append("g"),n.select("g"));n.attr("transform","translate("+d.left+","+d.top+")");var q=p.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});q.enter().append("g"),q.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var r=q.selectAll("line.nv-dist"+g).data(function(a){return a.values});r.enter().append("line").attr(g+"1",function(a,b){return c(h(a,b))}).attr(g+"2",function(a,b){return c(h(a,b))}),m.transition(q.exit().selectAll("line.nv-dist"+g),"dist exit").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}).style("stroke-opacity",0).remove(),r.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(k+"1",0).attr(k+"2",f),m.transition(r,"dist").attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),c=j.copy()}),m.renderEnd("distribution immediate"),b}var c,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=a.utils.defaultColor(),j=d3.scale.linear(),k=250,l=d3.dispatch("renderEnd"),m=a.utils.renderWatch(l,k);return b.options=a.utils.optionsFunc.bind(b),b.dispatch=l,b.margin=function(a){return arguments.length?(d.top="undefined"!=typeof a.top?a.top:d.top,d.right="undefined"!=typeof a.right?a.right:d.right,d.bottom="undefined"!=typeof a.bottom?a.bottom:d.bottom,d.left="undefined"!=typeof a.left?a.left:d.left,b):d},b.width=function(a){return arguments.length?(e=a,b):e},b.axis=function(a){return arguments.length?(g=a,b):g},b.size=function(a){return arguments.length?(f=a,b):f},b.getData=function(a){return arguments.length?(h=d3.functor(a),b):h},b.scale=function(a){return arguments.length?(j=a,b):j},b.color=function(c){return arguments.length?(i=a.utils.getColor(c),b):i},b.duration=function(a){return arguments.length?(k=a,m.reset(k),b):k},b},a.models.furiousLegend=function(){"use strict";function b(q){function r(a,b){return"furious"!=p?"#000":n?a.disengaged?g(a,b):"#fff":n?void 0:a.disabled?g(a,b):"#fff"}function s(a,b){return n&&"furious"==p?a.disengaged?"#fff":g(a,b):a.disabled?"#fff":g(a,b)}return q.each(function(b){var q=d-c.left-c.right,t=d3.select(this);a.utils.initSVG(t);var u=t.selectAll("g.nv-legend").data([b]),v=(u.enter().append("g").attr("class","nvd3 nv-legend").append("g"),u.select("g"));u.attr("transform","translate("+c.left+","+c.top+")");var w,x=v.selectAll(".nv-series").data(function(a){return"furious"!=p?a:a.filter(function(a){return n?!0:!a.disengaged})}),y=x.enter().append("g").attr("class","nv-series");if("classic"==p)y.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),w=x.select("circle");else if("furious"==p){y.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),w=x.select("rect"),y.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var z=x.select(".nv-check-box");z.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",r(a,b))})}y.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var A=x.select("text.nv-legend-text");x.on("mouseover",function(a,b){o.legendMouseover(a,b)}).on("mouseout",function(a,b){o.legendMouseout(a,b)}).on("click",function(a,b){o.legendClick(a,b);var c=x.data();if(l){if("classic"==p)m?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==p)if(n)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!n){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}o.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=p||!n)&&(o.legendDblclick(a,b),l)){var c=x.data();c.forEach(function(a){a.disabled=!0,"furious"==p&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==p&&(a.userDisabled=a.disabled),o.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),x.classed("nv-disabled",function(a){return a.userDisabled}),x.exit().remove(),A.attr("fill",r).text(f);var B;switch(p){case"furious":B=23;break;case"classic":B=20}if(i){var C=[];x.each(function(b,c){var d;if(f(b).length>h){var e=f(b).substring(0,h);d=d3.select(this).select("text").text(e+"..."),d3.select(this).append("svg:title").text(f(b))}else d=d3.select(this).select("text");var g;try{if(g=d.node().getComputedTextLength(),0>=g)throw Error()}catch(i){g=a.utils.calcApproxTextWidth(d)}C.push(g+j)});for(var D=0,E=0,F=[];q>E&&Dq&&D>1;){F=[],D--;for(var G=0;G(F[G%D]||0)&&(F[G%D]=C[G]);E=F.reduce(function(a,b,c,d){return a+b})}for(var H=[],I=0,J=0;D>I;I++)H[I]=J,J+=F[I];x.attr("transform",function(a,b){return"translate("+H[b%D]+","+(5+Math.floor(b/D)*B)+")"}),k?v.attr("transform","translate("+(d-c.right-E)+","+c.top+")"):v.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(C.length/D)*B}else{var K,L=5,M=5,N=0;x.attr("transform",function(a,b){var e=d3.select(this).select("text").node().getComputedTextLength()+j;return K=M,dN&&(N=M),"translate("+K+","+L+")"}),v.attr("transform","translate("+(d-c.right-N)+","+c.top+")"),e=c.top+c.bottom+L+15}"furious"==p&&w.attr("width",function(a,b){return A[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),w.style("fill",s).style("stroke",function(a,b){return a.color||g(a,b)})}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=20,i=!0,j=28,k=!0,l=!0,m=!1,n=!1,o=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),p="classic";return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return i},set:function(a){i=a}},rightAlign:{get:function(){return k},set:function(a){k=a}},maxKeyLength:{get:function(){return h},set:function(a){h=a}},padding:{get:function(){return j},set:function(a){j=a}},updateState:{get:function(){return l},set:function(a){l=a}},radioButtonMode:{get:function(){return m},set:function(a){m=a}},expanded:{get:function(){return n},set:function(a){n=a}},vers:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBar=function(){"use strict";function b(x){return x.each(function(b){w.reset(),k=d3.select(this);var x=a.utils.availableWidth(h,k,g),y=a.utils.availableHeight(i,k,g);a.utils.initSVG(k),l.domain(c||d3.extent(b[0].values.map(n).concat(p))),l.range(r?e||[.5*x/b[0].values.length,x*(b[0].values.length-.5)/b[0].values.length]:e||[0,x]),m.domain(d||d3.extent(b[0].values.map(o).concat(q))).range(f||[y,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var z=k.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([b[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),B=A.append("defs"),C=A.append("g"),D=z.select("g");C.append("g").attr("class","nv-bars"),z.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){u.chartClick({data:a,index:b,pos:d3.event,id:j})}),B.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),z.select("#nv-chart-clip-path-"+j+" rect").attr("width",x).attr("height",y),D.attr("clip-path",s?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return n(a,b)});E.exit().remove(),E.enter().append("rect").attr("x",0).attr("y",function(b,c){return a.utils.NaNtoZero(m(Math.max(0,o(b,c))))}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.abs(m(o(b,c))-m(0)))}).attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).on("mouseover",function(a,b){v&&(d3.select(this).classed("hover",!0),u.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mouseout",function(a,b){v&&(d3.select(this).classed("hover",!1),u.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")}))}).on("mousemove",function(a,b){v&&u.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){v&&(u.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}).on("dblclick",function(a,b){v&&(u.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation())}),E.attr("fill",function(a,b){return t(a,b)}).attr("class",function(a,b,c){return(o(a,b)<0?"nv-bar negative":"nv-bar positive")+" nv-bar-"+c+"-"+b}).watchTransition(w,"bars").attr("transform",function(a,c){return"translate("+(l(n(a,c))-x/b[0].values.length*.45)+",0)"}).attr("width",x/b[0].values.length*.9),E.watchTransition(w,"bars").attr("y",function(b,c){var d=o(b,c)<0?m(0):m(0)-m(o(b,c))<1?m(0)-1:m(o(b,c));return a.utils.NaNtoZero(d)}).attr("height",function(b,c){return a.utils.NaNtoZero(Math.max(Math.abs(m(o(b,c))-m(0)),1))})}),w.renderEnd("historicalBar immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=[],q=[0],r=!1,s=!0,t=a.utils.defaultColor(),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),v=!0,w=a.utils.renderWatch(u,0);return b.highlightPoint=function(a,b){k.select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},b.clearHighlights=function(){k.select(".nv-bars .nv-bar.hover").classed("hover",!1)},b.dispatch=u,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},forceX:{get:function(){return p},set:function(a){p=a}},forceY:{get:function(){return q},set:function(a){q=a}},padData:{get:function(){return r},set:function(a){r=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},clipEdge:{get:function(){return s},set:function(a){s=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return t},set:function(b){t=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.historicalBarChart=function(b){"use strict";function c(b){return b.each(function(k){z.reset(),z.models(f),q&&z.models(g),r&&z.models(h);var w=d3.select(this),A=this;a.utils.initSVG(w);var B=a.utils.availableWidth(n,w,l),C=a.utils.availableHeight(o,w,l);if(c.update=function(){w.transition().duration(y).call(c)},c.container=this,u.disabled=k.map(function(a){return!!a.disabled}),!v){var D;v={};for(D in u)u[D]instanceof Array?v[D]=u[D].slice(0):v[D]=u[D]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(c,w),c;w.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale();var E=w.selectAll("g.nv-wrap.nv-historicalBarChart").data([k]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBarChart").append("g"),G=E.select("g");F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-barsWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),p&&(i.width(B),G.select(".nv-legendWrap").datum(k).call(i),l.top!=i.height()&&(l.top=i.height(),C=a.utils.availableHeight(o,w,l)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")),E.attr("transform","translate("+l.left+","+l.top+")"),s&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),t&&(j.width(B).height(C).margin({left:l.left,top:l.top}).svgContainer(w).xScale(d),E.select(".nv-interactive").call(j)),f.width(B).height(C).color(k.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!k[b].disabled}));var H=G.select(".nv-barsWrap").datum(k.filter(function(a){return!a.disabled}));H.transition().call(f),q&&(g.scale(d)._ticks(a.utils.calcTicksX(B/100,k)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),G.select(".nv-x.nv-axis").transition().call(g)),r&&(h.scale(e)._ticks(a.utils.calcTicksY(C/36,k)).tickSize(-B,0),G.select(".nv-y.nv-axis").transition().call(h)),j.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,l=[];k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=a.interactiveBisect(g.values,b.pointXValue,c.x()),f.highlightPoint(e,!0);var j=g.values[e];void 0!==j&&(void 0===d&&(d=j),void 0===i&&(i=c.xScale()(c.x()(j,e))),l.push({key:g.key,value:c.y()(j,e),color:m(g,g.seriesIndex),data:g.values[e]}))});var n=g.tickFormat()(c.x()(d,e));j.tooltip.chartContainer(A.parentNode).valueFormatter(function(a,b){return h.tickFormat()(a)}).data({value:n,index:e,series:l})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(a){x.tooltipHide(),f.clearHighlights()}),i.dispatch.on("legendClick",function(a,d){a.disabled=!a.disabled,k.filter(function(a){return!a.disabled}).length||k.map(function(a){return a.disabled=!1,E.selectAll(".nv-series").classed("disabled",!1),a}),u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),b.transition().call(c)}),i.dispatch.on("legendDblclick",function(a){k.forEach(function(a){a.disabled=!0}),a.disabled=!1,u.disabled=k.map(function(a){return!!a.disabled}),x.stateChange(u),c.update()}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),c.update()})}),z.renderEnd("historicalBarChart immediate"),c}var d,e,f=b||a.models.historicalBar(),g=a.models.axis(),h=a.models.axis(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:90,bottom:50,left:90},m=a.utils.defaultColor(),n=null,o=null,p=!1,q=!0,r=!0,s=!1,t=!1,u={},v=null,w=null,x=d3.dispatch("tooltipHide","stateChange","changeState","renderEnd"),y=250;g.orient("bottom").tickPadding(7),h.orient(s?"right":"left"),k.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return h.tickFormat()(a,b)}).headerFormatter(function(a,b){return g.tickFormat()(a,b)});var z=a.utils.renderWatch(x,0);return f.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:c.x()(a.data),value:c.y()(a.data),color:a.color},k.data(a).hidden(!1)}),f.dispatch.on("elementMouseout.tooltip",function(a){k.hidden(!0)}),f.dispatch.on("elementMousemove.tooltip",function(a){k()}),c.dispatch=x,c.bars=f,c.legend=i,c.xAxis=g,c.yAxis=h,c.interactiveLayer=j,c.tooltip=k,c.options=a.utils.optionsFunc.bind(c),c._options=Object.create({},{width:{get:function(){return n},set:function(a){n=a}},height:{get:function(){return o},set:function(a){o=a}},showLegend:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return q},set:function(a){q=a}},showYAxis:{get:function(){return r},set:function(a){r=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b),i.color(m),f.color(m)}},duration:{get:function(){return y},set:function(a){y=a,z.reset(y),h.duration(y),g.duration(y)}},rightAlignYAxis:{get:function(){return s},set:function(a){s=a,h.orient(a?"right":"left")}},useInteractiveGuideline:{get:function(){return t},set:function(a){t=a,a===!0&&c.interactive(!1)}}}),a.utils.inheritOptions(c,f),a.utils.initOptions(c),c},a.models.ohlcBarChart=function(){var b=a.models.historicalBarChart(a.models.ohlcBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
open:"+b.yAxis.tickFormat()(c.open)+"
close:"+b.yAxis.tickFormat()(c.close)+"
high"+b.yAxis.tickFormat()(c.high)+"
low:"+b.yAxis.tickFormat()(c.low)+"
"}),b},a.models.candlestickBarChart=function(){var b=a.models.historicalBarChart(a.models.candlestickBar());return b.useInteractiveGuideline(!0),b.interactiveLayer.tooltip.contentGenerator(function(a){var c=a.series[0].data,d=c.open'+a.value+"
open:"+b.yAxis.tickFormat()(c.open)+"
close:"+b.yAxis.tickFormat()(c.close)+"
high"+b.yAxis.tickFormat()(c.high)+"
low:"+b.yAxis.tickFormat()(c.low)+"
"}),b},a.models.legend=function(){"use strict";function b(q){function r(a,b){return"furious"!=p?"#000":n?a.disengaged?"#000":"#fff":n?void 0:(a.color||(a.color=g(a,b)),a.disabled?a.color:"#fff")}function s(a,b){return n&&"furious"==p&&a.disengaged?"#eee":a.color||g(a,b)}function t(a,b){return n&&"furious"==p?1:a.disabled?0:1}return q.each(function(b){var g=d-c.left-c.right,q=d3.select(this);a.utils.initSVG(q);var u=q.selectAll("g.nv-legend").data([b]),v=u.enter().append("g").attr("class","nvd3 nv-legend").append("g"),w=u.select("g");u.attr("transform","translate("+c.left+","+c.top+")");var x,y,z=w.selectAll(".nv-series").data(function(a){return"furious"!=p?a:a.filter(function(a){return n?!0:!a.disengaged})}),A=z.enter().append("g").attr("class","nv-series");switch(p){case"furious":y=23;break;case"classic":y=20}if("classic"==p)A.append("circle").style("stroke-width",2).attr("class","nv-legend-symbol").attr("r",5),x=z.select("circle");else if("furious"==p){A.append("rect").style("stroke-width",2).attr("class","nv-legend-symbol").attr("rx",3).attr("ry",3),x=z.select(".nv-legend-symbol"),A.append("g").attr("class","nv-check-box").property("innerHTML",'').attr("transform","translate(-10,-8)scale(0.5)");var B=z.select(".nv-check-box");B.each(function(a,b){d3.select(this).selectAll("path").attr("stroke",r(a,b))})}A.append("text").attr("text-anchor","start").attr("class","nv-legend-text").attr("dy",".32em").attr("dx","8");var C=z.select("text.nv-legend-text");z.on("mouseover",function(a,b){o.legendMouseover(a,b)}).on("mouseout",function(a,b){o.legendMouseout(a,b)}).on("click",function(a,b){o.legendClick(a,b);var c=z.data();if(l){if("classic"==p)m?(c.forEach(function(a){a.disabled=!0}),a.disabled=!1):(a.disabled=!a.disabled,c.every(function(a){return a.disabled})&&c.forEach(function(a){a.disabled=!1}));else if("furious"==p)if(n)a.disengaged=!a.disengaged,a.userDisabled=void 0==a.userDisabled?!!a.disabled:a.userDisabled,a.disabled=a.disengaged||a.userDisabled;else if(!n){a.disabled=!a.disabled,a.userDisabled=a.disabled;var d=c.filter(function(a){return!a.disengaged});d.every(function(a){return a.userDisabled})&&c.forEach(function(a){a.disabled=a.userDisabled=!1})}o.stateChange({disabled:c.map(function(a){return!!a.disabled}),disengaged:c.map(function(a){return!!a.disengaged})})}}).on("dblclick",function(a,b){if(("furious"!=p||!n)&&(o.legendDblclick(a,b),l)){var c=z.data();c.forEach(function(a){a.disabled=!0,"furious"==p&&(a.userDisabled=a.disabled)}),a.disabled=!1,"furious"==p&&(a.userDisabled=a.disabled),o.stateChange({disabled:c.map(function(a){return!!a.disabled})})}}),z.classed("nv-disabled",function(a){return a.userDisabled}),z.exit().remove(),C.attr("fill",r).text(f);var D=0;if(i){var E=[];z.each(function(b,c){var d;if(f(b).length>h){var e=f(b).substring(0,h);d=d3.select(this).select("text").text(e+"..."),d3.select(this).append("svg:title").text(f(b))}else d=d3.select(this).select("text");var g;try{if(g=d.node().getComputedTextLength(),0>=g)throw Error()}catch(i){g=a.utils.calcApproxTextWidth(d)}E.push(g+j)});var F=0,G=[];for(D=0;g>D&&Fg&&F>1;){G=[],F--;for(var H=0;H(G[H%F]||0)&&(G[H%F]=E[H]);D=G.reduce(function(a,b,c,d){return a+b})}for(var I=[],J=0,K=0;F>J;J++)I[J]=K,K+=G[J];z.attr("transform",function(a,b){return"translate("+I[b%F]+","+(5+Math.floor(b/F)*y)+")"}),k?w.attr("transform","translate("+(d-c.right-D)+","+c.top+")"):w.attr("transform","translate(0,"+c.top+")"),e=c.top+c.bottom+Math.ceil(E.length/F)*y}else{var L,M=5,N=5,O=0;z.attr("transform",function(a,b){var e=d3.select(this).select("text").node().getComputedTextLength()+j;return L=N,dO&&(O=N),L+O>D&&(D=L+O),"translate("+L+","+M+")"}),w.attr("transform","translate("+(d-c.right-O)+","+c.top+")"),e=c.top+c.bottom+M+15}if("furious"==p){x.attr("width",function(a,b){return C[0][b].getComputedTextLength()+27}).attr("height",18).attr("y",-9).attr("x",-15),v.insert("rect",":first-child").attr("class","nv-legend-bg").attr("fill","#eee").attr("opacity",0);var P=w.select(".nv-legend-bg");P.transition().duration(300).attr("x",-y).attr("width",D+y-12).attr("height",e+10).attr("y",-c.top-10).attr("opacity",n?1:0)}x.style("fill",s).style("fill-opacity",t).style("stroke",s)}),b}var c={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=a.utils.getColor(),h=20,i=!0,j=32,k=!0,l=!0,m=!1,n=!1,o=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange"),p="classic";return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},key:{get:function(){return f},set:function(a){f=a}},align:{get:function(){return i},set:function(a){i=a}},maxKeyLength:{get:function(){return h},set:function(a){h=a}},rightAlign:{get:function(){return k},set:function(a){k=a}},padding:{get:function(){return j},set:function(a){j=a}},updateState:{get:function(){return l},set:function(a){l=a}},radioButtonMode:{get:function(){return m},set:function(a){m=a}},expanded:{get:function(){return n},set:function(a){n=a}},vers:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return g},set:function(b){g=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.line=function(){"use strict";function b(r){return v.reset(),v.models(e),r.each(function(b){i=d3.select(this);var r=a.utils.availableWidth(g,i,f),s=a.utils.availableHeight(h,i,f);a.utils.initSVG(i),c=e.xScale(),d=e.yScale(),t=t||c,u=u||d;var w=i.selectAll("g.nv-wrap.nv-line").data([b]),x=w.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),y=x.append("defs"),z=x.append("g"),A=w.select("g");z.append("g").attr("class","nv-groups"),z.append("g").attr("class","nv-scatterWrap"),w.attr("transform","translate("+f.left+","+f.top+")"),e.width(r).height(s);var B=w.select(".nv-scatterWrap");B.call(e),y.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),w.select("#nv-edge-clip-"+e.id()+" rect").attr("width",r).attr("height",s>0?s:0),A.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":""),B.attr("clip-path",p?"url(#nv-edge-clip-"+e.id()+")":"");var C=w.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});C.enter().append("g").style("stroke-opacity",1e-6).style("stroke-width",function(a){return a.strokeWidth||j}).style("fill-opacity",1e-6),C.exit().remove(),C.attr("class",function(a,b){return(a.classed||"")+" nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return k(a,b)}).style("stroke",function(a,b){return k(a,b)}),C.watchTransition(v,"line: groups").style("stroke-opacity",1).style("fill-opacity",function(a){return a.fillOpacity||.5});var D=C.selectAll("path.nv-area").data(function(a){return o(a)?[a]:[]});D.enter().append("path").attr("class","nv-area").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y0(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))}).y1(function(a,b){return u(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])}),C.exit().selectAll("path.nv-area").remove(),D.watchTransition(v,"line: areaPaths").attr("d",function(b){return d3.svg.area().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y0(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))}).y1(function(a,b){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[b.values])});var E=C.selectAll("path.nv-line").data(function(a){return[a.values]});E.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,c){return a.utils.NaNtoZero(t(l(b,c)))}).y(function(b,c){return a.utils.NaNtoZero(u(m(b,c)))})),E.watchTransition(v,"line: linePaths").attr("d",d3.svg.line().interpolate(q).defined(n).x(function(b,d){return a.utils.NaNtoZero(c(l(b,d)))}).y(function(b,c){return a.utils.NaNtoZero(d(m(b,c)))})),t=c.copy(),u=d.copy()}),v.renderEnd("line immediate"),b}var c,d,e=a.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=null,j=1.5,k=a.utils.defaultColor(),l=function(a){return a.x},m=function(a){return a.y},n=function(a,b){return!isNaN(m(a,b))&&null!==m(a,b)},o=function(a){return a.area},p=!1,q="linear",r=250,s=d3.dispatch("elementClick","elementMouseover","elementMouseout","renderEnd");e.pointSize(16).pointDomain([16,256]);var t,u,v=a.utils.renderWatch(s,r);return b.dispatch=s,b.scatter=e,e.dispatch.on("elementClick",function(){s.elementClick.apply(this,arguments)}),e.dispatch.on("elementMouseover",function(){s.elementMouseover.apply(this,arguments)}),e.dispatch.on("elementMouseout",function(){s.elementMouseout.apply(this,arguments)}),b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},defined:{get:function(){return n},set:function(a){n=a}},interpolate:{get:function(){return q},set:function(a){q=a}},clipEdge:{get:function(){return p},set:function(a){p=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}},duration:{get:function(){return r},set:function(a){r=a,v.reset(r),e.duration(r)}},isArea:{get:function(){return o},set:function(a){o=d3.functor(a)}},x:{get:function(){return l},set:function(a){l=a,e.x(a)}},y:{get:function(){return m},set:function(a){m=a,e.y(a)}},color:{get:function(){return k},set:function(b){k=a.utils.getColor(b),e.color(k)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.lineChart=function(){"use strict";function b(j){return y.reset(),y.models(e),p&&y.models(f),q&&y.models(g),j.each(function(j){var v=d3.select(this),y=this;a.utils.initSVG(v);var B=a.utils.availableWidth(m,v,k),C=a.utils.availableHeight(n,v,k);if(0>B&&(B=0),0>C&&(C=0),b.update=function(){0===x?v.call(b):v.transition().duration(x).call(b)},b.container=this,t.setter(A(j),b.update).getter(z(j)).update(),t.disabled=j.map(function(a){return!!a.disabled}),!u){var D;u={};for(D in t)t[D]instanceof Array?u[D]=t[D].slice(0):u[D]=t[D]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,v),b;v.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var E=v.selectAll("g.nv-wrap.nv-lineChart").data([j]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),G=E.select("g");F.append("rect").style("opacity",0),F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y nv-axis"),F.append("g").attr("class","nv-linesWrap"),F.append("g").attr("class","nv-legendWrap"),F.append("g").attr("class","nv-interactive"),F.append("g").attr("class","en-postMarkers"),G.select("rect").attr("width",B).attr("height",C>0?C:0); + +var H;j.some(function(a,b){return"Post Markers"==a.key?(H=j.splice(b,1)[0],!0):void 0}),o&&(h.width(B),G.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),C=a.utils.availableHeight(n,v,k)),E.select(".nv-legendWrap").attr("transform","translate(0,"+-k.top+")")),E.attr("transform","translate("+k.left+","+k.top+")"),r&&G.select(".nv-y.nv-axis").attr("transform","translate("+B+",0)"),s&&(i.width(B).height(C).margin({left:k.left,top:k.top}).svgContainer(v).xScale(c),E.select(".nv-interactive").call(i)),e.width(B).height(C).color(j.map(function(a,b){return a.color||l(a,b)}).filter(function(a,b){return!j[b].disabled}));var I=G.select(".nv-linesWrap").datum(j.filter(function(a){return!a.disabled}));if(I.call(e),H){var J;d3.select(".en-postMarkers").size()?(J=d3.select(".en-postMarkers"),J.selectAll("*").remove()):J=F.append("g").attr("class","en-postMarkers").attr("width",B).attr("height",C>0?C:0);var K=C-16,L=0;H.values.forEach(function(a,b){var e;if(j.some(function(b){(b.postURLs.indexOf(a.postURL)>-1||b.postURLs.indexOf("all")>-1)&&b.disabled&&(e=!0)}),!e){a.x=new Date(a.x);var f=Math.round(c(a.x)-8>=L?c(a.x)-8:L),g=Math.round(d(a.y)-8<=K?d(a.y)-8:K);a.markerX=f,a.markerY=g;{var h="translate("+f+","+g+")";J.append("g").attr("class","marker").attr("transform",h).append("svg:image").attr("height",16).attr("width",16).attr("xlink:href","/admin/images/icons16/"+a.network.toLowerCase()+".png")}}}),j.push(H)}p&&(f.scale(c)._ticks(a.utils.calcTicksX(B/100,j)).tickSize(-C,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),G.select(".nv-x.nv-axis").call(f)),q&&(g.scale(d)._ticks(a.utils.calcTicksY(C/36,j)).tickSize(-B,0),G.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)t[c]=a[c];w.stateChange(t),b.update()}),i.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,h,k,m=[];if(j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=a.interactiveBisect(f.values,c.pointXValue,b.x());var i=f.values[h],j=b.y()(i,h);null!=j&&e.highlightPoint(g,h,!0),void 0!==i&&(void 0===d&&(d=i),void 0===k&&(k=b.xScale()(b.x()(i,h))),m.push({key:f.key,value:j,color:l(f,f.seriesIndex)}))}),m.length>2){var n=b.yScale().invert(c.mouseY),o=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),p=.03*o,q=a.nearestValueIndex(m.map(function(a){return a.value}),n,p);null!==q&&(m[q].highlight=!0)}var r;H&&H.values.forEach(function(a){c.mouseX>=a.markerX&&c.mouseX<=a.markerX+16&&c.mouseY>=a.markerY&&c.mouseY<=a.markerY+16&&(r={label:a.label,postDate:a.x})});var s=f.tickFormat()(b.x()(d,h)),t={value:s,index:h,series:m};r&&(t.postMarkerTooltip=r),i.tooltip.chartContainer(y.parentNode).valueFormatter(function(a,b){return null==a?"N/A":g.tickFormat()(a)}).data(t)(),i.renderGuideLine(k)}),i.dispatch.on("elementClick",function(c){var d,f=[];j.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(e){var g=a.interactiveBisect(e.values,c.pointXValue,b.x()),h=e.values[g];if("undefined"!=typeof h){"undefined"==typeof d&&(d=b.xScale()(b.x()(h,g)));var i=b.yScale()(b.y()(h,g));f.push({point:h,pointIndex:g,pos:[d,i],seriesIndex:e.seriesIndex,series:e})}}),e.dispatch.elementClick(f)}),i.dispatch.on("elementMouseout",function(a){e.clearHighlights()}),w.on("changeState",function(a){"undefined"!=typeof a.disabled&&j.length===a.disabled.length&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),t.disabled=a.disabled),b.update()})}),y.renderEnd("lineChart immediate"),b}var c,d,e=a.models.line(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.interactiveGuideline(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=a.utils.defaultColor(),m=null,n=null,o=!0,p=!0,q=!0,r=!1,s=!1,t=a.utils.state(),u=null,v=null,w=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState","renderEnd"),x=250;f.orient("bottom").tickPadding(7),g.orient(r?"right":"left"),j.valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)});var y=a.utils.renderWatch(w,x),z=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},A=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){j.hidden(!0)}),b.dispatch=w,b.lines=e,b.legend=h,b.xAxis=f,b.yAxis=g,b.interactiveLayer=i,b.tooltip=j,b.dispatch=w,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return o},set:function(a){o=a}},showXAxis:{get:function(){return p},set:function(a){p=a}},showYAxis:{get:function(){return q},set:function(a){q=a}},defaultState:{get:function(){return u},set:function(a){u=a}},noData:{get:function(){return v},set:function(a){v=a}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return x},set:function(a){x=a,y.reset(x),e.duration(x),f.duration(x),g.duration(x)}},color:{get:function(){return l},set:function(b){l=a.utils.getColor(b),h.color(l),e.color(l)}},rightAlignYAxis:{get:function(){return r},set:function(a){r=a,g.orient(r?"right":"left")}},useInteractiveGuideline:{get:function(){return s},set:function(a){s=a,s&&(e.interactive(!1),e.useVoronoi(!1))}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.linePlusBarChart=function(){"use strict";function b(v){return v.each(function(v){function J(a){var b=+("e"==a),c=b?1:-1,d=Y/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function T(){u.empty()||u.extent(I),la.data([u.empty()?e.domain():I]).each(function(a,b){var c=e(a[0])-e.range()[0],d=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>c?0:c),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>d?0:d)})}function U(){I=u.empty()?null:u.extent(),c=u.empty()?e.domain():u.extent(),K.brush({extent:c,brush:u}),T(),l.width(W).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),j.width(W).height(X).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var b=ea.select(".nv-focus .nv-barsWrap").datum($.length?$.map(function(a,b){return{key:a.key,values:a.values.filter(function(a,b){return l.x()(a,b)>=c[0]&&l.x()(a,b)<=c[1]})}}):[{values:[]}]),h=ea.select(".nv-focus .nv-linesWrap").datum(S(_)?[{values:[]}]:_.filter(function(a){return!a.disabled}).map(function(a,b){return{area:a.area,fillOpacity:a.fillOpacity,key:a.key,values:a.values.filter(function(a,b){return j.x()(a,b)>=c[0]&&j.x()(a,b)<=c[1]})}}));d=$.length?l.xScale():j.xScale(),n.scale(d)._ticks(a.utils.calcTicksX(W/100,v)).tickSize(-X,0),n.domain([Math.ceil(c[0]),Math.floor(c[1])]),ea.select(".nv-x.nv-axis").transition().duration(L).call(n),b.transition().duration(L).call(l),h.transition().duration(L).call(j),ea.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f)._ticks(a.utils.calcTicksY(X/36,v)).tickSize(-W,0),q.scale(g)._ticks(a.utils.calcTicksY(X/36,v)).tickSize($.length?0:-W,0),ea.select(".nv-focus .nv-y1.nv-axis").style("opacity",$.length?1:0),ea.select(".nv-focus .nv-y2.nv-axis").style("opacity",_.length&&!S(_)?1:0).attr("transform","translate("+d.range()[1]+",0)"),ea.select(".nv-focus .nv-y1.nv-axis").transition().duration(L).call(p),ea.select(".nv-focus .nv-y2.nv-axis").transition().duration(L).call(q)}var V=d3.select(this);a.utils.initSVG(V);var W=a.utils.availableWidth(y,V,w),X=a.utils.availableHeight(z,V,w)-(E?H:0),Y=H-x.top-x.bottom;if(b.update=function(){V.transition().duration(L).call(b)},b.container=this,M.setter(R(v),b.update).getter(Q(v)).update(),M.disabled=v.map(function(a){return!!a.disabled}),!N){var Z;N={};for(Z in M)M[Z]instanceof Array?N[Z]=M[Z].slice(0):N[Z]=M[Z]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length))return a.utils.noData(b,V),b;V.selectAll(".nv-noData").remove();var $=v.filter(function(a){return!a.disabled&&a.bar}),_=v.filter(function(a){return!a.bar});d=l.xScale(),e=o.scale(),f=l.yScale(),g=j.yScale(),h=m.yScale(),i=k.yScale();var aa=v.filter(function(a){return!a.disabled&&a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})}),ba=v.filter(function(a){return!a.disabled&&!a.bar}).map(function(a){return a.values.map(function(a,b){return{x:A(a,b),y:B(a,b)}})});d.range([0,W]),e.domain(d3.extent(d3.merge(aa.concat(ba)),function(a){return a.x})).range([0,W]);var ca=V.selectAll("g.nv-wrap.nv-linePlusBar").data([v]),da=ca.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),ea=ca.select("g");da.append("g").attr("class","nv-legendWrap");var fa=da.append("g").attr("class","nv-focus");fa.append("g").attr("class","nv-x nv-axis"),fa.append("g").attr("class","nv-y1 nv-axis"),fa.append("g").attr("class","nv-y2 nv-axis"),fa.append("g").attr("class","nv-barsWrap"),fa.append("g").attr("class","nv-linesWrap");var ga=da.append("g").attr("class","nv-context");if(ga.append("g").attr("class","nv-x nv-axis"),ga.append("g").attr("class","nv-y1 nv-axis"),ga.append("g").attr("class","nv-y2 nv-axis"),ga.append("g").attr("class","nv-barsWrap"),ga.append("g").attr("class","nv-linesWrap"),ga.append("g").attr("class","nv-brushBackground"),ga.append("g").attr("class","nv-x nv-brush"),D){var ha=t.align()?W/2:W,ia=t.align()?ha:0;t.width(ha),ea.select(".nv-legendWrap").datum(v.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?O:P),a})).call(t),w.top!=t.height()&&(w.top=t.height(),X=a.utils.availableHeight(z,V,w)-H),ea.select(".nv-legendWrap").attr("transform","translate("+ia+","+-w.top+")")}ca.attr("transform","translate("+w.left+","+w.top+")"),ea.select(".nv-context").style("display",E?"initial":"none"),m.width(W).height(Y).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&v[b].bar})),k.width(W).height(Y).color(v.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!v[b].disabled&&!v[b].bar}));var ja=ea.select(".nv-context .nv-barsWrap").datum($.length?$:[{values:[]}]),ka=ea.select(".nv-context .nv-linesWrap").datum(S(_)?[{values:[]}]:_.filter(function(a){return!a.disabled}));ea.select(".nv-context").attr("transform","translate(0,"+(X+w.bottom+x.top)+")"),ja.transition().call(m),ka.transition().call(k),G&&(o._ticks(a.utils.calcTicksX(W/100,v)).tickSize(-Y,0),ea.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),ea.select(".nv-context .nv-x.nv-axis").transition().call(o)),F&&(r.scale(h)._ticks(Y/36).tickSize(-W,0),s.scale(i)._ticks(Y/36).tickSize($.length?0:-W,0),ea.select(".nv-context .nv-y3.nv-axis").style("opacity",$.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),ea.select(".nv-context .nv-y2.nv-axis").style("opacity",_.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),ea.select(".nv-context .nv-y1.nv-axis").transition().call(r),ea.select(".nv-context .nv-y2.nv-axis").transition().call(s)),u.x(e).on("brush",U),I&&u.extent(I);var la=ea.select(".nv-brushBackground").selectAll("g").data([I||u.extent()]),ma=la.enter().append("g");ma.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",Y),ma.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",Y);var na=ea.select(".nv-x.nv-brush").call(u);na.selectAll("rect").attr("height",Y),na.selectAll(".resize").append("path").attr("d",J),t.dispatch.on("stateChange",function(a){for(var c in a)M[c]=a[c];K.stateChange(M),b.update()}),K.on("changeState",function(a){"undefined"!=typeof a.disabled&&(v.forEach(function(b,c){b.disabled=a.disabled[c]}),M.disabled=a.disabled),b.update()}),U()}),b}var c,d,e,f,g,h,i,j=a.models.line(),k=a.models.line(),l=a.models.historicalBar(),m=a.models.historicalBar(),n=a.models.axis(),o=a.models.axis(),p=a.models.axis(),q=a.models.axis(),r=a.models.axis(),s=a.models.axis(),t=a.models.legend(),u=d3.svg.brush(),v=a.models.tooltip(),w={top:30,right:30,bottom:30,left:60},x={top:0,right:30,bottom:20,left:60},y=null,z=null,A=function(a){return a.x},B=function(a){return a.y},C=a.utils.defaultColor(),D=!0,E=!0,F=!1,G=!0,H=50,I=null,J=null,K=d3.dispatch("brush","stateChange","changeState"),L=0,M=a.utils.state(),N=null,O=" (left axis)",P=" (right axis)";j.clipEdge(!0),k.interactive(!1),k.pointActive(function(a){return!1}),n.orient("bottom").tickPadding(5),p.orient("left"),q.orient("right"),o.orient("bottom").tickPadding(5),r.orient("left"),s.orient("right"),v.headerEnabled(!0).headerFormatter(function(a,b){return n.tickFormat()(a,b)});var Q=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},R=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},S=function(a){return a.every(function(a){return a.disabled})};return j.dispatch.on("elementMouseover.tooltip",function(a){v.duration(100).valueFormatter(function(a,b){return q.tickFormat()(a,b)}).data(a).hidden(!1)}),j.dispatch.on("elementMouseout.tooltip",function(a){v.hidden(!0)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={value:b.y()(a.data),color:a.color},v.duration(0).valueFormatter(function(a,b){return p.tickFormat()(a,b)}).data(a).hidden(!1)}),l.dispatch.on("elementMouseout.tooltip",function(a){v.hidden(!0)}),l.dispatch.on("elementMousemove.tooltip",function(a){v()}),b.dispatch=K,b.legend=t,b.lines=j,b.lines2=k,b.bars=l,b.bars2=m,b.xAxis=n,b.x2Axis=o,b.y1Axis=p,b.y2Axis=q,b.y3Axis=r,b.y4Axis=s,b.tooltip=v,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return y},set:function(a){y=a}},height:{get:function(){return z},set:function(a){z=a}},showLegend:{get:function(){return D},set:function(a){D=a}},brushExtent:{get:function(){return I},set:function(a){I=a}},noData:{get:function(){return J},set:function(a){J=a}},focusEnable:{get:function(){return E},set:function(a){E=a}},focusHeight:{get:function(){return H},set:function(a){H=a}},focusShowAxisX:{get:function(){return G},set:function(a){G=a}},focusShowAxisY:{get:function(){return F},set:function(a){F=a}},legendLeftAxisHint:{get:function(){return O},set:function(a){O=a}},legendRightAxisHint:{get:function(){return P},set:function(a){P=a}},margin:{get:function(){return w},set:function(a){w.top=void 0!==a.top?a.top:w.top,w.right=void 0!==a.right?a.right:w.right,w.bottom=void 0!==a.bottom?a.bottom:w.bottom,w.left=void 0!==a.left?a.left:w.left}},focusMargin:{get:function(){return x},set:function(a){x.top=void 0!==a.top?a.top:x.top,x.right=void 0!==a.right?a.right:x.right,x.bottom=void 0!==a.bottom?a.bottom:x.bottom,x.left=void 0!==a.left?a.left:x.left}},duration:{get:function(){return L},set:function(a){L=a}},color:{get:function(){return C},set:function(b){C=a.utils.getColor(b),t.color(C)}},x:{get:function(){return A},set:function(a){A=a,j.x(a),k.x(a),l.x(a),m.x(a)}},y:{get:function(){return B},set:function(a){B=a,j.y(a),k.y(a),l.y(a),m.y(a)}}}),a.utils.inheritOptions(b,j),a.utils.initOptions(b),b},a.models.lineWithFocusChart=function(){"use strict";function b(o){return o.each(function(o){function z(a){var b=+("e"==a),c=b?1:-1,d=M/3;return"M"+.5*c+","+d+"A6,6 0 0 "+b+" "+6.5*c+","+(d+6)+"V"+(2*d-6)+"A6,6 0 0 "+b+" "+.5*c+","+2*d+"ZM"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function G(){n.empty()||n.extent(y),U.data([n.empty()?e.domain():y]).each(function(a,b){var d=e(a[0])-c.range()[0],f=K-e(a[1]);d3.select(this).select(".left").attr("width",0>d?0:d),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>f?0:f)})}function H(){y=n.empty()?null:n.extent();var a=n.empty()?e.domain():n.extent();if(!(Math.abs(a[0]-a[1])<=1)){A.brush({extent:a,brush:n}),G();var b=Q.select(".nv-focus .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}).map(function(b,c){return{key:b.key,area:b.area,classed:b.classed,values:b.values.filter(function(b,c){return g.x()(b,c)>=a[0]&&g.x()(b,c)<=a[1]})}}));b.transition().duration(B).call(g),Q.select(".nv-focus .nv-x.nv-axis").transition().duration(B).call(i),Q.select(".nv-focus .nv-y.nv-axis").transition().duration(B).call(j)}}var I=d3.select(this),J=this;a.utils.initSVG(I);var K=a.utils.availableWidth(t,I,q),L=a.utils.availableHeight(u,I,q)-v,M=v-r.top-r.bottom;if(b.update=function(){I.transition().duration(B).call(b)},b.container=this,C.setter(F(o),b.update).getter(E(o)).update(),C.disabled=o.map(function(a){return!!a.disabled}),!D){var N;D={};for(N in C)C[N]instanceof Array?D[N]=C[N].slice(0):D[N]=C[N]}if(!(o&&o.length&&o.filter(function(a){return a.values.length}).length))return a.utils.noData(b,I),b;I.selectAll(".nv-noData").remove(),c=g.xScale(),d=g.yScale(),e=h.xScale(),f=h.yScale();var O=I.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([o]),P=O.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),Q=O.select("g");P.append("g").attr("class","nv-legendWrap");var R=P.append("g").attr("class","nv-focus");R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-linesWrap"),R.append("g").attr("class","nv-interactive");var S=P.append("g").attr("class","nv-context");S.append("g").attr("class","nv-x nv-axis"),S.append("g").attr("class","nv-y nv-axis"),S.append("g").attr("class","nv-linesWrap"),S.append("g").attr("class","nv-brushBackground"),S.append("g").attr("class","nv-x nv-brush"),x&&(m.width(K),Q.select(".nv-legendWrap").datum(o).call(m),q.top!=m.height()&&(q.top=m.height(),L=a.utils.availableHeight(u,I,q)-v),Q.select(".nv-legendWrap").attr("transform","translate(0,"+-q.top+")")),O.attr("transform","translate("+q.left+","+q.top+")"),w&&(p.width(K).height(L).margin({left:q.left,top:q.top}).svgContainer(I).xScale(c),O.select(".nv-interactive").call(p)),g.width(K).height(L).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),h.defined(g.defined()).width(K).height(M).color(o.map(function(a,b){return a.color||s(a,b)}).filter(function(a,b){return!o[b].disabled})),Q.select(".nv-context").attr("transform","translate(0,"+(L+q.bottom+r.top)+")");var T=Q.select(".nv-context .nv-linesWrap").datum(o.filter(function(a){return!a.disabled}));d3.transition(T).call(h),i.scale(c)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-L,0),j.scale(d)._ticks(a.utils.calcTicksY(L/36,o)).tickSize(-K,0),Q.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+L+")"),n.x(e).on("brush",function(){H()}),y&&n.extent(y);var U=Q.select(".nv-brushBackground").selectAll("g").data([y||n.extent()]),V=U.enter().append("g");V.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",M),V.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",M);var W=Q.select(".nv-x.nv-brush").call(n);W.selectAll("rect").attr("height",M),W.selectAll(".resize").append("path").attr("d",z),H(),k.scale(e)._ticks(a.utils.calcTicksX(K/100,o)).tickSize(-M,0),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),d3.transition(Q.select(".nv-context .nv-x.nv-axis")).call(k),l.scale(f)._ticks(a.utils.calcTicksY(M/36,o)).tickSize(-K,0),d3.transition(Q.select(".nv-context .nv-y.nv-axis")).call(l),Q.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),m.dispatch.on("stateChange",function(a){for(var c in a)C[c]=a[c];A.stateChange(C),b.update()}),p.dispatch.on("elementMousemove",function(c){g.clearHighlights();var d,f,h,k=[];if(o.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(i,j){var l=n.empty()?e.domain():n.extent(),m=i.values.filter(function(a,b){return g.x()(a,b)>=l[0]&&g.x()(a,b)<=l[1]});f=a.interactiveBisect(m,c.pointXValue,g.x());var o=m[f],p=b.y()(o,f);null!=p&&g.highlightPoint(j,f,!0),void 0!==o&&(void 0===d&&(d=o),void 0===h&&(h=b.xScale()(b.x()(o,f))),k.push({key:i.key,value:b.y()(o,f),color:s(i,i.seriesIndex)}))}),k.length>2){var l=b.yScale().invert(c.mouseY),m=Math.abs(b.yScale().domain()[0]-b.yScale().domain()[1]),q=.03*m,r=a.nearestValueIndex(k.map(function(a){return a.value}),l,q);null!==r&&(k[r].highlight=!0)}var t=i.tickFormat()(b.x()(d,f));p.tooltip.chartContainer(J.parentNode).valueFormatter(function(a,b){return null==a?"N/A":j.tickFormat()(a)}).data({value:t,index:f,series:k})(),p.renderGuideLine(h)}),p.dispatch.on("elementMouseout",function(a){g.clearHighlights()}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&o.forEach(function(b,c){b.disabled=a.disabled[c]}),b.update()})}),b}var c,d,e,f,g=a.models.line(),h=a.models.line(),i=a.models.axis(),j=a.models.axis(),k=a.models.axis(),l=a.models.axis(),m=a.models.legend(),n=d3.svg.brush(),o=a.models.tooltip(),p=a.interactiveGuideline(),q={top:30,right:30,bottom:30,left:60},r={top:0,right:30,bottom:20,left:60},s=a.utils.defaultColor(),t=null,u=null,v=50,w=!1,x=!0,y=null,z=null,A=d3.dispatch("brush","stateChange","changeState"),B=250,C=a.utils.state(),D=null;g.clipEdge(!0).duration(0),h.interactive(!1),h.pointActive(function(a){return!1}),i.orient("bottom").tickPadding(5),j.orient("left"),k.orient("bottom").tickPadding(5),l.orient("left"),o.valueFormatter(function(a,b){return j.tickFormat()(a,b)}).headerFormatter(function(a,b){return i.tickFormat()(a,b)});var E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return g.dispatch.on("elementMouseover.tooltip",function(a){o.data(a).hidden(!1)}),g.dispatch.on("elementMouseout.tooltip",function(a){o.hidden(!0)}),b.dispatch=A,b.legend=m,b.lines=g,b.lines2=h,b.xAxis=i,b.yAxis=j,b.x2Axis=k,b.y2Axis=l,b.interactiveLayer=p,b.tooltip=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return t},set:function(a){t=a}},height:{get:function(){return u},set:function(a){u=a}},focusHeight:{get:function(){return v},set:function(a){v=a}},showLegend:{get:function(){return x},set:function(a){x=a}},brushExtent:{get:function(){return y},set:function(a){y=a}},defaultState:{get:function(){return D},set:function(a){D=a}},noData:{get:function(){return z},set:function(a){z=a}},margin:{get:function(){return q},set:function(a){q.top=void 0!==a.top?a.top:q.top,q.right=void 0!==a.right?a.right:q.right,q.bottom=void 0!==a.bottom?a.bottom:q.bottom,q.left=void 0!==a.left?a.left:q.left}},focusMargin:{get:function(){return r},set:function(a){r.top=void 0!==a.top?a.top:r.top,r.right=void 0!==a.right?a.right:r.right,r.bottom=void 0!==a.bottom?a.bottom:r.bottom,r.left=void 0!==a.left?a.left:r.left}},color:{get:function(){return s},set:function(b){s=a.utils.getColor(b),m.color(s)}},interpolate:{get:function(){return g.interpolate()},set:function(a){g.interpolate(a),h.interpolate(a)}},xTickFormat:{get:function(){return i.tickFormat()},set:function(a){i.tickFormat(a),k.tickFormat(a)}},yTickFormat:{get:function(){return j.tickFormat()},set:function(a){j.tickFormat(a),l.tickFormat(a)}},duration:{get:function(){return B},set:function(a){B=a,j.duration(B),l.duration(B),i.duration(B),k.duration(B)}},x:{get:function(){return g.x()},set:function(a){g.x(a),h.x(a)}},y:{get:function(){return g.y()},set:function(a){g.y(a),h.y(a)}},useInteractiveGuideline:{get:function(){return w},set:function(a){w=a,w&&(g.interactive(!1),g.useVoronoi(!1))}}}),a.utils.inheritOptions(b,g),a.utils.initOptions(b),b},a.models.multiBar=function(){"use strict";function b(E){return C.reset(),E.each(function(b){var E=k-j.left-j.right,F=l-j.top-j.bottom;0>E&&(E=0),0>F&&(F=0),p=d3.select(this),a.utils.initSVG(p);var G=0;if(x&&b.length&&(x=[{values:b[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),u){var H=d3.layout.stack().offset(v).values(function(a){return a.values}).y(r)(!b.length&&x?x:b);H.forEach(function(a,c){a.nonStackable?(b[c].nonStackableSeries=G++,H[c]=b[c]):c>0&&H[c-1].nonStackable&&H[c].values.map(function(a,b){a.y0-=H[c-1].values[b].y,a.y1=a.y0+a.y})}),b=H}b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),u&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a,f){if(!b[f].nonStackable){var g=a.values[c];g.size=Math.abs(g.y),g.y<0?(g.y1=e,e-=g.size):(g.y1=g.size+d,d+=g.size)}})});var I=d&&e?[]:b.map(function(a,b){return a.values.map(function(a,c){return{x:q(a,c),y:r(a,c),y0:a.y0,y1:a.y1,idx:b}})});m.domain(d||d3.merge(I).map(function(a){return a.x})).rangeBands(f||[0,E],A),n.domain(e||d3.extent(d3.merge(I).map(function(a){var c=a.y;return u&&!b[a.idx].nonStackable&&(c=a.y>0?a.y1:a.y1+a.y),c}).concat(s))).range(g||[F,0]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]:[-1,1]),h=h||m,i=i||n;var J=p.selectAll("g.nv-wrap.nv-multibar").data([b]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),L=K.append("defs"),M=K.append("g"),N=J.select("g");M.append("g").attr("class","nv-groups"),J.attr("transform","translate("+j.left+","+j.top+")"),L.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),J.select("#nv-edge-clip-"+o+" rect").attr("width",E).attr("height",F),N.attr("clip-path",t?"url(#nv-edge-clip-"+o+")":"");var O=J.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});O.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6);var P=C.transition(O.exit().selectAll("rect.nv-bar"),"multibarExit",Math.min(100,z)).attr("y",function(a,c,d){var e=i(0)||0;return u&&b[a.series]&&!b[a.series].nonStackable&&(e=i(a.y0)),e}).attr("height",0).remove();P.delay&&P.delay(function(a,b){var c=b*(z/(D+1))-b;return c}),O.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return w(a,b)}).style("stroke",function(a,b){return w(a,b)}),O.style("stroke-opacity",1).style("fill-opacity",.75);var Q=O.selectAll("rect.nv-bar").data(function(a){return x&&!b.length?x.values:a.values});Q.exit().remove();Q.enter().append("rect").attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(a,c,d){return u&&!b[d].nonStackable?0:d*m.rangeBand()/b.length}).attr("y",function(a,c,d){return i(u&&!b[d].nonStackable?a.y0:0)||0}).attr("height",0).attr("width",function(a,c,d){return m.rangeBand()/(u&&!b[d].nonStackable?1:b.length)}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"});Q.style("fill",function(a,b,c){return w(a,c,b)}).style("stroke",function(a,b,c){return w(a,c,b)}).on("mouseover",function(a,b){d3.select(this).classed("hover",!0),B.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),B.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){B.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){B.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){B.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),Q.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("transform",function(a,b){return"translate("+m(q(a,b))+",0)"}),y&&(c||(c=b.map(function(){return!0})),Q.style("fill",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(y(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}));var R=Q.watchTransition(C,"multibar",Math.min(250,z)).delay(function(a,c){return c*z/b[0].values.length});u?R.attr("y",function(a,c,d){var e=0;return e=b[d].nonStackable?r(a,c)<0?n(0):n(0)-n(r(a,c))<-1?n(0)-1:n(r(a,c))||0:n(a.y1)}).attr("height",function(a,c,d){return b[d].nonStackable?Math.max(Math.abs(n(r(a,c))-n(0)),0)||0:Math.max(Math.abs(n(a.y+a.y0)-n(a.y0)),0)}).attr("x",function(a,c,d){var e=0;return b[d].nonStackable&&(e=a.series*m.rangeBand()/b.length,b.length!==G&&(e=b[d].nonStackableSeries*m.rangeBand()/(2*G))),e}).attr("width",function(a,c,d){if(b[d].nonStackable){var e=m.rangeBand()/G;return b.length!==G&&(e=m.rangeBand()/(2*G)),e}return m.rangeBand()}):R.attr("x",function(a,c){return a.series*m.rangeBand()/b.length}).attr("width",m.rangeBand()/b.length).attr("y",function(a,b){return r(a,b)<0?n(0):n(0)-n(r(a,b))<1?n(0)-1:n(r(a,b))||0}).attr("height",function(a,b){return Math.max(Math.abs(n(r(a,b))-n(0)),1)||0}),h=m.copy(),i=n.copy(),b[0]&&b[0].values&&(D=b[0].values.length)}),C.renderEnd("multibar immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=d3.scale.ordinal(),n=d3.scale.linear(),o=Math.floor(1e4*Math.random()),p=null,q=function(a){return a.x},r=function(a){return a.y},s=[0],t=!0,u=!1,v="zero",w=a.utils.defaultColor(),x=!1,y=null,z=500,A=.1,B=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),C=a.utils.renderWatch(B,z),D=0;return b.dispatch=B,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return s},set:function(a){s=a}},stacked:{get:function(){return u},set:function(a){u=a}},stackOffset:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return t},set:function(a){t=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return o},set:function(a){o=a}},hideable:{get:function(){return x},set:function(a){x=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z)}},color:{get:function(){return w},set:function(b){w=a.utils.getColor(b)}},barColor:{get:function(){return y},set:function(b){y=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarChart=function(){"use strict";function b(j){return E.reset(),E.models(e),r&&E.models(f),s&&E.models(g),j.each(function(j){var A=d3.select(this);a.utils.initSVG(A);var E=a.utils.availableWidth(l,A,k),I=a.utils.availableHeight(m,A,k);if(b.update=function(){0===D?A.call(b):A.transition().duration(D).call(b)},b.container=this,y.setter(H(j),b.update).getter(G(j)).update(),y.disabled=j.map(function(a){return!!a.disabled}),!z){var J;z={};for(J in y)y[J]instanceof Array?z[J]=y[J].slice(0):z[J]=y[J]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,A),b;A.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var K=A.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([j]),L=K.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),M=K.select("g"); + +if(L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-barsWrap"),L.append("g").attr("class","nv-legendWrap"),L.append("g").attr("class","nv-controlsWrap"),q&&(h.width(E-C()),M.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),I=a.utils.availableHeight(m,A,k)),M.select(".nv-legendWrap").attr("transform","translate("+C()+","+-k.top+")")),o){var N=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(C()).color(["#444","#444","#444"]),M.select(".nv-controlsWrap").datum(N).attr("transform","translate(0,"+-k.top+")").call(i)}K.attr("transform","translate("+k.left+","+k.top+")"),t&&M.select(".nv-y.nv-axis").attr("transform","translate("+E+",0)"),e.disabled(j.map(function(a){return a.disabled})).width(E).height(I).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var O=M.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(O.call(e),r){f.scale(c)._ticks(a.utils.calcTicksX(E/100,j)).tickSize(-I,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),M.select(".nv-x.nv-axis").call(f);var P=M.select(".nv-x.nv-axis > g").selectAll("g");if(P.selectAll("line, text").style("opacity",1),v){var Q=function(a,b){return"translate("+a+","+b+")"},R=5,S=17;P.selectAll("text").attr("transform",function(a,b,c){return Q(0,c%2==0?R:S)});var T=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;M.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return Q(0,0===b||T%2!==0?S:R)})}w&&M.selectAll(".tick text").call(a.utils.wrapTicks,b.xAxis.rangeBand()),u&&P.filter(function(a,b){return b%Math.ceil(j[0].values.length/(E/100))!==0}).selectAll("text, line").style("opacity",0),x&&P.selectAll(".tick text").attr("transform","rotate("+x+" 0,0)").style("text-anchor",x>0?"start":"end"),M.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}s&&(g.scale(d)._ticks(a.utils.calcTicksY(I/36,j)).tickSize(-E,0),M.select(".nv-y.nv-axis").call(g)),h.dispatch.on("stateChange",function(a){for(var c in a)y[c]=a[c];B.stateChange(y),b.update()}),i.dispatch.on("legendClick",function(a,c){if(a.disabled){switch(N=N.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":case p.grouped:e.stacked(!1);break;case"Stacked":case p.stacked:e.stacked(!0)}y.stacked=e.stacked(),B.stateChange(y),b.update()}}),B.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),y.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),y.stacked=a.stacked,F=a.stacked),b.update()})}),E.renderEnd("multibarchart immediate"),b}var c,d,e=a.models.multiBar(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=!0,v=!1,w=!1,x=0,y=a.utils.state(),z=null,A=null,B=d3.dispatch("stateChange","changeState","renderEnd"),C=function(){return o?180:0},D=250;y.stacked=!1,e.stacked(!1),f.orient("bottom").tickPadding(7).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(t?"right":"left").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var E=a.utils.renderWatch(B),F=!1,G=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:F}}},H=function(a){return function(b){void 0!==b.stacked&&(F=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){j()}),b.dispatch=B,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=y,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return z},set:function(a){z=a}},noData:{get:function(){return A},set:function(a){A=a}},reduceXTicks:{get:function(){return u},set:function(a){u=a}},rotateLabels:{get:function(){return x},set:function(a){x=a}},staggerLabels:{get:function(){return v},set:function(a){v=a}},wrapLabels:{get:function(){return w},set:function(a){w=!!a}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return D},set:function(a){D=a,e.duration(D),f.duration(D),g.duration(D),E.reset(D)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiBarHorizontal=function(){"use strict";function b(m){return E.reset(),m.each(function(b){var m=k-j.left-j.right,C=l-j.top-j.bottom;n=d3.select(this),a.utils.initSVG(n),w&&(b=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(r)(b)),b.forEach(function(a,b){a.values.forEach(function(c){c.series=b,c.key=a.key})}),w&&b[0].values.map(function(a,c){var d=0,e=0;b.map(function(a){var b=a.values[c];b.size=Math.abs(b.y),b.y<0?(b.y1=e-b.size,e-=b.size):(b.y1=d,d+=b.size)})});var F=d&&e?[]:b.map(function(a){return a.values.map(function(a,b){return{x:q(a,b),y:r(a,b),y0:a.y0,y1:a.y1}})});o.domain(d||d3.merge(F).map(function(a){return a.x})).rangeBands(f||[0,C],A),p.domain(e||d3.extent(d3.merge(F).map(function(a){return w?a.y>0?a.y1+a.y:a.y1:a.y}).concat(t))),p.range(x&&!w?g||[p.domain()[0]<0?z:0,m-(p.domain()[1]>0?z:0)]:g||[0,m]),h=h||o,i=i||d3.scale.linear().domain(p.domain()).range([p(0),p(0)]);{var G=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([b]),H=G.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal"),I=(H.append("defs"),H.append("g"));G.select("g")}I.append("g").attr("class","nv-groups"),G.attr("transform","translate("+j.left+","+j.top+")");var J=G.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});J.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),J.exit().watchTransition(E,"multibarhorizontal: exit groups").style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),J.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return u(a,b)}).style("stroke",function(a,b){return u(a,b)}),J.watchTransition(E,"multibarhorizontal: groups").style("stroke-opacity",1).style("fill-opacity",.75);var K=J.selectAll("g.nv-bar").data(function(a){return a.values});K.exit().remove();var L=K.enter().append("g").attr("transform",function(a,c,d){return"translate("+i(w?a.y0:0)+","+(w?0:d*o.rangeBand()/b.length+o(q(a,c)))+")"});L.append("rect").attr("width",0).attr("height",o.rangeBand()/(w?1:b.length)),K.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),D.elementMouseover({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){D.elementMouseout({data:a,index:b,color:d3.select(this).style("fill")})}).on("mousemove",function(a,b){D.elementMousemove({data:a,index:b,color:d3.select(this).style("fill")})}).on("click",function(a,b){D.elementClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}).on("dblclick",function(a,b){D.elementDblClick({data:a,index:b,color:d3.select(this).style("fill")}),d3.event.stopPropagation()}),s(b[0],0)&&(L.append("polyline"),K.select("polyline").attr("fill","none").attr("points",function(a,c){var d=s(a,c),e=.8*o.rangeBand()/(2*(w?1:b.length));d=d.length?d:[-Math.abs(d),Math.abs(d)],d=d.map(function(a){return p(a)-p(0)});var f=[[d[0],-e],[d[0],e],[d[0],0],[d[1],0],[d[1],-e],[d[1],e]];return f.map(function(a){return a.join(",")}).join(" ")}).attr("transform",function(a,c){var d=o.rangeBand()/(2*(w?1:b.length));return"translate("+(r(a,c)<0?0:p(r(a,c))-p(0))+", "+d+")"})),L.append("text"),x&&!w?(K.select("text").attr("text-anchor",function(a,b){return r(a,b)<0?"end":"start"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){var c=B(r(a,b)),d=s(a,b);return void 0===d?c:d.length?c+"+"+B(Math.abs(d[1]))+"-"+B(Math.abs(d[0])):c+"±"+B(Math.abs(d))}),K.watchTransition(E,"multibarhorizontal: bars").select("text").attr("x",function(a,b){return r(a,b)<0?-4:p(r(a,b))-p(0)+4})):K.selectAll("text").text(""),y&&!w?(L.append("text").classed("nv-bar-label",!0),K.select("text.nv-bar-label").attr("text-anchor",function(a,b){return r(a,b)<0?"start":"end"}).attr("y",o.rangeBand()/(2*b.length)).attr("dy",".32em").text(function(a,b){return q(a,b)}),K.watchTransition(E,"multibarhorizontal: bars").select("text.nv-bar-label").attr("x",function(a,b){return r(a,b)<0?p(0)-p(r(a,b))+4:-4})):K.selectAll("text.nv-bar-label").text(""),K.attr("class",function(a,b){return r(a,b)<0?"nv-bar negative":"nv-bar positive"}),v&&(c||(c=b.map(function(){return!0})),K.style("fill",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()}).style("stroke",function(a,b,d){return d3.rgb(v(a,b)).darker(c.map(function(a,b){return b}).filter(function(a,b){return!c[b]})[d]).toString()})),w?K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,b){return"translate("+p(a.y1)+","+o(q(a,b))+")"}).select("rect").attr("width",function(a,b){return Math.abs(p(r(a,b)+a.y0)-p(a.y0))||0}).attr("height",o.rangeBand()):K.watchTransition(E,"multibarhorizontal: bars").attr("transform",function(a,c){return"translate("+p(r(a,c)<0?r(a,c):0)+","+(a.series*o.rangeBand()/b.length+o(q(a,c)))+")"}).select("rect").attr("height",o.rangeBand()/b.length).attr("width",function(a,b){return Math.max(Math.abs(p(r(a,b))-p(0)),1)||0}),h=o.copy(),i=p.copy()}),E.renderEnd("multibarHorizontal immediate"),b}var c,d,e,f,g,h,i,j={top:0,right:0,bottom:0,left:0},k=960,l=500,m=Math.floor(1e4*Math.random()),n=null,o=d3.scale.ordinal(),p=d3.scale.linear(),q=function(a){return a.x},r=function(a){return a.y},s=function(a){return a.yErr},t=[0],u=a.utils.defaultColor(),v=null,w=!1,x=!1,y=!1,z=60,A=.1,B=d3.format(",.2f"),C=250,D=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),E=a.utils.renderWatch(D,C);return b.dispatch=D,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},x:{get:function(){return q},set:function(a){q=a}},y:{get:function(){return r},set:function(a){r=a}},yErr:{get:function(){return s},set:function(a){s=a}},xScale:{get:function(){return o},set:function(a){o=a}},yScale:{get:function(){return p},set:function(a){p=a}},xDomain:{get:function(){return d},set:function(a){d=a}},yDomain:{get:function(){return e},set:function(a){e=a}},xRange:{get:function(){return f},set:function(a){f=a}},yRange:{get:function(){return g},set:function(a){g=a}},forceY:{get:function(){return t},set:function(a){t=a}},stacked:{get:function(){return w},set:function(a){w=a}},showValues:{get:function(){return x},set:function(a){x=a}},disabled:{get:function(){return c},set:function(a){c=a}},id:{get:function(){return m},set:function(a){m=a}},valueFormat:{get:function(){return B},set:function(a){B=a}},valuePadding:{get:function(){return z},set:function(a){z=a}},groupSpacing:{get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},duration:{get:function(){return C},set:function(a){C=a,E.reset(C)}},color:{get:function(){return u},set:function(b){u=a.utils.getColor(b)}},barColor:{get:function(){return v},set:function(b){v=b?a.utils.getColor(b):null}}}),a.utils.initOptions(b),b},a.models.multiBarHorizontalChart=function(){"use strict";function b(j){return C.reset(),C.models(e),r&&C.models(f),s&&C.models(g),j.each(function(j){var w=d3.select(this);a.utils.initSVG(w);var C=a.utils.availableWidth(l,w,k),D=a.utils.availableHeight(m,w,k);if(b.update=function(){w.transition().duration(z).call(b)},b.container=this,t=e.stacked(),u.setter(B(j),b.update).getter(A(j)).update(),u.disabled=j.map(function(a){return!!a.disabled}),!v){var E;v={};for(E in u)u[E]instanceof Array?v[E]=u[E].slice(0):v[E]=u[E]}if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,w),b;w.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var F=w.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([j]),G=F.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarHorizontalChart").append("g"),H=F.select("g");if(G.append("g").attr("class","nv-x nv-axis"),G.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),G.append("g").attr("class","nv-barsWrap"),G.append("g").attr("class","nv-legendWrap"),G.append("g").attr("class","nv-controlsWrap"),q&&(h.width(C-y()),H.select(".nv-legendWrap").datum(j).call(h),k.top!=h.height()&&(k.top=h.height(),D=a.utils.availableHeight(m,w,k)),H.select(".nv-legendWrap").attr("transform","translate("+y()+","+-k.top+")")),o){var I=[{key:p.grouped||"Grouped",disabled:e.stacked()},{key:p.stacked||"Stacked",disabled:!e.stacked()}];i.width(y()).color(["#444","#444","#444"]),H.select(".nv-controlsWrap").datum(I).attr("transform","translate(0,"+-k.top+")").call(i)}F.attr("transform","translate("+k.left+","+k.top+")"),e.disabled(j.map(function(a){return a.disabled})).width(C).height(D).color(j.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!j[b].disabled}));var J=H.select(".nv-barsWrap").datum(j.filter(function(a){return!a.disabled}));if(J.transition().call(e),r){f.scale(c)._ticks(a.utils.calcTicksY(D/24,j)).tickSize(-C,0),H.select(".nv-x.nv-axis").call(f);var K=H.select(".nv-x.nv-axis").selectAll("g");K.selectAll("line, text")}s&&(g.scale(d)._ticks(a.utils.calcTicksX(C/100,j)).tickSize(-D,0),H.select(".nv-y.nv-axis").attr("transform","translate(0,"+D+")"),H.select(".nv-y.nv-axis").call(g)),H.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-D),h.dispatch.on("stateChange",function(a){for(var c in a)u[c]=a[c];x.stateChange(u),b.update()}),i.dispatch.on("legendClick",function(a,c){if(a.disabled){switch(I=I.map(function(a){return a.disabled=!0,a}),a.disabled=!1,a.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}u.stacked=e.stacked(),x.stateChange(u),t=e.stacked(),b.update()}}),x.on("changeState",function(a){"undefined"!=typeof a.disabled&&(j.forEach(function(b,c){b.disabled=a.disabled[c]}),u.disabled=a.disabled),"undefined"!=typeof a.stacked&&(e.stacked(a.stacked),u.stacked=a.stacked,t=a.stacked),b.update()})}),C.renderEnd("multibar horizontal chart immediate"),b}var c,d,e=a.models.multiBarHorizontal(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend().height(30),i=a.models.legend().height(30),j=a.models.tooltip(),k={top:30,right:20,bottom:50,left:60},l=null,m=null,n=a.utils.defaultColor(),o=!0,p={},q=!0,r=!0,s=!0,t=!1,u=a.utils.state(),v=null,w=null,x=d3.dispatch("stateChange","changeState","renderEnd"),y=function(){return o?180:0},z=250;u.stacked=!1,e.stacked(t),f.orient("left").tickPadding(5).showMaxMin(!1).tickFormat(function(a){return a}),g.orient("bottom").tickFormat(d3.format(",.1f")),j.duration(0).valueFormatter(function(a,b){return g.tickFormat()(a,b)}).headerFormatter(function(a,b){return f.tickFormat()(a,b)}),i.updateState(!1);var A=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),stacked:t}}},B=function(a){return function(b){void 0!==b.stacked&&(t=b.stacked),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},C=a.utils.renderWatch(x,z);return e.dispatch.on("elementMouseover.tooltip",function(a){a.value=b.x()(a.data),a.series={key:a.data.key,value:b.y()(a.data),color:a.color},j.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){j.hidden(!0)}),e.dispatch.on("elementMousemove.tooltip",function(a){j()}),b.dispatch=x,b.multibar=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.state=u,b.tooltip=j,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return l},set:function(a){l=a}},height:{get:function(){return m},set:function(a){m=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showControls:{get:function(){return o},set:function(a){o=a}},controlLabels:{get:function(){return p},set:function(a){p=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return v},set:function(a){v=a}},noData:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return k},set:function(a){k.top=void 0!==a.top?a.top:k.top,k.right=void 0!==a.right?a.right:k.right,k.bottom=void 0!==a.bottom?a.bottom:k.bottom,k.left=void 0!==a.left?a.left:k.left}},duration:{get:function(){return z},set:function(a){z=a,C.reset(z),e.duration(z),f.duration(z),g.duration(z)}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),h.color(n)}},barColor:{get:function(){return e.barColor},set:function(a){e.barColor(a),h.color(function(a,b){return d3.rgb("#ccc").darker(1.5*b).toString()})}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.multiChart=function(){"use strict";function b(j){return j.each(function(j){function n(a){var b=2===j[a.seriesIndex].yAxis?B:A;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color,key:a.series.key},D.duration(0).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}function E(a){var b=2===j[a.seriesIndex].yAxis?B:A;a.value=a.point.x,a.series={value:a.point.y,color:a.point.color,key:a.series.key},D.duration(100).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}function F(a){var b=2===j[a.seriesIndex].yAxis?B:A;a.point.x=x.x()(a.point),a.point.y=x.y()(a.point),D.duration(0).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}function G(a){var b=2===j[a.data.series].yAxis?B:A;a.value=v.x()(a.data),a.series={value:v.y()(a.data),color:a.color,key:a.data.key},D.duration(0).valueFormatter(function(a,c){return b.tickFormat()(a,c)}).data(a).hidden(!1)}var H=d3.select(this);a.utils.initSVG(H),b.update=function(){H.transition().call(b)},b.container=this;var I=a.utils.availableWidth(g,H,e),J=a.utils.availableHeight(h,H,e),K=j.filter(function(a){return"line"==a.type&&1==a.yAxis}),L=j.filter(function(a){return"line"==a.type&&2==a.yAxis}),M=j.filter(function(a){return"scatter"==a.type&&1==a.yAxis}),N=j.filter(function(a){return"scatter"==a.type&&2==a.yAxis}),O=j.filter(function(a){return"bar"==a.type&&1==a.yAxis}),P=j.filter(function(a){return"bar"==a.type&&2==a.yAxis}),Q=j.filter(function(a){return"area"==a.type&&1==a.yAxis}),R=j.filter(function(a){return"area"==a.type&&2==a.yAxis});if(!(j&&j.length&&j.filter(function(a){return a.values.length}).length))return a.utils.noData(b,H),b;H.selectAll(".nv-noData").remove();var S=j.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a,b){return{x:k(a),y:l(a)}})}),T=j.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a,b){return{x:k(a),y:l(a)}})});o.domain(d3.extent(d3.merge(S.concat(T)),function(a){return k(a)})).range([0,I]);var U=H.selectAll("g.wrap.multiChart").data([j]),V=U.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");V.append("g").attr("class","nv-x nv-axis"),V.append("g").attr("class","nv-y1 nv-axis"),V.append("g").attr("class","nv-y2 nv-axis"),V.append("g").attr("class","lines1Wrap"),V.append("g").attr("class","lines2Wrap"),V.append("g").attr("class","scatters1Wrap"),V.append("g").attr("class","scatters2Wrap"),V.append("g").attr("class","bars1Wrap"),V.append("g").attr("class","bars2Wrap"),V.append("g").attr("class","stack1Wrap"),V.append("g").attr("class","stack2Wrap"),V.append("g").attr("class","legendWrap");var W=U.select("g"),X=j.map(function(a,b){return j[b].color||f(a,b)});if(i){var Y=C.align()?I/2:I,Z=C.align()?Y:0;C.width(Y),C.color(X),W.select(".legendWrap").datum(j.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(1==a.yAxis?"":" (right axis)"),a})).call(C),e.top!=C.height()&&(e.top=C.height(),J=a.utils.availableHeight(h,H,e)),W.select(".legendWrap").attr("transform","translate("+Z+","+-e.top+")")}r.width(I).height(J).interpolate(m).color(X.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"line"==j[b].type})),s.width(I).height(J).interpolate(m).color(X.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"line"==j[b].type})),t.width(I).height(J).color(X.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"scatter"==j[b].type})),u.width(I).height(J).color(X.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"scatter"==j[b].type})),v.width(I).height(J).color(X.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"bar"==j[b].type})),w.width(I).height(J).color(X.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"bar"==j[b].type})),x.width(I).height(J).color(X.filter(function(a,b){return!j[b].disabled&&1==j[b].yAxis&&"area"==j[b].type})),y.width(I).height(J).color(X.filter(function(a,b){return!j[b].disabled&&2==j[b].yAxis&&"area"==j[b].type})),W.attr("transform","translate("+e.left+","+e.top+")");var $=W.select(".lines1Wrap").datum(K.filter(function(a){return!a.disabled})),_=W.select(".scatters1Wrap").datum(M.filter(function(a){return!a.disabled})),aa=W.select(".bars1Wrap").datum(O.filter(function(a){return!a.disabled})),ba=W.select(".stack1Wrap").datum(Q.filter(function(a){return!a.disabled})),ca=W.select(".lines2Wrap").datum(L.filter(function(a){return!a.disabled})),da=W.select(".scatters2Wrap").datum(N.filter(function(a){return!a.disabled})),ea=W.select(".bars2Wrap").datum(P.filter(function(a){return!a.disabled})),fa=W.select(".stack2Wrap").datum(R.filter(function(a){return!a.disabled})),ga=Q.length?Q.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[],ha=R.length?R.map(function(a){return a.values}).reduce(function(a,b){return a.map(function(a,c){return{x:a.x,y:a.y+b[c].y}})}).concat([{x:0,y:0}]):[];p.domain(c||d3.extent(d3.merge(S).concat(ga),function(a){return a.y})).range([0,J]),q.domain(d||d3.extent(d3.merge(T).concat(ha),function(a){return a.y})).range([0,J]),r.yDomain(p.domain()),t.yDomain(p.domain()),v.yDomain(p.domain()),x.yDomain(p.domain()),s.yDomain(q.domain()),u.yDomain(q.domain()),w.yDomain(q.domain()),y.yDomain(q.domain()),Q.length&&d3.transition(ba).call(x),R.length&&d3.transition(fa).call(y),O.length&&d3.transition(aa).call(v),P.length&&d3.transition(ea).call(w),K.length&&d3.transition($).call(r),L.length&&d3.transition(ca).call(s),M.length&&d3.transition(_).call(t),N.length&&d3.transition(da).call(u),z._ticks(a.utils.calcTicksX(I/100,j)).tickSize(-J,0),W.select(".nv-x.nv-axis").attr("transform","translate(0,"+J+")"),d3.transition(W.select(".nv-x.nv-axis")).call(z),A._ticks(a.utils.calcTicksY(J/36,j)).tickSize(-I,0),d3.transition(W.select(".nv-y1.nv-axis")).call(A),B._ticks(a.utils.calcTicksY(J/36,j)).tickSize(-I,0),d3.transition(W.select(".nv-y2.nv-axis")).call(B),W.select(".nv-y1.nv-axis").classed("nv-disabled",S.length?!1:!0).attr("transform","translate("+o.range()[0]+",0)"),W.select(".nv-y2.nv-axis").classed("nv-disabled",T.length?!1:!0).attr("transform","translate("+o.range()[1]+",0)"),C.dispatch.on("stateChange",function(a){b.update()}),r.dispatch.on("elementMouseover.tooltip",n),s.dispatch.on("elementMouseover.tooltip",n),r.dispatch.on("elementMouseout.tooltip",function(a){D.hidden(!0)}),s.dispatch.on("elementMouseout.tooltip",function(a){D.hidden(!0)}),t.dispatch.on("elementMouseover.tooltip",E),u.dispatch.on("elementMouseover.tooltip",E),t.dispatch.on("elementMouseout.tooltip",function(a){D.hidden(!0)}),u.dispatch.on("elementMouseout.tooltip",function(a){D.hidden(!0)}),x.dispatch.on("elementMouseover.tooltip",F),y.dispatch.on("elementMouseover.tooltip",F),x.dispatch.on("elementMouseout.tooltip",function(a){D.hidden(!0)}),y.dispatch.on("elementMouseout.tooltip",function(a){D.hidden(!0)}),v.dispatch.on("elementMouseover.tooltip",G),w.dispatch.on("elementMouseover.tooltip",G),v.dispatch.on("elementMouseout.tooltip",function(a){D.hidden(!0)}),w.dispatch.on("elementMouseout.tooltip",function(a){D.hidden(!0)}),v.dispatch.on("elementMousemove.tooltip",function(a){D()}),w.dispatch.on("elementMousemove.tooltip",function(a){D()})}),b}var c,d,e={top:30,right:20,bottom:50,left:60},f=a.utils.defaultColor(),g=null,h=null,i=!0,j=null,k=function(a){return a.x},l=function(a){return a.y},m="monotone",n=!0,o=d3.scale.linear(),p=d3.scale.linear(),q=d3.scale.linear(),r=a.models.line().yScale(p),s=a.models.line().yScale(q),t=a.models.scatter().yScale(p),u=a.models.scatter().yScale(q),v=a.models.multiBar().stacked(!1).yScale(p),w=a.models.multiBar().stacked(!1).yScale(q),x=a.models.stackedArea().yScale(p),y=a.models.stackedArea().yScale(q),z=a.models.axis().scale(o).orient("bottom").tickPadding(5),A=a.models.axis().scale(p).orient("left"),B=a.models.axis().scale(q).orient("right"),C=a.models.legend().height(30),D=a.models.tooltip(),E=d3.dispatch();return b.dispatch=E,b.legend=C,b.lines1=r,b.lines2=s,b.scatters1=t,b.scatters2=u,b.bars1=v,b.bars2=w,b.stack1=x,b.stack2=y,b.xAxis=z,b.yAxis1=A,b.yAxis2=B,b.tooltip=D,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},showLegend:{get:function(){return i},set:function(a){i=a}},yDomain1:{get:function(){return c},set:function(a){c=a}},yDomain2:{get:function(){return d},set:function(a){d=a}},noData:{get:function(){return j},set:function(a){j=a}},interpolate:{get:function(){return m},set:function(a){m=a}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return f},set:function(b){f=a.utils.getColor(b)}},x:{get:function(){return k},set:function(a){k=a,r.x(a),s.x(a),t.x(a),u.x(a),v.x(a),w.x(a),x.x(a),y.x(a)}},y:{get:function(){return l},set:function(a){l=a,r.y(a),s.y(a),t.y(a),u.y(a),x.y(a),y.y(a),v.y(a),w.y(a)}},useVoronoi:{get:function(){return n},set:function(a){n=a,r.useVoronoi(a),s.useVoronoi(a),x.useVoronoi(a),y.useVoronoi(a)}}}),a.utils.initOptions(b),b},a.models.ohlcBar=function(){"use strict";function b(y){return y.each(function(b){k=d3.select(this);var y=a.utils.availableWidth(h,k,g),A=a.utils.availableHeight(i,k,g);a.utils.initSVG(k);var B=y/b[0].values.length*.9;l.domain(c||d3.extent(b[0].values.map(n).concat(t))),l.range(v?e||[.5*y/b[0].values.length,y*(b[0].values.length-.5)/b[0].values.length]:e||[5+B/2,y-B/2-5]),m.domain(d||[d3.min(b[0].values.map(s).concat(u)),d3.max(b[0].values.map(r).concat(u))]).range(f||[A,0]),l.domain()[0]===l.domain()[1]&&l.domain(l.domain()[0]?[l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]:[-1,1]),m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]+.01*m.domain()[0],m.domain()[1]-.01*m.domain()[1]]:[-1,1]);var C=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([b[0].values]),D=C.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),E=D.append("defs"),F=D.append("g"),G=C.select("g");F.append("g").attr("class","nv-ticks"),C.attr("transform","translate("+g.left+","+g.top+")"),k.on("click",function(a,b){z.chartClick({data:a,index:b,pos:d3.event,id:j})}),E.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),C.select("#nv-chart-clip-path-"+j+" rect").attr("width",y).attr("height",A),G.attr("clip-path",w?"url(#nv-chart-clip-path-"+j+")":"");var H=C.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});H.exit().remove(),H.enter().append("path").attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}).attr("d",function(a,b){return"m0,0l0,"+(m(p(a,b))-m(r(a,b)))+"l"+-B/2+",0l"+B/2+",0l0,"+(m(s(a,b))-m(p(a,b)))+"l0,"+(m(q(a,b))-m(s(a,b)))+"l"+B/2+",0l"+-B/2+",0z"}).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("fill",function(a,b){return x[0]}).attr("stroke",function(a,b){return x[0]}).attr("x",0).attr("y",function(a,b){return m(Math.max(0,o(a,b)))}).attr("height",function(a,b){return Math.abs(m(o(a,b))-m(0))}),H.attr("class",function(a,b,c){return(p(a,b)>q(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(H).attr("transform",function(a,b){return"translate("+l(n(a,b))+","+m(r(a,b))+")"}).attr("d",function(a,c){var d=y/b[0].values.length*.9;return"m0,0l0,"+(m(p(a,c))-m(r(a,c)))+"l"+-d/2+",0l"+d/2+",0l0,"+(m(s(a,c))-m(p(a,c)))+"l0,"+(m(q(a,c))-m(s(a,c)))+"l"+d/2+",0l"+-d/2+",0z"})}),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=Math.floor(1e4*Math.random()),k=null,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=function(a){return a.open},q=function(a){return a.close},r=function(a){return a.high},s=function(a){return a.low},t=[],u=[],v=!1,w=!0,x=a.utils.defaultColor(),y=!1,z=d3.dispatch("stateChange","changeState","renderEnd","chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove");return b.highlightPoint=function(a,c){b.clearHighlights(),k.select(".nv-ohlcBar .nv-tick-0-"+a).classed("hover",c)},b.clearHighlights=function(){k.select(".nv-ohlcBar .nv-tick.hover").classed("hover",!1)},b.dispatch=z,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},padData:{get:function(){return v},set:function(a){v=a}},clipEdge:{get:function(){return w},set:function(a){w=a}},id:{get:function(){return j},set:function(a){j=a}},interactive:{get:function(){return y},set:function(a){y=a}},x:{get:function(){return n},set:function(a){n=a}},y:{get:function(){return o},set:function(a){o=a}},open:{get:function(){return p()},set:function(a){p=a}},close:{get:function(){return q()},set:function(a){q=a}},high:{get:function(){return r},set:function(a){ +r=a}},low:{get:function(){return s},set:function(a){s=a}},margin:{get:function(){return g},set:function(a){g.top=void 0!=a.top?a.top:g.top,g.right=void 0!=a.right?a.right:g.right,g.bottom=void 0!=a.bottom?a.bottom:g.bottom,g.left=void 0!=a.left?a.left:g.left}},color:{get:function(){return x},set:function(b){x=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.parallelCoordinates=function(){"use strict";function b(p){return p.each(function(b){function p(a){return F(h.map(function(b){if(isNaN(a[b])||isNaN(parseFloat(a[b]))){var c=g[b].domain(),d=g[b].range(),e=c[0]-(c[1]-c[0])/9;if(J.indexOf(b)<0){var h=d3.scale.linear().domain([e,c[1]]).range([x-12,d[1]]);g[b].brush.y(h),J.push(b)}return[f(b),g[b](e)]}return J.length>0?(D.style("display","inline"),E.style("display","inline")):(D.style("display","none"),E.style("display","none")),[f(b),g[b](a[b])]}))}function q(){var a=h.filter(function(a){return!g[a].brush.empty()}),b=a.map(function(a){return g[a].brush.extent()});k=[],a.forEach(function(a,c){k[c]={dimension:a,extent:b[c]}}),l=[],M.style("display",function(c){var d=a.every(function(a,d){return isNaN(c[a])&&b[d][0]==g[a].brush.y().domain()[0]?!0:b[d][0]<=c[a]&&c[a]<=b[d][1]});return d&&l.push(c),d?null:"none"}),o.brush({filters:k,active:l})}function r(a,b){m[a]=this.parentNode.__origin__=f(a),L.attr("visibility","hidden")}function s(a,b){m[a]=Math.min(w,Math.max(0,this.parentNode.__origin__+=d3.event.x)),M.attr("d",p),h.sort(function(a,b){return u(a)-u(b)}),f.domain(h),N.attr("transform",function(a){return"translate("+u(a)+")"})}function t(a,b){delete this.parentNode.__origin__,delete m[a],d3.select(this.parentNode).attr("transform","translate("+f(a)+")"),M.attr("d",p),L.attr("d",p).attr("visibility",null)}function u(a){var b=m[a];return null==b?f(a):b}var v=d3.select(this),w=a.utils.availableWidth(d,v,c),x=a.utils.availableHeight(e,v,c);a.utils.initSVG(v),l=b,f.rangePoints([0,w],1).domain(h);var y={};h.forEach(function(a){var c=d3.extent(b,function(b){return+b[a]});return y[a]=!1,void 0===c[0]&&(y[a]=!0,c[0]=0,c[1]=0),c[0]===c[1]&&(c[0]=c[0]-1,c[1]=c[1]+1),g[a]=d3.scale.linear().domain(c).range([.9*(x-12),0]),g[a].brush=d3.svg.brush().y(g[a]).on("brush",q),"name"!=a});var z=v.selectAll("g.nv-wrap.nv-parallelCoordinates").data([b]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-parallelCoordinates"),B=A.append("g"),C=z.select("g");B.append("g").attr("class","nv-parallelCoordinates background"),B.append("g").attr("class","nv-parallelCoordinates foreground"),B.append("g").attr("class","nv-parallelCoordinates missingValuesline"),z.attr("transform","translate("+c.left+","+c.top+")");var D,E,F=d3.svg.line().interpolate("cardinal").tension(n),G=d3.svg.axis().orient("left"),H=d3.behavior.drag().on("dragstart",r).on("drag",s).on("dragend",t),I=f.range()[1]-f.range()[0],J=[],K=[0+I/2,x-12,w-I/2,x-12];D=z.select(".missingValuesline").selectAll("line").data([K]),D.enter().append("line"),D.exit().remove(),D.attr("x1",function(a){return a[0]}).attr("y1",function(a){return a[1]}).attr("x2",function(a){return a[2]}).attr("y2",function(a){return a[3]}),E=z.select(".missingValuesline").selectAll("text").data(["undefined values"]),E.append("text").data(["undefined values"]),E.enter().append("text"),E.exit().remove(),E.attr("y",x).attr("x",w-92-I/2).text(function(a){return a});var L=z.select(".background").selectAll("path").data(b);L.enter().append("path"),L.exit().remove(),L.attr("d",p);var M=z.select(".foreground").selectAll("path").data(b);M.enter().append("path"),M.exit().remove(),M.attr("d",p).attr("stroke",j),M.on("mouseover",function(a,b){d3.select(this).classed("hover",!0),o.elementMouseover({label:a.name,data:a.data,index:b,pos:[d3.mouse(this.parentNode)[0],d3.mouse(this.parentNode)[1]]})}),M.on("mouseout",function(a,b){d3.select(this).classed("hover",!1),o.elementMouseout({label:a.name,data:a.data,index:b})});var N=C.selectAll(".dimension").data(h),O=N.enter().append("g").attr("class","nv-parallelCoordinates dimension");O.append("g").attr("class","nv-parallelCoordinates nv-axis"),O.append("g").attr("class","nv-parallelCoordinates-brush"),O.append("text").attr("class","nv-parallelCoordinates nv-label"),N.attr("transform",function(a){return"translate("+f(a)+",0)"}),N.exit().remove(),N.select(".nv-label").style("cursor","move").attr("dy","-1em").attr("text-anchor","middle").text(String).on("mouseover",function(a,b){o.elementMouseover({dim:a,pos:[d3.mouse(this.parentNode.parentNode)[0],d3.mouse(this.parentNode.parentNode)[1]]})}).on("mouseout",function(a,b){o.elementMouseout({dim:a})}).call(H),N.select(".nv-axis").each(function(a,b){d3.select(this).call(G.scale(g[a]).tickFormat(d3.format(i[b])))}),N.select(".nv-parallelCoordinates-brush").each(function(a){d3.select(this).call(g[a].brush)}).selectAll("rect").attr("x",-8).attr("width",16)}),b}var c={top:30,right:0,bottom:10,left:0},d=null,e=null,f=d3.scale.ordinal(),g={},h=[],i=[],j=a.utils.defaultColor(),k=[],l=[],m=[],n=1,o=d3.dispatch("brush","elementMouseover","elementMouseout");return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},dimensionNames:{get:function(){return h},set:function(a){h=a}},dimensionFormats:{get:function(){return i},set:function(a){i=a}},lineTension:{get:function(){return n},set:function(a){n=a}},dimensions:{get:function(){return h},set:function(b){a.deprecated("dimensions","use dimensionNames instead"),h=b}},margin:{get:function(){return c},set:function(a){c.top=void 0!==a.top?a.top:c.top,c.right=void 0!==a.right?a.right:c.right,c.bottom=void 0!==a.bottom?a.bottom:c.bottom,c.left=void 0!==a.left?a.left:c.left}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.pie=function(){"use strict";function b(E){return D.reset(),E.each(function(b){function E(a,b){a.endAngle=isNaN(a.endAngle)?0:a.endAngle,a.startAngle=isNaN(a.startAngle)?0:a.startAngle,p||(a.innerRadius=0);var c=d3.interpolate(this._current,a);return this._current=c(0),function(a){return B[b](c(a))}}var F=d-c.left-c.right,G=e-c.top-c.bottom,H=Math.min(F,G)/2,I=[],J=[];if(i=d3.select(this),0===z.length)for(var K=H-H/5,L=y*H,M=0;Mc)return"";if("function"==typeof n)d=n(a,b,{key:f(a.data),value:g(a.data),percent:k(c)});else switch(n){case"key":d=f(a.data);break;case"value":d=k(g(a.data));break;case"percent":d=d3.format("%")(c)}return d})}}),D.renderEnd("pie immediate"),b}var c={top:0,right:0,bottom:0,left:0},d=500,e=500,f=function(a){return a.x},g=function(a){return a.y},h=Math.floor(1e4*Math.random()),i=null,j=a.utils.defaultColor(),k=d3.format(",.2f"),l=!0,m=!1,n="key",o=.02,p=!1,q=!1,r=!0,s=0,t=!1,u=!1,v=!1,w=!1,x=0,y=.5,z=[],A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout","elementMousemove","renderEnd"),B=[],C=[],D=a.utils.renderWatch(A);return b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{arcsRadius:{get:function(){return z},set:function(a){z=a}},width:{get:function(){return d},set:function(a){d=a}},height:{get:function(){return e},set:function(a){e=a}},showLabels:{get:function(){return l},set:function(a){l=a}},title:{get:function(){return q},set:function(a){q=a}},titleOffset:{get:function(){return s},set:function(a){s=a}},labelThreshold:{get:function(){return o},set:function(a){o=a}},valueFormat:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return f},set:function(a){f=a}},id:{get:function(){return h},set:function(a){h=a}},endAngle:{get:function(){return w},set:function(a){w=a}},startAngle:{get:function(){return u},set:function(a){u=a}},padAngle:{get:function(){return v},set:function(a){v=a}},cornerRadius:{get:function(){return x},set:function(a){x=a}},donutRatio:{get:function(){return y},set:function(a){y=a}},labelsOutside:{get:function(){return m},set:function(a){m=a}},labelSunbeamLayout:{get:function(){return t},set:function(a){t=a}},donut:{get:function(){return p},set:function(a){p=a}},growOnHover:{get:function(){return r},set:function(a){r=a}},pieLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("pieLabelsOutside","use labelsOutside instead")}},donutLabelsOutside:{get:function(){return m},set:function(b){m=b,a.deprecated("donutLabelsOutside","use labelsOutside instead")}},labelFormat:{get:function(){return k},set:function(b){k=b,a.deprecated("labelFormat","use valueFormat instead")}},margin:{get:function(){return c},set:function(a){c.top="undefined"!=typeof a.top?a.top:c.top,c.right="undefined"!=typeof a.right?a.right:c.right,c.bottom="undefined"!=typeof a.bottom?a.bottom:c.bottom,c.left="undefined"!=typeof a.left?a.left:c.left}},y:{get:function(){return g},set:function(a){g=d3.functor(a)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},labelType:{get:function(){return n},set:function(a){n=a||"key"}}}),a.utils.initOptions(b),b},a.models.pieChart=function(){"use strict";function b(e){return q.reset(),q.models(c),e.each(function(e){var k=d3.select(this);a.utils.initSVG(k);var n=a.utils.availableWidth(g,k,f),o=a.utils.availableHeight(h,k,f);if(b.update=function(){k.transition().call(b)},b.container=this,l.setter(s(e),b.update).getter(r(e)).update(),l.disabled=e.map(function(a){return!!a.disabled}),!m){var q;m={};for(q in l)l[q]instanceof Array?m[q]=l[q].slice(0):m[q]=l[q]}if(!e||!e.length)return a.utils.noData(b,k),b;k.selectAll(".nv-noData").remove();var t=k.selectAll("g.nv-wrap.nv-pieChart").data([e]),u=t.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),v=t.select("g");if(u.append("g").attr("class","nv-pieWrap"),u.append("g").attr("class","nv-legendWrap"),i)if("top"===j)d.width(n).key(c.x()),t.select(".nv-legendWrap").datum(e).call(d),f.top!=d.height()&&(f.top=d.height(),o=a.utils.availableHeight(h,k,f)),t.select(".nv-legendWrap").attr("transform","translate(0,"+-f.top+")");else if("right"===j){var w=a.models.legend().width();w>n/2&&(w=n/2),d.height(o).key(c.x()),d.width(w),n-=d.width(),t.select(".nv-legendWrap").datum(e).call(d).attr("transform","translate("+n+",0)")}t.attr("transform","translate("+f.left+","+f.top+")"),c.width(n).height(o);var x=v.select(".nv-pieWrap").datum([e]);d3.transition(x).call(c),d.dispatch.on("stateChange",function(a){for(var c in a)l[c]=a[c];p.stateChange(l),b.update()}),p.on("changeState",function(a){"undefined"!=typeof a.disabled&&(e.forEach(function(b,c){b.disabled=a.disabled[c]}),l.disabled=a.disabled),b.update()})}),q.renderEnd("pieChart immediate"),b}var c=a.models.pie(),d=a.models.legend(),e=a.models.tooltip(),f={top:30,right:20,bottom:20,left:20},g=null,h=null,i=!0,j="top",k=a.utils.defaultColor(),l=a.utils.state(),m=null,n=null,o=250,p=d3.dispatch("stateChange","changeState","renderEnd");e.duration(0).headerEnabled(!1).valueFormatter(function(a,b){return c.valueFormat()(a,b)});var q=a.utils.renderWatch(p),r=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},s=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:b.x()(a.data),value:b.y()(a.data),color:a.color},e.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(a){e.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(a){e()}),b.legend=d,b.dispatch=p,b.pie=c,b.tooltip=e,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return i},set:function(a){i=a}},legendPosition:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return m},set:function(a){m=a}},color:{get:function(){return k},set:function(a){k=a,d.color(k),c.color(k)}},duration:{get:function(){return o},set:function(a){o=a,q.reset(o)}},margin:{get:function(){return f},set:function(a){f.top=void 0!==a.top?a.top:f.top,f.right=void 0!==a.right?a.right:f.right,f.bottom=void 0!==a.bottom?a.bottom:f.bottom,f.left=void 0!==a.left?a.left:f.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.scatter=function(){"use strict";function b(N){return P.reset(),N.each(function(b){function N(){if(O=!1,!w)return!1;if(M===!0){var a=d3.merge(b.map(function(a,b){return a.values.map(function(a,c){var d=p(a,c),e=q(a,c);return[m(d)+1e-4*Math.random(),n(e)+1e-4*Math.random(),b,c,a]}).filter(function(a,b){return x(a[4],b)})}));if(0==a.length)return!1;a.length<3&&(a.push([m.range()[0]-20,n.range()[0]-20,null,null]),a.push([m.range()[1]+20,n.range()[1]+20,null,null]),a.push([m.range()[0]-20,n.range()[0]+20,null,null]),a.push([m.range()[1]+20,n.range()[1]-20,null,null]));var c=d3.geom.polygon([[-10,-10],[-10,i+10],[h+10,i+10],[h+10,-10]]),d=d3.geom.voronoi(a).map(function(b,d){return{data:c.clip(b),series:a[d][2],point:a[d][3]}});U.select(".nv-point-paths").selectAll("path").remove();var e=U.select(".nv-point-paths").selectAll("path").data(d),f=e.enter().append("svg:path").attr("d",function(a){return a&&a.data&&0!==a.data.length?"M"+a.data.join(",")+"Z":"M 0 0"}).attr("id",function(a,b){return"nv-path-"+b}).attr("clip-path",function(a,b){return"url(#nv-clip-"+k+"-"+b+")"});if(C&&f.style("fill",d3.rgb(230,230,230)).style("fill-opacity",.4).style("stroke-opacity",1).style("stroke",d3.rgb(200,200,200)),B){U.select(".nv-point-clips").selectAll("*").remove();{var o=U.select(".nv-point-clips").selectAll("clipPath").data(a);o.enter().append("svg:clipPath").attr("id",function(a,b){return"nv-clip-"+k+"-"+b}).append("svg:circle").attr("cx",function(a){return a[0]}).attr("cy",function(a){return a[1]}).attr("r",D)}}var r=function(a,c){if(O)return 0;var d=b[a.series];if(void 0!==d){var e=d.values[a.point];e.color=j(d,a.series),e.x=p(e),e.y=q(e);var f=l.node().getBoundingClientRect(),h=document.documentElement.scrollTop,i=document.documentElement.scrollLeft,k={left:m(p(e,a.point))+f.left+i+g.left+10,top:n(q(e,a.point))+f.top+h+g.top+10};c({point:e,series:d,pos:k,relativePos:[m(p(e,a.point))+g.left,n(q(e,a.point))+g.top],seriesIndex:a.series,pointIndex:a.point})}};e.on("click",function(a){r(a,L.elementClick)}).on("dblclick",function(a){r(a,L.elementDblClick)}).on("mouseover",function(a){r(a,L.elementMouseover)}).on("mouseout",function(a,b){r(a,L.elementMouseout)})}else U.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],relativePos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("dblclick",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementDblClick({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],relativePos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c})}).on("mouseover",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseover({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],relativePos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c,color:j(a,c)})}).on("mouseout",function(a,c){if(O||!b[a.series])return 0;var d=b[a.series],e=d.values[c];L.elementMouseout({point:e,series:d,pos:[m(p(e,c))+g.left,n(q(e,c))+g.top],relativePos:[m(p(e,c))+g.left,n(q(e,c))+g.top],seriesIndex:a.series,pointIndex:c,color:j(a,c)})})}l=d3.select(this);var R=a.utils.availableWidth(h,l,g),S=a.utils.availableHeight(i,l,g);a.utils.initSVG(l),b.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var T=E&&F&&I?[]:d3.merge(b.map(function(a){return a.values.map(function(a,b){return{x:p(a,b),y:q(a,b),size:r(a,b)}})}));m.domain(E||d3.extent(T.map(function(a){return a.x}).concat(t))),m.range(y&&b[0]?G||[(R*z+R)/(2*b[0].values.length),R-R*(1+z)/(2*b[0].values.length)]:G||[0,R]),n.domain(F||d3.extent(T.map(function(a){return a.y}).concat(u))).range(H||[S,0]),o.domain(I||d3.extent(T.map(function(a){return a.size}).concat(v))).range(J||Q),K=m.domain()[0]===m.domain()[1]||n.domain()[0]===n.domain()[1],m.domain()[0]===m.domain()[1]&&m.domain(m.domain()[0]?[m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]:[-1,1]),n.domain()[0]===n.domain()[1]&&n.domain(n.domain()[0]?[n.domain()[0]-.01*n.domain()[0],n.domain()[1]+.01*n.domain()[1]]:[-1,1]),isNaN(m.domain()[0])&&m.domain([-1,1]),isNaN(n.domain()[0])&&n.domain([-1,1]),c=c||m,d=d||n,e=e||o;var U=l.selectAll("g.nv-wrap.nv-scatter").data([b]),V=U.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+k),W=V.append("defs"),X=V.append("g"),Y=U.select("g");U.classed("nv-single-point",K),X.append("g").attr("class","nv-groups"),X.append("g").attr("class","nv-point-paths"),V.append("g").attr("class","nv-point-clips"),U.attr("transform","translate("+g.left+","+g.top+")"),W.append("clipPath").attr("id","nv-edge-clip-"+k).append("rect"),U.select("#nv-edge-clip-"+k+" rect").attr("width",R).attr("height",S>0?S:0),Y.attr("clip-path",A?"url(#nv-edge-clip-"+k+")":""),O=!0;var Z=U.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});Z.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),Z.exit().remove(),Z.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),Z.watchTransition(P,"scatter: groups").style("fill",function(a,b){return j(a,b)}).style("stroke",function(a,b){return j(a,b)}).style("stroke-opacity",1).style("fill-opacity",.5);var $=Z.selectAll("path.nv-point").data(function(a){return a.values.map(function(a,b){return[a,b]}).filter(function(a,b){return x(a[0],b)})});$.enter().append("path").style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("transform",function(a){return"translate("+c(p(a[0],a[1]))+","+d(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),$.exit().remove(),Z.exit().selectAll("path.nv-point").watchTransition(P,"scatter exit").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).remove(),$.each(function(a){d3.select(this).classed("nv-point",!0).classed("nv-point-"+a[1],!0).classed("nv-noninteractive",!w).classed("hover",!1)}),$.watchTransition(P,"scatter points").attr("transform",function(a){return"translate("+m(p(a[0],a[1]))+","+n(q(a[0],a[1]))+")"}).attr("d",a.utils.symbol().type(function(a){return s(a[0])}).size(function(a){return o(r(a[0],a[1]))})),clearTimeout(f),f=setTimeout(N,300),c=m.copy(),d=n.copy(),e=o.copy()}),P.renderEnd("scatter immediate"),b}var c,d,e,f,g={top:0,right:0,bottom:0,left:0},h=null,i=null,j=a.utils.defaultColor(),k=Math.floor(1e5*Math.random()),l=null,m=d3.scale.linear(),n=d3.scale.linear(),o=d3.scale.linear(),p=function(a){return a.x},q=function(a){return a.y},r=function(a){return a.size||1},s=function(a){return a.shape||"circle"},t=[],u=[],v=[],w=!0,x=function(a){return!a.notActive},y=!1,z=.1,A=!1,B=!0,C=!1,D=function(){return 25},E=null,F=null,G=null,H=null,I=null,J=null,K=!1,L=d3.dispatch("elementClick","elementDblClick","elementMouseover","elementMouseout","renderEnd"),M=!0,N=250,O=!1,P=a.utils.renderWatch(L,N),Q=[16,256];return b.dispatch=L,b.options=a.utils.optionsFunc.bind(b),b._calls=new function(){this.clearHighlights=function(){return a.dom.write(function(){l.selectAll(".nv-point.hover").classed("hover",!1)}),null},this.highlightPoint=function(b,c,d){a.dom.write(function(){l.select(".nv-groups").selectAll(".nv-series-"+b).selectAll(".nv-point-"+c).classed("hover",d)})}},L.on("elementMouseover.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!0)}),L.on("elementMouseout.point",function(a){w&&b._calls.highlightPoint(a.seriesIndex,a.pointIndex,!1)}),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xScale:{get:function(){return m},set:function(a){m=a}},yScale:{get:function(){return n},set:function(a){n=a}},pointScale:{get:function(){return o},set:function(a){o=a}},xDomain:{get:function(){return E},set:function(a){E=a}},yDomain:{get:function(){return F},set:function(a){F=a}},pointDomain:{get:function(){return I},set:function(a){I=a}},xRange:{get:function(){return G},set:function(a){G=a}},yRange:{get:function(){return H},set:function(a){H=a}},pointRange:{get:function(){return J},set:function(a){J=a}},forceX:{get:function(){return t},set:function(a){t=a}},forceY:{get:function(){return u},set:function(a){u=a}},forcePoint:{get:function(){return v},set:function(a){v=a}},interactive:{get:function(){return w},set:function(a){w=a}},pointActive:{get:function(){return x},set:function(a){x=a}},padDataOuter:{get:function(){return z},set:function(a){z=a}},padData:{get:function(){return y},set:function(a){y=a}},clipEdge:{get:function(){return A},set:function(a){A=a}},clipVoronoi:{get:function(){return B},set:function(a){B=a}},clipRadius:{get:function(){return D},set:function(a){D=a}},showVoronoi:{get:function(){return C},set:function(a){C=a}},id:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return p},set:function(a){p=d3.functor(a)}},y:{get:function(){return q},set:function(a){q=d3.functor(a)}},pointSize:{get:function(){return r},set:function(a){r=d3.functor(a)}},pointShape:{get:function(){return s},set:function(a){s=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},duration:{get:function(){return N},set:function(a){N=a,P.reset(N)}},color:{get:function(){return j},set:function(b){j=a.utils.getColor(b)}},useVoronoi:{get:function(){return M},set:function(a){M=a,M===!1&&(B=!1)}}}),a.utils.initOptions(b),b},a.models.scatterChart=function(){"use strict";function b(z){return D.reset(),D.models(c),t&&D.models(d),u&&D.models(e),q&&D.models(g),r&&D.models(h),z.each(function(z){m=d3.select(this),a.utils.initSVG(m);var G=a.utils.availableWidth(k,m,j),H=a.utils.availableHeight(l,m,j);if(b.update=function(){0===A?m.call(b):m.transition().duration(A).call(b)},b.container=this,w.setter(F(z),b.update).getter(E(z)).update(),w.disabled=z.map(function(a){return!!a.disabled}),!x){var I;x={};for(I in w)w[I]instanceof Array?x[I]=w[I].slice(0):x[I]=w[I]}if(!(z&&z.length&&z.filter(function(a){return a.values.length}).length))return a.utils.noData(b,m),D.renderEnd("scatter immediate"),b;m.selectAll(".nv-noData").remove(),o=c.xScale(),p=c.yScale();var J=m.selectAll("g.nv-wrap.nv-scatterChart").data([z]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+c.id()),L=K.append("g"),M=J.select("g");if(L.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),L.append("g").attr("class","nv-x nv-axis"),L.append("g").attr("class","nv-y nv-axis"),L.append("g").attr("class","nv-scatterWrap"),L.append("g").attr("class","nv-regressionLinesWrap"),L.append("g").attr("class","nv-distWrap"),L.append("g").attr("class","nv-legendWrap"),v&&M.select(".nv-y.nv-axis").attr("transform","translate("+G+",0)"),s){var N=G;f.width(N),J.select(".nv-legendWrap").datum(z).call(f),j.top!=f.height()&&(j.top=f.height(),H=a.utils.availableHeight(l,m,j)),J.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")}J.attr("transform","translate("+j.left+","+j.top+")"),c.width(G).height(H).color(z.map(function(a,b){return a.color=a.color||n(a,b),a.color}).filter(function(a,b){return!z[b].disabled})),J.select(".nv-scatterWrap").datum(z.filter(function(a){return!a.disabled})).call(c),J.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+c.id()+")");var O=J.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});O.enter().append("g").attr("class","nv-regLines");var P=O.selectAll(".nv-regLine").data(function(a){return[a]});P.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),P.filter(function(a){return a.intercept&&a.slope}).watchTransition(D,"scatterPlusLineChart: regline").attr("x1",o.range()[0]).attr("x2",o.range()[1]).attr("y1",function(a,b){return p(o.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a,b){return p(o.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return n(a,c)}).style("stroke-opacity",function(a,b){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),t&&(d.scale(o)._ticks(a.utils.calcTicksX(G/100,z)).tickSize(-H,0),M.select(".nv-x.nv-axis").attr("transform","translate(0,"+p.range()[0]+")").call(d)),u&&(e.scale(p)._ticks(a.utils.calcTicksY(H/36,z)).tickSize(-G,0),M.select(".nv-y.nv-axis").call(e)),q&&(g.getData(c.x()).scale(o).width(G).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),M.select(".nv-distributionX").attr("transform","translate(0,"+p.range()[0]+")").datum(z.filter(function(a){return!a.disabled})).call(g)),r&&(h.getData(c.y()).scale(p).width(H).color(z.map(function(a,b){return a.color||n(a,b)}).filter(function(a,b){return!z[b].disabled})),L.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),M.select(".nv-distributionY").attr("transform","translate("+(v?G:-h.size())+",0)").datum(z.filter(function(a){return!a.disabled})).call(h)),f.dispatch.on("stateChange",function(a){for(var c in a)w[c]=a[c];y.stateChange(w),b.update()}),y.on("changeState",function(a){"undefined"!=typeof a.disabled&&(z.forEach(function(b,c){b.disabled=a.disabled[c]}),w.disabled=a.disabled),b.update()}),c.dispatch.on("elementMouseout.tooltip",function(a){i.hidden(!0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),m.select(".nv-chart-"+c.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",h.size())}),c.dispatch.on("elementMouseover.tooltip",function(a){m.select(".nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.relativePos[1]-H),m.select(".nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.relativePos[0]+g.size()),i.data(a).hidden(!1)}),B=o.copy(),C=p.copy()}),D.renderEnd("scatter with line immediate"),b}var c=a.models.scatter(),d=a.models.axis(),e=a.models.axis(),f=a.models.legend(),g=a.models.distribution(),h=a.models.distribution(),i=a.models.tooltip(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=null,n=a.utils.defaultColor(),o=c.xScale(),p=c.yScale(),q=!1,r=!1,s=!0,t=!0,u=!0,v=!1,w=a.utils.state(),x=null,y=d3.dispatch("stateChange","changeState","renderEnd"),z=null,A=250;c.xScale(o).yScale(p),d.orient("bottom").tickPadding(10),e.orient(v?"right":"left").tickPadding(10),g.axis("x"),h.axis("y"),i.headerFormatter(function(a,b){return d.tickFormat()(a,b)}).valueFormatter(function(a,b){return e.tickFormat()(a,b)});var B,C,D=a.utils.renderWatch(y,A),E=function(a){return function(){return{active:a.map(function(a){return!a.disabled})}}},F=function(a){return function(b){void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}};return b.dispatch=y,b.scatter=c,b.legend=f,b.xAxis=d,b.yAxis=e,b.distX=g,b.distY=h,b.tooltip=i,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return k},set:function(a){k=a}},height:{get:function(){return l},set:function(a){l=a}},container:{get:function(){return m},set:function(a){m=a}},showDistX:{get:function(){return q},set:function(a){q=a}},showDistY:{get:function(){return r},set:function(a){r=a}},showLegend:{get:function(){return s},set:function(a){s=a}},showXAxis:{get:function(){return t},set:function(a){t=a}},showYAxis:{get:function(){return u},set:function(a){u=a}},defaultState:{get:function(){return x},set:function(a){x=a}},noData:{get:function(){return z},set:function(a){z=a}},duration:{ +get:function(){return A},set:function(a){A=a}},margin:{get:function(){return j},set:function(a){j.top=void 0!==a.top?a.top:j.top,j.right=void 0!==a.right?a.right:j.right,j.bottom=void 0!==a.bottom?a.bottom:j.bottom,j.left=void 0!==a.left?a.left:j.left}},rightAlignYAxis:{get:function(){return v},set:function(a){v=a,e.orient(a?"right":"left")}},color:{get:function(){return n},set:function(b){n=a.utils.getColor(b),f.color(n),g.color(n),h.color(n)}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.models.sparkline=function(){"use strict";function b(k){return k.each(function(b){var k=h-g.left-g.right,q=i-g.top-g.bottom;j=d3.select(this),a.utils.initSVG(j),l.domain(c||d3.extent(b,n)).range(e||[0,k]),m.domain(d||d3.extent(b,o)).range(f||[q,0]);{var r=j.selectAll("g.nv-wrap.nv-sparkline").data([b]),s=r.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");s.append("g"),r.select("g")}r.attr("transform","translate("+g.left+","+g.top+")");var t=r.selectAll("path").data(function(a){return[a]});t.enter().append("path"),t.exit().remove(),t.style("stroke",function(a,b){return a.color||p(a,b)}).attr("d",d3.svg.line().x(function(a,b){return l(n(a,b))}).y(function(a,b){return m(o(a,b))}));var u=r.selectAll("circle.nv-point").data(function(a){function b(b){if(-1!=b){var c=a[b];return c.pointIndex=b,c}return null}var c=a.map(function(a,b){return o(a,b)}),d=b(c.lastIndexOf(m.domain()[1])),e=b(c.indexOf(m.domain()[0])),f=b(c.length-1);return[e,d,f].filter(function(a){return null!=a})});u.enter().append("circle"),u.exit().remove(),u.attr("cx",function(a,b){return l(n(a,a.pointIndex))}).attr("cy",function(a,b){return m(o(a,a.pointIndex))}).attr("r",2).attr("class",function(a,b){return n(a,a.pointIndex)==l.domain()[1]?"nv-point nv-currentValue":o(a,a.pointIndex)==m.domain()[0]?"nv-point nv-minValue":"nv-point nv-maxValue"})}),b}var c,d,e,f,g={top:2,right:0,bottom:2,left:0},h=400,i=32,j=null,k=!0,l=d3.scale.linear(),m=d3.scale.linear(),n=function(a){return a.x},o=function(a){return a.y},p=a.utils.getColor(["#000"]);return b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return h},set:function(a){h=a}},height:{get:function(){return i},set:function(a){i=a}},xDomain:{get:function(){return c},set:function(a){c=a}},yDomain:{get:function(){return d},set:function(a){d=a}},xRange:{get:function(){return e},set:function(a){e=a}},yRange:{get:function(){return f},set:function(a){f=a}},xScale:{get:function(){return l},set:function(a){l=a}},yScale:{get:function(){return m},set:function(a){m=a}},animate:{get:function(){return k},set:function(a){k=a}},x:{get:function(){return n},set:function(a){n=d3.functor(a)}},y:{get:function(){return o},set:function(a){o=d3.functor(a)}},margin:{get:function(){return g},set:function(a){g.top=void 0!==a.top?a.top:g.top,g.right=void 0!==a.right?a.right:g.right,g.bottom=void 0!==a.bottom?a.bottom:g.bottom,g.left=void 0!==a.left?a.left:g.left}},color:{get:function(){return p},set:function(b){p=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sparklinePlus=function(){"use strict";function b(p){return p.each(function(p){function q(){if(!j){var a=z.selectAll(".nv-hoverValue").data(i),b=a.enter().append("g").attr("class","nv-hoverValue").style("stroke-opacity",0).style("fill-opacity",0);a.exit().transition().duration(250).style("stroke-opacity",0).style("fill-opacity",0).remove(),a.attr("transform",function(a){return"translate("+c(e.x()(p[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(b.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",u),b.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),z.select(".nv-hoverValue .nv-xValue").text(k(e.x()(p[i[0]],i[0]))),b.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),z.select(".nv-hoverValue .nv-yValue").text(l(e.y()(p[i[0]],i[0]))))}}function r(){function a(a,b){for(var c=Math.abs(e.x()(a[0],0)-b),d=0,f=0;fc;++c){for(b=0,d=0;bb;b++)a[b][c][1]/=d;else for(b=0;e>b;b++)a[b][c][1]=0}for(c=0;f>c;++c)g[c]=0;return g}}),u.renderEnd("stackedArea immediate"),b}var c,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=a.utils.defaultColor(),i=Math.floor(1e5*Math.random()),j=null,k=function(a){return a.x},l=function(a){return a.y},m="stack",n="zero",o="default",p="linear",q=!1,r=a.models.scatter(),s=250,t=d3.dispatch("areaClick","areaMouseover","areaMouseout","renderEnd","elementClick","elementMouseover","elementMouseout");r.pointSize(2.2).pointDomain([2.2,2.2]);var u=a.utils.renderWatch(t,s);return b.dispatch=t,b.scatter=r,r.dispatch.on("elementClick",function(){t.elementClick.apply(this,arguments)}),r.dispatch.on("elementMouseover",function(){t.elementMouseover.apply(this,arguments)}),r.dispatch.on("elementMouseout",function(){t.elementMouseout.apply(this,arguments)}),b.interpolate=function(a){return arguments.length?(p=a,b):p},b.duration=function(a){return arguments.length?(s=a,u.reset(s),r.duration(s),b):s},b.dispatch=t,b.scatter=r,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return f},set:function(a){f=a}},height:{get:function(){return g},set:function(a){g=a}},clipEdge:{get:function(){return q},set:function(a){q=a}},offset:{get:function(){return n},set:function(a){n=a}},order:{get:function(){return o},set:function(a){o=a}},interpolate:{get:function(){return p},set:function(a){p=a}},x:{get:function(){return k},set:function(a){k=d3.functor(a)}},y:{get:function(){return l},set:function(a){l=d3.functor(a)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}},color:{get:function(){return h},set:function(b){h=a.utils.getColor(b)}},style:{get:function(){return m},set:function(a){switch(m=a){case"stack":b.offset("zero"),b.order("default");break;case"stream":b.offset("wiggle"),b.order("inside-out");break;case"stream-center":b.offset("silhouette"),b.order("inside-out");break;case"expand":b.offset("expand"),b.order("default");break;case"stack_percent":b.offset(b.d3_stackedOffset_stackPercent),b.order("default")}}},duration:{get:function(){return s},set:function(a){s=a,u.reset(s),r.duration(s)}}}),a.utils.inheritOptions(b,r),a.utils.initOptions(b),b},a.models.stackedAreaChart=function(){"use strict";function b(k){return H.reset(),H.models(e),r&&H.models(f),s&&H.models(g),k.each(function(k){var z=d3.select(this),H=this;a.utils.initSVG(z);var M=a.utils.availableWidth(m,z,l),N=a.utils.availableHeight(n,z,l);if(b.update=function(){z.transition().duration(E).call(b)},b.container=this,x.setter(K(k),b.update).getter(J(k)).update(),x.disabled=k.map(function(a){return!!a.disabled}),!y){var O;y={};for(O in x)x[O]instanceof Array?y[O]=x[O].slice(0):y[O]=x[O]}if(!(k&&k.length&&k.filter(function(a){return a.values.length}).length))return a.utils.noData(b,z),b;z.selectAll(".nv-noData").remove(),c=e.xScale(),d=e.yScale();var P=z.selectAll("g.nv-wrap.nv-stackedAreaChart").data([k]),Q=P.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),R=P.select("g");if(Q.append("rect").style("opacity",0),Q.append("g").attr("class","nv-x nv-axis"),Q.append("g").attr("class","nv-y nv-axis"),Q.append("g").attr("class","nv-stackedWrap"),Q.append("g").attr("class","nv-legendWrap"),Q.append("g").attr("class","nv-controlsWrap"),Q.append("g").attr("class","nv-interactive"),R.select("rect").attr("width",M).attr("height",N),q){var S=p?M-B:M;h.width(S),R.select(".nv-legendWrap").datum(k).call(h),l.top!=h.height()&&(l.top=h.height(),N=a.utils.availableHeight(n,z,l)),R.select(".nv-legendWrap").attr("transform","translate("+(M-S)+","+-l.top+")")}if(p){var T=[{key:D.stacked||"Stacked",metaKey:"Stacked",disabled:"stack"!=e.style(),style:"stack"},{key:D.stream||"Stream",metaKey:"Stream",disabled:"stream"!=e.style(),style:"stream"},{key:D.expanded||"Expanded",metaKey:"Expanded",disabled:"expand"!=e.style(),style:"expand"},{key:D.stack_percent||"Stack %",metaKey:"Stack_Percent",disabled:"stack_percent"!=e.style(),style:"stack_percent"}];B=C.length/3*260,T=T.filter(function(a){return-1!==C.indexOf(a.metaKey)}),i.width(B).color(["#444","#444","#444"]),R.select(".nv-controlsWrap").datum(T).call(i),l.top!=Math.max(i.height(),h.height())&&(l.top=Math.max(i.height(),h.height()),N=a.utils.availableHeight(n,z,l)),R.select(".nv-controlsWrap").attr("transform","translate(0,"+-l.top+")")}P.attr("transform","translate("+l.left+","+l.top+")"),t&&R.select(".nv-y.nv-axis").attr("transform","translate("+M+",0)"),u&&(j.width(M).height(N).margin({left:l.left,top:l.top}).svgContainer(z).xScale(c),P.select(".nv-interactive").call(j)),e.width(M).height(N);var U=R.select(".nv-stackedWrap").datum(k);if(U.transition().call(e),r&&(f.scale(c)._ticks(a.utils.calcTicksX(M/100,k)).tickSize(-N,0),R.select(".nv-x.nv-axis").attr("transform","translate(0,"+N+")"),R.select(".nv-x.nv-axis").transition().duration(0).call(f)),s){var V;if(V="wiggle"===e.offset()?0:a.utils.calcTicksY(N/36,k),g.scale(d)._ticks(V).tickSize(-M,0),"expand"===e.style()||"stack_percent"===e.style()){var W=g.tickFormat();F&&W===L||(F=W),g.tickFormat(L)}else F&&(g.tickFormat(F),F=null);R.select(".nv-y.nv-axis").transition().duration(0).call(g)}e.dispatch.on("areaClick.toggle",function(a){k.forEach(1===k.filter(function(a){return!a.disabled}).length?function(a){a.disabled=!1}:function(b,c){b.disabled=c!=a.seriesIndex}),x.disabled=k.map(function(a){return!!a.disabled}),A.stateChange(x),b.update()}),h.dispatch.on("stateChange",function(a){for(var c in a)x[c]=a[c];A.stateChange(x),b.update()}),i.dispatch.on("legendClick",function(a,c){a.disabled&&(T=T.map(function(a){return a.disabled=!0,a}),a.disabled=!1,e.style(a.style),x.style=e.style(),A.stateChange(x),b.update())}),j.dispatch.on("elementMousemove",function(c){e.clearHighlights();var d,g,h,i=[],l=0;if(k.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,j){g=a.interactiveBisect(f.values,c.pointXValue,b.x());var k=f.values[g],m=b.y()(k,g);if(null!=m&&e.highlightPoint(j,g,!0),"undefined"!=typeof k){"undefined"==typeof d&&(d=k),"undefined"==typeof h&&(h=b.xScale()(b.x()(k,g)));var n="expand"==e.style()?k.display.y:b.y()(k,g);i.push({key:f.key,value:n,color:o(f,f.seriesIndex),stackedValue:k.display}),v&&"expand"!=e.style()&&(l+=n)}}),i.reverse(),i.length>2){var m=b.yScale().invert(c.mouseY),n=null;i.forEach(function(a,b){m=Math.abs(m);var c=Math.abs(a.stackedValue.y0),d=Math.abs(a.stackedValue.y);return m>=c&&d+c>=m?void(n=b):void 0}),null!=n&&(i[n].highlight=!0)}v&&"expand"!=e.style()&&i.length>=2&&i.push({key:w,value:l,total:!0});var p=f.tickFormat()(b.x()(d,g)),q=j.tooltip.valueFormatter();"expand"===e.style()||"stack_percent"===e.style()?(G||(G=q),q=d3.format(".1%")):G&&(q=G,G=null),j.tooltip.chartContainer(H.parentNode).valueFormatter(q).data({value:p,series:i})(),j.renderGuideLine(h)}),j.dispatch.on("elementMouseout",function(a){e.clearHighlights()}),A.on("changeState",function(a){"undefined"!=typeof a.disabled&&k.length===a.disabled.length&&(k.forEach(function(b,c){b.disabled=a.disabled[c]}),x.disabled=a.disabled),"undefined"!=typeof a.style&&(e.style(a.style),I=a.style),b.update()})}),H.renderEnd("stacked Area chart immediate"),b}var c,d,e=a.models.stackedArea(),f=a.models.axis(),g=a.models.axis(),h=a.models.legend(),i=a.models.legend(),j=a.interactiveGuideline(),k=a.models.tooltip(),l={top:30,right:25,bottom:50,left:60},m=null,n=null,o=a.utils.defaultColor(),p=!0,q=!0,r=!0,s=!0,t=!1,u=!1,v=!0,w="TOTAL",x=a.utils.state(),y=null,z=null,A=d3.dispatch("stateChange","changeState","renderEnd"),B=250,C=["Stacked","Stream","Expanded"],D={},E=250;x.style=e.style(),f.orient("bottom").tickPadding(7),g.orient(t?"right":"left"),k.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)}),j.tooltip.headerFormatter(function(a,b){return f.tickFormat()(a,b)}).valueFormatter(function(a,b){return g.tickFormat()(a,b)});var F=null,G=null;i.updateState(!1);var H=a.utils.renderWatch(A),I=e.style(),J=function(a){return function(){return{active:a.map(function(a){return!a.disabled}),style:e.style()}}},K=function(a){return function(b){void 0!==b.style&&(I=b.style),void 0!==b.active&&a.forEach(function(a,c){a.disabled=!b.active[c]})}},L=d3.format("%");return e.dispatch.on("elementMouseover.tooltip",function(a){a.point.x=e.x()(a.point),a.point.y=e.y()(a.point),k.data(a).hidden(!1)}),e.dispatch.on("elementMouseout.tooltip",function(a){k.hidden(!0)}),b.dispatch=A,b.stacked=e,b.legend=h,b.controls=i,b.xAxis=f,b.yAxis=g,b.interactiveLayer=j,b.tooltip=k,b.dispatch=A,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return m},set:function(a){m=a}},height:{get:function(){return n},set:function(a){n=a}},showLegend:{get:function(){return q},set:function(a){q=a}},showXAxis:{get:function(){return r},set:function(a){r=a}},showYAxis:{get:function(){return s},set:function(a){s=a}},defaultState:{get:function(){return y},set:function(a){y=a}},noData:{get:function(){return z},set:function(a){z=a}},showControls:{get:function(){return p},set:function(a){p=a}},controlLabels:{get:function(){return D},set:function(a){D=a}},controlOptions:{get:function(){return C},set:function(a){C=a}},showTotalInTooltip:{get:function(){return v},set:function(a){v=a}},totalLabel:{get:function(){return w},set:function(a){w=a}},margin:{get:function(){return l},set:function(a){l.top=void 0!==a.top?a.top:l.top,l.right=void 0!==a.right?a.right:l.right,l.bottom=void 0!==a.bottom?a.bottom:l.bottom,l.left=void 0!==a.left?a.left:l.left}},duration:{get:function(){return E},set:function(a){E=a,H.reset(E),e.duration(E),f.duration(E),g.duration(E)}},color:{get:function(){return o},set:function(b){o=a.utils.getColor(b),h.color(o),e.color(o)}},rightAlignYAxis:{get:function(){return t},set:function(a){t=a,g.orient(t?"right":"left")}},useInteractiveGuideline:{get:function(){return u},set:function(a){u=!!a,b.interactive(!a),b.useVoronoi(!a),e.scatter.interactive(!a)}}}),a.utils.inheritOptions(b,e),a.utils.initOptions(b),b},a.models.sunburst=function(){"use strict";function b(u){return t.reset(),u.each(function(b){function t(a){a.x0=a.x,a.dx0=a.dx}function u(a){var b=d3.interpolate(p.domain(),[a.x,a.x+a.dx]),c=d3.interpolate(q.domain(),[a.y,1]),d=d3.interpolate(q.range(),[a.y?20:0,y]);return function(a,e){return e?function(b){return s(a)}:function(e){return p.domain(b(e)),q.domain(c(e)).range(d(e)),s(a)}}}l=d3.select(this);var v,w=a.utils.availableWidth(g,l,f),x=a.utils.availableHeight(h,l,f),y=Math.min(w,x)/2;a.utils.initSVG(l);var z=l.selectAll(".nv-wrap.nv-sunburst").data(b),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburst nv-chart-"+k),B=A.selectAll("nv-sunburst");z.attr("transform","translate("+w/2+","+x/2+")"),l.on("click",function(a,b){o.chartClick({data:a,index:b,pos:d3.event,id:k})}),q.range([0,y]),c=c||b,e=b[0],r.value(j[i]||j.count),v=B.data(r.nodes).enter().append("path").attr("d",s).style("fill",function(a){return m((a.children?a:a.parent).name)}).style("stroke","#FFF").on("click",function(a){d!==c&&c!==a&&(d=c),c=a,v.transition().duration(n).attrTween("d",u(a))}).each(t).on("dblclick",function(a){d.parent==a&&v.transition().duration(n).attrTween("d",u(e))}).each(t).on("mouseover",function(a,b){d3.select(this).classed("hover",!0).style("opacity",.8),o.elementMouseover({data:a,color:d3.select(this).style("fill")})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1).style("opacity",1),o.elementMouseout({data:a})}).on("mousemove",function(a,b){o.elementMousemove({data:a})})}),t.renderEnd("sunburst immediate"),b}var c,d,e,f={top:0,right:0,bottom:0,left:0},g=null,h=null,i="count",j={count:function(a){return 1},size:function(a){return a.size}},k=Math.floor(1e4*Math.random()),l=null,m=a.utils.defaultColor(),n=500,o=d3.dispatch("chartClick","elementClick","elementDblClick","elementMousemove","elementMouseover","elementMouseout","renderEnd"),p=d3.scale.linear().range([0,2*Math.PI]),q=d3.scale.sqrt(),r=d3.layout.partition().sort(null).value(function(a){return 1}),s=d3.svg.arc().startAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x)))}).endAngle(function(a){return Math.max(0,Math.min(2*Math.PI,p(a.x+a.dx)))}).innerRadius(function(a){return Math.max(0,q(a.y))}).outerRadius(function(a){return Math.max(0,q(a.y+a.dy))}),t=a.utils.renderWatch(o);return b.dispatch=o,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{width:{get:function(){return g},set:function(a){g=a}},height:{get:function(){return h},set:function(a){h=a}},mode:{get:function(){return i},set:function(a){i=a}},id:{get:function(){return k},set:function(a){k=a}},duration:{get:function(){return n},set:function(a){n=a}},margin:{get:function(){return f},set:function(a){f.top=void 0!=a.top?a.top:f.top,f.right=void 0!=a.right?a.right:f.right,f.bottom=void 0!=a.bottom?a.bottom:f.bottom,f.left=void 0!=a.left?a.left:f.left}},color:{get:function(){return m},set:function(b){m=a.utils.getColor(b)}}}),a.utils.initOptions(b),b},a.models.sunburstChart=function(){"use strict";function b(d){return m.reset(),m.models(c),d.each(function(d){var h=d3.select(this);a.utils.initSVG(h);var i=a.utils.availableWidth(f,h,e),j=a.utils.availableHeight(g,h,e);if(b.update=function(){0===k?h.call(b):h.transition().duration(k).call(b)},b.container=this,!d||!d.length)return a.utils.noData(b,h),b;h.selectAll(".nv-noData").remove();var l=h.selectAll("g.nv-wrap.nv-sunburstChart").data(d),m=l.enter().append("g").attr("class","nvd3 nv-wrap nv-sunburstChart").append("g"),n=l.select("g");m.append("g").attr("class","nv-sunburstWrap"),l.attr("transform","translate("+e.left+","+e.top+")"),c.width(i).height(j);var o=n.select(".nv-sunburstWrap").datum(d);d3.transition(o).call(c)}),m.renderEnd("sunburstChart immediate"),b}var c=a.models.sunburst(),d=a.models.tooltip(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=a.utils.defaultColor(),i=(Math.round(1e5*Math.random()),null),j=null,k=250,l=d3.dispatch("stateChange","changeState","renderEnd");d.duration(0);var m=a.utils.renderWatch(l);return d.headerEnabled(!1).valueFormatter(function(a,b){return a}),c.dispatch.on("elementMouseover.tooltip",function(a){a.series={key:a.data.name,value:a.data.size,color:a.color},d.data(a).hidden(!1)}),c.dispatch.on("elementMouseout.tooltip",function(a){d.hidden(!0)}),c.dispatch.on("elementMousemove.tooltip",function(a){d()}),b.dispatch=l,b.sunburst=c,b.tooltip=d,b.options=a.utils.optionsFunc.bind(b),b._options=Object.create({},{noData:{get:function(){return j},set:function(a){j=a}},defaultState:{get:function(){return i},set:function(a){i=a}},color:{get:function(){return h},set:function(a){h=a,c.color(h)}},duration:{get:function(){return k},set:function(a){k=a,m.reset(k),c.duration(k)}},margin:{get:function(){return e},set:function(a){e.top=void 0!==a.top?a.top:e.top,e.right=void 0!==a.right?a.right:e.right,e.bottom=void 0!==a.bottom?a.bottom:e.bottom,e.left=void 0!==a.left?a.left:e.left}}}),a.utils.inheritOptions(b,c),a.utils.initOptions(b),b},a.version="1.8.1-dev"}(); \ No newline at end of file diff --git a/build/nv.d3.min.js.map b/build/nv.d3.min.js.map new file mode 100644 index 000000000..2390706f2 --- /dev/null +++ b/build/nv.d3.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nv.d3.min.js","sources":["nv.d3.js"],"names":["nv","dev","tooltip","utils","models","charts","logs","dom","dispatch","d3","Function","prototype","bind","oThis","this","TypeError","aArgs","Array","slice","call","arguments","fToBind","fNOP","fBound","apply","concat","on","e","startTime","Date","endTime","totalTime","log","window","console","length","deprecated","name","info","warn","render","step","active","render_start","renderLoop","chart","graph","i","queue","generate","callback","splice","setTimeout","render_end","addGraph","obj","push","module","exports","write","undefined","fastdom","read","interactiveGuideline","layer","selection","each","data","mouseHandler","d3mouse","mouse","mouseX","mouseY","subtractMargin","mouseOutAnyReason","isMSIE","event","offsetX","offsetY","target","tagName","className","baseVal","match","margin","left","top","availableWidth","availableHeight","relatedTarget","ownerSVGElement","nvPointerEventsClass","elementMouseout","renderGuideLine","hidden","pointXValue","xScale","invert","elementMousemove","type","elementDblclick","elementClick","elementMouseDown","elementMouseUp","container","select","width","height","wrap","selectAll","wrapEnter","enter","append","attr","svgContainer","guideLine","x","showGuideLine","line","NaNtoZero","String","d","exit","remove","scale","linear","duration","hideDelay","_","interactiveBisect","values","searchVal","xAccessor","_xAccessor","_cmp","v","bisect","bisector","index","max","currentValue","nextIndex","min","nextValue","Math","abs","nearestValueIndex","threshold","yDistMax","Infinity","indexToHighlight","forEach","delta","initTooltip","chartContainer","document","body","classes","id","style","classed","nvtooltip","enabled","dataSeriesExists","newContent","contentGenerator","node","innerHTML","positionTooltip","floor","random","gravity","distance","snapDistance","lastPosition","headerEnabled","position","clientX","clientY","valueFormatter","headerFormatter","keyFormatter","table","createElement","theadEnter","html","value","tbodyEnter","trowEnter","p","series","highlight","color","total","key","opacityScale","domain","range","opacity","outerHTML","footer","Object","calcGravityOffset","pos","tmp","offsetHeight","offsetWidth","clientWidth","documentElement","clientHeight","gravityOffset","interrupt","transition","delay","old_translate","new_translate","translateInterpolator","interpolateString","is_hidden","styleTween","options","optionsFunc","_options","create","get","set","point","y","initOptions","windowSize","size","innerWidth","innerHeight","compatMode","windowResize","handler","addEventListener","clear","removeEventListener","getColor","defaultColor","isArray","color_scale","ordinal","category20","customTheme","dictionary","getKey","defaultColors","defIndex","pjax","links","content","load","href","fragment","parentNode","replaceChild","history","pushState","textContent","preventDefault","state","calcApproxTextWidth","svgTextElem","text","fontSize","parseInt","replace","textLength","n","isNaN","watchTransition","renderWatch","args","_duration","renderStack","self","model","__rendered","m","arg","renderEnd","indexOf","reset","pop","every","deepExtend","dst","sources","source","isObject","srcObj","_setState","_getState","init","changed","getter","fn","setter","update","_set","settings","JSON","stringify","change","map","calcTicksX","numTicks","numValues","stream_len","calcTicksY","initOption","_calls","_overrides","ops","getOwnPropertyNames","calls","inheritOptionsD3","d3_source","oplist","_d3options","unshift","rebind","arrayUnique","a","sort","filter","item","symbolMap","symbol","t","s","svg","symbolTypes","functor","inheritOptions","inherited","_inherited","d3ops","initSVG","nvd3-svg","sanitizeHeight","sanitizeWidth","bottom","right","noData","opt","noDataText","wrapTicks","word","words","split","reverse","lineNumber","lineHeight","dy","parseFloat","tspan","join","getComputedTextLength","axis","g","ticks","orient","scale0","fmt","tickFormat","axisLabel","axisLabelText","xLabelMargin","axisMaxMin","w","isOrdinal","rangeBand","showMaxMin","tickPadding","axisLabelDistance","maxTextWidth","textHeight","xTicks","rotateLabelsRule","rotateLabels","box","getBoundingClientRect","sin","PI","staggerLabels","rotateYLabel","maxMinRange","err","round","copy","rangeBands","boxPlot","xDomain","getX","xRange","yData","yDomain","yMin","min_arr","Q1","hasOwnProperty","whisker_low","outliers","yMax","max_arr","Q3","whisker_high","yRange","x0","y0","boxplots","boxEnter","j","hover","elementMouseover","box_width","maxBoxWidth","box_left","box_right","endpoint","label","Q2","getY","yScale","boxPlotChart","boxplot","showXAxis","xAxis","showYAxis","yAxis","beforeUpdate","clamp","gEnter","defsEnter","rightAlignYAxis","barsWrap","datum","disabled","tickSize","format","evt","tooltipContent","bullet","rangez","ranges","descending","markerz","markers","measurez","measures","rangeLabelz","rangeLabels","markerLabelz","markerLabels","measureLabelz","measureLabels","x1","extent","merge","forceX","__chart__","rangeMin","rangeMax","rangeAvg","w1","xp1","h3","markerData","marker","bulletChart","title","subtitle","bulletWrap","tick","tickEnter","tickUpdate","timer","flush","candlestickBar","barWidth","padData","getLow","forceY","getHigh","chartClick","clipEdge","tickGroups","getOpen","getClose","open","close","high","low","interactive","highlightPoint","pointIndex","isHoverOver","clearHighlights","cumulativeLineChart","lines","dragStart","dragMove","dx","updateZero","dragEnd","stateChange","indexLine","oldDuration","that","stateSetter","stateGetter","defaultState","indexDrag","behavior","drag","rescaleY","seriesDomains","initialDomain","completeDomain","indexify","interactivePointerEvents","showLegend","legend","showControls","controlsData","controls","rightAlign","tempDisabled","useInteractiveGuideline","interactiveLayer","display","linesWrap","seriesIndex","avgLineData","average","avgLines","getAvgLineY","yVal","_ticks","newState","singlePoint","pointXLocation","allData","yValue","domainExtent","xValue","idx","indexifyYGetter","indexValue","noErrorCheck","updateState","useVoronoi","discreteBar","seriesData","showValues","groups","bars","barsEnter","stopPropagation","elementDblClick","valueFormat","rectClass","discreteBarChart","discretebar","wrapLabels","distribution","naxis","distWrap","dist","getData","furiousLegend","setTextColor","vers","expanded","disengaged","setBGColor","seriesShape","seriesEnter","property","seriesCheckbox","seriesText","legendMouseover","legendMouseout","legendClick","radioButtonMode","userDisabled","engaged","legendDblclick","versPadding","align","seriesWidths","legendText","maxKeyLength","trimmedKey","substring","nodeTextLength","Error","padding","seriesPerRow","legendWidth","columnWidths","k","reduce","prev","cur","array","xPositions","curX","ceil","xpos","ypos","newxpos","maxwidth","historicalBar","rval","historicalBarChart","bar_model","transitionDuration","tooltipHide","ohlcBarChart","ohlcBar","candlestickBarChart","setBGOpacity","insert","seriesBG","scatter","scatterWrap","strokeWidth","fillOpacity","areaPaths","isArea","area","interpolate","defined","y1","linePaths","pointSize","pointDomain","lineChart","pointYValue","yPos","linePlusBarChart","resizePath","availableHeight2","updateBrushBG","brush","empty","brushExtent","brushBG","x2","leftWidth","rightWidth","onBrush","availableHeight1","bar","focusBarsWrap","dataBars","focusLinesWrap","allDisabled","dataLines","dataLine","y1Axis","y2Axis","y2","focusEnable","focusHeight","margin2","x2Axis","y3","bars2","y4","lines2","series1","series2","focusEnter","contextEnter","legendXPosition","originalKey","legendLeftAxisHint","legendRightAxisHint","bars2Wrap","lines2Wrap","focusShowAxisX","focusShowAxisY","y3Axis","y4Axis","brushBGenter","gBrush","pointActive","focusMargin","lineWithFocusChart","height2","contextLinesWrap","currentValues","xTickFormat","yTickFormat","multiBar","nonStackableCount","hideable","stacked","parsed","layout","stack","offset","stackOffset","nonStackable","nonStackableSeries","posBase","negBase","f","groupSpacing","exitTransition","last_datalength","barColor","rgb","darker","toString","barSelection","multiBarChart","multibar","controlWidth","controlLabels","grouped","getTranslate","staggerUp","staggerDown","totalInBetweenTicks","reduceXTicks","multiBarHorizontal","valuePadding","getYerr","xerr","mid","path","yerr","showBarLabels","yErr","multiBarHorizontalChart","multiChart","mouseover_line","yaxis","yAxis2","yAxis1","mouseover_scatter","mouseover_stack","stack1","mouseover_bar","bars1","dataLines1","dataLines2","dataScatters1","dataScatters2","dataBars1","dataBars2","dataStack1","dataStack2","color_array","lines1","scatters1","scatters2","stack2","lines1Wrap","scatters1Wrap","bars1Wrap","stack1Wrap","scatters2Wrap","stack2Wrap","extraValue1","b","aVal","extraValue2","yScale1","yDomain1","yScale2","yDomain2","stackedArea","parallelCoordinates","dimensionNames","axisWithMissingValues","newscale","missingValuesline","missingValueslineText","actives","extents","filters","dimension","foreground","isActive","dragging","__origin__","background","dimensions","rangePoints","onlyNanValues","tension","lineTension","axisDrag","lineData","dimensionsEnter","dim","dimensionFormats","pie","arcTween","endAngle","startAngle","donut","innerRadius","_current","arcs","radius","arcsRadiusOuter","arcsRadiusInner","arcsRadius","outer","inner","donutRatio","g_pie","arcsOver","arc","outerRadius","arcOver","cornerRadius","padAngle","titleOffset","slices","pieLabels","ae","growOnHover","attrTween","showLabels","labelsArc","labelsOutside","group","labelSunbeamLayout","rotateAngle","centroid","labelLocationHash","avgHeight","avgWidth","createHashKey","coordinates","center","hashKey","percent","labelThreshold","labelType","pieLabelsOutside","donutLabelsOutside","labelFormat","pieChart","legendPosition","pieWrap","updateInteractiveLayer","needsUpdate","vertices","groupIndex","pX","pY","pointArray","bounds","geom","polygon","voronoi","clip","pointPaths","vPointPaths","showVoronoi","clipVoronoi","pointClips","clipRadius","mouseEventCallback","mDispatch","scrollTop","pageYOffset","scrollLeft","pageXOffset","relativePos","sizeDomain","getSize","padDataOuter","z","forceSize","sizeRange","_sizeRange_def","z0","points","getShape","clearTimeout","timeoutID","shape","notActive","pointScale","pointRange","forcePoint","pointShape","scatterChart","showDistX","distX","showDistY","distY","regWrap","regLine","intercept","slope","sparkline","paths","result","yValues","maxPoint","lastIndexOf","minPoint","currentPoint","animate","sparklinePlus","updateValueLine","paused","hoverValue","hoverEnter","sparklineHover","getClosestIndex","closestIndex","sparklineWrap","showLastValue","valueWrap","rightAlignValue","alignValue","dataRaw","aseries","dataFiltered","order","out","zeroArea","areaMouseover","pageX","pageY","areaMouseout","areaClick","d3_stackedOffset_stackPercent","stackData","o","stackedAreaChart","metaKey","stream","stack_percent","controlOptions","stackedWrap","currentFormat","oldYTickFormat","percentFormatter","valueSum","tooltipValue","stackedValue","showTotalInTooltip","stackedY0","stackedY","totalLabel","oldValueFormatter","sunburst","stash","dx0","arcTweenZoom","xd","yd","yr","rootNode","partition","modes","mode","nodes","children","parent","prevNode","count","sqrt","sunburstChart","sunWrap","version"],"mappings":";;CACA,WAGA,GAAIA,KAGJA,GAAGC,KAAM,EACTD,EAAGE,QAAUF,EAAGE,YAChBF,EAAGG,MAAQH,EAAGG,UACdH,EAAGI,OAASJ,EAAGI,WACfJ,EAAGK,UACHL,EAAGM,QACHN,EAAGO,OAEHP,EAAGQ,SAAWC,GAAGD,SAAS,eAAgB,cAOrCE,SAASC,UAAUC,OACpBF,SAASC,UAAUC,KAAO,SAAUC,GAChC,GAAoB,kBAATC,MAEP,KAAM,IAAIC,WAAU,uEAGxB,IAAIC,GAAQC,MAAMN,UAAUO,MAAMC,KAAKC,UAAW,GAC9CC,EAAUP,KACVQ,EAAO,aACPC,EAAS,WACL,MAAOF,GAAQG,MAAMV,eAAgBQ,IAAQT,EACnCC,KACAD,EACNG,EAAMS,OAAOR,MAAMN,UAAUO,MAAMC,KAAKC,aAKpD,OAFAE,GAAKX,UAAYG,KAAKH,UACtBY,EAAOZ,UAAY,GAAIW,GAChBC,IAKXvB,EAAGC,MACHD,EAAGQ,SAASkB,GAAG,eAAgB,SAASC,GACpC3B,EAAGM,KAAKsB,WAAa,GAAIC,QAG7B7B,EAAGQ,SAASkB,GAAG,aAAc,SAASC,GAClC3B,EAAGM,KAAKwB,SAAW,GAAID,MACvB7B,EAAGM,KAAKyB,UAAY/B,EAAGM,KAAKwB,QAAU9B,EAAGM,KAAKsB,UAC9C5B,EAAGgC,IAAI,QAAShC,EAAGM,KAAKyB,cAQhC/B,EAAGgC,IAAM,WACL,GAAIhC,EAAGC,KAAOgC,OAAOC,SAAWA,QAAQF,KAAOE,QAAQF,IAAIR,MACvDU,QAAQF,IAAIR,MAAMU,QAASd,eAC1B,IAAIpB,EAAGC,KAAOgC,OAAOC,SAAiC,kBAAfA,SAAQF,KAAqBtB,SAASC,UAAUC,KAAM,CAC9F,GAAIoB,GAAMtB,SAASC,UAAUC,KAAKO,KAAKe,QAAQF,IAAKE,QACpDF,GAAIR,MAAMU,QAASd,WAEvB,MAAOA,WAAUA,UAAUe,OAAS,IAIxCnC,EAAGoC,WAAa,SAASC,EAAMC,GACvBJ,SAAWA,QAAQK,MACnBL,QAAQK,KAAK,kBAAoBF,EAAO,0BAA2BC,GAAQ,KAOnFtC,EAAGwC,OAAS,SAAgBC,GAExBA,EAAOA,GAAQ,EAEfzC,EAAGwC,OAAOE,QAAS,EACnB1C,EAAGQ,SAASmC,cAEZ,IAAIC,GAAa,WAGb,IAAK,GAFDC,GAAOC,EAEFC,EAAI,EAAON,EAAJM,IAAaD,EAAQ9C,EAAGwC,OAAOQ,MAAMD,IAAKA,IACtDF,EAAQC,EAAMG,iBACHH,GAAMI,gBAAkB,WAAYJ,EAAMI,SAASL,EAGlE7C,GAAGwC,OAAOQ,MAAMG,OAAO,EAAGJ,GAEtB/C,EAAGwC,OAAOQ,MAAMb,OAChBiB,WAAWR,IAGX5C,EAAGQ,SAAS6C,aACZrD,EAAGwC,OAAOE,QAAS,GAI3BU,YAAWR,IAGf5C,EAAGwC,OAAOE,QAAS,EACnB1C,EAAGwC,OAAOQ,SAmBVhD,EAAGsD,SAAW,SAASC,SACRnC,WAAU,UAAa,YAC9BmC,GAAON,SAAU7B,UAAU,GAAI8B,SAAU9B,UAAU,KAGvDpB,EAAGwC,OAAOQ,MAAMQ,KAAKD,GAEhBvD,EAAGwC,OAAOE,QACX1C,EAAGwC,UAKY,mBAAb,SAAgD,mBAAd,WAC1CiB,OAAOC,QAAU1D,GAGI,mBAAb,UACRiC,OAAOjC,GAAKA,GAQdA,EAAGO,IAAIoD,MAAQ,SAAST,GACvB,MAAuBU,UAAnB3B,OAAO4B,QACHA,QAAQF,MAAMT,GAEfA,KASRlD,EAAGO,IAAIuD,KAAO,SAASZ,GACtB,MAAuBU,UAAnB3B,OAAO4B,QACHA,QAAQC,KAAKZ,GAEdA,KASRlD,EAAG+D,qBAAuB,WACtB,YAkBA,SAASC,GAAMC,GACXA,EAAUC,KAAK,SAASC,GAapB,QAASC,KACL,GAAIC,GAAU5D,GAAG6D,MAAMxD,MACnByD,EAASF,EAAQ,GACjBG,EAASH,EAAQ,GACjBI,GAAiB,EACjBC,GAAoB,CAuCxB,IAtCIC,IAQAJ,EAAS9D,GAAGmE,MAAMC,QAClBL,EAAS/D,GAAGmE,MAAME,QAWa,QAA5BrE,GAAGmE,MAAMG,OAAOC,UACfP,GAAiB,GAGjBhE,GAAGmE,MAAMG,OAAOE,UAAUC,QAAQC,MAAM,eACxCT,GAAoB,IAKzBD,IACCF,GAAUa,EAAOC,KACjBb,GAAUY,EAAOE,KAMR,EAATf,GAAuB,EAATC,GACXD,EAASgB,GAAkBf,EAASgB,GACnC/E,GAAGmE,MAAMa,eAA4D7B,SAA3CnD,GAAGmE,MAAMa,cAAcC,iBAClDhB,EACD,CAEF,GAAIC,GACIlE,GAAGmE,MAAMa,eACqC7B,SAA3CnD,GAAGmE,MAAMa,cAAcC,kBACe9B,SAArCnD,GAAGmE,MAAMa,cAAcR,WACpBxE,GAAGmE,MAAMa,cAAcR,UAAUE,MAAMjF,EAAQyF,uBAEtD,MASR,OANAnF,GAASoF,iBACLrB,OAAQA,EACRC,OAAQA,IAEZR,EAAM6B,gBAAgB,UACtB3F,GAAQ4F,QAAO,GAGf5F,EAAQ4F,QAAO,EAGnB,IAAIC,GAAcC,EAAOC,OAAO1B,EAChC/D,GAAS0F,kBACL3B,OAAQA,EACRC,OAAQA,EACRuB,YAAaA,IAIK,aAAlBtF,GAAGmE,MAAMuB,MACT3F,EAAS4F,iBACL7B,OAAQA,EACRC,OAAQA,EACRuB,YAAaA,IAKC,UAAlBtF,GAAGmE,MAAMuB,MACT3F,EAAS6F,cACL9B,OAAQA,EACRC,OAAQA,EACRuB,YAAaA,IAKC,cAAlBtF,GAAGmE,MAAMuB,MACZ3F,EAAS8F,kBACR/B,OAAQA,EACRC,OAAQA,EACRuB,YAAaA,IAKO,YAAlBtF,GAAGmE,MAAMuB,MACZ3F,EAAS+F,gBACRhC,OAAQA,EACRC,OAAQA,EACRuB,YAAaA,IAzHnB,GAAIS,GAAY/F,GAAGgG,OAAO3F,MACtByE,EAAkBmB,GAAS,IAAMlB,EAAmBmB,GAAU,IAC9DC,EAAOJ,EAAUK,UAAU,qCAC1B1C,MAAMA,IACP2C,EAAYF,EAAKG,QAChBC,OAAO,KAAKC,KAAK,QAAS,mCAC/BH,GAAUE,OAAO,KAAKC,KAAK,QAAQ,2BAE9BC,IAsHLA,EACKxF,GAAG,YAAY0C,GACf1C,GAAG,YAAY0C,GAAc,GAC7B1C,GAAG,WAAY0C,GAAa,GAC5B1C,GAAG,YAAa0C,GAAa,GAC7B1C,GAAG,UAAW0C,GAAa,GAC3B1C,GAAG,WAAY0C,GACf1C,GAAG,QAAS0C,GAGjBJ,EAAMmD,UAAY,KAElBnD,EAAM6B,gBAAkB,SAASuB,GACxBC,IACDrD,EAAMmD,WAAanD,EAAMmD,UAAUF,KAAK,QAAUG,GACtDpH,EAAGO,IAAIoD,MAAM,WACT,GAAI2D,GAAOV,EAAKH,OAAO,4BAClBI,UAAU,QACV1C,KAAW,MAALiD,GAAcpH,EAAGG,MAAMoH,UAAUH,OAAUI,OACtDF,GAAKP,QACAC,OAAO,QACPC,KAAK,QAAS,gBACdA,KAAK,KAAM,SAASQ,GAAK,MAAOA,KAChCR,KAAK,KAAM,SAASQ,GAAK,MAAOA,KAChCR,KAAK,KAAMzB,GACXyB,KAAK,KAAK,GACfK,EAAKI,OAAOC,gBA1K5B,GAAIvC,IAAWC,KAAM,EAAGC,IAAK,GACrBoB,EAAQ,KACRC,EAAS,KACTX,EAASvF,GAAGmH,MAAMC,SAClBrH,EAAWC,GAAGD,SAAS,mBAAoB,kBAAmB,eAAgB,kBAAmB,mBAAoB,kBACrH6G,GAAgB,EAChBH,EAAe,KACfhH,EAAUF,EAAGI,OAAOF,UACpByE,EAAS,iBAAmB1C,OAgNpC,OA7MA/B,GACK4H,SAAS,GACTC,UAAU,GACVjC,QAAO,GAkKZ9B,EAAMxD,SAAWA,EACjBwD,EAAM9D,QAAUA,EAEhB8D,EAAMoB,OAAS,SAAS4C,GACpB,MAAK5G,WAAUe,QACfiD,EAAOE,IAA4B,mBAAZ0C,GAAE1C,IAAwB0C,EAAE1C,IAASF,EAAOE,IACnEF,EAAOC,KAA4B,mBAAZ2C,GAAE3C,KAAwB2C,EAAE3C,KAASD,EAAOC,KAC5DrB,GAHuBoB,GAMlCpB,EAAM0C,MAAQ,SAASsB,GACnB,MAAK5G,WAAUe,QACfuE,EAAQsB,EACDhE,GAFuB0C,GAKlC1C,EAAM2C,OAAS,SAASqB,GACpB,MAAK5G,WAAUe,QACfwE,EAASqB,EACFhE,GAFuB2C,GAKlC3C,EAAMgC,OAAS,SAASgC,GACpB,MAAK5G,WAAUe,QACf6D,EAASgC,EACFhE,GAFuBgC,GAKlChC,EAAMqD,cAAgB,SAASW,GAC3B,MAAK5G,WAAUe,QACfkF,EAAgBW,EACThE,GAFuBqD,GAKlCrD,EAAMkD,aAAe,SAASc,GAC1B,MAAK5G,WAAUe,QACf+E,EAAec,EACRhE,GAFuBkD,GAK3BlD,GAgBXhE,EAAGiI,kBAAoB,SAAUC,EAAQC,EAAWC,GAChD,YACA,MAAOF,YAAkBjH,QACrB,MAAO,KAEX,IAAIoH,EAEAA,GADqB,kBAAdD,GACM,SAASX,GAClB,MAAOA,GAAEL,GAGAgB,CAEjB,IAAIE,GAAO,SAASb,EAAGc,GAUnB,MAAOF,GAAWZ,GAAKc,GAGvBC,EAAS/H,GAAGgI,SAASH,GAAMjD,KAC3BqD,EAAQjI,GAAGkI,KAAK,EAAGH,EAAON,EAAOC,GAAa,IAC9CS,EAAeP,EAAWH,EAAOQ,GAMrC,IAJ4B,mBAAjBE,KACPA,EAAeF,GAGfE,IAAiBT,EACjB,MAAOO,EAGX,IAAIG,GAAYpI,GAAGqI,KAAKJ,EAAM,EAAGR,EAAO/F,OAAS,IAC7C4G,EAAYV,EAAWH,EAAOW,GAMlC,OAJyB,mBAAdE,KACPA,EAAYF,GAGZG,KAAKC,IAAIF,EAAYZ,IAAca,KAAKC,IAAIL,EAAeT,GACpDO,EAEAG,GASf7I,EAAGkJ,kBAAoB,SAAUhB,EAAQC,EAAWgB,GAChD,YACA,IAAIC,GAAWC,EAAAA,EAAUC,EAAmB,IAQ5C,OAPApB,GAAOqB,QAAQ,SAAS9B,EAAE1E,GACtB,GAAIyG,GAAQR,KAAKC,IAAId,EAAYV,EACvB,OAALA,GAAsB2B,GAATI,GAA6BL,EAARK,IACnCJ,EAAWI,EACXF,EAAmBvG,KAGpBuG,GAUXtJ,EAAGI,OAAOF,QAAU,WAChB,YA4OA,SAASuJ,KACL,IAAKvJ,EAAS,CACV,GAAIsG,GAAYkD,EAAiBA,EAAiBC,SAASC,IAG3D1J,GAAUO,GAAGgG,OAAOD,GAAWQ,OAAO,OACjCC,KAAK,QAAS,cAAgB4C,EAAUA,EAAU,eAClD5C,KAAK,KAAM6C,GAChB5J,EAAQ6J,MAAM,MAAO,GAAGA,MAAM,OAAQ,GACtC7J,EAAQ6J,MAAM,UAAW,GACzB7J,EAAQ6J,MAAM,WAAY,SAC1B7J,EAAQ2G,UAAU,sBAAsBmD,QAAQrE,GAAsB,GACtEzF,EAAQ8J,QAAQrE,GAAsB,IAK9C,QAASsE,KACL,MAAKC,IACAC,EAAiBhG,IAEtBnE,EAAGO,IAAIoD,MAAM,WACT8F,GAIA,IAAIW,GAAaC,EAAiBlG,EAC9BiG,KACAlK,EAAQoK,OAAOC,UAAYH,GAG/BI,MAGGP,GAhBP,OAhPJ,GAAIH,GAAK,aAAed,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UAChCvG,EAAO,KACPwG,EAAU,IACVC,EAAW,GACXC,EAAe,EAEfhB,EAAU,KACVH,EAAiB,KACjB5D,GAAS,EACTiC,EAAY,IACZ7H,EAAU,KACV4K,GAAiBzF,KAAM,KAAMC,IAAK,MAClC4E,GAAU,EACVpC,EAAW,IACXiD,GAAgB,EAChBpF,EAAuB,yBAU3BqF,EAAW,WACX,OACI3F,KAAM5E,GAAGmE,MAAMqG,QACf3F,IAAK7E,GAAGmE,MAAMsG,UAKlBC,EAAiB,SAAS1D,EAAG1E,GAC7B,MAAO0E,IAIP2D,EAAkB,SAAS3D,GAC3B,MAAOA,IAGP4D,EAAe,SAAS5D,EAAG1E,GAC3B,MAAO0E,IAKP4C,EAAmB,SAAS5C,GAC5B,GAAU,OAANA,EACA,MAAO,EAGX,IAAI6D,GAAQ7K,GAAGgG,OAAOkD,SAAS4B,cAAc,SAC7C,IAAIR,EAAe,CACf,GAAIS,GAAaF,EAAMzE,UAAU,SAC5B1C,MAAMsD,IACNV,QAAQC,OAAO,QAEpBwE,GAAWxE,OAAO,MACbA,OAAO,MACPC,KAAK,UAAW,GAChBD,OAAO,UACPgD,QAAQ,WAAW,GACnByB,KAAKL,EAAgB3D,EAAEiE,QAGhC,GAAIC,GAAaL,EAAMzE,UAAU,SAC5B1C,MAAMsD,IACNV,QAAQC,OAAO,SAEhB4E,EAAYD,EAAW9E,UAAU,MAC5B1C,KAAK,SAAS0H,GAAK,MAAOA,GAAEC,SAC5B/E,QACAC,OAAO,MACPgD,QAAQ,YAAa,SAAS6B,GAAK,MAAOA,GAAEE,WAErDH,GAAU5E,OAAO,MACZgD,QAAQ,sBAAqB,GAC7BhD,OAAO,OACP+C,MAAM,mBAAoB,SAAS8B,GAAK,MAAOA,GAAEG,QAEtDJ,EAAU5E,OAAO,MACZgD,QAAQ,OAAM,GACdA,QAAQ,QAAQ,SAAS6B,GAAK,QAASA,EAAEI,QACzCR,KAAK,SAASI,EAAG9I,GAAK,MAAOsI,GAAaQ,EAAEK,IAAKnJ,KAEtD6I,EAAU5E,OAAO,MACZgD,QAAQ,SAAQ,GAChByB,KAAK,SAASI,EAAG9I,GAAK,MAAOoI,GAAeU,EAAEH,MAAO3I,KAE1D6I,EAAU/E,UAAU,MAAM3C,KAAK,SAAS2H,GACpC,GAAIA,EAAEE,UAAW,CACb,GAAII,GAAe1L,GAAGmH,MAAMC,SAASuE,QAAQ,EAAE,IAAIC,OAAO,OAAOR,EAAEG,QAC/DM,EAAU,EACd7L,IAAGgG,OAAO3F,MACLiJ,MAAM,sBAAuBoC,EAAaG,IAC1CvC,MAAM,mBAAoBoC,EAAaG,MAKpD,IAAIb,GAAOH,EAAMhB,OAAOiC,SAGxB,OAFiB3I,UAAb6D,EAAE+E,SACFf,GAAQ,uBAAyBhE,EAAE+E,OAAS,UACzCf,GAIPtB,EAAmB,SAAS1C,GAC5B,GAAIA,GAAKA,EAAEqE,OAAQ,CACf,GAAIrE,EAAEqE,iBAAkB7K,OACpB,QAASwG,EAAEqE,OAAO3J,MAGtB,IAAIsF,EAAEqE,iBAAkBW,QAEpB,MADAhF,GAAEqE,QAAUrE,EAAEqE,SACP,EAGf,OAAO,GAKPY,EAAoB,SAASC,GAC7B,GAIItH,GAAMC,EAAKsH,EAJXjG,EAASzG,EAAQoK,OAAOuC,aACxBnG,EAAQxG,EAAQoK,OAAOwC,YACvBC,EAAcpD,SAASqD,gBAAgBD,YACvCE,EAAetD,SAASqD,gBAAgBC,YAI5C,QAAQtC,GACJ,IAAK,IACDtF,GAASqB,EAAQkE,EACjBtF,IAASqB,EAAS,GACfgG,EAAItH,KAAOA,EAAO,IAAGA,EAAOuF,IAC3BgC,EAAMD,EAAIrH,IAAMA,GAAO,IAAGA,GAAOsH,IACjCA,EAAMD,EAAIrH,IAAMA,EAAMqB,GAAUsG,IAAc3H,GAAOsH,EAAMK,EAC/D,MACJ,KAAK,IACD5H,EAAOuF,EACPtF,IAASqB,EAAS,GACdgG,EAAItH,KAAOA,EAAOqB,EAAQqG,IAAa1H,GAASqB,EAAQkE,IACvDgC,EAAMD,EAAIrH,IAAMA,GAAO,IAAGA,GAAOsH,IACjCA,EAAMD,EAAIrH,IAAMA,EAAMqB,GAAUsG,IAAc3H,GAAOsH,EAAMK,EAChE,MACJ,KAAK,IACD5H,IAAUqB,EAAQ,GAAK,EACvBpB,EAAMsF,EACF+B,EAAIrH,IAAMA,EAAMqB,EAASsG,IAAc3H,GAAQqB,EAASiE,IACvDgC,EAAMD,EAAItH,KAAOA,GAAQ,IAAGA,GAAQuH,IACpCA,EAAMD,EAAItH,KAAOA,EAAOqB,GAASqG,IAAa1H,GAAQuH,EAAMG,EACjE,MACJ,KAAK,IACD1H,IAAUqB,EAAQ,GAClBpB,GAAQqB,EAASiE,EACb+B,EAAIrH,IAAMA,EAAM,IAAGA,EAAMsF,IACxBgC,EAAMD,EAAItH,KAAOA,GAAQ,IAAGA,GAAQuH,IACpCA,EAAMD,EAAItH,KAAOA,EAAOqB,GAASqG,IAAa1H,GAAQuH,EAAMG,EACjE,MACJ,KAAK,SACD1H,IAAUqB,EAAQ,GAClBpB,IAASqB,EAAS,EAClB,MACJ,SACItB,EAAO,EACPC,EAAM,EAId,OAASD,KAAQA,EAAMC,IAAOA,IAM9BkF,EAAkB,WAClBxK,EAAGO,IAAIuD,KAAK,WACR,GAAI6I,GAAM3B,IACNkC,EAAgBR,EAAkBC,GAClCtH,EAAOsH,EAAItH,KAAO6H,EAAc7H,KAChCC,EAAMqH,EAAIrH,IAAM4H,EAAc5H,GAGlC,IAAIQ,EACA5F,EACKiN,YACAC,aACAC,MAAMtF,GACND,SAAS,GACTiC,MAAM,UAAW,OACnB,CAEH,GAAIuD,GAAgB,aAAexC,EAAazF,KAAO,OAASyF,EAAaxF,IAAM,MAC/EiI,EAAgB,aAAelI,EAAO,OAASC,EAAM,MACrDkI,EAAwB/M,GAAGgN,kBAAkBH,EAAeC,GAC5DG,EAAYxN,EAAQ6J,MAAM,WAAa,EAE3C7J,GACKiN,YACAC,aACAtF,SAAS4F,EAAY,EAAI5F,GAEzB6F,WAAW,YAAa,SAAUlG,GAC/B,MAAO+F,IACR,aAEFG,WAAW,oBAAqB,SAAUlG,GACvC,MAAO+F,KAEVzD,MAAM,gBAAiBwD,GACvBxD,MAAM,UAAW,GAG1Be,EAAazF,KAAOA,EACpByF,EAAaxF,IAAMA,IAsF3B,OA5CA2E,GAAUtE,qBAAuBA,EACjCsE,EAAU2D,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKqJ,GAE9CA,EAAU6D,SAAWrB,OAAOsB,WAExBjG,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GAAGF,EAASE,IACxE2C,SAAUqD,IAAK,WAAW,MAAOrD,IAAWsD,IAAK,SAASjG,GAAG2C,EAAQ3C,IACrE4C,UAAWoD,IAAK,WAAW,MAAOpD,IAAYqD,IAAK,SAASjG,GAAG4C,EAAS5C,IACxE6C,cAAemD,IAAK,WAAW,MAAOnD,IAAgBoD,IAAK,SAASjG,GAAG6C,EAAa7C,IACpF6B,SAAUmE,IAAK,WAAW,MAAOnE,IAAWoE,IAAK,SAASjG,GAAG6B,EAAQ7B,IACrE0B,gBAAiBsE,IAAK,WAAW,MAAOtE,IAAkBuE,IAAK,SAASjG,GAAG0B,EAAe1B,IAC1FkC,SAAU8D,IAAK,WAAW,MAAO9D,IAAW+D,IAAK,SAASjG,GAAGkC,EAAQlC,IACrED,WAAYiG,IAAK,WAAW,MAAOjG,IAAakG,IAAK,SAASjG,GAAGD,EAAUC,IAC3EqC,kBAAmB2D,IAAK,WAAW,MAAO3D,IAAoB4D,IAAK,SAASjG,GAAGqC,EAAiBrC,IAChGmD,gBAAiB6C,IAAK,WAAW,MAAO7C,IAAkB8C,IAAK,SAASjG,GAAGmD,EAAenD,IAC1FoD,iBAAkB4C,IAAK,WAAW,MAAO5C,IAAmB6C,IAAK,SAASjG,GAAGoD,EAAgBpD,IAC7FqD,cAAe2C,IAAK,WAAW,MAAO3C,IAAgB4C,IAAK,SAASjG,GAAGqD,EAAarD,IACpF+C,eAAgBiD,IAAK,WAAW,MAAOjD,IAAiBkD,IAAK,SAASjG,GAAG+C,EAAc/C,IACvFgD,UAAWgD,IAAK,WAAW,MAAOhD,IAAYiD,IAAK,SAASjG,GAAGgD,EAAShD,IAGxElC,QAASkI,IAAK,WAAW,MAAOlI,IAAUmI,IAAK,SAASjG,GAChDlC,GAAUkC,IACVlC,IAAWkC,EACXiC,OAGR9F,MAAO6J,IAAK,WAAW,MAAO7J,IAAQ8J,IAAK,SAASjG,GAE5CA,EAAEkG,QACFlG,EAAE0D,MAAQ1D,EAAEkG,MAAM9G,EAClBY,EAAE8D,OAAS9D,EAAE8D,WACb9D,EAAE8D,OAAOJ,MAAQ1D,EAAEkG,MAAMC,EACzBnG,EAAE8D,OAAOE,MAAQhE,EAAEkG,MAAMlC,OAAShE,EAAE8D,OAAOE,OAE/C7H,EAAO6D,IAIXsC,MAAO0D,IAAK,WAAW,MAAO9N,GAAQoK,QAAU2D,IAAK,SAASjG,MAC9D8B,IAAKkE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,QAGpDhI,EAAGG,MAAMiO,YAAYnE,GACdA,GASXjK,EAAGG,MAAMkO,WAAa,WAElB,GAAIC,IAAQ5H,MAAO,IAAKC,OAAQ,IAGhC,OAAI1E,QAAOsM,YAActM,OAAOuM,aAC5BF,EAAK5H,MAAQzE,OAAOsM,WACpBD,EAAK3H,OAAS1E,OAAOuM,YACd,GAIc,cAArB7E,SAAS8E,YACT9E,SAASqD,iBACTrD,SAASqD,gBAAgBF,aAEzBwB,EAAK5H,MAAQiD,SAASqD,gBAAgBF,YACtCwB,EAAK3H,OAASgD,SAASqD,gBAAgBH,aAChC,GAIPlD,SAASC,MAAQD,SAASC,KAAKkD,aAC/BwB,EAAK5H,MAAQiD,SAASC,KAAKkD,YAC3BwB,EAAK3H,OAASgD,SAASC,KAAKiD,aACrB,GAGJ,GAMX7M,EAAGG,MAAMuO,aAAe,SAASC,GAO7B,MANI1M,QAAO2M,iBACP3M,OAAO2M,iBAAiB,SAAUD,GAElC3O,EAAGgC,IAAI,gDAAiD2M,IAIxDzL,SAAUyL,EACVE,MAAO,WACH5M,OAAO6M,oBAAoB,SAAUH,MAYjD3O,EAAGG,MAAM4O,SAAW,SAAS/C,GAEzB,GAAcpI,SAAVoI,EACA,MAAOhM,GAAGG,MAAM6O,cAIb,IAAG/N,MAAMgO,QAAQjD,GAAQ,CAC5B,GAAIkD,GAAczO,GAAGmH,MAAMuH,UAAU9C,MAAML,EAC3C,OAAO,UAASvE,EAAG1E,GACf,GAAImJ,GAAYtI,SAANb,EAAkB0E,EAAI1E,CAChC,OAAO0E,GAAEuE,OAASkD,EAAYhD,IAOlC,MAAOF,IASfhM,EAAGG,MAAM6O,aAAe,WAEpB,MAAOhP,GAAGG,MAAM4O,SAAStO,GAAGmH,MAAMwH,aAAa/C,UAQnDrM,EAAGG,MAAMkP,YAAc,SAASC,EAAYC,EAAQC,GAEhDD,EAASA,GAAU,SAASzD,GAAU,MAAOA,GAAOI,KACpDsD,EAAgBA,GAAiB/O,GAAGmH,MAAMwH,aAAa/C,OAGvD,IAAIoD,GAAWD,EAAcrN,MAE7B,OAAO,UAAS2J,EAAQpD,GACpB,GAAIwD,GAAMqD,EAAOzD,EACjB,OAA+B,kBAApBwD,GAAWpD,GACXoD,EAAWpD,KACStI,SAApB0L,EAAWpD,GACXoD,EAAWpD,IAGbuD,IAEDA,EAAWD,EAAcrN,QAE7BsN,GAAsB,EACfD,EAAcC,MAWjCzP,EAAGG,MAAMuP,KAAO,SAASC,EAAOC,GAE5B,GAAIC,GAAO,SAASC,GAChBrP,GAAGgL,KAAKqE,EAAM,SAASC,GACnB,GAAIhL,GAAStE,GAAGgG,OAAOmJ,GAAStF,MAChCvF,GAAOiL,WAAWC,aACdxP,GAAGgG,OAAOsJ,GAAUtJ,OAAOmJ,GAAStF,OACpCvF,GACJ/E,EAAGG,MAAMuP,KAAKC,EAAOC,KAI7BnP,IAAGoG,UAAU8I,GAAOjO,GAAG,QAAS,WAC5BwO,QAAQC,UAAUrP,KAAKgP,KAAMhP,KAAKsP,YAAatP,KAAKgP,MACpDD,EAAK/O,KAAKgP,MACVrP,GAAGmE,MAAMyL,mBAGb5P,GAAGgG,OAAOxE,QAAQP,GAAG,WAAY,WACzBjB,GAAGmE,MAAM0L,OACTT,EAAKpP,GAAGmE,MAAM0L,UAW1BtQ,EAAGG,MAAMoQ,oBAAsB,SAAUC,GACrC,GAAiC,kBAAtBA,GAAYzG,OACY,kBAArByG,GAAYC,KAAqB,CAE3C,GAAIC,GAAWC,SAASH,EAAYzG,MAAM,aAAa6G,QAAQ,KAAK,IAAK,IACrEC,EAAaL,EAAYC,OAAOtO,MACpC,OAAO0O,GAAaH,EAAW,GAEnC,MAAO,IAOX1Q,EAAGG,MAAMoH,UAAY,SAASuJ,GAC1B,MAAiB,gBAANA,IACJC,MAAMD,IACA,OAANA,GACAA,IAAMzH,EAAAA,GACNyH,MAAOzH,EAAAA,GAEH,EAEJyH,GAMXrQ,GAAGwD,UAAUtD,UAAUqQ,gBAAkB,SAASC,GAC9C,GAAIC,IAAQpQ,MAAMW,UAAUP,MAAMC,KAAKC,UAAW,GAClD,OAAO6P,GAAY7D,WAAW5L,MAAMyP,EAAaC,IAOrDlR,EAAGG,MAAM8Q,YAAc,SAASzQ,EAAUsH,GACtC,KAAMhH,eAAgBd,GAAGG,MAAM8Q,aAC3B,MAAO,IAAIjR,GAAGG,MAAM8Q,YAAYzQ,EAAUsH,EAG9C,IAAIqJ,GAAyBvN,SAAbkE,EAAyBA,EAAW,IAChDsJ,KACAC,EAAOvQ,IAEXA,MAAKV,OAAS,SAASA,GAevB,MAdIA,MAAYc,MAAMC,KAAKC,UAAW,GAClChB,EAAOmJ,QAAQ,SAAS+H,GACpBA,EAAMC,YAAa,EACnB,SAAUC,GACNA,EAAEhR,SAASkB,GAAG,YAAa,SAAS+P,GAChCD,EAAED,YAAa,EACfF,EAAKK,UAAU,YAEpBJ,GAECF,EAAYO,QAAQL,GAAS,GAC7BF,EAAY5N,KAAK8N,KAGtBxQ,MAGPA,KAAK8Q,MAAQ,SAAS9J,GACDlE,SAAbkE,IACAqJ,EAAYrJ,GAEhBsJ,MAGJtQ,KAAKsM,WAAa,SAASnJ,EAAWiN,EAAMpJ,GAcxC,GAbAoJ,EAAO9P,UAAUe,OAAS,KAAOjB,MAAMC,KAAKC,UAAW,MAGnD0G,EADAoJ,EAAK/O,OAAS,EACH+O,EAAKW,MAESjO,SAAduN,EAA0BA,EAAY,IAErDlN,EAAUsN,YAAa,EAEnBH,EAAYO,QAAQ1N,GAAa,GACjCmN,EAAY5N,KAAKS,GAGJ,IAAb6D,EAIA,MAHA7D,GAAUsN,YAAa,EACvBtN,EAAUoJ,MAAQ,WAAa,MAAOvM,OACtCmD,EAAU6D,SAAW,WAAa,MAAOhH,OAClCmD,CAEkB,KAArBA,EAAU9B,OACV8B,EAAUsN,YAAa,EAChBtN,EAAU6N,MAAO,SAASrK,GAAI,OAAQA,EAAEtF,SAC/C8B,EAAUsN,YAAa,EAEvBtN,EAAUsN,YAAa,CAG3B,IAAIT,GAAI,CACR,OAAO7M,GACFmJ,aACAtF,SAASA,GACT5D,KAAK,aAAc4M,IACnB5M,KAAK,MAAO,SAASuD,EAAG1E,GACT,MAAN+N,IACF7M,EAAUsN,YAAa,EACvBF,EAAKK,UAAUlQ,MAAMV,KAAMoQ,OAM/CpQ,KAAK4Q,UAAY,WACTN,EAAYU,MAAO,SAASrK,GAAI,MAAOA,GAAE8J,eACzCH,EAAY7H,QAAS,SAAS9B,GAAIA,EAAE8J,YAAa,IACjD/Q,EAASkR,UAAUlQ,MAAMV,KAAMM,cAY3CpB,EAAGG,MAAM4R,WAAa,SAASC,GAC3B,GAAIC,GAAU7Q,UAAUe,OAAS,KAAOjB,MAAMC,KAAKC,UAAW,KAC9D6Q,GAAQ1I,QAAQ,SAAS2I,GACrB,IAAK,GAAIhG,KAAOgG,GAAQ,CACpB,GAAIjD,GAAU+C,EAAI9F,YAAgBjL,OAC9BkR,EAA+B,gBAAbH,GAAI9F,GACtBkG,EAAgC,gBAAhBF,GAAOhG,EAEvBiG,KAAalD,GAAWmD,EACxBpS,EAAGG,MAAM4R,WAAWC,EAAI9F,GAAMgG,EAAOhG,IAErC8F,EAAI9F,GAAOgG,EAAOhG,OAUlClM,EAAGG,MAAMmQ,MAAQ,WACb,KAAMxP,eAAgBd,GAAGG,MAAMmQ,OAC3B,MAAO,IAAItQ,GAAGG,MAAMmQ,KAExB,IAAIA,MAEA+B,EAAY,aACZC,EAAY,WAAY,UACxBC,EAAO,KACPC,EAAU,IAEd1R,MAAKN,SAAWC,GAAGD,SAAS,SAAU,OAEtCM,KAAKN,SAASkB,GAAG,MAAO,SAAS4O,GAC7B+B,EAAU/B,GAAO,KAGrBxP,KAAK2R,OAAS,SAASC,GAEnB,MADAJ,GAAYI,EACL5R,MAGXA,KAAK6R,OAAS,SAASD,EAAIxP,GAUvB,MATKA,KACDA,EAAW,cAEfmP,EAAY,SAAS/B,EAAOsC,GACxBF,EAAGpC,GACCsC,GACA1P,KAGDpC,MAGXA,KAAKyR,KAAO,SAASjC,GACjBiC,EAAOA,MACPvS,EAAGG,MAAM4R,WAAWQ,EAAMjC,GAG9B,IAAIuC,GAAO,WACP,GAAIC,GAAWR,GAEf,IAAIS,KAAKC,UAAUF,KAAcC,KAAKC,UAAU1C,GAC5C,OAAO,CAGX,KAAK,GAAIpE,KAAO4G,GACOlP,SAAf0M,EAAMpE,KACNoE,EAAMpE,OAEVoE,EAAMpE,GAAO4G,EAAS5G,GACtBsG,GAAU,CAEd,QAAO,EAGX1R,MAAK8R,OAAS,WACNL,IACAF,EAAUE,GAAM,GAChBA,EAAO,MAEPM,EAAK1R,KAAKL,OACVA,KAAKN,SAASyS,OAAO3C,KAkBjCtQ,EAAGG,MAAM0N,YAAc,SAASqD,GAQ5B,MAPIA,IACAzQ,GAAGyS,IAAIhC,GAAM3H,QAAQ,SAAU2C,EAAIR,GACN,kBAAd5K,MAAKoL,IACZpL,KAAKoL,GAAKR,IAEf9K,KAAKE,OAELA,MAWXd,EAAGG,MAAMgT,WAAa,SAASC,EAAUjP,GAErC,GAAIkP,GAAY,EACZtQ,EAAI,CACR,KAAKA,EAAGA,EAAIoB,EAAKhC,OAAQY,GAAK,EAAG,CAC7B,GAAIuQ,GAAanP,EAAKpB,IAAMoB,EAAKpB,GAAGmF,OAAS/D,EAAKpB,GAAGmF,OAAO/F,OAAS,CACrEkR,GAAYC,EAAaD,EAAYC,EAAaD,EAWtD,MATArT,GAAGgC,IAAI,8BAA+BoR,GACtCpT,EAAGgC,IAAI,gCAAiCqR,GAExCD,EAAWA,EAAWC,EAAYD,EAAWC,EAAY,EAAID,EAE7DA,EAAsB,EAAXA,EAAe,EAAIA,EAE9BA,EAAWpK,KAAKyB,MAAM2I,GACtBpT,EAAGgC,IAAI,8BAA+BoR,GAC/BA,GAOXpT,EAAGG,MAAMoT,WAAa,SAASH,EAAUjP,GAErC,MAAOnE,GAAGG,MAAMgT,WAAWC,EAAUjP,IAYzCnE,EAAGG,MAAMqT,WAAa,SAAS3Q,EAAOR,GAE9BQ,EAAM4Q,QAAU5Q,EAAM4Q,OAAOpR,GAC7BQ,EAAMR,GAAQQ,EAAM4Q,OAAOpR,IAE3BQ,EAAMR,GAAQ,SAAU2F,GACpB,MAAK5G,WAAUe,QACfU,EAAM6Q,WAAWrR,IAAQ,EACzBQ,EAAMiL,SAASzL,GAAQ2F,EAChBnF,GAHuBA,EAAMiL,SAASzL,IAOjDQ,EAAM,IAAMR,GAAQ,SAAS2F,GACzB,MAAK5G,WAAUe,QACVU,EAAM6Q,WAAWrR,KAClBQ,EAAMiL,SAASzL,GAAQ2F,GAEpBnF,GAJuBA,EAAMiL,SAASzL,MAazDrC,EAAGG,MAAMiO,YAAc,SAASvL,GAC5BA,EAAM6Q,WAAa7Q,EAAM6Q,cACzB,IAAIC,GAAMlH,OAAOmH,oBAAoB/Q,EAAMiL,cACvC+F,EAAQpH,OAAOmH,oBAAoB/Q,EAAM4Q,WAC7CE,GAAMA,EAAIlS,OAAOoS,EACjB,KAAK,GAAI9Q,KAAK4Q,GACV3T,EAAGG,MAAMqT,WAAW3Q,EAAO8Q,EAAI5Q,KAUvC/C,EAAGG,MAAM2T,iBAAmB,SAAS/O,EAAQgP,EAAWC,GACpDjP,EAAOkP,WAAaD,EAAOvS,OAAOsD,EAAOkP,gBACzCD,EAAOE,QAAQH,GACfC,EAAOE,QAAQnP,GACftE,GAAG0T,OAAO3S,MAAMV,KAAMkT,IAO1BhU,EAAGG,MAAMiU,YAAc,SAASC,GAC5B,MAAOA,GAAEC,OAAOC,OAAO,SAASC,EAAM7H,GAClC,OAAQA,GAAO6H,GAAQH,EAAE1H,EAAM,MAUvC3M,EAAGG,MAAMsU,UAAYhU,GAAGyS,MAMxBlT,EAAGG,MAAMuU,OAAS,WAGd,QAASA,GAAOjN,EAAE1E,GACd,GAAI4R,GAAIxO,EAAKhF,KAAKL,KAAK2G,EAAE1E,GACrB6R,EAAItG,EAAKnN,KAAKL,KAAK2G,EAAE1E,EACzB,OAAsC,KAAlCtC,GAAGoU,IAAIC,YAAYnD,QAAQgD,GACpBlU,GAAGoU,IAAIH,SAASvO,KAAKwO,GAAGrG,KAAKsG,KAE7B5U,EAAGG,MAAMsU,UAAUzG,IAAI2G,GAAGC,GARzC,GAAIzO,GACAmI,EAAO,EAoBX,OAVAoG,GAAOvO,KAAO,SAAS6B,GACnB,MAAK5G,WAAUe,QACfgE,EAAO1F,GAAGsU,QAAQ/M,GACX0M,GAFuBvO,GAIlCuO,EAAOpG,KAAO,SAAStG,GACnB,MAAK5G,WAAUe,QACfmM,EAAO7N,GAAGsU,QAAQ/M,GACX0M,GAFuBpG,GAI3BoG,GAUX1U,EAAGG,MAAM6U,eAAiB,SAASjQ,EAAQmN,GAEvC,GAAIyB,GAAMlH,OAAOmH,oBAAoB1B,EAAOpE,cACxC+F,EAAQpH,OAAOmH,oBAAoB1B,EAAOuB,YAC1CwB,EAAY/C,EAAOgD,eACnBC,EAAQjD,EAAO+B,eACf/C,EAAOyC,EAAIlS,OAAOoS,GAAOpS,OAAOwT,GAAWxT,OAAO0T,EACtDjE,GAAKgD,QAAQhC,GACbhB,EAAKgD,QAAQnP,GACbtE,GAAG0T,OAAO3S,MAAMV,KAAMoQ,GAEtBnM,EAAOmQ,WAAalV,EAAGG,MAAMiU,YAAYT,EAAIlS,OAAOoS,GAAOpS,OAAOwT,GAAWxT,OAAOkS,GAAKlS,OAAOsD,EAAOmQ,iBACvGnQ,EAAOkP,WAAajU,EAAGG,MAAMiU,YAAYe,EAAM1T,OAAOsD,EAAOkP,kBAOjEjU,EAAGG,MAAMiV,QAAU,SAASP,GACxBA,EAAI7K,SAASqL,YAAW,KAO5BrV,EAAGG,MAAMmV,eAAiB,SAAS3O,EAAQH,GACvC,MAAQG,IAAUgK,SAASnK,EAAUuD,MAAM,UAAW,KAAO,KAOjE/J,EAAGG,MAAMoV,cAAgB,SAAS7O,EAAOF,GACrC,MAAQE,IAASiK,SAASnK,EAAUuD,MAAM,SAAU,KAAO,KAO/D/J,EAAGG,MAAMqF,gBAAkB,SAASmB,EAAQH,EAAWpB,GACnD,MAAOpF,GAAGG,MAAMmV,eAAe3O,EAAQH,GAAapB,EAAOE,IAAMF,EAAOoQ,QAM5ExV,EAAGG,MAAMoF,eAAiB,SAASmB,EAAOF,EAAWpB,GACjD,MAAOpF,GAAGG,MAAMoV,cAAc7O,EAAOF,GAAapB,EAAOC,KAAOD,EAAOqQ,OAM3EzV,EAAGG,MAAMuV,OAAS,SAAS7S,EAAO2D,GAC9B,GAAImP,GAAM9S,EAAM+K,UACZxI,EAASuQ,EAAIvQ,SACbsQ,EAASC,EAAID,SACbvR,EAAkB,MAAVuR,GAAmB,uBAAyBA,GACpD/O,EAAS3G,EAAGG,MAAMqF,gBAAgB,KAAMgB,EAAWpB,GACnDsB,EAAQ1G,EAAGG,MAAMoF,eAAe,KAAMiB,EAAWpB,GACjDgC,EAAIhC,EAAOC,KAAOqB,EAAM,EACxByH,EAAI/I,EAAOE,IAAMqB,EAAO,CAG5BH,GAAUK,UAAU,KAAKc,QAEzB,IAAIiO,GAAapP,EAAUK,UAAU,cAAc1C,KAAKA,EAExDyR,GAAW7O,QAAQC,OAAO,QACrBC,KAAK,QAAS,kBACdA,KAAK,KAAM,SACX8C,MAAM,cAAe,UAE1B6L,EACK3O,KAAK,IAAKG,GACVH,KAAK,IAAKkH,GACVsC,KAAK,SAASkE,GAAI,MAAOA,MAMlC3U,EAAGG,MAAM0V,UAAY,SAAUpF,EAAM/J,GACjC+J,EAAKvM,KAAK,WAUN,IATA,GAEI4R,GAFArF,EAAOhQ,GAAGgG,OAAO3F,MACjBiV,EAAQtF,EAAKA,OAAOuF,MAAM,OAAOC,UAEjC3O,KACA4O,EAAa,EACbC,EAAa,IACbhI,EAAIsC,EAAKxJ,KAAK,KACdmP,EAAKC,WAAW5F,EAAKxJ,KAAK,OAC1BqP,EAAQ7F,EAAKA,KAAK,MAAMzJ,OAAO,SAASC,KAAK,IAAK,GAAGA,KAAK,IAAKkH,GAAGlH,KAAK,KAAMmP,EAAK,MAC/EN,EAAOC,EAAMlE,OAChBvK,EAAK9D,KAAKsS,GACVQ,EAAM7F,KAAKnJ,EAAKiP,KAAK,MACjBD,EAAMhM,OAAOkM,wBAA0B9P,IACvCY,EAAKuK,MACLyE,EAAM7F,KAAKnJ,EAAKiP,KAAK,MACrBjP,GAAQwO,GACRQ,EAAQ7F,EAAKzJ,OAAO,SAASC,KAAK,IAAK,GAAGA,KAAK,IAAKkH,GAAGlH,KAAK,OAAQiP,EAAaC,EAAaC,EAAK,MAAM3F,KAAKqF,OAI5H9V,EAAGI,OAAOqW,KAAO,WACf,YAoCA,SAAS5T,GAAMoB,GAqSX,MApSAgN,GAAYW,QACZ3N,EAAUC,KAAK,SAASC,GACpB,GAAIqC,GAAY/F,GAAGgG,OAAO3F,KAC1Bd,GAAGG,MAAMiV,QAAQ5O,EAGjB,IAAII,GAAOJ,EAAUK,UAAU,qBAAqB1C,MAAMA,IACtD2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,wBAEnDyP,GADS5P,EAAUE,OAAO,KACtBJ,EAAKH,OAAO,KAEN,QAAVkQ,EACAF,EAAKE,MAAMA,IACW,OAAjBF,EAAKG,UAAsC,UAAjBH,EAAKG,WACpCH,EAAKE,MAAM3N,KAAKC,IAAIrB,EAAMyE,QAAQ,GAAKzE,EAAMyE,QAAQ,IAAM,KAG/DqK,EAAE1F,gBAAgBC,EAAa,QAAQ9P,KAAKsV,GAE5CI,EAASA,GAAUJ,EAAK7O,OAExB,IAAIkP,GAAML,EAAKM,YACJ,OAAPD,IACAA,EAAMD,EAAOE,aAGjB,IAAIC,GAAYN,EAAE7P,UAAU,qBACvB1C,MAAM8S,GAAiB,MAC5BD,GAAUtP,OAAOC,QAEjB,IAAIuP,GACAC,EACAC,CACJ,QAAQX,EAAKG,UACT,IAAK,MACDI,EAAUjQ,QAAQC,OAAO,QAAQC,KAAK,QAAS,gBACjDmQ,EAAI,EACyB,IAAzBxP,EAAMyE,QAAQlK,OAChBiV,EAAIC,EAA+B,EAAnBzP,EAAMyE,QAAQ,GAASzE,EAAM0P,YAAc,EACzB,IAAzB1P,EAAMyE,QAAQlK,OACvBiV,EAAIC,EAAYzP,EAAMyE,QAAQ,GAAKzE,EAAMyE,QAAQ,GAAKzE,EAAM0P,YAAc1P,EAAMyE,QAAQ,GAC9EzE,EAAMyE,QAAQlK,OAAS,IACjCiV,EAAIxP,EAAMyE,QAAQzE,EAAMyE,QAAQlK,OAAO,IAAIyF,EAAMyE,QAAQ,GAAGzE,EAAMyE,QAAQ,KAE1E2K,EACK/P,KAAK,cAAe,UACpBA,KAAK,IAAK,GACVA,KAAK,IAAKmQ,EAAE,GACbG,IACAJ,EAAavQ,EAAKC,UAAU,mBACvB1C,KAAKyD,EAAMwE,UAChB+K,EAAWpQ,QAAQC,OAAO,KAAKC,KAAK,QAAQ,SAASQ,EAAE1E,GAC/C,OAAQ,gBAAgB,kBAAwB,GAALA,EAAS,eAAe,gBAAiBwT,KAAK,OAC9FvP,OAAO,QACVmQ,EAAWzP,OAAOC,SAClBwP,EACKlQ,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,aAAe/C,EAAGG,MAAMoH,UAAUK,EAAMH,IAAM,QAExDhB,OAAO,QACPQ,KAAK,KAAM,UACXA,KAAK,KAAMwP,EAAKe,eAChBvQ,KAAK,cAAe,UACpBwJ,KAAK,SAAShJ,EAAE1E,GACb,GAAIwF,GAAIuO,EAAIrP,EACZ,QAAQ,GAAKc,GAAGpD,MAAM,OAAS,GAAKoD,IAE5C4O,EAAWnG,gBAAgBC,EAAa,eACnChK,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,aAAe/C,EAAGG,MAAMoH,UAAUK,EAAMyE,QAAQtJ,IAAM,QAGzE,MACJ,KAAK,SACDmU,EAAeO,EAAoB,EACnC,IAAIC,GAAe,GACfC,EAAa,EACbC,EAASlB,EAAE7P,UAAU,KAAKJ,OAAO,QACjCoR,EAAmB,EACvB,IAAIC,EAAa,IAAK,CAElBF,EAAO1T,KAAK,SAASuD,EAAE1E,GACnB,GAAIgV,GAAMjX,KAAKkX,wBACXtR,EAAQqR,EAAIrR,KAChBiR,GAAaI,EAAIpR,OACdD,EAAQgR,IAAcA,EAAehR,KAE5CmR,EAAmB,UAAYC,EAAe,OAASH,EAAW,EAAIlB,EAAKe,eAAiB,GAE5F,IAAIS,GAAMjP,KAAKC,IAAID,KAAKiP,IAAIH,EAAa9O,KAAKkP,GAAG,KACjDhB,IAAgBe,EAAMA,EAAIP,EAAeA,GAAc,GAEvDE,EACK3Q,KAAK,YAAa4Q,GAClB9N,MAAM,cAAe+N,EAAa,IAAM,EAAI,QAAU,OAE/Dd,EAAUjQ,QAAQC,OAAO,QAAQC,KAAK,QAAS,gBAC/CmQ,EAAI,EACyB,IAAzBxP,EAAMyE,QAAQlK,OACdiV,EAAIC,EAA+B,EAAnBzP,EAAMyE,QAAQ,GAASzE,EAAM0P,YAAc,EAC3B,IAAzB1P,EAAMyE,QAAQlK,OACrBiV,EAAIC,EAAYzP,EAAMyE,QAAQ,GAAKzE,EAAMyE,QAAQ,GAAKzE,EAAM0P,YAAc1P,EAAMyE,QAAQ,GAChFzE,EAAMyE,QAAQlK,OAAS,IAC/BiV,EAAIxP,EAAMyE,QAAQzE,EAAMyE,QAAQlK,OAAO,IAAIyF,EAAMyE,QAAQ,GAAGzE,EAAMyE,QAAQ,KAE9E2K,EACK/P,KAAK,cAAe,UACpBA,KAAK,IAAKiQ,GACVjQ,KAAK,IAAKmQ,EAAE,GACbG,IAEAJ,EAAavQ,EAAKC,UAAU,mBAEvB1C,MAAMyD,EAAMwE,SAAS,GAAIxE,EAAMwE,SAASxE,EAAMwE,SAASjK,OAAS,KACrEgV,EAAWpQ,QAAQC,OAAO,KAAKC,KAAK,QAAQ,SAASQ,EAAE1E,GAC/C,OAAQ,gBAAgB,kBAAwB,GAALA,EAAS,eAAe,gBAAiBwT,KAAK,OAC9FvP,OAAO,QACVmQ,EAAWzP,OAAOC,SAClBwP,EACKlQ,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,aAAe/C,EAAGG,MAAMoH,UAAWK,EAAMH,IAAM4P,EAAYzP,EAAM0P,YAAc,EAAI,IAAO,QAEpG7Q,OAAO,QACPQ,KAAK,KAAM,SACXA,KAAK,IAAKwP,EAAKe,eACfvQ,KAAK,YAAa4Q,GAClB9N,MAAM,cAAe+N,EAAgBA,EAAa,IAAM,EAAI,QAAU,MAAS,UAC/ErH,KAAK,SAAShJ,EAAE1E,GACb,GAAIwF,GAAIuO,EAAIrP,EACZ,QAAQ,GAAKc,GAAGpD,MAAM,OAAS,GAAKoD,IAE5C4O,EAAWnG,gBAAgBC,EAAa,kBACnChK,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,aAAe/C,EAAGG,MAAMoH,UAAWK,EAAMH,IAAM4P,EAAYzP,EAAM0P,YAAc,EAAI,IAAO,SAGzGa,GACAP,EACK3Q,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,gBAAkBA,EAAI,GAAK,EAAI,IAAM,MAAQ,KAGhE,MACJ,KAAK,QACDiU,EAAUjQ,QAAQC,OAAO,QAAQC,KAAK,QAAS,gBAC/C+P,EACKjN,MAAM,cAAeqO,EAAe,SAAW,SAC/CnR,KAAK,YAAamR,EAAe,aAAe,IAChDnR,KAAK,IAAKmR,GAAiBpP,KAAKL,IAAIvD,EAAOqQ,MAAO/O,GAAS,GAAM,KACjEO,KAAK,IAAKmR,EAAgB3X,GAAGkI,IAAIf,EAAMyE,SAAW,EAAKoK,EAAKe,eAC7DD,IACAJ,EAAavQ,EAAKC,UAAU,mBACvB1C,KAAKyD,EAAMwE,UAChB+K,EAAWpQ,QAAQC,OAAO,KAAKC,KAAK,QAAQ,SAASQ,EAAE1E,GAC/C,OAAQ,gBAAgB,kBAAwB,GAALA,EAAS,eAAe,gBAAiBwT,KAAK,OAC9FvP,OAAO,QACL+C,MAAM,UAAW,GACtBoN,EAAWzP,OAAOC,SAClBwP,EACKlQ,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,eAAiB/C,EAAGG,MAAMoH,UAAUK,EAAMH,IAAM,MAE1DhB,OAAO,QACPQ,KAAK,KAAM,SACXA,KAAK,IAAK,GACVA,KAAK,IAAKwP,EAAKe,eACfzN,MAAM,cAAe,SACrB0G,KAAK,SAAShJ,EAAG1E,GACd,GAAIwF,GAAIuO,EAAIrP,EACZ,QAAQ,GAAKc,GAAGpD,MAAM,OAAS,GAAKoD,IAE5C4O,EAAWnG,gBAAgBC,EAAa,iBACnChK,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,eAAiB/C,EAAGG,MAAMoH,UAAUK,EAAMyE,QAAQtJ,IAAM,MAElE0D,OAAO,QACPsD,MAAM,UAAW,GAE1B,MACJ,KAAK,OASDiN,EAAUjQ,QAAQC,OAAO,QAAQC,KAAK,QAAS,gBAC/C+P,EACKjN,MAAM,cAAeqO,EAAe,SAAW,OAC/CnR,KAAK,YAAamR,EAAe,cAAgB,IACjDnR,KAAK,IAAKmR,GAAiBpP,KAAKL,IAAIvD,EAAOC,KAAMqB,GAAS,IAAM+Q,GAAqB,GAAM,KAC3FxQ,KAAK,IAAKmR,GAAiB3X,GAAGkI,IAAIf,EAAMyE,SAAW,GAAMoK,EAAKe,eAC/DD,IACAJ,EAAavQ,EAAKC,UAAU,mBACvB1C,KAAKyD,EAAMwE,UAChB+K,EAAWpQ,QAAQC,OAAO,KAAKC,KAAK,QAAQ,SAASQ,EAAE1E,GAC/C,OAAQ,gBAAgB,kBAAwB,GAALA,EAAS,eAAe,gBAAiBwT,KAAK,OAC9FvP,OAAO,QACL+C,MAAM,UAAW,GACtBoN,EAAWzP,OAAOC,SAClBwP,EACKlQ,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,eAAiB/C,EAAGG,MAAMoH,UAAUsP,EAAOpP,IAAM,MAE3DhB,OAAO,QACPQ,KAAK,KAAM,SACXA,KAAK,IAAK,GACVA,KAAK,KAAMwP,EAAKe,eAChBvQ,KAAK,cAAe,OACpBwJ,KAAK,SAAShJ,EAAE1E,GACb,GAAIwF,GAAIuO,EAAIrP,EACZ,QAAQ,GAAKc,GAAGpD,MAAM,OAAS,GAAKoD,IAE5C4O,EAAWnG,gBAAgBC,EAAa,iBACnChK,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,eAAiB/C,EAAGG,MAAMoH,UAAUK,EAAMyE,QAAQtJ,IAAM,MAElE0D,OAAO,QACPsD,MAAM,UAAW,IA2BlC,GAvBAiN,EAAUvG,KAAK,SAAShJ,GAAK,MAAOA,MAEhC8P,GAAiC,SAAlBd,EAAKG,UAAyC,UAAlBH,EAAKG,WAEhDF,EAAE7P,UAAU,KACP3C,KAAK,SAASuD,EAAE1E,GACbtC,GAAGgG,OAAO3F,MAAM2F,OAAO,QAAQQ,KAAK,UAAW,IAC3CW,EAAMH,GAAKG,EAAMyE,QAAQ,GAAK,IAAMzE,EAAMH,GAAKG,EAAMyE,QAAQ,GAAK,OAC9D5E,EAAI,OAAa,OAAJA,IACbhH,GAAGgG,OAAO3F,MAAMmG,KAAK,UAAW,GAEpCxG,GAAGgG,OAAO3F,MAAM2F,OAAO,QAAQQ,KAAK,UAAW,MAKvDW,EAAMwE,SAAS,IAAMxE,EAAMwE,SAAS,IAA2B,GAArBxE,EAAMwE,SAAS,IACzDxF,EAAKC,UAAU,mBAAmBkD,MAAM,UAAW,SAAUtC,EAAG1E,GAC5D,MAAQA,GAAQ,EAAJ,KAKpBwU,IAAiC,QAAlBd,EAAKG,UAAwC,WAAlBH,EAAKG,UAAwB,CACvE,GAAIyB,KACJzR,GAAKC,UAAU,mBACV3C,KAAK,SAASuD,EAAE1E,GACb,IACQA,EACAsV,EAAY7U,KAAKoE,EAAMH,GAAK3G,KAAKkX,wBAAwBtR,MAAQ,GAEjE2R,EAAY7U,KAAKoE,EAAMH,GAAK3G,KAAKkX,wBAAwBtR,MAAQ,GACxE,MAAO4R,GACAvV,EACAsV,EAAY7U,KAAKoE,EAAMH,GAAK,GAE5B4Q,EAAY7U,KAAKoE,EAAMH,GAAK,MAI5CiP,EAAE7P,UAAU,KAAK3C,KAAK,SAASuD,EAAG1E,IAC1B6E,EAAMH,GAAK4Q,EAAY,IAAMzQ,EAAMH,GAAK4Q,EAAY,MAChD5Q,EAAI,OAAa,OAAJA,EACbhH,GAAGgG,OAAO3F,MAAM6G,SAEhBlH,GAAGgG,OAAO3F,MAAM2F,OAAO,QAAQkB,YAM/C+O,EAAE7P,UAAU,SACP0N,OAAO,SAAU9M,GAMd,OAAQ4O,WAAWrN,KAAKuP,MAAU,IAAJ9Q,GAAc,MAAmB7D,SAAN6D,IAE5DuC,QAAQ,QAAQ,GAGrB6M,EAASjP,EAAM4Q,SAInBvH,EAAYS,UAAU,kBACf7O,EAnUX,GAAI4T,GAAOhW,GAAGoU,IAAI4B,OACd7O,EAAQnH,GAAGmH,MAAMC,SAEjBzC,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,GACRC,EAAS,GACTsQ,EAAgB,KAChBM,GAAa,EACbO,EAAe,EACfM,GAAe,EACfD,GAAgB,EAChBd,GAAY,EACZV,EAAQ,KACRc,EAAoB,EACpB3P,EAAW,IACXtH,EAAWC,GAAGD,SAAS,YAE7BiW,GACK7O,MAAMA,GACNgP,OAAO,UACPG,WAAW,SAAStP,GAAK,MAAOA,IAOrC,IAAIoP,GACA5F,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,EAsVjD,OAvCAjF,GAAM4T,KAAOA,EACb5T,EAAMrC,SAAWA,EAEjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAC1CA,EAAMiL,SAAWrB,OAAOsB,WAEpB0J,mBAAoBzJ,IAAK,WAAW,MAAOyJ,IAAqBxJ,IAAK,SAASjG,GAAGyP,EAAkBzP,IACnGmQ,eAAoBnK,IAAK,WAAW,MAAOmK,IAAiBlK,IAAK,SAASjG,GAAGmQ,EAAcnQ,IAC3F8P,cAAoB9J,IAAK,WAAW,MAAO8J,IAAgB7J,IAAK,SAASjG,GAAG8P,EAAa9P,IACzFoQ,cAAoBpK,IAAK,WAAW,MAAOoK,IAAgBnK,IAAK,SAASjG,GAAGoQ,EAAapQ,IACzFuP,YAAoBvJ,IAAK,WAAW,MAAOuJ,IAActJ,IAAK,SAASjG,GAAGuP,EAAWvP,IACrFgP,WAAoBhJ,IAAK,WAAW,MAAOiJ,IAAiBhJ,IAAK,SAASjG,GAAGiP,EAAcjP,IAC3FrB,QAAoBqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IAC7E2O,OAAoB3I,IAAK,WAAW,MAAO2I,IAAS1I,IAAK,SAASjG,GAAG2O,EAAM3O,IAC3EtB,OAAoBsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IAG3E5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAmB1B,SAAVoE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAqB7R,SAAZoE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAoBzB,SAAXoE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAASE,EACTiJ,EAAYW,MAAM9J,KAEtBF,OAAQoG,IAAK,WAAW,MAAOpG,IAASqG,IAAK,SAASjG,GAClDJ,EAAQI,EACRyO,EAAK7O,MAAMA,GACXyP,EAAwC,kBAArBzP,GAAM6Q,WACzBzY,EAAGG,MAAM2T,iBAAiBjR,EAAO+E,GAAQ,SAAU,QAAS,YAAa,mBAIjF5H,EAAGG,MAAMiO,YAAYvL,GACrB7C,EAAGG,MAAM2T,iBAAiBjR,EAAO4T,GAAO,SAAU,aAAc,gBAAiB,WAAY,cAAe,eAC5GzW,EAAGG,MAAM2T,iBAAiBjR,EAAO+E,GAAQ,SAAU,QAAS,YAAa,eAElE/E,GAEX7C,EAAGI,OAAOsY,QAAU,WAChB,YAgCA,SAAS7V,GAAMoB,GAyOX,MAxOAgN,GAAYW,QACZ3N,EAAUC,KAAK,SAASC,GACpB,GAAIoB,GAAiBmB,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAC9CjQ,EAAkBmB,EAASvB,EAAOE,IAAMF,EAAOoQ,MAEnDhP,GAAY/F,GAAGgG,OAAO3F,MACtBd,EAAGG,MAAMiV,QAAQ5O,GAGjBY,EAAKgF,OAAOuM,GAAWxU,EAAK+O,IAAI,SAASzL,EAAE1E,GAAK,MAAO6V,GAAKnR,EAAE1E,MACzD0V,WAAWI,IAAW,EAAGtT,GAAiB,GAG/C,IAAIuT,KACJ,KAAKC,EAAS,CAIV,GAAIC,GAAOvY,GAAGqI,IAAI3E,EAAK+O,IAAI,SAASzL,GAChC,GAAIwR,KAMJ,OAJAA,GAAQzV,KAAKiE,EAAES,OAAOgR,IAClBzR,EAAES,OAAOiR,eAAe,gBAA2C,OAAzB1R,EAAES,OAAOkR,aAAwBH,EAAQzV,KAAKiE,EAAES,OAAOkR,aACjG3R,EAAES,OAAOiR,eAAe,aAAqC,OAAtB1R,EAAES,OAAOmR,WAAqBJ,EAAUA,EAAQxX,OAAOgG,EAAES,OAAOmR,WAEpG5Y,GAAGqI,IAAImQ,MAIdK,EAAO7Y,GAAGkI,IAAIxE,EAAK+O,IAAI,SAASzL,GAChC,GAAI8R,KAMJ,OAJAA,GAAQ/V,KAAKiE,EAAES,OAAOsR,IAClB/R,EAAES,OAAOiR,eAAe,iBAA6C,OAA1B1R,EAAES,OAAOuR,cAAyBF,EAAQ/V,KAAKiE,EAAES,OAAOuR,cACnGhS,EAAES,OAAOiR,eAAe,aAAqC,OAAtB1R,EAAES,OAAOmR,WAAqBE,EAAUA,EAAQ9X,OAAOgG,EAAES,OAAOmR,WAEpG5Y,GAAGkI,IAAI4Q,KAGlBT,IAAUE,EAAMM,GAGpBnL,EAAE/B,OAAO2M,GAAWD,GACpB3K,EAAE9B,MAAMqN,IAAWlU,EAAiB,IAGpCmU,EAAKA,GAAMvS,EACXwS,EAAKA,GAAMzL,EAAEqK,OAAOnM,OAAO8B,EAAE,GAAGA,EAAE,IAGlC,IAAIvH,GAAOJ,EAAUK,UAAU,aAAa1C,MAAMA,GAClCyC,GAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,eACvDL,GAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAEvE,IAAIuU,GAAWjT,EAAKC,UAAU,eAAe1C,KAAK,SAASsD,GAAK,MAAOA,KACnEqS,EAAWD,EAAS9S,QAAQC,OAAO,KAAK+C,MAAM,iBAAkB,MAAMA,MAAM,eAAgB,KAChG8P,GACK5S,KAAK,QAAS,cACdA,KAAK,YAAa,SAASQ,EAAE1E,EAAEgX,GAAK,MAAO,cAAgB3S,EAAEwR,EAAKnR,EAAE1E,IAAsB,IAAhBqE,EAAEkQ,aAAqB,SACjGtN,QAAQ,QAAS,SAASvC,GAAK,MAAOA,GAAEuS,QAC7CH,EACK7I,gBAAgBC,EAAa,wBAC7BlH,MAAM,iBAAkB,GACxBA,MAAM,eAAgB,KACtBsD,MAAM,SAAS5F,EAAE1E,GAAK,MAAOA,GAAI+E,EAAW3D,EAAKhC,SACjD8E,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,cAAgBqE,EAAEwR,EAAKnR,EAAE1E,IAAsB,IAAhBqE,EAAEkQ,aAAqB,SAErEuC,EAASnS,OAAOC,SAKhBmS,EAAS5V,KAAK,SAASuD,EAAE1E,GACvB,GAAIgV,GAAMtX,GAAGgG,OAAO3F,OAEnB,MAAO,QAAQyI,QAAQ,SAAS2C,GAC3BzE,EAAES,OAAOiR,eAAe,WAAajN,IAAuC,OAA/BzE,EAAES,OAAO,WAAagE,KACrE6L,EAAI/Q,OAAO,QACR+C,MAAM,SAAWtC,EAAO,MAAIA,EAAEuE,MAAQA,EAAMvE,EAAE1E,IAC9CkE,KAAK,QAAS,iCAAmCiF,GAEpD6L,EAAI/Q,OAAO,QACR+C,MAAM,SAAWtC,EAAO,MAAIA,EAAEuE,MAAQA,EAAMvE,EAAE1E,IAC9CkE,KAAK,QAAS,8BAAgCiF,OAOvD,IAAImN,GAAWQ,EAAShT,UAAU,uBAAuB1C,KAAK,SAASsD,GACnE,MAAIA,GAAES,OAAOiR,eAAe,aAAqC,OAAtB1R,EAAES,OAAOmR,SAA4B5R,EAAES,OAAOmR,aAG7FA,GAAStS,QAAQC,OAAO,UACnB+C,MAAM,OAAQ,SAAStC,EAAE1E,EAAEgX,GAAK,MAAO/N,GAAMvE,EAAEsS,KAAMhQ,MAAM,SAAU,SAAStC,EAAE1E,EAAEgX,GAAK,MAAO/N,GAAMvE,EAAEsS,KACtGrY,GAAG,YAAa,SAAS+F,EAAE1E,EAAEgX,GAC1BtZ,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASyZ,kBACLnO,QAAUI,IAAKzE,EAAGuE,MAAOA,EAAMvE,EAAEsS,IACjCpY,EAAGlB,GAAGmE,UAGblD,GAAG,WAAY,SAAS+F,EAAE1E,EAAEgX,GACzBtZ,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASoF,iBACLkG,QAAUI,IAAKzE,EAAGuE,MAAOA,EAAMvE,EAAEsS,IACjCpY,EAAGlB,GAAGmE,UAGblD,GAAG,YAAa,SAAS+F,EAAE1E,GACxBvC,EAAS0F,kBAAkBvE,EAAGlB,GAAGmE,UAGzCyU,EAASpS,KAAK,QAAS,sBACvBoS,EACGrI,gBAAgBC,EAAa,kCAC3BhK,KAAK,KAAsB,IAAhBG,EAAEkQ,aACbrQ,KAAK,KAAM,SAASQ,EAAE1E,EAAEgX,GAAK,MAAO5L,GAAE1G,KACtCR,KAAK,IAAK,KACfoS,EAAS3R,OAAOC,QAEhB,IAAIuS,GAAY,WAAa,MAAwB,QAAhBC,EAAuC,GAAhB/S,EAAEkQ,YAAmBtO,KAAKF,IAAI,GAAoB,GAAhB1B,EAAEkQ,cAC5F8C,EAAY,WAAa,MAAuB,IAAhBhT,EAAEkQ,YAAoB4C,IAAY,GAClEG,EAAY,WAAa,MAAuB,IAAhBjT,EAAEkQ,YAAoB4C,IAAY,IAGrE,MAAO,QAAQ3Q,QAAQ,SAAS2C,GAC/B,GAAIoO,GAAoB,QAARpO,EAAiB,KAAO,IAExC2N,GAASpT,OAAO,sCAAwCyF,GACrD8E,gBAAgBC,EAAa,wBAC3BhK,KAAK,KAAsB,IAAhBG,EAAEkQ,aACbrQ,KAAK,KAAM,SAASQ,EAAE1E,GAAK,MAAOoL,GAAE1G,EAAES,OAAO,WAAagE,MAC1DjF,KAAK,KAAsB,IAAhBG,EAAEkQ,aACbrQ,KAAK,KAAM,SAASQ,EAAE1E,GAAK,MAAOoL,GAAE1G,EAAES,OAAOoS,MAElDT,EAASpT,OAAO,mCAAqCyF,GAClD8E,gBAAgBC,EAAa,wBAC3BhK,KAAK,KAAMmT,GACXnT,KAAK,KAAM,SAASQ,EAAE1E,GAAK,MAAOoL,GAAE1G,EAAES,OAAO,WAAagE,MAC1DjF,KAAK,KAAMoT,GACXpT,KAAK,KAAM,SAASQ,EAAE1E,GAAK,MAAOoL,GAAE1G,EAAES,OAAO,WAAagE,SAGhE,MAAO,QAAQ3C,QAAQ,SAAS2C,GAC/B4N,EAASjT,UAAU,eAAiBqF,GACjCxK,GAAG,YAAa,SAAS+F,EAAE1E,EAAEgX,GAC1BtZ,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASyZ,kBACLnO,QAAUI,IAAKzE,EAAES,OAAO,WAAagE,GAAMF,MAAOA,EAAMvE,EAAEsS,IAC1DpY,EAAGlB,GAAGmE,UAGblD,GAAG,WAAY,SAAS+F,EAAE1E,EAAEgX,GACzBtZ,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASoF,iBACLkG,QAAUI,IAAKzE,EAAES,OAAO,WAAagE,GAAMF,MAAOA,EAAMvE,EAAEsS,IAC1DpY,EAAGlB,GAAGmE,UAGblD,GAAG,YAAa,SAAS+F,EAAE1E,GACxBvC,EAAS0F,kBAAkBvE,EAAGlB,GAAGmE,YAKzCkV,EAAS9S,OAAO,QACXC,KAAK,QAAS,kBAEdvF,GAAG,YAAa,SAAS+F,EAAE1E,GACxBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASyZ,kBACL/N,IAAKzE,EAAE8S,MACP7O,MAAOjE,EAAE8S,MACTzO,SACMI,IAAK,KAAMR,MAAOjE,EAAES,OAAOsR,GAAIxN,MAAOvE,EAAEuE,OAASA,EAAMvE,EAAE1E,KACzDmJ,IAAK,KAAMR,MAAOjE,EAAES,OAAOsS,GAAIxO,MAAOvE,EAAEuE,OAASA,EAAMvE,EAAE1E,KACzDmJ,IAAK,KAAMR,MAAOjE,EAAES,OAAOgR,GAAIlN,MAAOvE,EAAEuE,OAASA,EAAMvE,EAAE1E,KAE/DoB,KAAMsD,EACNiB,MAAO3F,EACPpB,EAAGlB,GAAGmE,UAGblD,GAAG,WAAY,SAAS+F,EAAE1E,GACvBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASoF,iBACLsG,IAAKzE,EAAE8S,MACP7O,MAAOjE,EAAE8S,MACTzO,SACMI,IAAK,KAAMR,MAAOjE,EAAES,OAAOsR,GAAIxN,MAAOvE,EAAEuE,OAASA,EAAMvE,EAAE1E,KACzDmJ,IAAK,KAAMR,MAAOjE,EAAES,OAAOsS,GAAIxO,MAAOvE,EAAEuE,OAASA,EAAMvE,EAAE1E,KACzDmJ,IAAK,KAAMR,MAAOjE,EAAES,OAAOgR,GAAIlN,MAAOvE,EAAEuE,OAASA,EAAMvE,EAAE1E,KAE/DoB,KAAMsD,EACNiB,MAAO3F,EACPpB,EAAGlB,GAAGmE,UAGblD,GAAG,YAAa,SAAS+F,EAAE1E,GACxBvC,EAAS0F,kBAAkBvE,EAAGlB,GAAGmE,UAIzCiV,EAASpT,OAAO,uBACbuK,gBAAgBC,EAAa,qBAC3BhK,KAAK,IAAK,SAASQ,EAAE1E,GAAK,MAAOoL,GAAE1G,EAAES,OAAOsR,MAC5CvS,KAAK,QAASiT,GACdjT,KAAK,IAAKmT,GAEVnT,KAAK,SAAU,SAASQ,EAAE1E,GAAK,MAAOiG,MAAKC,IAAIkF,EAAE1G,EAAES,OAAOsR,IAAMrL,EAAE1G,EAAES,OAAOgR,MAAQ,IACnFnP,MAAM,OAAQ,SAAStC,EAAE1E,GAAK,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAE1E,KACxDgH,MAAM,SAAU,SAAStC,EAAE1E,GAAK,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAE1E,KAG/D+W,EAAS9S,OAAO,QAAQC,KAAK,QAAS,qBAEtC4S,EAASpT,OAAO,0BACbuK,gBAAgBC,EAAa,6BAC3BhK,KAAK,KAAMmT,GACXnT,KAAK,KAAM,SAASQ,EAAE1E,GAAK,MAAOoL,GAAE1G,EAAES,OAAOsS,MAC7CvT,KAAK,KAAMoT,GACXpT,KAAK,KAAM,SAASQ,EAAE1E,GAAK,MAAOoL,GAAE1G,EAAES,OAAOsS,MAGlDb,EAAKvS,EAAEoR,OACPoB,EAAKzL,EAAEqK,SAGXvH,EAAYS,UAAU,wBACf7O,EAnQX,GAUM8V,GACAI,EACAF,EACAa,EAUFC,EAAIC,EAvBJxU,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACRC,EAAS,IACTmD,EAAKd,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UACrBtD,EAAI3G,GAAGmH,MAAMuH,UACbhB,EAAI1N,GAAGmH,MAAMC,SACb+Q,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9BnC,EAAQhM,EAAGG,MAAM6O,eACjBxI,EAAY,KAKZhG,EAAWC,GAAGD,SAAS,mBAAoB,kBAAmB,mBAAoB,aAClFsH,EAAW,IACXqS,EAAc,KAQhBlJ,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,EAuRjD,OArCAjF,GAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAUsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACjErB,QAAUqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACnEmS,aAAcnM,IAAK,WAAW,MAAOmM,IAAelM,IAAK,SAASjG,GAAGmS,EAAYnS,IACjFZ,GAAU4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAK5Q,IAC/DmG,GAAUH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAAGyS,EAAKzS,IAC/DhC,QAAUgI,IAAK,WAAW,MAAO5G,IAAK6G,IAAK,SAASjG,GAAGZ,EAAEY,IACzD0S,QAAU1M,IAAK,WAAW,MAAOG,IAAKF,IAAK,SAASjG,GAAGmG,EAAEnG,IACzD2Q,SAAU3K,IAAK,WAAW,MAAO2K,IAAW1K,IAAK,SAASjG,GAAG2Q,EAAQ3Q,IACrE+Q,SAAU/K,IAAK,WAAW,MAAO+K,IAAW9K,IAAK,SAASjG,GAAG+Q,EAAQ/Q,IACrE6Q,QAAU7K,IAAK,WAAW,MAAO6K,IAAU5K,IAAK,SAASjG,GAAG6Q,EAAO7Q,IACnE0R,QAAU1L,IAAK,WAAW,MAAO0L,IAAUzL,IAAK,SAASjG,GAAG0R,EAAO1R,IACnE8B,IAAckE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,GAAG8B,EAAG9B,IAI/D5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,KAE9BF,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,OAI1B9H,EAAGG,MAAMiO,YAAYvL,GAEdA,GAEX7C,EAAGI,OAAOua,aAAe,WACrB,YA6CA,SAAS9X,GAAMoB,GA8HX,MA7HAgN,GAAYW,QACZX,EAAY7Q,OAAOwa,GACfC,GAAW5J,EAAY7Q,OAAO0a,GAC9BC,GAAW9J,EAAY7Q,OAAO4a,GAElC/W,EAAUC,KAAK,SAASC,GACpB,GAAIqC,GAAY/F,GAAGgG,OAAO3F,KAE1Bd,GAAGG,MAAMiV,QAAQ5O,EACjB,IAAIjB,IAAkBmB,GAAUiK,SAASnK,EAAUuD,MAAM,WAAa,KAC5D3E,EAAOC,KAAOD,EAAOqQ,MAC3BjQ,GAAmBmB,GAAUgK,SAASnK,EAAUuD,MAAM,YAAc,KAC9D3E,EAAOE,IAAMF,EAAOoQ,MAS9B,IAPA3S,EAAM+P,OAAS,WACXpS,EAASya,eACTzU,EAAU4G,aAAatF,SAASA,GAAU3G,KAAK0B,IAEnDA,EAAM2D,UAAY1F,OAGbqD,GAASA,EAAKhC,QACVgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAOiR,eAAe,OAAS1R,EAAES,OAAOiR,eAAe,OAAS1R,EAAES,OAAOiR,eAAe,QAAUhX,QAAQ,CAClJ,GAAIyT,GAAapP,EAAUK,UAAU,cAAc1C,MAAMuR,GAYzD,OAVAE,GAAW7O,QAAQC,OAAO,QACrBC,KAAK,QAAS,kBACdA,KAAK,KAAM,SACX8C,MAAM,cAAe,UAE1B6L,EACK3O,KAAK,IAAK7B,EAAOC,KAAOE,EAAiB,GACzC0B,KAAK,IAAK7B,EAAOE,IAAME,EAAkB,GACzCiL,KAAK,SAAShJ,GAAK,MAAOA,KAExB5E,EAEP2D,EAAUK,UAAU,cAAcc,SAItCP,EAAIwT,EAAQ5U,SACZmI,EAAIyM,EAAQF,SAASQ,OAAM,EAG3B,IAAItU,GAAOJ,EAAUK,UAAU,gCAAgC1C,MAAMA,IACjEgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,mCAAmCD,OAAO,KAC1FoU,EAAYD,EAAOnU,OAAO,QAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBAC5BD,OAAO,KAAKC,KAAK,QAAS,eAC1BD,OAAO,QAEZmU,EAAOnU,OAAO,KAAKC,KAAK,QAAS;AAEjCyP,EAAEzP,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEhE+V,GACA3E,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,aAAe1B,EAAiB,OAI3DqV,EACKlU,MAAMnB,GACNoB,OAAOnB,EAEZ,IAAI8V,GAAW5E,EAAEjQ,OAAO,gBACnB8U,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAe/C,IAbAF,EAASlO,aAAajM,KAAKyZ,GAG3BQ,EAAUpU,OAAO,YACZC,KAAK,KAAM,mBAAqB2T,EAAQ9Q,MACxC9C,OAAO,QAEZ0P,EAAEjQ,OAAO,oBAAsBmU,EAAQ9Q,KAAO,SACzC7C,KAAK,QAASG,EAAEkQ,aAAea,EAAgB,EAAI,IACnDlR,KAAK,SAAU,IACfA,KAAK,KAAMG,EAAEkQ,aAAea,EAAgB,EAAI,IAGjD0C,EAAW,CACXC,EACKlT,MAAMR,GACNuP,MAAO3W,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAC/CsX,UAAUjW,EAAiB,GAEhCkR,EAAEjQ,OAAO,iBAAiBQ,KAAK,YAAa,eAAiBkH,EAAE9B,QAAQ,GAAK,KAC5EqK,EAAEjQ,OAAO,iBAAiBtF,KAAK2Z,EAE/B,IAAIlD,GAASlB,EAAEjQ,OAAO,iBAAiBI,UAAU,IAC7CsR,IACAP,EACK/Q,UAAU,QACVI,KAAK,YAAa,SAASQ,EAAE1E,EAAEgX,GAAK,MAAO,gBAAkBA,EAAI,GAAK,EAAI,IAAM,MAAQ,MAIjGgB,IACAC,EACKpT,MAAMuG,GACNwI,MAAO3N,KAAKyB,MAAMjF,EAAgB,KAClCiW,UAAWlW,EAAgB,GAEhCmR,EAAEjQ,OAAO,iBAAiBtF,KAAK6Z,IAInCtE,EAAEjQ,OAAO,qBACJQ,KAAK,KAAK,GACVA,KAAK,KAAK1B,GACV0B,KAAK,KAAMkH,EAAE,IACblH,KAAK,KAAMkH,EAAE,MAQtB8C,EAAYS,UAAU,8BACf7O,EArKX,GAcMuE,GACA+G,EAfFyM,EAAU5a,EAAGI,OAAOsY,UAClBoC,EAAQ9a,EAAGI,OAAOqW,OAClBuE,EAAQhb,EAAGI,OAAOqW,OAGpBrR,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9CqB,EAAQ,KACRC,EAAS,KACTqF,EAAQhM,EAAGG,MAAM4O,WACjB8L,GAAY,EACZE,GAAY,EACZM,GAAkB,EAClBlD,GAAgB,EAChBjY,EAAUF,EAAGI,OAAOF,UAGpBwV,EAAS,qBACTlV,EAAWC,GAAGD,SAAS,eAAgB,aACvCsH,EAAW,GAGjBgT,GACKlE,OAAO,UACPW,YAAW,GACXR,WAAW,SAAStP,GAAK,MAAOA,KAErCuT,EACKpE,OAAO,EAAoB,QAAU,QACrCG,WAAWtW,GAAGib,OAAO,SAG1Bxb,EAAQ4H,SAAS,EAMjB,IAAImJ,GAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,EAoMjD,OA7DA8S,GAAQpa,SAASkB,GAAG,2BAA4B,SAASia,GACrDzb,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7B8U,EAAQpa,SAASkB,GAAG,0BAA2B,SAASia,GACpDzb,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7B8U,EAAQpa,SAASkB,GAAG,2BAA4B,SAASia,GACrDzb,MAOJ2C,EAAMrC,SAAWA,EACjBqC,EAAM+X,QAAUA,EAChB/X,EAAMiY,MAAQA,EACdjY,EAAMmY,MAAQA,EACdnY,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtEmQ,eAAgBnK,IAAK,WAAW,MAAOmK,IAAiBlK,IAAK,SAASjG,GAAGmQ,EAAcnQ,IACvF6S,WAAY7M,IAAK,WAAW,MAAO6M,IAAa5M,IAAK,SAASjG,GAAG6S,EAAU7S,IAC3E+S,WAAY/M,IAAK,WAAW,MAAO+M,IAAa9M,IAAK,SAASjG,GAAG+S,EAAU/S,IAC3E4T,gBAAoB5N,IAAK,WAAW,MAAO9N,IAAW+N,IAAK,SAASjG,GAAG9H,EAAQ8H,IAC/E0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IAGrE5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,GAClB8S,EAAQ9S,SAASA,GACjBgT,EAAMhT,SAASA,GACfkT,EAAMlT,SAASA,KAEnBkE,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1B4S,EAAQ5O,MAAMA,KAElBqP,iBAAkBrN,IAAK,WAAW,MAAOqN,IAAmBpN,IAAK,SAASjG,GACtEqT,EAAkBrT,EAClBgT,EAAMpE,OAAQ,EAAM,QAAU,YAItC5W,EAAGG,MAAM6U,eAAenS,EAAO+X,GAC/B5a,EAAGG,MAAMiO,YAAYvL,GAEdA,GAOX7C,EAAGI,OAAOyb,OAAS,WACf,YAwBA,SAAShZ,GAAMoB,GAoKX,MAnKAA,GAAUC,KAAK,SAASuD,EAAG1E,GACvB,GAAIwC,GAAiBmB,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAC9CjQ,EAAkBmB,EAASvB,EAAOE,IAAMF,EAAOoQ,MAEnDhP,GAAY/F,GAAGgG,OAAO3F,MACtBd,EAAGG,MAAMiV,QAAQ5O,EAEjB,IAAIsV,GAASC,EAAO5a,KAAKL,KAAM2G,EAAG1E,GAAG7B,QAAQoT,KAAK7T,GAAGub,YACjDC,EAAUC,EAAQ/a,KAAKL,KAAM2G,EAAG1E,GAAG7B,QAAQoT,KAAK7T,GAAGub,YACnDG,EAAWC,EAASjb,KAAKL,KAAM2G,EAAG1E,GAAG7B,QAAQoT,KAAK7T,GAAGub,YACrDK,EAAcC,EAAYnb,KAAKL,KAAM2G,EAAG1E,GAAG7B,QAC3Cqb,EAAeC,EAAarb,KAAKL,KAAM2G,EAAG1E,GAAG7B,QAC7Cub,EAAgBC,EAAcvb,KAAKL,KAAM2G,EAAG1E,GAAG7B,QAI/Cyb,EAAKlc,GAAGmH,MAAMC,SACbuE,OAAQ3L,GAAGmc,OAAOnc,GAAGoc,OAAOC,EAAQhB,MACpCzP,MAAM4J,GAAW1Q,EAAgB,IAAM,EAAGA,GAGtCzE,MAAKic,WAAatc,GAAGmH,MAAMC,SAC/BuE,QAAQ,EAAG/C,EAAAA,IACXgD,MAAMsQ,EAAGtQ,QAGdvL,MAAKic,UAAYJ,CAEjB,IAAIK,GAAWvc,GAAGqI,IAAIgT,GAClBmB,EAAWxc,GAAGkI,IAAImT,GAClBoB,EAAWpB,EAAO,GAGlBlV,EAAOJ,EAAUK,UAAU,uBAAuB1C,MAAMsD,IACxDX,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,0BACnDkU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,QAAQC,KAAK,QAAS,wBACpCkU,EAAOnU,OAAO,QAAQC,KAAK,QAAS,wBACpCkU,EAAOnU,OAAO,QAAQC,KAAK,QAAS,wBACpCkU,EAAOnU,OAAO,QAAQC,KAAK,QAAS,cAEpCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAEvE,IACI6X,GAAK,SAAS1V,GAAK,MAAOuB,MAAKC,IAAI0T,EAAGlV,GAAKkV,EAAG,KAE9CS,EAAM,SAAS3V,GAAK,MAAekV,GAAJ,EAAJlV,EAAWA,EAAQ,GAElDiP,GAAEjQ,OAAO,oBACJQ,KAAK,SAAUzB,GACfyB,KAAK,QAASkW,EAAGF,EAAW,EAAIA,EAAWD,IAC3C/V,KAAK,IAAKmW,EAAIH,EAAW,EAAIA,EAAWD,IACxCzB,MAAM0B,EAAW,EAAIA,EAAWD,GAErCtG,EAAEjQ,OAAO,oBACJQ,KAAK,SAAUzB,GACfyB,KAAK,QAASkW,EAAGD,IACjBjW,KAAK,IAAKmW,EAAIF,IACd3B,MAAM2B,GAEXxG,EAAEjQ,OAAO,oBACJQ,KAAK,SAAUzB,GACfyB,KAAK,QAASkW,EAAGF,IACjBhW,KAAK,IAAKmW,EAAIH,IACdhW,KAAK,QAASkW,EAAGF,EAAW,EAAID,EAAWC,IAC3ChW,KAAK,IAAKmW,EAAIH,EAAW,EAAID,EAAWC,IACxC1B,MAAM0B,EAAW,EAAID,EAAWC,GAErCvG,EAAEjQ,OAAO,mBACJsD,MAAM,OAAQiC,GACd/E,KAAK,SAAUzB,EAAkB,GACjCyB,KAAK,IAAKzB,EAAkB,GAC5ByB,KAAK,QAAoB,EAAXkV,EACXQ,EAAG,GAAKA,EAAGR,EAAS,IAClBQ,EAAGR,EAAS,IAAMQ,EAAG,IAC1B1V,KAAK,IAAKmW,EAAIjB,IACdza,GAAG,YAAa,WACblB,EAASyZ,kBACLvO,MAAOyQ,EAAS,GAChB5B,MAAOkC,EAAc,IAAM,UAC3BzQ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,YAAa,WACblB,EAAS0F,kBACLwF,MAAOyQ,EAAS,GAChB5B,MAAOkC,EAAc,IAAM,UAC3BzQ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,WAAY,WACZlB,EAASoF,iBACL8F,MAAOyQ,EAAS,GAChB5B,MAAOkC,EAAc,IAAM,UAC3BzQ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,WAIzC,IAAIsT,GAAM7X,EAAkB,EAExB8X,EAAarB,EAAQ/I,IAAK,SAASqK,EAAQ7U,GAC3C,OAAQgD,MAAO6R,EAAQhD,MAAOgC,EAAa7T,KAE/CyS,GACGtU,UAAU,0BACV1C,KAAKmZ,GACLvW,QACAC,OAAO,QACPC,KAAK,QAAS,qBACdA,KAAK,YAAa,SAASQ,GAAK,MAAO,aAAekV,EAAGlV,EAAEiE,OAAS,IAAOlG,EAAkB,EAAK,MAClGyB,KAAK,IAAK,MAAQoW,EAAK,IAAMA,EAAK,KAAQA,EAAM,KAAQA,EAAM,KAAQA,EAAM,KAC5E3b,GAAG,YAAa,SAAS+F,GACxBjH,EAASyZ,kBACPvO,MAAOjE,EAAEiE,MACT6O,MAAO9S,EAAE8S,OAAS,WAClBvO,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,QAC7B4C,KAAMgQ,EAAGlV,EAAEiE,OAAQlG,EAAgB,OAItC9D,GAAG,YAAa,SAAS+F,GACtBjH,EAAS0F,kBACLwF,MAAOjE,EAAEiE,MACT6O,MAAO9S,EAAE8S,OAAS,WAClBvO,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,WAAY,SAAS+F,EAAG1E,GACxBvC,EAASoF,iBACL8F,MAAOjE,EAAEiE,MACT6O,MAAO9S,EAAE8S,OAAS,WAClBvO,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAIvCnD,EAAKC,UAAU,aACVnF,GAAG,YAAa,SAAS+F,EAAE1E,GACxB,GAAIwX,GAAQ8B,EAAYtZ,KAAQA,EAAqB,GAALA,EAAS,OAAS,UAA9B,UACpCvC,GAASyZ,kBACLvO,MAAOjE,EACP8S,MAAOA,EACPvO,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,YAAa,WACblB,EAAS0F,kBACLwF,MAAOyQ,EAAS,GAChB5B,MAAOkC,EAAc,IAAM,WAC3BzQ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,WAAY,SAAS+F,EAAE1E,GACvB,GAAIwX,GAAQ8B,EAAYtZ,KAAQA,EAAqB,GAALA,EAAS,OAAS,UAA9B,UACpCvC,GAASoF,iBACL8F,MAAOjE,EACP8S,MAAOA,EACPvO,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,cAKtClH,EAtLX,GAAIuC,IAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CuR,EAAS,OACTX,GAAU,EACV8F,EAAS,SAAStU,GAAK,MAAOA,GAAEsU,QAChCG,EAAU,SAASzU,GAAK,MAAOA,GAAEyU,QAAUzU,EAAEyU,SAAW,IACxDE,EAAW,SAAS3U,GAAK,MAAOA,GAAE2U,UAClCE,EAAc,SAAS7U,GAAK,MAAOA,GAAE6U,YAAc7U,EAAE6U,gBACrDE,EAAe,SAAS/U,GAAK,MAAOA,GAAE+U,aAAe/U,EAAE+U,iBACvDE,EAAgB,SAASjV,GAAK,MAAOA,GAAEiV,cAAgBjV,EAAEiV,kBACzDI,GAAU,GACVpW,EAAQ,IACRC,EAAS,GACTH,EAAY,KACZuQ,EAAa,KACb/K,EAAQhM,EAAGG,MAAM4O,UAAU,YAC3BvO,EAAWC,GAAGD,SAAS,mBAAoB,kBAAmB,mBA4MpE,OA9BAqC,GAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBgO,QAAc/N,IAAK,WAAW,MAAO+N,IAAU9N,IAAK,SAASjG,GAAG+T,EAAO/T,IACvEkU,SAAclO,IAAK,WAAW,MAAOkO,IAAWjO,IAAK,SAASjG,GAAGkU,EAAQlU,IACzEoU,UAAWpO,IAAK,WAAW,MAAOoO,IAAYnO,IAAK,SAASjG,GAAGoU,EAASpU,IACxE8U,QAAc9O,IAAK,WAAW,MAAO8O,IAAU7O,IAAK,SAASjG,GAAG8U,EAAO9U,IACvEtB,OAAWsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IAClErB,QAAYqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACrE+O,YAAgB/I,IAAK,WAAW,MAAO+I,IAAc9I,IAAK,SAASjG,GAAG+O,EAAW/O,IAGjF5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DuR,QAAS5I,IAAK,WAAW,MAAO4I,IAAU3I,IAAK,SAASjG,GACpD4O,EAAS5O,EACTiO,EAAoB,SAAVW,GAA+B,UAAVA,IAEnC5K,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,OAIlChI,EAAGG,MAAMiO,YAAYvL,GACdA,GAQX7C,EAAGI,OAAOod,YAAc,WACpB,YA2BA,SAAS3a,GAAMoB,GAmHX,MAlHAA,GAAUC,KAAK,SAASuD,EAAG1E,GACvB,GAAIyD,GAAY/F,GAAGgG,OAAO3F,KAC1Bd,GAAGG,MAAMiV,QAAQ5O,EAEjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBmB,EAASvB,EAAOE,IAAMF,EAAOoQ,MAOnD,IAJA3S,EAAM+P,OAAS,WAAa/P,EAAMoB,IAClCpB,EAAM2D,UAAY1F,MAGb2G,IAAMsU,EAAO5a,KAAKL,KAAM2G,EAAG1E,GAE5B,MADA/C,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,QAGtC,IAAImU,GAASC,EAAO5a,KAAKL,KAAM2G,EAAG1E,GAAG7B,QAAQoT,KAAK7T,GAAGub,YACjDC,EAAUC,EAAQ/a,KAAKL,KAAM2G,EAAG1E,GAAG7B,QAAQoT,KAAK7T,GAAGub,YACnDG,EAAWC,EAASjb,KAAKL,KAAM2G,EAAG1E,GAAG7B,QAAQoT,KAAK7T,GAAGub,YAGrDpV,EAAOJ,EAAUK,UAAU,4BAA4B1C,MAAMsD,IAC7DX,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,+BACnDkU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,aAEjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAGvE,IAAIqX,GAAKlc,GAAGmH,MAAMC,SACbuE,QAAQ,EAAGpD,KAAKL,IAAImT,EAAO,GAAIG,EAAQ,GAAIE,EAAS,MACpD9P,MAAM4J,GAAW1Q,EAAgB,IAAM,EAAGA,IAG3CoU,EAAK7Y,KAAKic,WAAatc,GAAGmH,MAAMC,SAC/BuE,QAAQ,EAAG/C,EAAAA,IACXgD,MAAMsQ,EAAGtQ,QAGdvL,MAAKic,UAAYJ,CAEjB,IAGIc,GAAQtC,EAAO1U,OAAO,cAAcO,OAAO,KAC1CC,KAAK,cAAe,OACpBA,KAAK,YAAa,iBAAmBN,EAASvB,EAAOE,IAAMF,EAAOoQ,QAAU,EAAI,IACrFiI,GAAMzW,OAAO,QACRC,KAAK,QAAS,YACdwJ,KAAK,SAAShJ,GAAK,MAAOA,GAAEgW,QAEjCA,EAAMzW,OAAO,QACRC,KAAK,QAAS,eACdA,KAAK,KAAM,OACXwJ,KAAK,SAAShJ,GAAK,MAAOA,GAAEiW,WAEjC7B,EACKnV,MAAMnB,GACNoB,OAAOnB,EAEZ,IAAImY,GAAajH,EAAEjQ,OAAO,iBAC1BhG,IAAG2M,WAAWuQ,GAAYxc,KAAK0a,EAG/B,IAAIH,GAAS3E,GAAc4F,EAAG5F,WAAYxR,EAAiB,KAGvDqY,EAAOlH,EAAE7P,UAAU,aAClB1C,KAAKwY,EAAGhG,MAAOA,EAAQA,EAASpR,EAAiB,IAAO,SAASkC,GAC9D,MAAO3G,MAAKsP,aAAesL,EAAOjU,KAItCoW,EAAYD,EAAK7W,QAAQC,OAAO,KAC/BC,KAAK,QAAS,WACdA,KAAK,YAAa,SAASQ,GAAK,MAAO,aAAekS,EAAGlS,GAAK,QAC9DsC,MAAM,UAAW,KAEtB8T,GAAU7W,OAAO,QACZC,KAAK,KAAMzB,GACXyB,KAAK,KAAwB,EAAlBzB,EAAsB,GAEtCqY,EAAU7W,OAAO,QACZC,KAAK,cAAe,UACpBA,KAAK,KAAM,OACXA,KAAK,IAAuB,EAAlBzB,EAAsB,GAChCiL,KAAKiL,EAGV,IAAIoC,GAAard,GAAG2M,WAAWwQ,GAC1B3W,KAAK,YAAa,SAASQ,GAAK,MAAO,aAAekV,EAAGlV,GAAK,QAC9DsC,MAAM,UAAW,EAEtB+T,GAAWrX,OAAO,QACbQ,KAAK,KAAMzB,GACXyB,KAAK,KAAwB,EAAlBzB,EAAsB,GAEtCsY,EAAWrX,OAAO,QACbQ,KAAK,IAAuB,EAAlBzB,EAAsB,GAGrC/E,GAAG2M,WAAWwQ,EAAKlW,QACdT,KAAK,YAAa,SAASQ,GAAK,MAAO,aAAekV,EAAGlV,GAAK,QAC9DsC,MAAM,UAAW,MACjBpC,WAGTlH,GAAGsd,MAAMC,QACFnb,EAxIX,GAAIgZ,GAAS7b,EAAGI,OAAOyb,SACnB3b,EAAUF,EAAGI,OAAOF,UAEpB0W,EAAS,OACPX,GAAU,EACV7Q,GAAUE,IAAK,EAAGmQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,KAC/C0W,EAAS,SAAStU,GAAK,MAAOA,GAAEsU,QAChCG,EAAU,SAASzU,GAAK,MAAOA,GAAEyU,QAAUzU,EAAEyU,SAAW,IACxDE,EAAW,SAAS3U,GAAK,MAAOA,GAAE2U,UAClC1V,EAAQ,KACRC,EAAS,GACToQ,EAAa,KACpBJ,EAAQ,KACDjB,EAAS,KACTlV,EAAWC,GAAGD,UAuLpB,OApLAN,GACK4H,SAAS,GACTiD,eAAc,GA4HnB8Q,EAAOrb,SAASkB,GAAG,2BAA4B,SAASia,GACpDA,EAAY,QACRzP,IAAKyP,EAAIpB,MACT7O,MAAOiQ,EAAIjQ,MACXM,MAAO2P,EAAI3P,OAEf9L,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7B+V,EAAOrb,SAASkB,GAAG,0BAA2B,SAASia,GACnDzb,EAAQ4F,QAAO,KAGnB+V,EAAOrb,SAASkB,GAAG,2BAA4B,SAASia,GACpDzb,MAOJ2C,EAAMgZ,OAASA,EACfhZ,EAAMrC,SAAWA,EACjBqC,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBgO,QAAc/N,IAAK,WAAW,MAAO+N,IAAU9N,IAAK,SAASjG,GAAG+T,EAAO/T,IACvEkU,SAAclO,IAAK,WAAW,MAAOkO,IAAWjO,IAAK,SAASjG,GAAGkU,EAAQlU,IACzEoU,UAAWpO,IAAK,WAAW,MAAOoO,IAAYnO,IAAK,SAASjG,GAAGoU,EAASpU,IACxEtB,OAAWsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IAClErB,QAAYqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACrE+O,YAAgB/I,IAAK,WAAW,MAAO+I,IAAc9I,IAAK,SAASjG,GAAG+O,EAAW/O,IACjF2O,OAAW3I,IAAK,WAAW,MAAO2I,IAAS1I,IAAK,SAASjG,GAAG2O,EAAM3O,IAClE0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IAGrE5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DuR,QAAS5I,IAAK,WAAW,MAAO4I,IAAU3I,IAAK,SAASjG,GACpD4O,EAAS5O,EACTiO,EAAoB,SAAVW,GAA+B,UAAVA,MAIvC5W,EAAGG,MAAM6U,eAAenS,EAAOgZ,GAC/B7b,EAAGG,MAAMiO,YAAYvL,GAEdA,GAKX7C,EAAGI,OAAO6d,eAAiB,WACvB,YAoCA,SAASpb,GAAMoB,GA4HX,MA3HAA,GAAUC,KAAK,SAASC,GACpBqC,EAAY/F,GAAGgG,OAAO3F,KACtB,IAAIyE,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAElEpF,GAAGG,MAAMiV,QAAQ5O,EAGjB,IAAI0X,GAAY3Y,EAAiBpB,EAAK,GAAG+D,OAAO/F,OAAU,GAG1DiF,GAAEgF,OAAOuM,GAAWlY,GAAGmc,OAAOzY,EAAK,GAAG+D,OAAOgL,IAAI0F,GAAMnX,OAAOqb,KAE1DqB,EACA/W,EAAEiF,MAAMwM,IAA4B,GAAjBtT,EAAsBpB,EAAK,GAAG+D,OAAO/F,OAAQoD,GAAkBpB,EAAK,GAAG+D,OAAO/F,OAAS,IAAOgC,EAAK,GAAG+D,OAAO/F,SAEhIiF,EAAEiF,MAAMwM,IAAW,EAAIqF,EAAW,EAAG3Y,EAAiB2Y,EAAW,EAAI,IAEzE/P,EAAE/B,OAAO2M,IACDtY,GAAGqI,IAAI3E,EAAK,GAAG+D,OAAOgL,IAAIkL,GAAQ3c,OAAO4c,IACzC5d,GAAGkI,IAAIxE,EAAK,GAAG+D,OAAOgL,IAAIoL,GAAS7c,OAAO4c,MAEhDhS,MAAMqN,IAAWlU,EAAiB,IAGhC4B,EAAEgF,SAAS,KAAOhF,EAAEgF,SAAS,KAC7BhF,EAAEgF,SAAS,GACPhF,EAAEgF,QAAQhF,EAAEgF,SAAS,GAAqB,IAAhBhF,EAAEgF,SAAS,GAAWhF,EAAEgF,SAAS,GAAqB,IAAhBhF,EAAEgF,SAAS,KACzEhF,EAAEgF,QAAQ,GAAG,KAEnB+B,EAAE/B,SAAS,KAAO+B,EAAE/B,SAAS,KAC7B+B,EAAE/B,SAAS,GACP+B,EAAE/B,QAAQ+B,EAAE/B,SAAS,GAAqB,IAAhB+B,EAAE/B,SAAS,GAAW+B,EAAE/B,SAAS,GAAqB,IAAhB+B,EAAE/B,SAAS,KACzE+B,EAAE/B,QAAQ,GAAG,IAGvB,IAAIxF,GAAOnG,GAAGgG,OAAO3F,MAAM+F,UAAU,+BAA+B1C,MAAMA,EAAK,GAAG+D,SAC9EpB,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,kCACnDmU,EAAYtU,EAAUE,OAAO,QAC7BmU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,YAEjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEvEkB,EACK9E,GAAG,QAAS,SAAS+F,EAAE1E,GACpBvC,EAAS+d,YACLpa,KAAMsD,EACNiB,MAAO3F,EACP4J,IAAKlM,GAAGmE,MACRkF,GAAIA,MAIhBsR,EAAUpU,OAAO,YACZC,KAAK,KAAM,sBAAwB6C,GACnC9C,OAAO,QAEZJ,EAAKH,OAAO,uBAAyBqD,EAAK,SACrC7C,KAAK,QAAS1B,GACd0B,KAAK,SAAUzB,GAEpBkR,EAAKzP,KAAK,YAAauX,EAAW,2BAA6B1U,EAAK,IAAM,GAE1E,IAAI6M,GAAQ/P,EAAKH,OAAO,aAAaI,UAAU,YAC1C1C,KAAK,SAASsD,GAAK,MAAOA,IAC/BkP,GAAMjP,OAAOC,QAEb,IAAI8W,GAAa9H,EAAM5P,QAAQC,OAAO,IAGtC2P,GACK1P,KAAK,QAAS,SAASQ,EAAG1E,EAAGgX,GAAK,OAAQ2E,EAAQjX,EAAG1E,GAAK4b,EAASlX,EAAG1E,GAAK,mBAAqB,oBAAsB,YAAcgX,EAAI,IAAMhX,GAEvI0b,GAAWzX,OAAO,QACzBC,KAAK,QAAS,wBACdA,KAAK,YAAa,SAASQ,EAAG1E,GAAK,MAAO,aAAeqE,EAAEwR,EAAKnR,EAAG1E,IAAM,QACzEkE,KAAK,KAAM,GACXA,KAAK,KAAM,SAASQ,EAAG1E,GAAK,MAAOoL,GAAEmQ,EAAQ7W,EAAG1E,MAChDkE,KAAK,KAAM,GACXA,KAAK,KAAM,SAASQ,EAAG1E,GAAK,MAAOoL,GAAEiQ,EAAO3W,EAAG1E,MAExC0b,EAAWzX,OAAO,QACzBC,KAAK,QAAS,gCACdA,KAAK,YAAa,SAASQ,EAAG1E,GAC3B,MAAO,cAAgBqE,EAAEwR,EAAKnR,EAAG1E,IAAMmb,EAAS,GAAK,KAClD/P,EAAEsM,EAAKhT,EAAG1E,KAAO2b,EAAQjX,EAAG1E,GAAK4b,EAASlX,EAAG1E,GAAMoL,EAAEwQ,EAASlX,EAAG1E,IAAMoL,EAAEuQ,EAAQjX,EAAG1E,IAAO,IAC5F,MAELkE,KAAK,IAAK,GACVA,KAAK,IAAK,GACVA,KAAK,QAASiX,GACdjX,KAAK,SAAU,SAASQ,EAAG1E,GACxB,GAAI6b,GAAOF,EAAQjX,EAAG1E,GAClB8b,EAAQF,EAASlX,EAAG1E,EACxB,OAAO6b,GAAOC,EAAQ1Q,EAAE0Q,GAAS1Q,EAAEyQ,GAAQzQ,EAAEyQ,GAAQzQ,EAAE0Q,IAG/DlI,GAAMlQ,OAAO,yBAAyB2G,aACjCnG,KAAK,YAAa,SAASQ,EAAG1E,GAAK,MAAO,aAAeqE,EAAEwR,EAAKnR,EAAG1E,IAAM,QACzEkE,KAAK,KAAM,GACXA,KAAK,KAAM,SAASQ,EAAG1E,GAAK,MAAOoL,GAAEmQ,EAAQ7W,EAAG1E,MAChDkE,KAAK,KAAM,GACXA,KAAK,KAAM,SAASQ,EAAG1E,GAAK,MAAOoL,GAAEiQ,EAAO3W,EAAG1E,MAEpD4T,EAAMlQ,OAAO,yBAAyB2G,aACjCnG,KAAK,YAAa,SAASQ,EAAG1E,GAC3B,MAAO,cAAgBqE,EAAEwR,EAAKnR,EAAG1E,IAAMmb,EAAS,GAAK,KAClD/P,EAAEsM,EAAKhT,EAAG1E,KAAO2b,EAAQjX,EAAG1E,GAAK4b,EAASlX,EAAG1E,GAAMoL,EAAEwQ,EAASlX,EAAG1E,IAAMoL,EAAEuQ,EAAQjX,EAAG1E,IAAO,IAC5F,MAELkE,KAAK,IAAK,GACVA,KAAK,IAAK,GACVA,KAAK,QAASiX,GACdjX,KAAK,SAAU,SAASQ,EAAG1E,GACxB,GAAI6b,GAAOF,EAAQjX,EAAG1E,GAClB8b,EAAQF,EAASlX,EAAG1E,EACxB,OAAO6b,GAAOC,EAAQ1Q,EAAE0Q,GAAS1Q,EAAEyQ,GAAQzQ,EAAEyQ,GAAQzQ,EAAE0Q,OAI5Dhc,EA1JX,GAIM2D,GAeAmS,EACAI,EACAF,EACAa,EAtBFtU,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,KACRC,EAAS,KACTmD,EAAKd,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UAErBtD,EAAI3G,GAAGmH,MAAMC,SACbsG,EAAI1N,GAAGmH,MAAMC,SACb+Q,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9BuQ,EAAU,SAASjX,GAAK,MAAOA,GAAEmX,MACjCD,EAAW,SAASlX,GAAK,MAAOA,GAAEoX,OAClCP,EAAU,SAAS7W,GAAK,MAAOA,GAAEqX,MACjCV,EAAS,SAAS3W,GAAK,MAAOA,GAAEsX,KAChCjC,KACAuB,KACAF,GAAc,EACdK,GAAW,EACXxS,EAAQhM,EAAGG,MAAM6O,eACjBgQ,GAAc,EAKdxe,EAAWC,GAAGD,SAAS,cAAe,cAAe,YAAa,aAAc,eAAgB,kBAAmB,mBAAoB,kBAAmB,mBAiMhK,OAzDAqC,GAAMoc,eAAiB,SAASC,EAAYC,GACxCtc,EAAMuc,kBACN5Y,EAAUC,OAAO,iCAAmCyY,GAC/ClV,QAAQ,QAASmV,IAI1Btc,EAAMuc,gBAAkB,WACpB5Y,EAAUC,OAAO,qCACZuD,QAAQ,SAAS,IAQ1BnH,EAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAWsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IAClErB,QAAWqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACpEhC,QAAWgI,IAAK,WAAW,MAAO5G,IAAK6G,IAAK,SAASjG,GAAGZ,EAAEY,IAC1D0S,QAAW1M,IAAK,WAAW,MAAOG,IAAKF,IAAK,SAASjG,GAAGmG,EAAEnG,IAC1D2Q,SAAW3K,IAAK,WAAW,MAAO2K,IAAW1K,IAAK,SAASjG,GAAG2Q,EAAQ3Q,IACtE+Q,SAAW/K,IAAK,WAAW,MAAO+K,IAAW9K,IAAK,SAASjG,GAAG+Q,EAAQ/Q,IACtE6Q,QAAW7K,IAAK,WAAW,MAAO6K,IAAU5K,IAAK,SAASjG,GAAG6Q,EAAO7Q,IACpE0R,QAAW1L,IAAK,WAAW,MAAO0L,IAAUzL,IAAK,SAASjG,GAAG0R,EAAO1R,IACpE8U,QAAW9O,IAAK,WAAW,MAAO8O,IAAU7O,IAAK,SAASjG,GAAG8U,EAAO9U,IACpEqW,QAAWrQ,IAAK,WAAW,MAAOqQ,IAAUpQ,IAAK,SAASjG,GAAGqW,EAAOrW,IACpEmW,SAAWnQ,IAAK,WAAW,MAAOmQ,IAAWlQ,IAAK,SAASjG,GAAGmW,EAAQnW,IACtEwW,UAAWxQ,IAAK,WAAW,MAAOwQ,IAAYvQ,IAAK,SAASjG,GAAGwW,EAASxW,IACxE8B,IAAWkE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,GAAG8B,EAAG9B,IAC5DgX,aAAchR,IAAK,WAAW,MAAOgR,IAAe/Q,IAAK,SAASjG,GAAGgX,EAAYhX,IAEjFZ,GAAQ4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAK5Q,IAC7DmG,GAAQH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAAGyS,EAAKzS,IAC7D4W,MAAQ5Q,IAAK,WAAW,MAAO0Q,MAAazQ,IAAK,SAASjG,GAAG0W,EAAQ1W,IACrE6W,OAAQ7Q,IAAK,WAAW,MAAO2Q,MAAc1Q,IAAK,SAASjG,GAAG2W,EAAS3W,IACvE8W,MAAQ9Q,IAAK,WAAW,MAAOsQ,IAAWrQ,IAAK,SAASjG,GAAGsW,EAAQtW,IACnE+W,KAAQ/Q,IAAK,WAAW,MAAOoQ,IAAUnQ,IAAK,SAASjG,GAAGoW,EAAOpW,IAGjE5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAqB1B,QAAZoE,EAAE1C,IAAsB0C,EAAE1C,IAASF,EAAOE,IAC1DF,EAAOqQ,MAAqB7R,QAAZoE,EAAEyN,MAAsBzN,EAAEyN,MAASrQ,EAAOqQ,MAC1DrQ,EAAOoQ,OAAqB5R,QAAZoE,EAAEwN,OAAsBxN,EAAEwN,OAASpQ,EAAOoQ,OAC1DpQ,EAAOC,KAAqBzB,QAAZoE,EAAE3C,KAAsB2C,EAAE3C,KAASD,EAAOC,OAE9D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,OAIlChI,EAAGG,MAAMiO,YAAYvL,GACdA,GAGX7C,EAAGI,OAAOif,oBAAsB,WAC5B,YAqFA,SAASxc,GAAMoB,GAmbX,MAlbAgN,GAAYW,QACZX,EAAY7Q,OAAOkf,GACfzE,GAAW5J,EAAY7Q,OAAO0a,GAC9BC,GAAW9J,EAAY7Q,OAAO4a,GAClC/W,EAAUC,KAAK,SAASC,GA0CpB,QAASob,GAAU9X,EAAE1E,GACjBtC,GAAGgG,OAAO5D,EAAM2D,WACXuD,MAAM,SAAU,aAGzB,QAASyV,GAAS/X,EAAE1E,GAChB2F,EAAMtB,EAAI3G,GAAGmE,MAAMwC,EACnBsB,EAAM3F,EAAIiG,KAAKuP,MAAMkH,EAAGxZ,OAAOyC,EAAMtB,IACrCsY,IAGJ,QAASC,GAAQlY,EAAE1E,GACftC,GAAGgG,OAAO5D,EAAM2D,WACXuD,MAAM,SAAU,QAGrBuG,EAAM5H,MAAQA,EAAM3F,EACpBvC,EAASof,YAAYtP,GA4OzB,QAASoP,KACLG,GACK1b,MAAMuE,GAIX,IAAIoX,GAAcjd,EAAMiF,UACxBjF,GAAMiF,SAAS,GACfjF,EAAM+P,SACN/P,EAAMiF,SAASgY,GA/SnB,GAAItZ,GAAY/F,GAAGgG,OAAO3F,KAC1Bd,GAAGG,MAAMiV,QAAQ5O,GACjBA,EAAUwD,QAAQ,YAAcF,GAAI,EACpC,IAAIiW,GAAOjf,KAEPyE,EAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAkBlE,IAhBAvC,EAAM+P,OAAS,WACM,IAAb9K,EACAtB,EAAUrF,KAAK0B,GAEf2D,EAAU4G,aAAatF,SAASA,GAAU3G,KAAK0B,IAEvDA,EAAM2D,UAAY1F,KAElBwP,EACKqC,OAAOqN,EAAY7b,GAAOtB,EAAM+P,QAChCH,OAAOwN,EAAY9b,IACnByO,SAGLtC,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,YAE9C0E,EAAc,CACf,GAAIhU,EACJgU,KACA,KAAKhU,IAAOoE,GACJA,EAAMpE,YAAgBjL,OACtBif,EAAahU,GAAOoE,EAAMpE,GAAKhL,MAAM,GAErCgf,EAAahU,GAAOoE,EAAMpE,GAItC,GAAIiU,GAAY1f,GAAG2f,SAASC,OACvB3e,GAAG,YAAa6d,GAChB7d,GAAG,OAAQ8d,GACX9d,GAAG,UAAWie,EAwBnB,MAAKxb,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAE9E,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CASX,IAPI2D,EAAUK,UAAU,cAAcc,SAItCP,EAAIkY,EAAMtZ,SACVmI,EAAImR,EAAM5E,SAEL4F,EAsBDhB,EAAMvG,QAAQ,UAtBH,CACX,GAAIwH,GAAgBpc,EACfoQ,OAAO,SAASzI,GAAU,OAAQA,EAAO0P,WACzCtI,IAAI,SAASpH,EAAO/I,GACjB,GAAIyd,GAAgB/f,GAAGmc,OAAO9Q,EAAO5D,OAAQoX,EAAMnR,IAKnD,OAFIqS,GAAc,IAAM,MAAKA,EAAc,IAAM,OAGxCA,EAAc,GAAKA,EAAc,KAAO,EAAIA,EAAc,KAC1DA,EAAc,GAAKA,EAAc,KAAO,EAAIA,EAAc,OAIvEC,GACAhgB,GAAGqI,IAAIyX,EAAe,SAAS9Y,GAAK,MAAOA,GAAE,KAC7ChH,GAAGkI,IAAI4X,EAAe,SAAS9Y,GAAK,MAAOA,GAAE,KAGjD6X,GAAMvG,QAAQ0H,GAKlBhB,EAAGrT,QAAQ,EAAGjI,EAAK,GAAG+D,OAAO/F,OAAS,IACjCkK,OAAO,EAAG9G,IACV2V,OAAM,EAEX,IAAI/W,GAAOuc,EAAShY,EAAM3F,EAAGoB,GAGzBwc,EAA2B,EAA4B,OAAS,MAChE/Z,EAAOJ,EAAUK,UAAU,+BAA+B1C,MAAMA,IAChEgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,kCAAkCD,OAAO,KACzF0P,EAAI9P,EAAKH,OAAO,IA6BpB,IA3BA0U,EAAOnU,OAAO,KAAKC,KAAK,QAAS,kBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBAAgB8C,MAAM,iBAAiB,QACxEoR,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBAAgB8C,MAAM,iBAAiB4W,GACxExF,EAAOnU,OAAO,KAAKC,KAAK,QAAS,mBAAmB8C,MAAM,iBAAiB,QAC3EoR,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,mBAG7B2Z,IACAC,EAAOna,MAAMnB,GAEbmR,EAAEjQ,OAAO,kBACJ8U,MAAMpX,GACNhD,KAAK0f,GAELzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SACpBnB,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IAGlEsR,EAAEjQ,OAAO,kBACJQ,KAAK,YAAa,gBAAmB7B,EAAOE,IAAM,MAIvDwb,EAAc,CACd,GAAIC,KACE7U,IAAK,kBAAmBsP,UAAW8E,GAGzCU,GACKta,MAAM,KACNsF,OAAO,OAAQ,OAAQ,SACvBiV,YAAW,GACX7b,QAAQE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,KAGhDqR,EAAEjQ,OAAO,oBACJ8U,MAAMwF,GACN9Z,KAAK,YAAa,gBAAmB7B,EAAOE,IAAM,KAClDnE,KAAK6f,GAGdpa,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEnE+V,GACA3E,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,aAAe1B,EAAiB,MAI3D,IAAI2b,GAAe/c,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAEyZ,cAEtDta,GAAKH,OAAO,iBAAiBkB,SACzBuZ,EAAa/e,QACbyE,EAAKI,OAAO,QAAQC,KAAK,QAAS,gBAC7BA,KAAK,IAAK1B,EAAiB,GAC3B0B,KAAK,IAAK,UACV8C,MAAM,cAAe,OACrB0G,KAAKyQ,EAAahO,IAAI,SAASzL,GAAK,MAAOA,GAAEyE,MAAOqK,KAAK,MAAQ,sDAItE4K,IACAC,EACK1a,MAAMnB,GACNoB,OAAOnB,GACPJ,QAAQC,KAAKD,EAAOC,KAAKC,IAAIF,EAAOE,MACpC4B,aAAaV,GACbR,OAAOoB,GACZR,EAAKH,OAAO,mBAAmBtF,KAAKigB,IAGxCjG,EAAO1U,OAAO,kBACTO,OAAO,QAEZ0P,EAAEjQ,OAAO,uBACJQ,KAAK,QAAS1B,GACd0B,KAAK,SAAUzB,GAEpB8Z,EAEKnR,EAAE,SAAS1G,GAAK,MAAOA,GAAE4Z,QAAQlT,IACjCzH,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GACvB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,WAAarX,EAAKpB,GAAGme,eAEnE,IAAII,GAAY5K,EAAEjQ,OAAO,iBACpB8U,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAASA,EAAE+T,WAAa/T,EAAEyZ,eAE/DI,GAAUngB,KAAKme,GAGfnb,EAAKoF,QAAQ,SAAS9B,EAAE1E,GACpB0E,EAAE8Z,YAAcxe,GAGpB,IAAIye,GAAcrd,EAAKoQ,OAAO,SAAS9M,GACnC,OAAQA,EAAE+T,YAAciG,EAAQha,KAGhCia,EAAWhL,EAAEjQ,OAAO,oBAAoBI,UAAU,QACjD1C,KAAKqd,EAAa,SAAS/Z,GAAK,MAAOA,GAAEyE,MAE1CyV,GAAc,SAASla,GAEvB,GAAIma,GAAOzT,EAAEsT,EAAQha,GACrB,OAAW,GAAPma,EAAiB,EACjBA,EAAOpc,EAAwBA,EAC5Boc,EAGXF,GAAS3a,QACJC,OAAO,QACP+C,MAAM,eAAe,GACrBA,MAAM,mBAAmB,SACzBA,MAAM,SAAS,SAAUtC,EAAE1E,GACxB,MAAOuc,GAAMtT,QAAQvE,EAAEA,EAAE8Z,eAE5Bta,KAAK,KAAK,GACVA,KAAK,KAAK1B,GACV0B,KAAK,KAAM0a,IACX1a,KAAK,KAAM0a,IAEhBD,EACK3X,MAAM,iBAAiB,SAAStC,GAE7B,GAAIma,GAAOzT,EAAEsT,EAAQha,GACrB,OAAW,GAAPma,GAAYA,EAAOpc,EAAwB,EACxC,IAEVyB,KAAK,KAAK,GACVA,KAAK,KAAK1B,GACV0B,KAAK,KAAM0a,IACX1a,KAAK,KAAM0a,IAEhBD,EAASha,OAAOC,QAGhB,IAAIkY,IAAYyB,EAAUza,UAAU,iBAC/B1C,MAAMuE,GACXmX,IAAU9Y,QAAQC,OAAO,QAAQC,KAAK,QAAS,gBAC1CA,KAAK,QAAS,GACdA,KAAK,IAAK,IACVA,KAAK,OAAQ,OACbA,KAAK,eAAgB,IACrB8C,MAAM,iBAAiB,OACvB5I,KAAKgf,GAEVN,GACK5Y,KAAK,YAAa,SAASQ,GAAK,MAAO,aAAegY,EAAGhY,EAAE1E,GAAK,QAChEkE,KAAK,SAAUzB,GAGhBqV,IACAC,EACKlT,MAAMR,GACNya,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,GAAIpB,IAC/CsX,UAAUjW,EAAiB,GAEhCkR,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,eAAiBkH,EAAE9B,QAAQ,GAAK,KACvDqK,EAAEjQ,OAAO,iBACJtF,KAAK2Z,IAGVC,IACAC,EACKpT,MAAMuG,GACN0T,OAAQ7hB,EAAGG,MAAMoT,WAAW/N,EAAgB,GAAIrB,IAChDsX,UAAWlW,EAAgB,GAEhCmR,EAAEjQ,OAAO,iBACJtF,KAAK6Z,IAmBdtE,EAAEjQ,OAAO,uBACJ/E,GAAG,QAAS,WACTgH,EAAMtB,EAAI3G,GAAG6D,MAAMxD,MAAM,GACzB4H,EAAM3F,EAAIiG,KAAKuP,MAAMkH,EAAGxZ,OAAOyC,EAAMtB,IAGrCkJ,EAAM5H,MAAQA,EAAM3F,EACpBvC,EAASof,YAAYtP,GAErBoP,MAGRJ,EAAM9e,SAASkB,GAAG,eAAgB,SAASC,GACvC+G,EAAM3F,EAAIpB,EAAEud,WACZxW,EAAMtB,EAAIqY,EAAG/W,EAAM3F,GAGnBuN,EAAM5H,MAAQA,EAAM3F,EACpBvC,EAASof,YAAYtP,GAErBoP,MAGJsB,EAASxgB,SAASkB,GAAG,cAAe,SAAS+F,EAAE1E,GAC3C0E,EAAE+T,UAAY/T,EAAE+T,SAChB8E,GAAY7Y,EAAE+T,SAEdlL,EAAMgQ,SAAWA,EACjB9f,EAASof,YAAYtP,GACrBzN,EAAM+P,WAGViO,EAAOrgB,SAASkB,GAAG,cAAe,SAASogB,GACvC,IAAK,GAAI5V,KAAO4V,GACZxR,EAAMpE,GAAO4V,EAAS5V,EAC1B1L,GAASof,YAAYtP,GACrBzN,EAAM+P,WAGVwO,EAAiB5gB,SAASkB,GAAG,mBAAoB,SAASC,GACtD2d,EAAMF,iBACN,IAAI2C,GAAa7C,EAAY8C,EAAgBC,IAsB7C,IApBA9d,EACKoQ,OAAO,SAASzI,EAAQ/I,GAErB,MADA+I,GAAOyV,YAAcxe,GACb+I,EAAO0P,WAElBjS,QAAQ,SAASuC,EAAO/I,GACrBmc,EAAalf,EAAGiI,kBAAkB6D,EAAO5D,OAAQvG,EAAEoE,YAAalD,EAAMuE,KACtEkY,EAAML,eAAelc,EAAGmc,GAAY,EACpC,IAAIhR,GAAQpC,EAAO5D,OAAOgX,EACL,oBAAVhR,KACgB,mBAAhB6T,KAA6BA,EAAc7T,GACxB,mBAAnB8T,KAAgCA,EAAiBnf,EAAMmD,SAASnD,EAAMuE,IAAI8G,EAAMgR,KAC3F+C,EAAQze,MACJ0I,IAAKJ,EAAOI,IACZR,MAAO7I,EAAMsL,IAAID,EAAOgR,GACxBlT,MAAOA,EAAMF,EAAOA,EAAOyV,kBAKnCU,EAAQ9f,OAAS,EAAG,CACpB,GAAI+f,GAASrf,EAAM6X,SAASzU,OAAOtE,EAAE6C,QACjC2d,EAAenZ,KAAKC,IAAIpG,EAAM6X,SAAStO,SAAS,GAAKvJ,EAAM6X,SAAStO,SAAS,IAC7EjD,EAAY,IAAOgZ,EACnB7Y,EAAmBtJ,EAAGkJ,kBAAkB+Y,EAAQ/O,IAAI,SAASzL,GAAG,MAAOA,GAAEiE,QAAQwW,EAAO/Y,EACnE,QAArBG,IACA2Y,EAAQ3Y,GAAkByC,WAAY,GAG9C,GAAIqW,GAAStH,EAAM/D,aAAalU,EAAMuE,IAAI2a,EAAY7C,GAAaA,EACnEkC,GAAiBlhB,QACZwJ,eAAeqW,EAAK/P,YACpB7E,eAAe,SAAS1D,EAAE1E,GACvB,MAAOiY,GAAMjE,aAAatP,KAE7BtD,MAEGuH,MAAO0W,EACPtW,OAAQmW,MAIhBb,EAAiBvb,gBAAgBmc,KAGrCZ,EAAiB5gB,SAASkB,GAAG,kBAAkB,SAASC,GACpD2d,EAAMF,oBAIV5e,EAASkB,GAAG,cAAe,SAASC,GACN,mBAAfA,GAAE6Z,WACTrX,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,SAAW7Z,EAAE6Z,SAASzY,KAGjCuN,EAAMkL,SAAW7Z,EAAE6Z,UAGA,mBAAZ7Z,GAAE+G,QACTA,EAAM3F,EAAIpB,EAAE+G,MACZA,EAAMtB,EAAIqY,EAAG/W,EAAM3F,GAEnBuN,EAAM5H,MAAQ/G,EAAE+G,MAEhBmX,GACK1b,MAAMuE,KAGW,mBAAf/G,GAAE2e,WACTA,EAAW3e,EAAE2e,UAGjBzd,EAAM+P,aAKd3B,EAAYS,UAAU,iCAEf7O,EA2BX,QAAS6d,GAAS2B,EAAKle,GAEnB,MADKme,KAAiBA,EAAkBhD,EAAMnR,KACvChK,EAAK+O,IAAI,SAAS5L,EAAMvE,GAC3B,IAAKuE,EAAKY,OACN,MAAOZ,EAEX,IAAIib,GAAajb,EAAKY,OAAOma,EAC7B,IAAkB,MAAdE,EACA,MAAOjb,EAEX,IAAIiB,GAAI+Z,EAAgBC,EAAYF,EAGpC,QAAS,IAAL9Z,IAAaia,GAGblb,EAAK4Z,cAAe,EACb5Z,IAGXA,EAAK4Z,cAAe,EAEpB5Z,EAAKY,OAASZ,EAAKY,OAAOgL,IAAI,SAAShF,EAAOgR,GAE1C,MADAhR,GAAMmT,SAAWlT,GAAMmU,EAAgBpU,EAAOgR,GAAc3W,IAAM,EAAIA,IAC/D2F,IAGJ5G,KAxjBf,GAoBMF,GACA+G,EArBFmR,EAAQtf,EAAGI,OAAOkH,OAChBwT,EAAQ9a,EAAGI,OAAOqW,OAClBuE,EAAQhb,EAAGI,OAAOqW,OAClBoK,EAAS7gB,EAAGI,OAAOygB,SACnBG,EAAWhhB,EAAGI,OAAOygB,SACrBO,EAAmBphB,EAAG+D,uBACtB7D,EAAUF,EAAGI,OAAOF,UAGtBkF,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9C2G,EAAQhM,EAAGG,MAAM6O,eACjBtI,EAAQ,KACRC,EAAS,KACTia,GAAa,EACb/F,GAAY,EACZE,GAAY,EACZM,GAAkB,EAClByF,GAAe,EACfK,GAA0B,EAC1Bb,GAAW,EAGXxW,EAAKwV,EAAMxV,KACXwG,EAAQtQ,EAAGG,MAAMmQ,QACjB4P,EAAe,KACfxK,EAAS,KACT+L,EAAU,SAASha,GAAK,MAAOA,GAAEga,SACjCjhB,EAAWC,GAAGD,SAAS,cAAe,cAAe,aAErDsH,EAAW,IACX0a,GAAe,CAGrBlS,GAAM5H,MAAQ,EACd4H,EAAMgQ,SAAWA,EAEjBxF,EAAMlE,OAAO,UAAUY,YAAY,GACnCwD,EAAMpE,OAAO,EAAoB,QAAU,QAE3C1W,EAAQiL,eAAe,SAAS1D,EAAG1E,GAC/B,MAAOiY,GAAMjE,aAAatP,EAAG1E,KAC9BqI,gBAAgB,SAAS3D,EAAG1E,GAC3B,MAAO+X,GAAM/D,aAAatP,EAAG1E,KAGjCie,EAASyB,aAAY,EAMrB,IAAIhD,GAAKhf,GAAGmH,MAAMC,SACZa,GAAS3F,EAAG,EAAGqE,EAAG,GAClB6J,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,GAG/CmY,EAAc,SAAS9b,GACvB,MAAO,YACH,OACIzB,OAAQyB,EAAK+O,IAAI,SAASzL,GAAK,OAAQA,EAAE+T,WACzC9S,MAAOA,EAAM3F,EACbud,SAAUA,KAKlBN,EAAc,SAAS7b,GACvB,MAAO,UAASmM,GACQ1M,SAAhB0M,EAAM5H,QACNA,EAAM3F,EAAIuN,EAAM5H,OACG9E,SAAnB0M,EAAMgQ,WACNA,EAAWhQ,EAAMgQ,UACA1c,SAAjB0M,EAAM5N,QACNyB,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,UAAYlL,EAAM5N,OAAOK,MA+bhDuc,GAAM9e,SAASkB,GAAG,2BAA4B,SAASia,GACnD,GAAIzN,IACA9G,EAAGvE,EAAMuE,IAAIuU,EAAIzN,OACjBC,EAAGtL,EAAMsL,IAAIwN,EAAIzN,OACjBlC,MAAO2P,EAAIzN,MAAMlC,MAErB2P,GAAIzN,MAAQA,EACZhO,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7BwZ,EAAM9e,SAASkB,GAAG,0BAA2B,SAASia,GAClDzb,EAAQ4F,QAAO,IAOnB,IAAIwc,GAAkB,IAkGtB,OA5DAzf,GAAMrC,SAAWA,EACjBqC,EAAMyc,MAAQA,EACdzc,EAAMge,OAASA,EACfhe,EAAMme,SAAWA,EACjBne,EAAMiY,MAAQA,EACdjY,EAAMmY,MAAQA,EACdnY,EAAMue,iBAAmBA,EACzBve,EAAMyN,MAAQA,EACdzN,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtEsY,UAAetS,IAAK,WAAW,MAAOsS,IAAYrS,IAAK,SAASjG,GAAGsY,EAAStY,IAC5E8Y,cAAmB9S,IAAK,WAAW,MAAO8S,IAAgB7S,IAAK,SAASjG,GAAG8Y,EAAa9Y,IACxF4Y,YAAa5S,IAAK,WAAW,MAAO4S,IAAc3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IAC9EyZ,SAAUzT,IAAK,WAAW,MAAOyT,IAAWxT,IAAK,SAASjG,GAAGyZ,EAAQzZ,IACrEkY,cAAkBlS,IAAK,WAAW,MAAOkS,IAAgBjS,IAAK,SAASjG,GAAGkY,EAAalY,IACvF0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IACrE6S,WAAe7M,IAAK,WAAW,MAAO6M,IAAa5M,IAAK,SAASjG,GAAG6S,EAAU7S,IAC9E+S,WAAe/M,IAAK,WAAW,MAAO+M,IAAa9M,IAAK,SAASjG,GAAG+S,EAAU/S,IAC9Ewa,cAAkBxU,IAAK,WAAW,MAAOwU,IAAgBvU,IAAK,SAASjG,GAAGwa,EAAaxa,IAGvF5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1B6Y,EAAO7U,MAAMA,KAEjBmV,yBAA0BnT,IAAK,WAAW,MAAOmT,IAA2BlT,IAAK,SAASjG,GACtFmZ,EAA0BnZ,EACtBA,KAAM,IACNnF,EAAMmc,aAAY,GAClBnc,EAAM6f,YAAW,MAGzBrH,iBAAkBrN,IAAK,WAAW,MAAOqN,IAAmBpN,IAAK,SAASjG,GACtEqT,EAAkBrT,EAClBgT,EAAMpE,OAAQ,EAAM,QAAU,UAElC9O,UAAckG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GAC3DF,EAAWE,EACXsX,EAAMxX,SAASA,GACfgT,EAAMhT,SAASA,GACfkT,EAAMlT,SAASA,GACfmJ,EAAYW,MAAM9J,OAI1B9H,EAAGG,MAAM6U,eAAenS,EAAOyc,GAC/Btf,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAOuiB,YAAc,WACpB,YAmCA,SAAS9f,GAAMoB,GAsKX,MArKAgN,GAAYW,QACZ3N,EAAUC,KAAK,SAASC,GACpB,GAAIoB,GAAiBmB,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAC9CjQ,EAAkBmB,EAASvB,EAAOE,IAAMF,EAAOoQ,MAEnDhP,GAAY/F,GAAGgG,OAAO3F,MACtBd,EAAGG,MAAMiV,QAAQ5O,GAGjBrC,EAAKoF,QAAQ,SAASuC,EAAQ/I,GAC1B+I,EAAO5D,OAAOqB,QAAQ,SAAS2E,GAC3BA,EAAMpC,OAAS/I,KAMvB,IAAI6f,GAAcjK,GAAWI,KACzB5U,EAAK+O,IAAI,SAASzL,GACd,MAAOA,GAAES,OAAOgL,IAAI,SAASzL,EAAE1E,GAC3B,OAASqE,EAAGwR,EAAKnR,EAAE1E,GAAIoL,EAAGsM,EAAKhT,EAAE1E,GAAI6W,GAAInS,EAAEmS,OAIvDxS,GAAKgF,OAAOuM,GAAWlY,GAAGoc,MAAM+F,GAAY1P,IAAI,SAASzL,GAAK,MAAOA,GAAEL,KAClEqR,WAAWI,IAAW,EAAGtT,GAAiB,IAC/C4I,EAAK/B,OAAO2M,GAAWtY,GAAGmc,OAAOnc,GAAGoc,MAAM+F,GAAY1P,IAAI,SAASzL,GAAK,MAAOA,GAAE0G,IAAK1M,OAAO4c,KAGzFwE,EAAY1U,EAAE9B,MAAMqN,IAAWlU,GAAmB2I,EAAE/B,SAAS,GAAK,EAAI,GAAK,GAAI+B,EAAE/B,SAAS,GAAK,EAAI,GAAK,IACvG+B,EAAE9B,MAAMqN,IAAWlU,EAAiB,IAGzCmU,EAAKA,GAAMvS,EACXwS,EAAKA,GAAMzL,EAAEqK,OAAOnM,OAAO8B,EAAE,GAAGA,EAAE,IAGlC,IAAIvH,GAAOJ,EAAUK,UAAU,4BAA4B1C,MAAMA,IAC7D2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,+BACnDkU,EAASrU,EAAUE,OAAO,IACtBJ,GAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,aACjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAGvE,IAAIwd,GAASlc,EAAKH,OAAO,cAAcI,UAAU,aAC5C1C,KAAK,SAASsD,GAAK,MAAOA,IAAK,SAASA,GAAK,MAAOA,GAAEyE,KAC3D4W,GAAO/b,QAAQC,OAAO,KACjB+C,MAAM,iBAAkB,MACxBA,MAAM,eAAgB,MAC3B+Y,EAAOpb,OACFsJ,gBAAgBC,EAAa,4BAC7BlH,MAAM,iBAAkB,MACxBA,MAAM,eAAgB,MACtBpC,SACLmb,EACK7b,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO,sBAAwBA,IAC7DiH,QAAQ,QAAS,SAASvC,GAAK,MAAOA,GAAEuS,QAC7C8I,EACK9R,gBAAgBC,EAAa,uBAC7BlH,MAAM,iBAAkB,GACxBA,MAAM,eAAgB,IAE3B,IAAIgZ,GAAOD,EAAOjc,UAAU,YACvB1C,KAAK,SAASsD,GAAK,MAAOA,GAAES,QACjC6a,GAAKrb,OAAOC,QAEZ,IAAIqb,GAAYD,EAAKhc,QAAQC,OAAO,KAC/BC,KAAK,YAAa,SAASQ,EAAE1E,EAAEgX,GAC5B,MAAO,cAAgB3S,EAAEwR,EAAKnR,EAAE1E,IAAsB,IAAhBqE,EAAEkQ,aAAsB,KAAOnJ,EAAE,GAAK,MAE/EzM,GAAG,YAAa,SAAS+F,EAAE1E,GACxBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASyZ,kBACL9V,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,WAAY,SAAS+F,EAAE1E,GACvBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASoF,iBACLzB,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,YAAa,SAAS+F,EAAE1E,GACxBvC,EAAS0F,kBACL/B,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,QAAS,SAAS+F,EAAE1E,GACpBvC,EAAS6F,cACLlC,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,UAEjCtJ,GAAGmE,MAAMqe,oBAEZvhB,GAAG,WAAY,SAAS+F,EAAE1E,GACvBvC,EAAS0iB,iBACL/e,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,UAEjCtJ,GAAGmE,MAAMqe,mBAGjBD,GAAUhc,OAAO,QACZC,KAAK,SAAU,GACfA,KAAK,QAAyB,GAAhBG,EAAEkQ,YAAmBnT,EAAKhC,QAEzC0gB,GACAG,EAAUhc,OAAO,QACZC,KAAK,cAAe,UAGzB8b,EAAKtc,OAAO,QACPgK,KAAK,SAAShJ,EAAE1E,GAAK,MAAOogB,GAAY1I,EAAKhT,EAAE1E,MAC/CiO,gBAAgBC,EAAa,0BAC7BhK,KAAK,IAAqB,GAAhBG,EAAEkQ,YAAmB,GAC/BrQ,KAAK,IAAK,SAASQ,EAAE1E,GAAK,MAAO0X,GAAKhT,EAAE1E,GAAK,EAAIoL,EAAEsM,EAAKhT,EAAE1E,IAAMoL,EAAE,GAAK,GAAK,MAIjF4U,EAAKlc,UAAU,QAAQc,SAG3Bob,EACK9b,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO0X,GAAKhT,EAAE1E,GAAK,EAAI,kBAAoB,oBACzEgH,MAAM,OAAQ,SAAStC,EAAE1E,GAAK,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAE1E,KACxDgH,MAAM,SAAU,SAAStC,EAAE1E,GAAK,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAE1E,KAC1D0D,OAAO,QACPQ,KAAK,QAASmc,GACdpS,gBAAgBC,EAAa,0BAC7BhK,KAAK,QAAyB,GAAhBG,EAAEkQ,YAAmBnT,EAAKhC,QAC7C4gB,EAAK/R,gBAAgBC,EAAa,qBAE7BhK,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,GAAIsC,GAAO+B,EAAEwR,EAAKnR,EAAE1E,IAAsB,IAAhBqE,EAAEkQ,YACxBhS,EAAMmV,EAAKhT,EAAE1E,GAAK,EACdoL,EAAE,GACEA,EAAE,GAAKA,EAAEsM,EAAKhT,EAAE1E,IAAM,EAC1BoL,EAAE,GAAK,EACPA,EAAEsM,EAAKhT,EAAE1E,GAEjB,OAAO,aAAesC,EAAO,KAAOC,EAAM,MAE7CmB,OAAO,QACPQ,KAAK,SAAU,SAASQ,EAAE1E,GACvB,MAAQiG,MAAKL,IAAIK,KAAKC,IAAIkF,EAAEsM,EAAKhT,EAAE1E,IAAMoL,EAAG4K,GAAWA,EAAQ,IAAO,KAAO,KAKrFY,EAAKvS,EAAEoR,OACPoB,EAAKzL,EAAEqK,SAIXvH,EAAYS,UAAU,yBACf7O,EAnMX,GAIM2D,GASAmS,EACAI,EACAF,EACAa,EAUFC,EAAIC,EA1BJxU,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACRC,EAAS,IACTmD,EAAKd,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UAErBtD,EAAI3G,GAAGmH,MAAMuH,UACbhB,EAAI1N,GAAGmH,MAAMC,SACb+Q,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9BkQ,GAAU,GACVrS,EAAQhM,EAAGG,MAAM6O,eACjB6T,GAAa,EACbM,EAAc1iB,GAAGib,OAAO,QAKxBlb,EAAWC,GAAGD,SAAS,aAAc,eAAgB,kBAAmB,mBAAoB,kBAAmB,mBAAoB,aACnI4iB,EAAY,cACZtb,EAAW,IAQbmJ,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,EAsNjD,OAvCAjF,GAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAUsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACjErB,QAAUqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACnEqW,QAAUrQ,IAAK,WAAW,MAAOqQ,IAAUpQ,IAAK,SAASjG,GAAGqW,EAAOrW,IACnE6a,YAAa7U,IAAK,WAAW,MAAO6U,IAAc5U,IAAK,SAASjG,GAAG6a,EAAW7a,IAC9EZ,GAAU4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAK5Q,IAC/DmG,GAAUH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAAGyS,EAAKzS,IAC/DhC,QAAUgI,IAAK,WAAW,MAAO5G,IAAK6G,IAAK,SAASjG,GAAGZ,EAAEY,IACzD0S,QAAU1M,IAAK,WAAW,MAAOG,IAAKF,IAAK,SAASjG,GAAGmG,EAAEnG,IACzD2Q,SAAU3K,IAAK,WAAW,MAAO2K,IAAW1K,IAAK,SAASjG,GAAG2Q,EAAQ3Q,IACrE+Q,SAAU/K,IAAK,WAAW,MAAO+K,IAAW9K,IAAK,SAASjG,GAAG+Q,EAAQ/Q,IACrE6Q,QAAU7K,IAAK,WAAW,MAAO6K,IAAU5K,IAAK,SAASjG,GAAG6Q,EAAO7Q,IACnE0R,QAAU1L,IAAK,WAAW,MAAO0L,IAAUzL,IAAK,SAASjG,GAAG0R,EAAO1R,IACnEmb,aAAiBnV,IAAK,WAAW,MAAOmV,IAAelV,IAAK,SAASjG,GAAGmb,EAAYnb,IACpF8B,IAAckE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,GAAG8B,EAAG9B,IAC/Dob,WAAYpV,IAAK,WAAW,MAAOoV,IAAanV,IAAK,SAASjG,GAAGob,EAAUpb,IAG3E5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,KAE9BF,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,OAI1B9H,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAOijB,iBAAmB,WACzB,YAuDA,SAASxgB,GAAMoB,GAyHX,MAxHAgN,GAAYW,QACZX,EAAY7Q,OAAOkjB,GACfzI,GAAW5J,EAAY7Q,OAAO0a,GAC9BC,GAAW9J,EAAY7Q,OAAO4a,GAElC/W,EAAUC,KAAK,SAASC,GACpB,GAAIqC,GAAY/F,GAAGgG,OAAO3F,KAE1Bd,GAAGG,MAAMiV,QAAQ5O,EACjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EASlE,IAPAvC,EAAM+P,OAAS,WACXpS,EAASya,eACTzU,EAAU4G,aAAatF,SAASA,GAAU3G,KAAK0B,IAEnDA,EAAM2D,UAAY1F,OAGbqD,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAE9E,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,SAItCP,EAAIkc,EAAYtd,SAChBmI,EAAImV,EAAY5I,SAASQ,OAAM,EAG/B,IAAItU,GAAOJ,EAAUK,UAAU,oCAAoC1C,MAAMA,IACrEgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,uCAAuCD,OAAO,KAC9FoU,EAAYD,EAAOnU,OAAO,QAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBAC5BD,OAAO,KAAKC,KAAK,QAAS,eAC1BD,OAAO,QAEZmU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,eAEjCyP,EAAEzP,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEhE+V,GACA3E,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,aAAe1B,EAAiB,OAI3D+d,EACK5c,MAAMnB,GACNoB,OAAOnB,EAEZ,IAAI8V,GAAW5E,EAAEjQ,OAAO,gBACnB8U,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAe/C,IAbAF,EAASlO,aAAajM,KAAKmiB,GAG3BlI,EAAUpU,OAAO,YACZC,KAAK,KAAM,mBAAqBqc,EAAYxZ,MAC5C9C,OAAO,QAEZ0P,EAAEjQ,OAAO,oBAAsB6c,EAAYxZ,KAAO,SAC7C7C,KAAK,QAASG,EAAEkQ,aAAea,EAAgB,EAAI,IACnDlR,KAAK,SAAU,IACfA,KAAK,KAAMG,EAAEkQ,aAAea,EAAgB,EAAI,IAGjD0C,EAAW,CACXC,EACKlT,MAAMR,GACNya,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAChDsX,UAAUjW,EAAiB,GAEhCkR,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,gBAAkBkH,EAAE9B,QAAQ,IAAOiX,EAAYT,cAAgB1U,EAAE/B,SAAS,GAAK,EAAK,GAAK,IAAM,KACtHsK,EAAEjQ,OAAO,iBAAiBtF,KAAK2Z,EAE/B,IAAIlD,GAASlB,EAAEjQ,OAAO,iBAAiBI,UAAU,IAC7CsR,IACAP,EACK/Q,UAAU,QACVI,KAAK,YAAa,SAASQ,EAAE1E,EAAEgX,GAAK,MAAO,gBAAkBA,EAAI,GAAK,EAAI,IAAM,MAAQ,MAG7FjC,GACAF,EACK/Q,UAAU,cACVI,KAAK,YAAa,UAAY6Q,EAAe,SAC7C/N,MAAM,cAAe+N,EAAe,EAAI,QAAU,OAGvDyL,GACA7M,EAAE7P,UAAU,cACP1F,KAAKnB,EAAGG,MAAM0V,UAAWhT,EAAMiY,MAAMxD,aAI9CyD,IACAC,EACKpT,MAAMuG,GACN0T,OAAQ7hB,EAAGG,MAAMoT,WAAW/N,EAAgB,GAAIrB,IAChDsX,UAAWlW,EAAgB,GAEhCmR,EAAEjQ,OAAO,iBAAiBtF,KAAK6Z,IAInCtE,EAAEjQ,OAAO,qBACJQ,KAAK,KAAK,GACVA,KAAK,KAAK1B,GACV0B,KAAK,KAAMkH,EAAE,IACblH,KAAK,KAAMkH,EAAE,MAItB8C,EAAYS,UAAU,+BACf7O,EA1KX,GAgBMuE,GACA+G,EAjBFmV,EAActjB,EAAGI,OAAOuiB,cACtB7H,EAAQ9a,EAAGI,OAAOqW,OAClBuE,EAAQhb,EAAGI,OAAOqW,OAClBvW,EAAUF,EAAGI,OAAOF,UAGtBkF,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9CqB,EAAQ,KACRC,EAAS,KACTqF,EAAQhM,EAAGG,MAAM4O,WACjB8L,GAAY,EACZE,GAAY,EACZM,GAAkB,EAClBlD,GAAgB,EAChBoL,GAAa,EACbzL,EAAe,EAGfpC,EAAS,KACTlV,EAAWC,GAAGD,SAAS,eAAe,aACtCsH,EAAW,GAGjBgT,GACKlE,OAAO,UACPW,YAAW,GACXR,WAAW,SAAStP,GAAK,MAAOA,KAErCuT,EACKpE,OAAO,EAAoB,QAAU,QACrCG,WAAWtW,GAAGib,OAAO,SAG1Bxb,EACK4H,SAAS,GACTiD,eAAc,GACdI,eAAe,SAAS1D,EAAG1E;AACxB,MAAOiY,GAAMjE,aAAatP,EAAG1E,KAEhCsI,aAAa,SAAS5D,EAAG1E,GACtB,MAAO+X,GAAM/D,aAAatP,EAAG1E,IAOrC,IAAIkO,GAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,EAqMjD,OAnEAwb,GAAY9iB,SAASkB,GAAG,2BAA4B,SAASia,GACzDA,EAAY,QACRzP,IAAKrJ,EAAMuE,IAAIuU,EAAIxX,MACnBuH,MAAO7I,EAAMsL,IAAIwN,EAAIxX,MACrB6H,MAAO2P,EAAI3P,OAEf9L,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7Bwd,EAAY9iB,SAASkB,GAAG,0BAA2B,SAASia,GACxDzb,EAAQ4F,QAAO,KAGnBwd,EAAY9iB,SAASkB,GAAG,2BAA4B,SAASia,GACzDzb,MAOJ2C,EAAMrC,SAAWA,EACjBqC,EAAMygB,YAAcA,EACpBzgB,EAAMiY,MAAQA,EACdjY,EAAMmY,MAAQA,EACdnY,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtEmQ,eAAgBnK,IAAK,WAAW,MAAOmK,IAAiBlK,IAAK,SAASjG,GAAGmQ,EAAcnQ,IACvF8P,cAAgB9J,IAAK,WAAW,MAAO8J,IAAgB7J,IAAK,SAASjG,GAAG8P,EAAa9P,IACrFub,YAAcvV,IAAK,WAAW,MAAOuV,IAActV,IAAK,SAASjG,GAAGub,IAAavb,IACjF6S,WAAY7M,IAAK,WAAW,MAAO6M,IAAa5M,IAAK,SAASjG,GAAG6S,EAAU7S,IAC3E+S,WAAY/M,IAAK,WAAW,MAAO+M,IAAa9M,IAAK,SAASjG,GAAG+S,EAAU/S,IAC3E0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IAGrE5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,GAClBwb,EAAYxb,SAASA,GACrBgT,EAAMhT,SAASA,GACfkT,EAAMlT,SAASA,KAEnBkE,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1Bsb,EAAYtX,MAAMA,KAEtBqP,iBAAkBrN,IAAK,WAAW,MAAOqN,IAAmBpN,IAAK,SAASjG,GACtEqT,EAAkBrT,EAClBgT,EAAMpE,OAAQ,EAAM,QAAU,YAItC5W,EAAGG,MAAM6U,eAAenS,EAAOygB,GAC/BtjB,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAOojB,aAAe,WACrB,YA8BA,SAAS3gB,GAAMoB,GA8DX,MA7DAgN,GAAYW,QACZ3N,EAAUC,KAAK,SAASC,GACpB,GACIsf,IADkB/c,GAAkB,MAAT+P,EAAerR,EAAOC,KAAOD,EAAOqQ,MAAQrQ,EAAOE,IAAMF,EAAOoQ,QAC3E,KAARiB,EAAc,IAAM,KAC5BjQ,EAAY/F,GAAGgG,OAAO3F,KAC1Bd,GAAGG,MAAMiV,QAAQ5O,GAKjBqQ,EAASA,GAAUjP,CAQnB,IAAIhB,GAAOJ,EAAUK,UAAU,qBAAqB1C,MAAMA,IACtD2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,wBAEnDyP,GADS5P,EAAUE,OAAO,KACtBJ,EAAKH,OAAO,KAEpBG,GAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAKvE,IAAIoe,GAAWhN,EAAE7P,UAAU,aACtB1C,KAAK,SAASsD,GAAK,MAAOA,IAAK,SAASA,GAAK,MAAOA,GAAEyE,KAE3DwX,GAAS3c,QAAQC,OAAO,KACxB0c,EACKzc,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO,qBAAuBA,IAC5DgH,MAAM,SAAU,SAAStC,EAAE1E,GAAK,MAAOiJ,GAAMvE,EAAG1E,IAErD,IAAI4gB,GAAOD,EAAS7c,UAAU,eAAiB4P,GAC1CtS,KAAK,SAASsD,GAAK,MAAOA,GAAES,QACjCyb,GAAK5c,QAAQC,OAAO,QACfC,KAAKwP,EAAO,IAAK,SAAShP,EAAE1E,GAAK,MAAO8T,GAAO+M,EAAQnc,EAAE1E,MACzDkE,KAAKwP,EAAO,IAAK,SAAShP,EAAE1E,GAAK,MAAO8T,GAAO+M,EAAQnc,EAAE1E,MAC9DkO,EAAY7D,WAAWsW,EAAShc,OAAOb,UAAU,eAAiB4P,GAAO,aAEpExP,KAAKwP,EAAO,IAAK,SAAShP,EAAE1E,GAAK,MAAO6E,GAAMgc,EAAQnc,EAAE1E,MACxDkE,KAAKwP,EAAO,IAAK,SAAShP,EAAE1E,GAAK,MAAO6E,GAAMgc,EAAQnc,EAAE1E,MACxDgH,MAAM,iBAAkB,GACxBpC,SACLgc,EACK1c,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO,UAAY0T,EAAO,WAAaA,EAAO,IAAM1T,IAClFkE,KAAKwc,EAAQ,IAAK,GAClBxc,KAAKwc,EAAQ,IAAKnV,GACvB2C,EAAY7D,WAAWuW,EAAM,QAExB1c,KAAKwP,EAAO,IAAK,SAAShP,EAAE1E,GAAK,MAAO6E,GAAMgc,EAAQnc,EAAE1E,MACxDkE,KAAKwP,EAAO,IAAK,SAAShP,EAAE1E,GAAK,MAAO6E,GAAMgc,EAAQnc,EAAE1E,MAG7D8T,EAASjP,EAAM4Q,SAGnBvH,EAAYS,UAAU,0BACf7O,EAvFX,GAmBIgU,GAnBAzR,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACR4H,EAAO,EACPmI,EAAO,IACPmN,EAAU,SAASnc,GAAK,MAAOA,GAAEgP,IACjCzK,EAAQhM,EAAGG,MAAM6O,eACjBpH,EAAQnH,GAAGmH,MAAMC,SAEjBC,EAAW,IACXtH,EAAWC,GAAGD,SAAS,aAWzByQ,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,EAmIjD,OAzDAjF,GAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAC1CA,EAAMrC,SAAWA,EAEjBqC,EAAMuC,OAAS,SAAS4C,GACpB,MAAK5G,WAAUe,QACfiD,EAAOE,IAA4B,mBAAZ0C,GAAE1C,IAAwB0C,EAAE1C,IAASF,EAAOE,IACnEF,EAAOqQ,MAA4B,mBAAZzN,GAAEyN,MAAwBzN,EAAEyN,MAASrQ,EAAOqQ,MACnErQ,EAAOoQ,OAA4B,mBAAZxN,GAAEwN,OAAwBxN,EAAEwN,OAASpQ,EAAOoQ,OACnEpQ,EAAOC,KAA4B,mBAAZ2C,GAAE3C,KAAwB2C,EAAE3C,KAASD,EAAOC,KAC5DxC,GALuBuC,GAQlCvC,EAAM6D,MAAQ,SAASsB,GACnB,MAAK5G,WAAUe,QACfuE,EAAQsB,EACDnF,GAFuB6D,GAKlC7D,EAAM4T,KAAO,SAASzO,GAClB,MAAK5G,WAAUe,QACfsU,EAAOzO,EACAnF,GAFuB4T,GAKlC5T,EAAMyL,KAAO,SAAStG,GAClB,MAAK5G,WAAUe,QACfmM,EAAOtG,EACAnF,GAFuByL,GAKlCzL,EAAM+gB,QAAU,SAAS5b,GACrB,MAAK5G,WAAUe,QACfyhB,EAAUnjB,GAAGsU,QAAQ/M,GACdnF,GAFuB+gB,GAKlC/gB,EAAM+E,MAAQ,SAASI,GACnB,MAAK5G,WAAUe,QACfyF,EAAQI,EACDnF,GAFuB+E,GAKlC/E,EAAMmJ,MAAQ,SAAShE,GACnB,MAAK5G,WAAUe,QACf6J,EAAQhM,EAAGG,MAAM4O,SAAS/G,GACnBnF,GAFuBmJ,GAKlCnJ,EAAMiF,SAAW,SAASE,GACtB,MAAK5G,WAAUe,QACf2F,EAAWE,EACXiJ,EAAYW,MAAM9J,GACXjF,GAHuBiF,GAQ3BjF,GAEX7C,EAAGI,OAAOyjB,cAAgB,WACtB,YAsBA,SAAShhB,GAAMoB,GA2QX,QAAS6f,GAAarc,EAAE1E,GACpB,MAAW,WAARghB,EAA0B,OAC1BC,EACQvc,EAAEwc,WAAajY,EAAMvE,EAAE1E,GAAK,OAC3BihB,EAAL,OACMvc,EAAE+T,SAAWxP,EAAMvE,EAAE1E,GAAK,OAI3C,QAASmhB,GAAWzc,EAAE1E,GAClB,MAAGihB,IAAoB,WAARD,EACJtc,EAAEwc,WAAa,OAASjY,EAAMvE,EAAE1E,GAE9B0E,EAAE+T,SAAW,OAASxP,EAAMvE,EAAE1E,GAI/C,MA3RAkB,GAAUC,KAAK,SAASC,GACpB,GAAIoB,GAAiBmB,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAC9CjP,EAAY/F,GAAGgG,OAAO3F,KAC1Bd,GAAGG,MAAMiV,QAAQ5O,EAGjB,IAAII,GAAOJ,EAAUK,UAAU,eAAe1C,MAAMA,IAEhDuS,GADS9P,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,kBAAkBD,OAAO,KACrEJ,EAAKH,OAAO,KAEpBG,GAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAEvE,IAUI6e,GAVArY,EAAS4K,EAAE7P,UAAU,cACpB1C,KAAK,SAASsD,GACX,MAAW,WAARsc,EAA0Btc,EAEtBA,EAAE8M,OAAO,SAASzD,GACrB,MAAOkT,IAAW,GAAQlT,EAAEmT,eAGpCG,EAActY,EAAO/E,QAAQC,OAAO,KAAKC,KAAK,QAAS,YAI3D,IAAW,WAAR8c,EACCK,EAAYpd,OAAO,UACd+C,MAAM,eAAgB,GACtB9C,KAAK,QAAQ,oBACbA,KAAK,IAAK,GAEfkd,EAAcrY,EAAOrF,OAAO,cACzB,IAAY,WAARsd,EAAmB,CAC1BK,EAAYpd,OAAO,QACd+C,MAAM,eAAgB,GACtB9C,KAAK,QAAQ,oBACbA,KAAK,KAAM,GACXA,KAAK,KAAM,GAEhBkd,EAAcrY,EAAOrF,OAAO,QAE5B2d,EAAYpd,OAAO,KACdC,KAAK,QAAS,gBACdod,SAAS,YAAY,0KACrBpd,KAAK,YAAa,8BAEvB,IAAIqd,GAAiBxY,EAAOrF,OAAO,gBAEnC6d,GAAepgB,KAAK,SAASuD,EAAE1E,GAC3BtC,GAAGgG,OAAO3F,MAAM+F,UAAU,QACrBI,KAAK,SAAU6c,EAAarc,EAAE1E,MAI3CqhB,EAAYpd,OAAO,QACdC,KAAK,cAAe,SACpBA,KAAK,QAAQ,kBACbA,KAAK,KAAM,SACXA,KAAK,KAAM,IAEhB,IAAIsd,GAAazY,EAAOrF,OAAO,sBAE/BqF,GACKpK,GAAG,YAAa,SAAS+F,EAAE1E,GACxBvC,EAASgkB,gBAAgB/c,EAAE1E,KAE9BrB,GAAG,WAAY,SAAS+F,EAAE1E,GACvBvC,EAASikB,eAAehd,EAAE1E,KAE7BrB,GAAG,QAAS,SAAS+F,EAAE1E,GACpBvC,EAASkkB,YAAYjd,EAAE1E,EAEvB,IAAIoB,GAAO2H,EAAO3H,MAClB,IAAIse,EAAa,CACb,GAAU,WAAPsB,EACKY,GAGAxgB,EAAKoF,QAAQ,SAASuC,GAAUA,EAAO0P,UAAW,IAClD/T,EAAE+T,UAAW,IAGb/T,EAAE+T,UAAY/T,EAAE+T,SACZrX,EAAK2N,MAAM,SAAShG,GAAU,MAAOA,GAAO0P,YAG5CrX,EAAKoF,QAAQ,SAASuC,GAAUA,EAAO0P,UAAW,SAGvD,IAAW,WAARuI,EACN,GAAGC,EACCvc,EAAEwc,YAAcxc,EAAEwc,WAClBxc,EAAEmd,aAAiChhB,QAAlB6D,EAAEmd,eAA8Bnd,EAAE+T,SAAW/T,EAAEmd,aAChEnd,EAAE+T,SAAW/T,EAAEwc,YAAcxc,EAAEmd,iBAC5B,KAAKZ,EAAU,CAClBvc,EAAE+T,UAAY/T,EAAE+T,SAChB/T,EAAEmd,aAAend,EAAE+T,QACnB,IAAIqJ,GAAU1gB,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAEwc,YAC9CY,GAAQ/S,MAAM,SAAShG,GAAU,MAAOA,GAAO8Y,gBAG/CzgB,EAAKoF,QAAQ,SAASuC,GAClBA,EAAO0P,SAAW1P,EAAO8Y,cAAe,IAKxDpkB,EAASof,aACLpE,SAAUrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,WAC5CyI,WAAY9f,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAEwc,kBAKzDviB,GAAG,WAAY,SAAS+F,EAAE1E,GACvB,IAAW,WAARghB,IAAqBC,KACxBxjB,EAASskB,eAAerd,EAAE1E,GACtB0f,GAAa,CAEb,GAAIte,GAAO2H,EAAO3H,MAGlBA,GAAKoF,QAAQ,SAASuC,GAClBA,EAAO0P,UAAW,EACP,WAARuI,IAAmBjY,EAAO8Y,aAAe9Y,EAAO0P,YAEvD/T,EAAE+T,UAAW,EACF,WAARuI,IAAmBtc,EAAEmd,aAAend,EAAE+T,UACzChb,EAASof,aACLpE,SAAUrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,gBAK5D1P,EAAO9B,QAAQ,cAAe,SAASvC,GAAK,MAAOA,GAAEmd,eACrD9Y,EAAOpE,OAAOC,SAEd4c,EACKtd,KAAK,OAAQ6c,GACbrT,KAAKlB,EAKV,IAAIwV,EACJ,QAAOhB,GACH,IAAK,UACDgB,EAAc,EACd,MACJ,KAAK,UACDA,EAAc,GAGtB,GAAIC,EAAO,CAEP,GAAIC,KACJnZ,GAAO5H,KAAK,SAASuD,EAAE1E,GACnB,GAAImiB,EACJ,IAAI3V,EAAO9H,GAAGtF,OAASgjB,EAAc,CACjC,GAAIC,GAAa7V,EAAO9H,GAAG4d,UAAU,EAAGF,EACxCD,GAAazkB,GAAGgG,OAAO3F,MAAM2F,OAAO,QAAQgK,KAAK2U,EAAa,OAC9D3kB,GAAGgG,OAAO3F,MAAMkG,OAAO,aAAayJ,KAAKlB,EAAO9H,QAEhDyd,GAAazkB,GAAGgG,OAAO3F,MAAM2F,OAAO,OAExC,IAAI6e,EACJ,KAGI,GAFAA,EAAiBJ,EAAW5a,OAAOkM,wBAEd,GAAlB8O,EAAqB,KAAMC,SAElC,MAAM5jB,GACF2jB,EAAiBtlB,EAAGG,MAAMoQ,oBAAoB2U,GAGlDD,EAAazhB,KAAK8hB,EAAiBE,IAOvC,KAJA,GAAIC,GAAe,EACfC,EAAc,EACdC,KAEkBpgB,EAAdmgB,GAAgCD,EAAeR,EAAa9iB,QAChEwjB,EAAaF,GAAgBR,EAAaQ,GAC1CC,GAAeT,EAAaQ,IAIhC,KAFqB,IAAjBA,IAAoBA,EAAe,GAE/BC,EAAcngB,GAAkBkgB,EAAe,GAAI,CACvDE,KACAF,GAEA,KAAK,GAAIG,GAAI,EAAGA,EAAIX,EAAa9iB,OAAQyjB,IACjCX,EAAaW,IAAMD,EAAaC,EAAIH,IAAiB,KACrDE,EAAaC,EAAIH,GAAgBR,EAAaW,GAGtDF,GAAcC,EAAaE,OAAO,SAASC,EAAMC,EAAKrd,EAAOsd,GACzD,MAAOF,GAAOC,IAKtB,IAAK,GADDE,MACKljB,EAAI,EAAGmjB,EAAO,EAAOT,EAAJ1iB,EAAkBA,IACxCkjB,EAAWljB,GAAKmjB,EAChBA,GAAQP,EAAa5iB,EAGzB+I,GACK7E,KAAK,YAAa,SAASQ,EAAG1E,GAC3B,MAAO,aAAekjB,EAAWljB,EAAI0iB,GAAgB,KAAO,EAAIzc,KAAKyB,MAAM1H,EAAI0iB,GAAgBV,GAAe,MAIlH9D,EACAvK,EAAEzP,KAAK,YAAa,cAAgBP,EAAQtB,EAAOqQ,MAAQiQ,GAAe,IAAMtgB,EAAOE,IAAM,KAG7FoR,EAAEzP,KAAK,YAAa,eAAsB7B,EAAOE,IAAM,KAG3DqB,EAASvB,EAAOE,IAAMF,EAAOoQ,OAAUxM,KAAKmd,KAAKlB,EAAa9iB,OAASsjB,GAAgBV,MAEpF,CAEH,GAGIqB,GAHAC,EAAO,EACPC,EAAU,EACVC,EAAW,CAEfza,GACK7E,KAAK,YAAa,SAASQ,EAAG1E,GAC3B,GAAIZ,GAAS1B,GAAGgG,OAAO3F,MAAM2F,OAAO,QAAQ6D,OAAOkM,wBAA0BgP,CAW7E,OAVAY,GAAOE,EAEH5f,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAAQ2Q,EAAOjkB,IAC5CmkB,EAAUF,EAAO,EACjBC,GAAQtB,GAGZuB,GAAWnkB,EACPmkB,EAAUC,IAAUA,EAAWD,GAE5B,aAAeF,EAAO,IAAMC,EAAO,MAIlD3P,EAAEzP,KAAK,YAAa,cAAgBP,EAAQtB,EAAOqQ,MAAQ8Q,GAAY,IAAMnhB,EAAOE,IAAM,KAE1FqB,EAASvB,EAAOE,IAAMF,EAAOoQ,OAAS6Q,EAAO,GAGtC,WAARtC,GAECI,EACKld,KAAK,QAAS,SAASQ,EAAE1E,GACtB,MAAOwhB,GAAW,GAAGxhB,GAAGyT,wBAA0B,KAErDvP,KAAK,SAAU,IACfA,KAAK,IAAK,IACVA,KAAK,IAAK,KAGnBkd,EACKpa,MAAM,OAAQma,GACdna,MAAM,SAAU,SAAStC,EAAE1E,GAAK,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,OAoB7DF,EA5SX,GAAIuC,IAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACRC,EAAS,GACT4I,EAAS,SAAS9H,GAAK,MAAOA,GAAEyE,KAChCF,EAAQhM,EAAGG,MAAM4O,WACjBoW,EAAe,GACfH,GAAQ,EACRQ,EAAU,GACVvE,GAAa,EACbwB,GAAc,EACdkC,GAAkB,EAClBX,GAAW,EACXxjB,EAAWC,GAAGD,SAAS,cAAe,iBAAkB,kBAAmB,iBAAkB,eAC7FujB,EAAO,SAqUb,OA/BAlhB,GAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtEkE,KAAa8B,IAAK,WAAW,MAAOuB,IAAUtB,IAAK,SAASjG,GAAGuH,EAAOvH,IACtEgd,OAAahX,IAAK,WAAW,MAAOgX,IAAS/W,IAAK,SAASjG,GAAGgd,EAAMhd,IACpEiZ,YAAgBjT,IAAK,WAAW,MAAOiT,IAAchT,IAAK,SAASjG,GAAGiZ,EAAWjZ,IACjFmd,cAAgBnX,IAAK,WAAW,MAAOmX,IAAgBlX,IAAK,SAASjG,GAAGmd,EAAand,IACrFwd,SAAgBxX,IAAK,WAAW,MAAOwX,IAAWvX,IAAK,SAASjG,GAAGwd,EAAQxd,IAC3Eya,aAAgBzU,IAAK,WAAW,MAAOyU,IAAexU,IAAK,SAASjG,GAAGya,EAAYza,IACnF2c,iBAAqB3W,IAAK,WAAW,MAAO2W,IAAmB1W,IAAK,SAASjG,GAAG2c,EAAgB3c,IAChGgc,UAAahW,IAAK,WAAW,MAAOgW,IAAY/V,IAAK,SAASjG,GAAGgc,EAAShc,IAC1E+b,MAAS/V,IAAK,WAAW,MAAO+V,IAAQ9V,IAAK,SAASjG,GAAG+b,EAAK/b,IAG9D5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,OAIlChI,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAOomB,cAAgB,WACtB,YA8BA,SAAS3jB,GAAMoB,GA2IX,MA1IAA,GAAUC,KAAK,SAASC,GACpB8M,EAAYW,QAEZpL,EAAY/F,GAAGgG,OAAO3F,KACtB,IAAIyE,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAElEpF,GAAGG,MAAMiV,QAAQ5O,GAGjBY,EAAEgF,OAAOuM,GAAWlY,GAAGmc,OAAOzY,EAAK,GAAG+D,OAAOgL,IAAI0F,GAAMnX,OAAOqb,KAE1DqB,EACA/W,EAAEiF,MAAMwM,IAA4B,GAAjBtT,EAAsBpB,EAAK,GAAG+D,OAAO/F,OAAQoD,GAAkBpB,EAAK,GAAG+D,OAAO/F,OAAS,IAAOgC,EAAK,GAAG+D,OAAO/F,SAEhIiF,EAAEiF,MAAMwM,IAAW,EAAGtT,IAE1B4I,EAAE/B,OAAO2M,GAAWtY,GAAGmc,OAAOzY,EAAK,GAAG+D,OAAOgL,IAAIuH,GAAMhZ,OAAO4c,KACzDhS,MAAMqN,IAAWlU,EAAiB,IAGnC4B,EAAEgF,SAAS,KAAOhF,EAAEgF,SAAS,KAC7BhF,EAAEgF,SAAS,GACPhF,EAAEgF,QAAQhF,EAAEgF,SAAS,GAAqB,IAAhBhF,EAAEgF,SAAS,GAAWhF,EAAEgF,SAAS,GAAqB,IAAhBhF,EAAEgF,SAAS,KACzEhF,EAAEgF,QAAQ,GAAG,KAEnB+B,EAAE/B,SAAS,KAAO+B,EAAE/B,SAAS,KAC7B+B,EAAE/B,SAAS,GACP+B,EAAE/B,QAAQ+B,EAAE/B,SAAS,GAAqB,IAAhB+B,EAAE/B,SAAS,GAAW+B,EAAE/B,SAAS,GAAqB,IAAhB+B,EAAE/B,SAAS,KACzE+B,EAAE/B,QAAQ,GAAG,IAGvB,IAAIxF,GAAOJ,EAAUK,UAAU,8BAAgCiD,GAAI3F,MAAMA,EAAK,GAAG+D,SAC7EpB,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,iCAAmC6C,GACtFsR,EAAYtU,EAAUE,OAAO,QAC7BmU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,WACjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEvEkB,EACK9E,GAAG,QAAS,SAAS+F,EAAE1E,GACpBvC,EAAS+d,YACLpa,KAAMsD,EACNiB,MAAO3F,EACP4J,IAAKlM,GAAGmE,MACRkF,GAAIA,MAIhBsR,EAAUpU,OAAO,YACZC,KAAK,KAAM,sBAAwB6C,GACnC9C,OAAO,QAEZJ,EAAKH,OAAO,uBAAyBqD,EAAK,SACrC7C,KAAK,QAAS1B,GACd0B,KAAK,SAAUzB,GAEpBkR,EAAEzP,KAAK,YAAauX,EAAW,2BAA6B1U,EAAK,IAAM,GAEvE,IAAIiZ,GAAOnc,EAAKH,OAAO,YAAYI,UAAU,WACxC1C,KAAK,SAASsD,GAAK,MAAOA,IAAK,SAASA,EAAE1E,GAAI,MAAO6V,GAAKnR,EAAE1E,IACjEggB,GAAKrb,OAAOC,SAEZob,EAAKhc,QAAQC,OAAO,QACfC,KAAK,IAAK,GACVA,KAAK,IAAK,SAASQ,EAAE1E,GAAM,MAAO/C,GAAGG,MAAMoH,UAAU4G,EAAEnF,KAAKL,IAAI,EAAG8R,EAAKhT,EAAE1E,QAC1EkE,KAAK,SAAU,SAASQ,EAAE1E,GAAK,MAAO/C,GAAGG,MAAMoH,UAAUyB,KAAKC,IAAIkF,EAAEsM,EAAKhT,EAAE1E,IAAMoL,EAAE,OACnFlH,KAAK,YAAa,SAASQ,EAAE1E,GAAK,MAAO,cAAgBqE,EAAEwR,EAAKnR,EAAE1E,IAAMwC,EAAiBpB,EAAK,GAAG+D,OAAO/F,OAAS,KAAO,QACxHT,GAAG,YAAa,SAAS+F,EAAE1E,GACnBic,IACLve,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASyZ,kBACL9V,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,aAIpCrI,GAAG,WAAY,SAAS+F,EAAE1E,GAClBic,IACLve,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASoF,iBACLzB,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,aAGpCrI,GAAG,YAAa,SAAS+F,EAAE1E,GACnBic,GACLxe,EAAS0F,kBACL/B,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,QAAS,SAAS+F,EAAE1E,GACfic,IACLxe,EAAS6F,cACLlC,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,UAEjCtJ,GAAGmE,MAAMqe,qBAEZvhB,GAAG,WAAY,SAAS+F,EAAE1E,GAClBic,IACLxe,EAAS0iB,iBACL/e,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,UAEjCtJ,GAAGmE,MAAMqe,qBAGjBF,EACK9b,KAAK,OAAQ,SAASQ,EAAE1E,GAAK,MAAOiJ,GAAMvE,EAAG1E,KAC7CkE,KAAK,QAAS,SAASQ,EAAE1E,EAAEgX,GAAK,OAAQU,EAAKhT,EAAE1E,GAAK,EAAI,kBAAoB,mBAAqB,WAAagX,EAAI,IAAMhX,IACxHiO,gBAAgBC,EAAa,QAC7BhK,KAAK,YAAa,SAASQ,EAAE1E,GAAK,MAAO,cAAgBqE,EAAEwR,EAAKnR,EAAE1E,IAAMwC,EAAiBpB,EAAK,GAAG+D,OAAO/F,OAAS,KAAO,QAExH8E,KAAK,QAAU1B,EAAiBpB,EAAK,GAAG+D,OAAO/F,OAAU,IAE9D4gB,EAAK/R,gBAAgBC,EAAa,QAC7BhK,KAAK,IAAK,SAASQ,EAAE1E,GAClB,GAAI0jB,GAAOhM,EAAKhT,EAAE1E,GAAK,EACnBoL,EAAE,GACEA,EAAE,GAAKA,EAAEsM,EAAKhT,EAAE1E,IAAM,EAC1BoL,EAAE,GAAK,EACPA,EAAEsM,EAAKhT,EAAE1E,GACb,OAAO/C,GAAGG,MAAMoH,UAAUkf,KAE7Bxf,KAAK,SAAU,SAASQ,EAAE1E,GAAK,MAAO/C,GAAGG,MAAMoH,UAAUyB,KAAKL,IAAIK,KAAKC,IAAIkF,EAAEsM,EAAKhT,EAAE1E,IAAMoL,EAAE,IAAI,QAIzG8C,EAAYS,UAAU,2BACf7O,EAnKX,GAcM8V,GACAI,EACAF,EACAa,EAjBFtU,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,KACRC,EAAS,KACTmD,EAAKd,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UACrBlE,EAAY,KACZY,EAAI3G,GAAGmH,MAAMC,SACbsG,EAAI1N,GAAGmH,MAAMC,SACb+Q,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9B2O,KACAuB,GAAU,GACVF,GAAU,EACVK,GAAW,EACXxS,EAAQhM,EAAGG,MAAM6O,eAKjBxO,EAAWC,GAAGD,SAAS,aAAc,eAAgB,kBAAmB,mBAAoB,kBAAmB,mBAAoB,aACnIwe,GAAc,EAGhB/N,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAU,EAuMjD,OAtDAqC,GAAMoc,eAAiB,SAASC,EAAYC,GACxC3Y,EACKC,OAAO,sBAAwByY,GAC/BlV,QAAQ,QAASmV,IAI1Btc,EAAMuc,gBAAkB,WACpB5Y,EACKC,OAAO,0BACPuD,QAAQ,SAAS,IAQ1BnH,EAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAUsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACjErB,QAAUqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACnE8U,QAAU9O,IAAK,WAAW,MAAO8O,IAAU7O,IAAK,SAASjG,GAAG8U,EAAO9U,IACnEqW,QAAUrQ,IAAK,WAAW,MAAOqQ,IAAUpQ,IAAK,SAASjG,GAAGqW,EAAOrW,IACnEmW,SAAUnQ,IAAK,WAAW,MAAOmQ,IAAWlQ,IAAK,SAASjG,GAAGmW,EAAQnW,IACrEZ,GAAU4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAK5Q,IAC/DmG,GAAUH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAAGyS,EAAKzS,IAC/DhC,QAAUgI,IAAK,WAAW,MAAO5G,IAAK6G,IAAK,SAASjG,GAAGZ,EAAEY,IACzD0S,QAAU1M,IAAK,WAAW,MAAOG,IAAKF,IAAK,SAASjG,GAAGmG,EAAEnG,IACzD2Q,SAAU3K,IAAK,WAAW,MAAO2K,IAAW1K,IAAK,SAASjG,GAAG2Q,EAAQ3Q,IACrE+Q,SAAU/K,IAAK,WAAW,MAAO+K,IAAW9K,IAAK,SAASjG,GAAG+Q,EAAQ/Q,IACrE6Q,QAAU7K,IAAK,WAAW,MAAO6K,IAAU5K,IAAK,SAASjG,GAAG6Q,EAAO7Q,IACnE0R,QAAU1L,IAAK,WAAW,MAAO0L,IAAUzL,IAAK,SAASjG,GAAG0R,EAAO1R,IACnEwW,UAAcxQ,IAAK,WAAW,MAAOwQ,IAAYvQ,IAAK,SAASjG,GAAGwW,EAASxW,IAC3E8B,IAAckE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,GAAG8B,EAAG9B,IAC/DgX,aAAchR,IAAK,WAAW,MAAOgR,IAAe/Q,IAAK,SAASjG,GAAGgX,EAAYhX,IAGjF5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,OAIlChI,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAOsmB,mBAAqB,SAASC,GACpC,YAoDA,SAAS9jB,GAAMoB,GAsNX,MArNAA,GAAUC,KAAK,SAASC,GACpB8M,EAAYW,QACZX,EAAY7Q,OAAO2iB,GACflI,GAAW5J,EAAY7Q,OAAO0a,GAC9BC,GAAW9J,EAAY7Q,OAAO4a,EAElC,IAAIxU,GAAY/F,GAAGgG,OAAO3F,MACtBif,EAAOjf,IACXd,GAAGG,MAAMiV,QAAQ5O,EACjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAQlE,IANAvC,EAAM+P,OAAS,WAAapM,EAAU4G,aAAatF,SAAS8e,GAAoBzlB,KAAK0B,IACrFA,EAAM2D,UAAY1F,KAGlBwP,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,YAE9C0E,EAAc,CACf,GAAIhU,EACJgU,KACA,KAAKhU,IAAOoE,GACJA,EAAMpE,YAAgBjL,OACtBif,EAAahU,GAAOoE,EAAMpE,GAAKhL,MAAM,GAErCgf,EAAahU,GAAOoE,EAAMpE,GAKtC,KAAK/H,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAE9E,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,SAItCP,EAAI2b,EAAK/c,SACTmI,EAAI4U,EAAKrI,QAGT,IAAI9T,GAAOJ,EAAUK,UAAU,mCAAmC1C,MAAMA,IACpEgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,sCAAsCD,OAAO,KAC7F0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,eACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,kBAG7B2Z,IACAC,EAAOna,MAAMnB,GAEbmR,EAAEjQ,OAAO,kBACJ8U,MAAMpX,GACNhD,KAAK0f,GAELzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SACpBnB,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IAGlEwB,EAAKH,OAAO,kBACPQ,KAAK,YAAa,gBAAmB7B,EAAOE,IAAM,MAE3DsB,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEnE+V,GACA3E,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,aAAe1B,EAAiB,OAIvD4b,IACAC,EACK1a,MAAMnB,GACNoB,OAAOnB,GACPJ,QAAQC,KAAKD,EAAOC,KAAMC,IAAIF,EAAOE,MACrC4B,aAAaV,GACbR,OAAOoB,GACZR,EAAKH,OAAO,mBAAmBtF,KAAKigB,IAExC2B,EACKrc,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GACvB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,WAE9C,IAAIF,GAAW5E,EAAEjQ,OAAO,gBACnB8U,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAC/CF,GAASlO,aAAajM,KAAK4hB,GAGvBlI,IACAC,EACKlT,MAAMR,GACNya,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAChDsX,UAAUjW,EAAiB,GAEhCkR,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,eAAiBkH,EAAE9B,QAAQ,GAAK,KACvDqK,EAAEjQ,OAAO,iBACJ2G,aACAjM,KAAK2Z,IAGVC,IACAC,EACKpT,MAAMuG,GACN0T,OAAQ7hB,EAAGG,MAAMoT,WAAW/N,EAAgB,GAAIrB,IAChDsX,UAAWlW,EAAgB,GAEhCmR,EAAEjQ,OAAO,iBACJ2G,aACAjM,KAAK6Z,IAOdoG,EAAiB5gB,SAASkB,GAAG,mBAAoB,SAASC,GACtDohB,EAAK3D,iBAEL,IAAI2C,GAAa7C,EAAY8C,EAAgBC,IAC7C9d,GACKoQ,OAAO,SAASzI,EAAQ/I,GAErB,MADA+I,GAAOyV,YAAcxe,GACb+I,EAAO0P,WAElBjS,QAAQ,SAASuC,EAAO/I,GACrBmc,EAAalf,EAAGiI,kBAAkB6D,EAAO5D,OAAQvG,EAAEoE,YAAalD,EAAMuE,KACtE2b,EAAK9D,eAAeC,GAAW,EAC/B,IAAIhR,GAAQpC,EAAO5D,OAAOgX,EACZtb,UAAVsK,IACgBtK,SAAhBme,IAA2BA,EAAc7T,GACtBtK,SAAnBoe,IAA8BA,EAAiBnf,EAAMmD,SAASnD,EAAMuE,IAAI8G,EAAMgR,KAClF+C,EAAQze,MACJ0I,IAAKJ,EAAOI,IACZR,MAAO7I,EAAMsL,IAAID,EAAOgR,GACxBlT,MAAOA,EAAMF,EAAOA,EAAOyV,aAC3Bpd,KAAM2H,EAAO5D,OAAOgX,OAIhC,IAAIkD,GAAStH,EAAM/D,aAAalU,EAAMuE,IAAI2a,EAAY7C,GACtDkC,GAAiBlhB,QACZwJ,eAAeqW,EAAK/P,YACpB7E,eAAe,SAAS1D,EAAE1E,GACvB,MAAOiY,GAAMjE,aAAatP,KAE7BtD,MACGuH,MAAO0W,EACP1Z,MAAOwW,EACPpT,OAAQmW,MAGhBb,EAAiBvb,gBAAgBmc,KAIrCZ,EAAiB5gB,SAASkB,GAAG,kBAAkB,SAASC,GACpDnB,EAASqmB,cACT9D,EAAK3D,oBAGTyB,EAAOrgB,SAASkB,GAAG,cAAe,SAAS+F,EAAE1E,GACzC0E,EAAE+T,UAAY/T,EAAE+T,SAEXrX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAAYrZ,QACjDgC,EAAK+O,IAAI,SAASzL,GAGd,MAFAA,GAAE+T,UAAW,EACb5U,EAAKC,UAAU,cAAcmD,QAAQ,YAAY,GAC1CvC,IAIf6I,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,WACnDhb,EAASof,YAAYtP,GAErBrM,EAAUmJ,aAAajM,KAAK0B,KAGhCge,EAAOrgB,SAASkB,GAAG,iBAAkB,SAAS+F,GAE1CtD,EAAKoF,QAAQ,SAAS9B,GAClBA,EAAE+T,UAAW,IAEjB/T,EAAE+T,UAAW,EAEblL,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,WACnDhb,EAASof,YAAYtP,GACrBzN,EAAM+P,WAGVpS,EAASkB,GAAG,cAAe,SAASC,GACN,mBAAfA,GAAE6Z,WACTrX,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,SAAW7Z,EAAE6Z,SAASzY,KAGjCuN,EAAMkL,SAAW7Z,EAAE6Z,UAGvB3Y,EAAM+P,aAId3B,EAAYS,UAAU,gCACf7O,EApQX,GAkBMuE,GACA+G,EAnBF4U,EAAO4D,GAAa3mB,EAAGI,OAAOomB,gBAC5B1L,EAAQ9a,EAAGI,OAAOqW,OAClBuE,EAAQhb,EAAGI,OAAOqW,OAClBoK,EAAS7gB,EAAGI,OAAOygB,SACnBO,EAAmBphB,EAAG+D,uBACtB7D,EAAUF,EAAGI,OAAOF,UAItBkF,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9C2G,EAAQhM,EAAGG,MAAM6O,eACjBtI,EAAQ,KACRC,EAAS,KACTia,GAAa,EACb/F,GAAY,EACZE,GAAY,EACZM,GAAkB,EAClB8F,GAA0B,EAG1B7Q,KACA4P,EAAe,KACfxK,EAAS,KACTlV,EAAWC,GAAGD,SAAS,cAAe,cAAe,cAAe,aACpEomB,EAAqB,GAG3B9L,GAAMlE,OAAO,UAAUY,YAAY,GACnCwD,EAAMpE,OAAQ,EAAoB,QAAU,QAC5C1W,EACK4H,SAAS,GACTiD,eAAc,GACdI,eAAe,SAAS1D,EAAG1E,GACxB,MAAOiY,GAAMjE,aAAatP,EAAG1E,KAEhCqI,gBAAgB,SAAS3D,EAAG1E,GACzB,MAAO+X,GAAM/D,aAAatP,EAAG1E,IAQrC,IAAIkO,GAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAU,EA0SjD,OA3EAuiB,GAAKviB,SAASkB,GAAG,2BAA4B,SAASia,GAClDA,EAAY,QACRzP,IAAKrJ,EAAMuE,IAAIuU,EAAIxX,MACnBuH,MAAO7I,EAAMsL,IAAIwN,EAAIxX,MACrB6H,MAAO2P,EAAI3P,OAEf9L,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7Bid,EAAKviB,SAASkB,GAAG,0BAA2B,SAASia,GACjDzb,EAAQ4F,QAAO,KAGnBid,EAAKviB,SAASkB,GAAG,2BAA4B,SAASia,GAClDzb,MAQJ2C,EAAMrC,SAAWA,EACjBqC,EAAMkgB,KAAOA,EACblgB,EAAMge,OAASA,EACfhe,EAAMiY,MAAQA,EACdjY,EAAMmY,MAAQA,EACdnY,EAAMue,iBAAmBA,EACzBve,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtE4Y,YAAa5S,IAAK,WAAW,MAAO4S,IAAc3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IAC9E6S,WAAY7M,IAAK,WAAW,MAAO6M,IAAa5M,IAAK,SAASjG,GAAG6S,EAAU7S,IAC3E+S,WAAY/M,IAAK,WAAW,MAAO+M,IAAa9M,IAAK,SAASjG,GAAG+S,EAAU/S,IAC3EkY,cAAkBlS,IAAK,WAAW,MAAOkS,IAAgBjS,IAAK,SAASjG,GAAGkY,EAAalY,IACvF0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IAGrE5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1B6Y,EAAO7U,MAAMA,GACb+W,EAAK/W,MAAMA,KAEflE,UAAckG,IAAK,WAAW,MAAO4Y,IAAsB3Y,IAAK,SAASjG,GACrE4e,EAAmB5e,EACnBiJ,EAAYW,MAAMgV,GAClB5L,EAAMlT,SAAS8e,GACf9L,EAAMhT,SAAS8e,KAEnBvL,iBAAkBrN,IAAK,WAAW,MAAOqN,IAAmBpN,IAAK,SAASjG,GACtEqT,EAAkBrT,EAClBgT,EAAMpE,OAAQ,EAAM,QAAU,UAElCuK,yBAA0BnT,IAAK,WAAW,MAAOmT,IAA2BlT,IAAK,SAASjG,GACtFmZ,EAA0BnZ,EACtBA,KAAM,GACNnF,EAAMmc,aAAY,OAK9Bhf,EAAGG,MAAM6U,eAAenS,EAAOkgB,GAC/B/iB,EAAGG,MAAMiO,YAAYvL,GAEdA,GAKX7C,EAAGI,OAAO0mB,aAAe,WACrB,GAAIjkB,GAAQ7C,EAAGI,OAAOsmB,mBAAmB1mB,EAAGI,OAAO2mB,UAkBnD,OAfAlkB,GAAMse,yBAAwB,GAC9Bte,EAAMue,iBAAiBlhB,QAAQmK,iBAAiB,SAASlG,GAErD,GAAIsD,GAAItD,EAAK2H,OAAO,GAAG3H,KAEnB6H,EAAQvE,EAAEmX,KAAOnX,EAAEoX,MAAQ,SAAW,QAC1C,OAAO,sBACqB7S,EAAQ,KAAO7H,EAAKuH,MAAQ,qCAEzB7I,EAAMmY,MAAMjE,aAAatP,EAAEmX,MAAQ,oCAClC/b,EAAMmY,MAAMjE,aAAatP,EAAEoX,OAAS,kCACtChc,EAAMmY,MAAMjE,aAAatP,EAAEqX,MAAQ,kCACnCjc,EAAMmY,MAAMjE,aAAatP,EAAEsX,KAAO,uBAG7Dlc,GAIX7C,EAAGI,OAAO4mB,oBAAsB,WAC5B,GAAInkB,GAAQ7C,EAAGI,OAAOsmB,mBAAmB1mB,EAAGI,OAAO6d,iBAkBnD,OAfApb,GAAMse,yBAAwB,GAC9Bte,EAAMue,iBAAiBlhB,QAAQmK,iBAAiB,SAASlG,GAErD,GAAIsD,GAAItD,EAAK2H,OAAO,GAAG3H,KAEnB6H,EAAQvE,EAAEmX,KAAOnX,EAAEoX,MAAQ,SAAW,QAC1C,OAAO,sBACqB7S,EAAQ,KAAO7H,EAAKuH,MAAQ,qCAEzB7I,EAAMmY,MAAMjE,aAAatP,EAAEmX,MAAQ,oCAClC/b,EAAMmY,MAAMjE,aAAatP,EAAEoX,OAAS,kCACtChc,EAAMmY,MAAMjE,aAAatP,EAAEqX,MAAQ,kCACnCjc,EAAMmY,MAAMjE,aAAatP,EAAEsX,KAAO,uBAG7Dlc,GAEX7C,EAAGI,OAAOygB,OAAS,WACf,YAsBA,SAAShe,GAAMoB,GAiSX,QAAS6f,GAAarc,EAAE1E,GACpB,MAAW,WAARghB,EAA0B,OAC1BC,EACQvc,EAAEwc,WAAa,OAAS,OACvBD,EAAL,QACCvc,EAAEuE,QAAOvE,EAAEuE,MAAQA,EAAMvE,EAAE1E,IACtB0E,EAAE+T,SAAW/T,EAAEuE,MAAQ,QAIxC,QAASkY,GAAWzc,EAAE1E,GAClB,MAAGihB,IAAoB,WAARD,GACJtc,EAAEwc,WAAa,OAEfxc,EAAEuE,OAASA,EAAMvE,EAAE1E,GAKlC,QAASkkB,GAAaxf,EAAE1E,GACpB,MAAGihB,IAAoB,WAARD,EACJ,EAEEtc,EAAE+T,SAAW,EAAI,EAIlC,MA3TAvX,GAAUC,KAAK,SAASC,GACpB,GAAIoB,GAAiBmB,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAC9CjP,EAAY/F,GAAGgG,OAAO3F,KAC1Bd,GAAGG,MAAMiV,QAAQ5O,EAGjB,IAAII,GAAOJ,EAAUK,UAAU,eAAe1C,MAAMA,IAChDgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,kBAAkBD,OAAO,KACzE0P,EAAI9P,EAAKH,OAAO,IAEpBG,GAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAEvE,IAUI6e,GAEAY,EAZAjZ,EAAS4K,EAAE7P,UAAU,cACpB1C,KAAK,SAASsD,GACX,MAAW,WAARsc,EAA0Btc,EAEtBA,EAAE8M,OAAO,SAASzD,GACrB,MAAOkT,IAAW,GAAQlT,EAAEmT,eAIpCG,EAActY,EAAO/E,QAAQC,OAAO,KAAKC,KAAK,QAAS,YAI3D,QAAO8c,GACH,IAAK,UACDgB,EAAc,EACd,MACJ,KAAK,UACDA,EAAc,GAGtB,GAAW,WAARhB,EACCK,EAAYpd,OAAO,UACd+C,MAAM,eAAgB,GACtB9C,KAAK,QAAQ,oBACbA,KAAK,IAAK,GAEfkd,EAAcrY,EAAOrF,OAAO,cACzB,IAAY,WAARsd,EAAmB,CAC1BK,EAAYpd,OAAO,QACd+C,MAAM,eAAgB,GACtB9C,KAAK,QAAQ,oBACbA,KAAK,KAAM,GACXA,KAAK,KAAM,GAChBkd,EAAcrY,EAAOrF,OAAO,qBAE5B2d,EAAYpd,OAAO,KACdC,KAAK,QAAS,gBACdod,SAAS,YAAY,0KACrBpd,KAAK,YAAa,8BAEvB,IAAIqd,GAAiBxY,EAAOrF,OAAO,gBAEnC6d,GAAepgB,KAAK,SAASuD,EAAE1E,GAC3BtC,GAAGgG,OAAO3F,MAAM+F,UAAU,QACrBI,KAAK,SAAU6c,EAAarc,EAAE1E,MAI3CqhB,EAAYpd,OAAO,QACdC,KAAK,cAAe,SACpBA,KAAK,QAAQ,kBACbA,KAAK,KAAM,SACXA,KAAK,KAAM,IAEhB,IAAIsd,GAAazY,EAAOrF,OAAO,sBAE/BqF,GACKpK,GAAG,YAAa,SAAS+F,EAAE1E,GACxBvC,EAASgkB,gBAAgB/c,EAAE1E,KAE9BrB,GAAG,WAAY,SAAS+F,EAAE1E,GACvBvC,EAASikB,eAAehd,EAAE1E,KAE7BrB,GAAG,QAAS,SAAS+F,EAAE1E,GACpBvC,EAASkkB,YAAYjd,EAAE1E,EAEvB,IAAIoB,GAAO2H,EAAO3H,MAClB,IAAIse,EAAa,CACb,GAAU,WAAPsB,EACKY,GAGAxgB,EAAKoF,QAAQ,SAASuC,GAAUA,EAAO0P,UAAW,IAClD/T,EAAE+T,UAAW,IAGb/T,EAAE+T,UAAY/T,EAAE+T,SACZrX,EAAK2N,MAAM,SAAShG,GAAU,MAAOA,GAAO0P,YAG5CrX,EAAKoF,QAAQ,SAASuC,GAAUA,EAAO0P,UAAW,SAGvD,IAAW,WAARuI,EACN,GAAGC,EACCvc,EAAEwc,YAAcxc,EAAEwc,WAClBxc,EAAEmd,aAAiChhB,QAAlB6D,EAAEmd,eAA8Bnd,EAAE+T,SAAW/T,EAAEmd,aAChEnd,EAAE+T,SAAW/T,EAAEwc,YAAcxc,EAAEmd,iBAC5B,KAAKZ,EAAU,CAClBvc,EAAE+T,UAAY/T,EAAE+T,SAChB/T,EAAEmd,aAAend,EAAE+T,QACnB,IAAIqJ,GAAU1gB,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAEwc,YAC9CY,GAAQ/S,MAAM,SAAShG,GAAU,MAAOA,GAAO8Y,gBAG/CzgB,EAAKoF,QAAQ,SAASuC,GAClBA,EAAO0P,SAAW1P,EAAO8Y,cAAe,IAKxDpkB,EAASof,aACLpE,SAAUrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,WAC5CyI,WAAY9f,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAEwc,kBAKzDviB,GAAG,WAAY,SAAS+F,EAAE1E,GACvB,IAAW,WAARghB,IAAqBC,KACxBxjB,EAASskB,eAAerd,EAAE1E,GACtB0f,GAAa,CAEb,GAAIte,GAAO2H,EAAO3H,MAGlBA,GAAKoF,QAAQ,SAASuC,GAClBA,EAAO0P,UAAW,EACP,WAARuI,IAAmBjY,EAAO8Y,aAAe9Y,EAAO0P,YAEvD/T,EAAE+T,UAAW,EACF,WAARuI,IAAmBtc,EAAEmd,aAAend,EAAE+T,UACzChb,EAASof,aACLpE,SAAUrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,gBAK5D1P,EAAO9B,QAAQ,cAAe,SAASvC,GAAK,MAAOA,GAAEmd,eACrD9Y,EAAOpE,OAAOC,SAEd4c,EACKtd,KAAK,OAAQ6c,GACbrT,KAAKlB,EAIV,IAAImW,GAAc,CAClB,IAAIV,EAAO,CAEP,GAAIC,KACJnZ,GAAO5H,KAAK,SAASuD,EAAE1E,GACnB,GAAImiB,EACJ,IAAI3V,EAAO9H,GAAGtF,OAASgjB,EAAc,CACjC,GAAIC,GAAa7V,EAAO9H,GAAG4d,UAAU,EAAGF,EACxCD,GAAazkB,GAAGgG,OAAO3F,MAAM2F,OAAO,QAAQgK,KAAK2U,EAAa,OAC9D3kB,GAAGgG,OAAO3F,MAAMkG,OAAO,aAAayJ,KAAKlB,EAAO9H,QAEhDyd,GAAazkB,GAAGgG,OAAO3F,MAAM2F,OAAO,OAExC,IAAI6e,EACJ,KAGI,GAFAA,EAAiBJ,EAAW5a,OAAOkM,wBAEd,GAAlB8O,EAAqB,KAAMC,SAElC,MAAM5jB,GACF2jB,EAAiBtlB,EAAGG,MAAMoQ,oBAAoB2U,GAGlDD,EAAazhB,KAAK8hB,EAAiBE,IAGvC,IAAIC,GAAe,EACfE,IAGJ,KAFAD,EAAc,EAEQngB,EAAdmgB,GAAgCD,EAAeR,EAAa9iB,QAChEwjB,EAAaF,GAAgBR,EAAaQ,GAC1CC,GAAeT,EAAaQ,IAIhC,KAFqB,IAAjBA,IAAoBA,EAAe,GAE/BC,EAAcngB,GAAkBkgB,EAAe,GAAI,CACvDE,KACAF,GAEA,KAAK,GAAIG,GAAI,EAAGA,EAAIX,EAAa9iB,OAAQyjB,IACjCX,EAAaW,IAAMD,EAAaC,EAAIH,IAAiB,KACrDE,EAAaC,EAAIH,GAAgBR,EAAaW,GAGtDF,GAAcC,EAAaE,OAAO,SAASC,EAAMC,EAAKrd,EAAOsd,GACzD,MAAOF,GAAOC,IAKtB,IAAK,GADDE,MACKljB,EAAI,EAAGmjB,EAAO,EAAOT,EAAJ1iB,EAAkBA,IACxCkjB,EAAWljB,GAAKmjB,EAChBA,GAAQP,EAAa5iB,EAGzB+I,GACK7E,KAAK,YAAa,SAASQ,EAAG1E,GAC3B,MAAO,aAAekjB,EAAWljB,EAAI0iB,GAAgB,KAAO,EAAIzc,KAAKyB,MAAM1H,EAAI0iB,GAAgBV,GAAe,MAIlH9D,EACAvK,EAAEzP,KAAK,YAAa,cAAgBP,EAAQtB,EAAOqQ,MAAQiQ,GAAe,IAAMtgB,EAAOE,IAAM,KAG7FoR,EAAEzP,KAAK,YAAa,eAAsB7B,EAAOE,IAAM,KAG3DqB,EAASvB,EAAOE,IAAMF,EAAOoQ,OAAUxM,KAAKmd,KAAKlB,EAAa9iB,OAASsjB,GAAgBV,MAEpF,CAEH,GAGIqB,GAHAC,EAAO,EACPC,EAAU,EACVC,EAAW,CAEfza,GACK7E,KAAK,YAAa,SAASQ,EAAG1E,GAC3B,GAAIZ,GAAS1B,GAAGgG,OAAO3F,MAAM2F,OAAO,QAAQ6D,OAAOkM,wBAA0BgP,CAc7E,OAbAY,GAAOE,EAEH5f,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAAQ2Q,EAAOjkB,IAC5CmkB,EAAUF,EAAO,EACjBC,GAAQtB,GAGZuB,GAAWnkB,EACPmkB,EAAUC,IAAUA,EAAWD,GAElBF,EAAOG,EAArBb,IACCA,EAAcU,EAAOG,GAElB,aAAeH,EAAO,IAAMC,EAAO,MAIlD3P,EAAEzP,KAAK,YAAa,cAAgBP,EAAQtB,EAAOqQ,MAAQ8Q,GAAY,IAAMnhB,EAAOE,IAAM,KAE1FqB,EAASvB,EAAOE,IAAMF,EAAOoQ,OAAS6Q,EAAO,GAGjD,GAAW,WAARtC,EAAmB,CAElBI,EACKld,KAAK,QAAS,SAASQ,EAAE1E,GACtB,MAAOwhB,GAAW,GAAGxhB,GAAGyT,wBAA0B,KAErDvP,KAAK,SAAU,IACfA,KAAK,IAAK,IACVA,KAAK,IAAK,KAGfkU,EAAO+L,OAAO,OAAO,gBAChBjgB,KAAK,QAAS,gBACdA,KAAK,OAAQ,QAEbA,KAAK,UAAU,EAEpB,IAAIkgB,GAAWzQ,EAAEjQ,OAAO,gBAExB0gB,GACC/Z,aAAatF,SAAS,KAClBb,KAAK,KAAM8d,GACX9d,KAAK,QAASye,EAAcX,EAAc,IAC1C9d,KAAK,SAAUN,EAAS,IACxBM,KAAK,KAAM7B,EAAOE,IAAM,IACxB2B,KAAK,UAAW+c,EAAW,EAAI,GAKxCG,EACKpa,MAAM,OAAQma,GACdna,MAAM,eAAgBkd,GACtBld,MAAM,SAAUma,KA8BlBrhB,EA5UX,GAAIuC,IAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACRC,EAAS,GACT4I,EAAS,SAAS9H,GAAK,MAAOA,GAAEyE,KAChCF,EAAQhM,EAAGG,MAAM4O,WACjBoW,EAAe,GACfH,GAAQ,EACRQ,EAAU,GACVvE,GAAa,EACbwB,GAAc,EACdkC,GAAkB,EAClBX,GAAW,EACXxjB,EAAWC,GAAGD,SAAS,cAAe,iBAAkB,kBAAmB,iBAAkB,eAC7FujB,EAAO,SAqWb,OA/BAlhB,GAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtEkE,KAAa8B,IAAK,WAAW,MAAOuB,IAAUtB,IAAK,SAASjG,GAAGuH,EAAOvH,IACtEgd,OAAahX,IAAK,WAAW,MAAOgX,IAAS/W,IAAK,SAASjG,GAAGgd,EAAMhd,IACpEmd,cAAiBnX,IAAK,WAAW,MAAOmX,IAAgBlX,IAAK,SAASjG,GAAGmd,EAAand,IACtFiZ,YAAgBjT,IAAK,WAAW,MAAOiT,IAAchT,IAAK,SAASjG,GAAGiZ,EAAWjZ,IACjFwd,SAAgBxX,IAAK,WAAW,MAAOwX,IAAWvX,IAAK,SAASjG,GAAGwd,EAAQxd,IAC3Eya,aAAgBzU,IAAK,WAAW,MAAOyU,IAAexU,IAAK,SAASjG,GAAGya,EAAYza,IACnF2c,iBAAqB3W,IAAK,WAAW,MAAO2W,IAAmB1W,IAAK,SAASjG,GAAG2c,EAAgB3c,IAChGgc,UAAahW,IAAK,WAAW,MAAOgW,IAAY/V,IAAK,SAASjG,GAAGgc,EAAShc,IAC1E+b,MAAS/V,IAAK,WAAW,MAAO+V,IAAQ9V,IAAK,SAASjG,GAAG+b,EAAK/b,IAG9D5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,OAIlChI,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAOkH,KAAO,WACb,YA6CA,SAASzE,GAAMoB,GA2HX,MA1HAgN,GAAYW,QACZX,EAAY7Q,OAAOgnB,GACnBnjB,EAAUC,KAAK,SAASC,GACpBqC,EAAY/F,GAAGgG,OAAO3F,KACtB,IAAIyE,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAClEpF,GAAGG,MAAMiV,QAAQ5O,GAGjBY,EAAIggB,EAAQphB,SACZmI,EAAIiZ,EAAQ1M,SAEZf,EAAKA,GAAMvS,EACXwS,EAAKA,GAAMzL,CAGX,IAAIvH,GAAOJ,EAAUK,UAAU,qBAAqB1C,MAAMA,IACtD2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,wBACnDmU,EAAYtU,EAAUE,OAAO,QAC7BmU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,aACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,kBAEjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEvE8hB,EACK1gB,MAAMnB,GACNoB,OAAOnB,EAEZ,IAAI6hB,GAAczgB,EAAKH,OAAO,kBAC9B4gB,GAAYlmB,KAAKimB,GAEjBhM,EAAUpU,OAAO,YACZC,KAAK,KAAM,gBAAkBmgB,EAAQtd,MACrC9C,OAAO,QAEZJ,EAAKH,OAAO,iBAAmB2gB,EAAQtd,KAAO,SACzC7C,KAAK,QAAS1B,GACd0B,KAAK,SAAWzB,EAAkB,EAAKA,EAAkB,GAE9DkR,EAAKzP,KAAK,YAAauX,EAAW,qBAAuB4I,EAAQtd,KAAO,IAAM,IAC9Eud,EACKpgB,KAAK,YAAauX,EAAW,qBAAuB4I,EAAQtd,KAAO,IAAM,GAE9E,IAAIgZ,GAASlc,EAAKH,OAAO,cAAcI,UAAU,aAC5C1C,KAAK,SAASsD,GAAK,MAAOA,IAAK,SAASA,GAAK,MAAOA,GAAEyE,KAC3D4W,GAAO/b,QAAQC,OAAO,KACjB+C,MAAM,iBAAkB,MACxBA,MAAM,eAAgB,SAAStC,GAAK,MAAOA,GAAE6f,aAAeA,IAC5Dvd,MAAM,eAAgB,MAE3B+Y,EAAOpb,OAAOC,SAEdmb,EACK7b,KAAK,QAAS,SAASQ,EAAE1E,GACtB,OAAQ0E,EAAEuC,SAAW,IAAM,uBAAyBjH,IAEvDiH,QAAQ,QAAS,SAASvC,GAAK,MAAOA,GAAEuS,QACxCjQ,MAAM,OAAQ,SAAStC,EAAE1E,GAAI,MAAOiJ,GAAMvE,EAAG1E,KAC7CgH,MAAM,SAAU,SAAStC,EAAE1E,GAAI,MAAOiJ,GAAMvE,EAAG1E,KACpD+f,EAAO9R,gBAAgBC,EAAa,gBAC/BlH,MAAM,iBAAkB,GACxBA,MAAM,eAAgB,SAAStC,GAAK,MAAOA,GAAE8f,aAAe,IAEjE,IAAIC,GAAY1E,EAAOjc,UAAU,gBAC5B1C,KAAK,SAASsD,GAAK,MAAOggB,GAAOhgB,IAAMA,OAC5C+f,GAAUzgB,QAAQC,OAAO,QACpBC,KAAK,QAAS,WACdA,KAAK,IAAK,SAASQ,GAChB,MAAOhH,IAAGoU,IAAI6S,OACTC,YAAYA,GACZC,QAAQA,GACRxgB,EAAE,SAASK,EAAE1E,GAAK,MAAO/C,GAAGG,MAAMoH,UAAUoS,EAAGf,EAAKnR,EAAE1E,OACtD6W,GAAG,SAASnS,EAAE1E,GAAK,MAAO/C,GAAGG,MAAMoH,UAAUqS,EAAGa,EAAKhT,EAAE1E,OACvD8kB,GAAG,SAASpgB,EAAE1E,GAAK,MAAO6W,GAAIzL,EAAE/B,SAAS,IAAM,EAAI+B,EAAE/B,SAAS,IAAM,EAAI,EAAI+B,EAAE/B,SAAS,GAAK+B,EAAE/B,SAAS,MAEvG5K,MAAMV,MAAO2G,EAAES,WAE5B4a,EAAOpb,OAAOb,UAAU,gBACnBc,SAEL6f,EAAUxW,gBAAgBC,EAAa,mBAClChK,KAAK,IAAK,SAASQ,GAChB,MAAOhH,IAAGoU,IAAI6S,OACTC,YAAYA,GACZC,QAAQA,GACRxgB,EAAE,SAASK,EAAE1E,GAAK,MAAO/C,GAAGG,MAAMoH,UAAUH,EAAEwR,EAAKnR,EAAE1E,OACrD6W,GAAG,SAASnS,EAAE1E,GAAK,MAAO/C,GAAGG,MAAMoH,UAAU4G,EAAEsM,EAAKhT,EAAE1E,OACtD8kB,GAAG,SAASpgB,EAAE1E,GAAK,MAAOoL,GAAGA,EAAE/B,SAAS,IAAM,EAAI+B,EAAE/B,SAAS,IAAM,EAAI,EAAI+B,EAAE/B,SAAS,GAAK+B,EAAE/B,SAAS,MAEtG5K,MAAMV,MAAO2G,EAAES,UAG5B,IAAI4f,GAAYhF,EAAOjc,UAAU,gBAC5B1C,KAAK,SAASsD,GAAK,OAAQA,EAAES,SAElC4f,GAAU/gB,QAAQC,OAAO,QACpBC,KAAK,QAAS,WACdA,KAAK,IACFxG,GAAGoU,IAAIvN,OACNqgB,YAAYA,GACZC,QAAQA,GACRxgB,EAAE,SAASK,EAAE1E,GAAK,MAAO/C,GAAGG,MAAMoH,UAAUoS,EAAGf,EAAKnR,EAAE1E,OACtDoL,EAAE,SAAS1G,EAAE1E,GAAK,MAAO/C,GAAGG,MAAMoH,UAAUqS,EAAGa,EAAKhT,EAAE1E,QAG/D+kB,EAAU9W,gBAAgBC,EAAa,mBAClChK,KAAK,IACFxG,GAAGoU,IAAIvN,OACNqgB,YAAYA,GACZC,QAAQA,GACRxgB,EAAE,SAASK,EAAE1E,GAAK,MAAO/C,GAAGG,MAAMoH,UAAUH,EAAEwR,EAAKnR,EAAE1E,OACrDoL,EAAE,SAAS1G,EAAE1E,GAAK,MAAO/C,GAAGG,MAAMoH,UAAU4G,EAAEsM,EAAKhT,EAAE1E,QAI9D4W,EAAKvS,EAAEoR,OACPoB,EAAKzL,EAAEqK,SAEXvH,EAAYS,UAAU,kBACf7O,EAnKX,GAcMuE,GACA+G,EAfDiZ,EAAUpnB,EAAGI,OAAOgnB,UAGrBhiB,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACRC,EAAS,IACTH,EAAY,KACZ8gB,EAAc,IACdtb,EAAQhM,EAAGG,MAAM6O,eACjB4J,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9ByZ,EAAU,SAASngB,EAAE1E,GAAK,OAAQgO,MAAM0J,EAAKhT,EAAE1E,KAAqB,OAAd0X,EAAKhT,EAAE1E,IAC7D0kB,EAAS,SAAShgB,GAAK,MAAOA,GAAEigB,MAChClJ,GAAW,EAGXmJ,EAAc,SACd7f,EAAW,IACXtH,EAAWC,GAAGD,SAAS,eAAgB,mBAAoB,kBAAmB,YAGpF4mB,GACKW,UAAU,IACVC,aAAa,GAAG,KAUrB,IAAIrO,GAAIC,EACF3I,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,EA0LnD,OAjDAjF,GAAMrC,SAAWA,EACjBqC,EAAMukB,QAAUA,EAEhBA,EAAQ5mB,SAASkB,GAAG,eAAgB,WAAYlB,EAAS6F,aAAa7E,MAAMV,KAAMM,aAClFgmB,EAAQ5mB,SAASkB,GAAG,mBAAoB,WAAYlB,EAASyZ,iBAAiBzY,MAAMV,KAAMM,aAC1FgmB,EAAQ5mB,SAASkB,GAAG,kBAAmB,WAAYlB,EAASoF,gBAAgBpE,MAAMV,KAAMM,aAExFyB,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtE4f,SAAU5Z,IAAK,WAAW,MAAO4Z,IAAW3Z,IAAK,SAASjG,GAAG4f,EAAQ5f,IACrE2f,aAAmB3Z,IAAK,WAAW,MAAO2Z,IAAe1Z,IAAK,SAASjG,GAAG2f,EAAY3f,IACtFwW,UAAcxQ,IAAK,WAAW,MAAOwQ,IAAYvQ,IAAK,SAASjG,GAAGwW,EAASxW,IAG3E5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,GAClBsf,EAAQtf,SAASA,KAErB2f,QAASzZ,IAAK,WAAW,MAAOyZ,IAAUxZ,IAAK,SAASjG,GACpDyf,EAAShnB,GAAGsU,QAAQ/M,KAExBZ,GAAI4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAC7C4Q,EAAO5Q,EACPof,EAAQhgB,EAAEY,KAEdmG,GAAIH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAC7CyS,EAAOzS,EACPof,EAAQjZ,EAAEnG,KAEdgE,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1Bof,EAAQpb,MAAMA,OAItBhM,EAAGG,MAAM6U,eAAenS,EAAOukB,GAC/BpnB,EAAGG,MAAMiO,YAAYvL,GAEdA,GAEX7C,EAAGI,OAAO6nB,UAAY,WAClB,YAiEA,SAASplB,GAAMoB,GAoPX,MAnPAgN,GAAYW,QACZX,EAAY7Q,OAAOkf,GACfzE,GAAW5J,EAAY7Q,OAAO0a,GAC9BC,GAAW9J,EAAY7Q,OAAO4a,GAElC/W,EAAUC,KAAK,SAASC,GACpB,GAAIqC,GAAY/F,GAAGgG,OAAO3F,MACtBif,EAAOjf,IACXd,GAAGG,MAAMiV,QAAQ5O,EACjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAkBlE,IAhBAvC,EAAM+P,OAAS,WACM,IAAb9K,EACAtB,EAAUrF,KAAK0B,GAEf2D,EAAU4G,aAAatF,SAASA,GAAU3G,KAAK0B,IAEvDA,EAAM2D,UAAY1F,KAElBwP,EACKqC,OAAOqN,EAAY7b,GAAOtB,EAAM+P,QAChCH,OAAOwN,EAAY9b,IACnByO,SAGLtC,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,YAE9C0E,EAAc,CACf,GAAIhU,EACJgU,KACA,KAAKhU,IAAOoE,GACJA,EAAMpE,YAAgBjL,OACtBif,EAAahU,GAAOoE,EAAMpE,GAAKhL,MAAM,GAErCgf,EAAahU,GAAOoE,EAAMpE,GAKtC,KAAK/H,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAE9E,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,SAKtCP,EAAIkY,EAAMtZ,SACVmI,EAAImR,EAAM5E,QAGV,IAAI9T,GAAOJ,EAAUK,UAAU,0BAA0B1C,MAAMA,IAC3DgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,6BAA6BD,OAAO,KACpF0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,QAAQ+C,MAAM,UAAU,GACtCoR,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,kBAEjCyP,EAAEjQ,OAAO,QACJQ,KAAK,QAAQ1B,GACb0B,KAAK,SAAUzB,EAAkB,EAAKA,EAAkB,GAGzDob,IACAC,EAAOna,MAAMnB,GAEbmR,EAAEjQ,OAAO,kBACJ8U,MAAMpX,GACNhD,KAAK0f,GAELzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SACpBnB,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IAGlEwB,EAAKH,OAAO,kBACPQ,KAAK,YAAa,gBAAmB7B,EAAOE,IAAM,MAG3DsB,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEnE+V,GACA3E,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,aAAe1B,EAAiB,OAIvD4b,IACAC,EACK1a,MAAMnB,GACNoB,OAAOnB,GACPJ;AAAQC,KAAKD,EAAOC,KAAMC,IAAIF,EAAOE,MACrC4B,aAAaV,GACbR,OAAOoB,GACZR,EAAKH,OAAO,mBAAmBtF,KAAKigB,IAGxC9B,EACK5Y,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GACvB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,WAG9C,IAAI8F,GAAY5K,EAAEjQ,OAAO,iBACpB8U,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAE/C8F,GAAUngB,KAAKme,GAGXzE,IACAC,EACKlT,MAAMR,GACNya,OAAO7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAC/CsX,UAAUjW,EAAiB,GAEhCkR,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,eAAiBkH,EAAE9B,QAAQ,GAAK,KACvDqK,EAAEjQ,OAAO,iBACJtF,KAAK2Z,IAGVC,IACAC,EACKpT,MAAMuG,GACN0T,OAAO7hB,EAAGG,MAAMoT,WAAW/N,EAAgB,GAAIrB,IAC/CsX,UAAWlW,EAAgB,GAEhCmR,EAAEjQ,OAAO,iBACJtF,KAAK6Z,IAOd6F,EAAOrgB,SAASkB,GAAG,cAAe,SAASogB,GACvC,IAAK,GAAI5V,KAAO4V,GACZxR,EAAMpE,GAAO4V,EAAS5V,EAC1B1L,GAASof,YAAYtP,GACrBzN,EAAM+P,WAGVwO,EAAiB5gB,SAASkB,GAAG,mBAAoB,SAASC,GACtD2d,EAAMF,iBACN,IAAI2C,GAAa7C,EAAY8C,EAAgBC,IAuB7C,IAtBA9d,EACKoQ,OAAO,SAASzI,EAAQ/I,GAErB,MADA+I,GAAOyV,YAAcxe,GACb+I,EAAO0P,WAElBjS,QAAQ,SAASuC,EAAO/I,GACrBmc,EAAalf,EAAGiI,kBAAkB6D,EAAO5D,OAAQvG,EAAEoE,YAAalD,EAAMuE,IACtE,IAAI8G,GAAQpC,EAAO5D,OAAOgX,GACtBgJ,EAAcrlB,EAAMsL,IAAID,EAAOgR,EAChB,OAAfgJ,GACA5I,EAAML,eAAelc,EAAGmc,GAAY,GAE1Btb,SAAVsK,IACgBtK,SAAhBme,IAA2BA,EAAc7T,GACtBtK,SAAnBoe,IAA8BA,EAAiBnf,EAAMmD,SAASnD,EAAMuE,IAAI8G,EAAMgR,KAClF+C,EAAQze,MACJ0I,IAAKJ,EAAOI,IACZR,MAAOwc,EACPlc,MAAOA,EAAMF,EAAOA,EAAOyV,kBAInCU,EAAQ9f,OAAS,EAAG,CACpB,GAAI+f,GAASrf,EAAM6X,SAASzU,OAAOtE,EAAE6C,QACjC2d,EAAenZ,KAAKC,IAAIpG,EAAM6X,SAAStO,SAAS,GAAKvJ,EAAM6X,SAAStO,SAAS,IAC7EjD,EAAY,IAAOgZ,EACnB7Y,EAAmBtJ,EAAGkJ,kBAAkB+Y,EAAQ/O,IAAI,SAASzL,GAAG,MAAOA,GAAEiE,QAAQwW,EAAO/Y,EACnE,QAArBG,IACA2Y,EAAQ3Y,GAAkByC,WAAY,GAG9C,GAAIqW,GAAStH,EAAM/D,aAAalU,EAAMuE,IAAI2a,EAAY7C,GACtDkC,GAAiBlhB,QACZwJ,eAAeqW,EAAK/P,YACpB7E,eAAe,SAAS1D,EAAE1E,GACvB,MAAY,OAAL0E,EAAY,MAAQuT,EAAMjE,aAAatP,KAEjDtD,MACGuH,MAAO0W,EACP1Z,MAAOwW,EACPpT,OAAQmW,MAGhBb,EAAiBvb,gBAAgBmc,KAIrCZ,EAAiB5gB,SAASkB,GAAG,eAAgB,SAASC,GAClD,GAAIqgB,GAAgBC,IAEpB9d,GAAKoQ,OAAO,SAASzI,EAAQ/I,GAEzB,MADA+I,GAAOyV,YAAcxe,GACb+I,EAAO0P,WAChBjS,QAAQ,SAASuC,GAChB,GAAIoT,GAAalf,EAAGiI,kBAAkB6D,EAAO5D,OAAQvG,EAAEoE,YAAalD,EAAMuE,KACtE8G,EAAQpC,EAAO5D,OAAOgX,EAC1B,IAAqB,mBAAVhR,GAAX,CAC8B,mBAAnB8T,KAAgCA,EAAiBnf,EAAMmD,SAASnD,EAAMuE,IAAI8G,EAAMgR,IAC3F,IAAIiJ,GAAOtlB,EAAM6X,SAAS7X,EAAMsL,IAAID,EAAMgR,GAC1C+C,GAAQze,MACJ0K,MAAOA,EACPgR,WAAYA,EACZvS,KAAMqV,EAAgBmG,GACtB5G,YAAazV,EAAOyV,YACpBzV,OAAQA,OAIhBwT,EAAM9e,SAAS6F,aAAa4b,KAGhCb,EAAiB5gB,SAASkB,GAAG,kBAAkB,SAASC,GACpD2d,EAAMF,oBAGV5e,EAASkB,GAAG,cAAe,SAASC,GACN,mBAAfA,GAAE6Z,UAA4BrX,EAAKhC,SAAWR,EAAE6Z,SAASrZ,SAChEgC,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,SAAW7Z,EAAE6Z,SAASzY,KAGjCuN,EAAMkL,SAAW7Z,EAAE6Z,UAGvB3Y,EAAM+P,aAKd3B,EAAYS,UAAU,uBACf7O,EA/SX,GAiBMuE,GACA+G,EAlBFmR,EAAQtf,EAAGI,OAAOkH,OAChBwT,EAAQ9a,EAAGI,OAAOqW,OAClBuE,EAAQhb,EAAGI,OAAOqW,OAClBoK,EAAS7gB,EAAGI,OAAOygB,SACnBO,EAAmBphB,EAAG+D,uBACtB7D,EAAUF,EAAGI,OAAOF,UAGtBkF,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9C2G,EAAQhM,EAAGG,MAAM6O,eACjBtI,EAAQ,KACRC,EAAS,KACTia,GAAa,EACb/F,GAAY,EACZE,GAAY,EACZM,GAAkB,EAClB8F,GAA0B,EAG1B7Q,EAAQtQ,EAAGG,MAAMmQ,QACjB4P,EAAe,KACfxK,EAAS,KACTlV,EAAWC,GAAGD,SAAS,cAAe,cAAe,cAAe,cAAe,aACnFsH,EAAW,GAIjBgT,GAAMlE,OAAO,UAAUY,YAAY,GACnCwD,EAAMpE,OAAOyE,EAAkB,QAAU,QACzCnb,EAAQiL,eAAe,SAAS1D,EAAG1E,GAC/B,MAAOiY,GAAMjE,aAAatP,EAAG1E,KAC9BqI,gBAAgB,SAAS3D,EAAG1E,GAC3B,MAAO+X,GAAM/D,aAAatP,EAAG1E,IAQjC,IAAIkO,GAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,GAE7CmY,EAAc,SAAS9b,GACvB,MAAO,YACH,OACIzB,OAAQyB,EAAK+O,IAAI,SAASzL,GAAK,OAAQA,EAAE+T,cAKjDwE,EAAc,SAAS7b,GACvB,MAAO,UAASmM,GACS1M,SAAjB0M,EAAM5N,QACNyB,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,UAAYlL,EAAM5N,OAAOK,MAqUhD,OArEAuc,GAAM9e,SAASkB,GAAG,2BAA4B,SAASia,GACnDzb,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7BwZ,EAAM9e,SAASkB,GAAG,0BAA2B,SAASia,GAClDzb,EAAQ4F,QAAO,KAQnBjD,EAAMrC,SAAWA,EACjBqC,EAAMyc,MAAQA,EACdzc,EAAMge,OAASA,EACfhe,EAAMiY,MAAQA,EACdjY,EAAMmY,MAAQA,EACdnY,EAAMue,iBAAmBA,EACzBve,EAAM3C,QAAUA,EAEhB2C,EAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtE4Y,YAAa5S,IAAK,WAAW,MAAO4S,IAAc3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IAC9E6S,WAAiB7M,IAAK,WAAW,MAAO6M,IAAa5M,IAAK,SAASjG,GAAG6S,EAAU7S,IAChF+S,WAAe/M,IAAK,WAAW,MAAO+M,IAAa9M,IAAK,SAASjG,GAAG+S,EAAU/S,IAC9EkY,cAAkBlS,IAAK,WAAW,MAAOkS,IAAgBjS,IAAK,SAASjG,GAAGkY,EAAalY,IACvF0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IAGrE5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,GAClBwX,EAAMxX,SAASA,GACfgT,EAAMhT,SAASA,GACfkT,EAAMlT,SAASA,KAEnBkE,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1B6Y,EAAO7U,MAAMA,GACbsT,EAAMtT,MAAMA,KAEhBqP,iBAAkBrN,IAAK,WAAW,MAAOqN,IAAmBpN,IAAK,SAASjG,GACtEqT,EAAkBrT,EAClBgT,EAAMpE,OAAQyE,EAAkB,QAAU,UAE9C8F,yBAA0BnT,IAAK,WAAW,MAAOmT,IAA2BlT,IAAK,SAASjG,GACtFmZ,EAA0BnZ,EACtBmZ,IACA7B,EAAMN,aAAY,GAClBM,EAAMoD,YAAW,QAK7B1iB,EAAGG,MAAM6U,eAAenS,EAAOyc,GAC/Btf,EAAGG,MAAMiO,YAAYvL,GAEdA,GAEX7C,EAAGI,OAAOgoB,iBAAmB,WACzB,YA4FA,SAASvlB,GAAMoB,GAuYX,MAtYAA,GAAUC,KAAK,SAASC,GAkQpB,QAASkkB,GAAW5gB,GAChB,GAAI9F,KAAW,KAAL8F,GACNL,EAAIzF,EAAI,EAAI,GACZwM,EAAIma,EAAmB,CAC3B,OAAO,IAAO,GAAKlhB,EAAK,IAAM+G,EACxB,YAAcxM,EAAI,IAAO,IAAMyF,EAAK,KAAO+G,EAAI,GAC/C,KAAO,EAAIA,EAAI,GACf,YAAcxM,EAAI,IAAO,GAAKyF,EAAK,IAAO,EAAI+G,EAC9C,KACO,IAAM/G,EAAK,KAAO+G,EAAI,GAC7B,KAAO,EAAIA,EAAI,GACf,IAAO,IAAM/G,EAAK,KAAO+G,EAAI,GAC7B,KAAO,EAAIA,EAAI,GAIzB,QAASoa,KACAC,EAAMC,SAASD,EAAM5L,OAAO8L,GACjCC,GACKxkB,MAAMqkB,EAAMC,QAAUG,EAAGxc,SAAWsc,IACpCxkB,KAAK,SAASuD,EAAE1E,GACb,GAAI8lB,GAAYD,EAAGnhB,EAAE,IAAMmhB,EAAGvc,QAAQ,GAClCyc,EAAaF,EAAGvc,QAAQ,GAAKuc,EAAGnhB,EAAE,GACtChH,IAAGgG,OAAO3F,MAAM2F,OAAO,SAClBQ,KAAK,QAAsB,EAAZ4hB,EAAgB,EAAIA,GAExCpoB,GAAGgG,OAAO3F,MAAM2F,OAAO,UAClBQ,KAAK,IAAK2hB,EAAGnhB,EAAE,KACfR,KAAK,QAAsB,EAAb6hB,EAAiB,EAAIA,KAIpD,QAASC,KACLL,EAAcF,EAAMC,QAAU,KAAOD,EAAM5L,SAC3CA,EAAS4L,EAAMC,QAAUG,EAAGxc,SAAWoc,EAAM5L,SAC7Cpc,EAASgoB,OAAO5L,OAAQA,EAAQ4L,MAAOA,IACvCD,IAGAxF,EACKrc,MAAMnB,GACNoB,OAAOqiB,GACPhd,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GACvB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,UAAYrX,EAAKpB,GAAGkmB,OAElE3J,EACK5Y,MAAMnB,GACNoB,OAAOqiB,GACPhd,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GACvB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,WAAarX,EAAKpB,GAAGkmB,MAEnE,IAAIC,GAAgBxS,GAAEjQ,OAAO,0BACxB8U,MAAO4N,EAAShnB,OACbgnB,EACKjW,IAAI,SAASzL,EAAE1E,GACZ,OACImJ,IAAKzE,EAAEyE,IACPhE,OAAQT,EAAES,OAAOqM,OAAO,SAAS9M,EAAE1E,GAC/B,MAAOggB,GAAK3b,IAAIK,EAAE1E,IAAM6Z,EAAO,IAAMmG,EAAK3b,IAAIK,EAAE1E,IAAM6Z,EAAO,UANrD1U,aAY5BkhB,EAAiB1S,GAAEjQ,OAAO,2BACzB8U,MAAM8N,EAAYC,KAAephB,YAC3BohB,EACC/U,OAAO,SAASgV,GAAY,OAAQA,EAAS/N,WAC7CtI,IAAI,SAASzL,EAAE1E,GACX,OACI2kB,KAAMjgB,EAAEigB,KACRH,YAAa9f,EAAE8f,YACfrb,IAAKzE,EAAEyE,IACPhE,OAAQT,EAAES,OAAOqM,OAAO,SAAS9M,EAAE1E,GAC/B,MAAOuc,GAAMlY,IAAIK,EAAE1E,IAAM6Z,EAAO,IAAM0C,EAAMlY,IAAIK,EAAE1E,IAAM6Z,EAAO,QAQnFxV,GADA+hB,EAAShnB,OACL4gB,EAAK/c,SAELsZ,EAAMtZ,SAGd8U,EACKlT,MAAMR,GACNya,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAChDsX,UAAUuN,EAAkB,GAEjClO,EAAM1O,QAAQpD,KAAKmd,KAAKvJ,EAAO,IAAK5T,KAAKyB,MAAMmS,EAAO,MAEtDlG,GAAEjQ,OAAO,iBAAiB2G,aAAatF,SAAS8e,GAC3CzlB,KAAK2Z,GAGVoO,EAAc9b,aAAatF,SAAS8e,GAAoBzlB,KAAK4hB,GAC7DqG,EAAehc,aAAatF,SAAS8e,GAAoBzlB,KAAKme,GAG9D5I,GAAEjQ,OAAO,2BACJQ,KAAK,YAAa,eAAiB4gB,EAAGxb,QAAQ,GAAK,KAExDmd,EACK5hB,MAAMigB,GACNhG,OAAQ7hB,EAAGG,MAAMoT,WAAWyV,EAAiB,GAAI7kB,IACjDsX,UAAUlW,EAAgB,GAC/BkkB,EACK7hB,MAAM8hB,GACN7H,OAAQ7hB,EAAGG,MAAMoT,WAAWyV,EAAiB,GAAI7kB,IACjDsX,SAAS0N,EAAShnB,OAAS,GAAKoD,EAAgB,GAErDmR,GAAEjQ,OAAO,4BACJsD,MAAM,UAAWof,EAAShnB,OAAS,EAAI,GAC5CuU,GAAEjQ,OAAO,4BACJsD,MAAM,UAAWuf,EAAUnnB,SAAWknB,EAAYC,GAAa,EAAI,GACnEriB,KAAK,YAAa,aAAeG,EAAEiF,QAAQ,GAAK,OAErDqK,GAAEjQ,OAAO,4BAA4B2G,aAAatF,SAAS8e,GACtDzlB,KAAKqoB,GACV9S,GAAEjQ,OAAO,4BAA4B2G,aAAatF,SAAS8e,GACtDzlB,KAAKsoB,GA9Xd,GAAIjjB,GAAY/F,GAAGgG,OAAO3F,KAE1Bd,GAAGG,MAAMiV,QAAQ5O,EACjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3D4jB,EAAmBhpB,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IACxDukB,EAAcC,EAAc,GACnCtB,EAAmBsB,EAAcC,EAAQvkB,IAAMukB,EAAQrU,MAa3D,IAXA3S,EAAM+P,OAAS,WAAapM,EAAU4G,aAAatF,SAAS8e,GAAoBzlB,KAAK0B,IACrFA,EAAM2D,UAAY1F,KAElBwP,EACKqC,OAAOqN,EAAY7b,GAAOtB,EAAM+P,QAChCH,OAAOwN,EAAY9b,IACnByO,SAGLtC,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,YAE9C0E,EAAc,CACf,GAAIhU,EACJgU,KACA,KAAKhU,IAAOoE,GACJA,EAAMpE,YAAgBjL,OACtBif,EAAahU,GAAOoE,EAAMpE,GAAKhL,MAAM,GAErCgf,EAAahU,GAAOoE,EAAMpE,GAKtC,KAAK/H,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAE9E,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,QAItC,IAAIwhB,GAAWhlB,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,UAAY/T,EAAEwhB,MAC7DK,EAAYnlB,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAEwhB,KAEpD7hB,GAAI2b,EAAK/c,SACT4iB,EAAKkB,EAAOliB,QACZigB,EAAK9E,EAAKrI,SACVgP,EAAKpK,EAAM5E,SACXqP,EAAKC,EAAMtP,SACXuP,EAAKC,EAAOxP,QAEZ,IAAIyP,IAAUhmB,EACToQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,UAAY/T,EAAEwhB,MAC7C/V,IAAI,SAASzL,GACV,MAAOA,GAAES,OAAOgL,IAAI,SAASzL,EAAE1E,GAC3B,OAASqE,EAAGwR,EAAKnR,EAAE1E,GAAIoL,EAAGsM,EAAKhT,EAAE1E,QAIzCqnB,GAAUjmB,EACToQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAAa/T,EAAEwhB,MAC9C/V,IAAI,SAASzL,GACV,MAAOA,GAAES,OAAOgL,IAAI,SAASzL,EAAE1E,GAC3B,OAASqE,EAAGwR,EAAKnR,EAAE1E,GAAIoL,EAAGsM,EAAKhT,EAAE1E,OAI7CqE,GAAEiF,OAAO,EAAG9G,IAEZqjB,EAAKxc,OAAO3L,GAAGmc,OAAOnc,GAAGoc,MAAMsN,GAAQ1oB,OAAO2oB,KAAW,SAAS3iB,GAAK,MAAOA,GAAEL,KAC3EiF,OAAO,EAAG9G,GAGf,IAAIqB,IAAOJ,EAAUK,UAAU,4BAA4B1C,MAAMA,IAC7DgX,GAASvU,GAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,+BAA+BD,OAAO,KACtF0P,GAAI9P,GAAKH,OAAO,IAEpB0U,IAAOnU,OAAO,KAAKC,KAAK,QAAS,gBAGjC,IAAIojB,IAAalP,GAAOnU,OAAO,KAAKC,KAAK,QAAS,WAClDojB,IAAWrjB,OAAO,KAAKC,KAAK,QAAS,gBACrCojB,GAAWrjB,OAAO,KAAKC,KAAK,QAAS,iBACrCojB,GAAWrjB,OAAO,KAAKC,KAAK,QAAS,iBACrCojB,GAAWrjB,OAAO,KAAKC,KAAK,QAAS,eACrCojB,GAAWrjB,OAAO,KAAKC,KAAK,QAAS,eAGrC,IAAIqjB,IAAenP,GAAOnU,OAAO,KAAKC,KAAK,QAAS,aAapD,IAZAqjB,GAAatjB,OAAO,KAAKC,KAAK,QAAS,gBACvCqjB,GAAatjB,OAAO,KAAKC,KAAK,QAAS,iBACvCqjB,GAAatjB,OAAO,KAAKC,KAAK,QAAS,iBACvCqjB,GAAatjB,OAAO,KAAKC,KAAK,QAAS,eACvCqjB,GAAatjB,OAAO,KAAKC,KAAK,QAAS,gBACvCqjB,GAAatjB,OAAO,KAAKC,KAAK,QAAS,sBACvCqjB,GAAatjB,OAAO,KAAKC,KAAK,QAAS,iBAMnC2Z,EAAY,CACZ,GAAI8E,IAAc7E,EAAOmE,QAAUzf,EAAiB,EAAIA,EACpDglB,GAAkB1J,EAAOmE,QAAUU,GAAc,CAErD7E,GAAOna,MAAMgf,IAEbhP,GAAEjQ,OAAO,kBACJ8U,MAAMpX,EAAK+O,IAAI,SAASpH,GAGrB,MAFAA,GAAO0e,YAAqC5mB,SAAvBkI,EAAO0e,YAA4B1e,EAAOI,IAAMJ,EAAO0e,YAC5E1e,EAAOI,IAAMJ,EAAO0e,aAAe1e,EAAOmd,IAAMwB,EAAqBC,GAC9D5e,KAEV3K,KAAK0f,GAELzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SAEpBqiB,EAAmBhpB,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,GAAUwkB,GAG7ElT,GAAEjQ,OAAO,kBACJQ,KAAK,YAAa,aAAesjB,GAAkB,KAAQnlB,EAAOE,IAAM,KAGjFsB,GAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAOvEoR,GAAEjQ,OAAO,eAAesD,MAAM,UAAW4f,EAAc,UAAY,QAEnEK,EACKtjB,MAAMnB,GACNoB,OAAO2hB,GACPtc,MAAM7H,EAAK+O,IAAI,SAAUzL,EAAG1E,GACzB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAU9M,EAAG1E,GACnB,OAAQoB,EAAKpB,GAAGyY,UAAYrX,EAAKpB,GAAGkmB,OAE5CiB,EACKxjB,MAAMnB,GACNoB,OAAO2hB,GACPtc,MAAM7H,EAAK+O,IAAI,SAAUzL,EAAG1E,GACzB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAU9M,EAAG1E,GACnB,OAAQoB,EAAKpB,GAAGyY,WAAarX,EAAKpB,GAAGkmB,MAG7C,IAAI0B,IAAYjU,GAAEjQ,OAAO,4BACpB8U,MAAM4N,EAAShnB,OAASgnB,IACpBjhB,aAEL0iB,GAAalU,GAAEjQ,OAAO,6BACrB8U,MAAM8N,EAAYC,KACVphB,YACFohB,EAAU/U,OAAO,SAASgV,GACxB,OAAQA,EAAS/N,WAG9B9E,IAAEjQ,OAAO,eACJQ,KAAK,YAAa,gBAAmB+hB,EAAmB5jB,EAAOoQ,OAASqU,EAAQvkB,KAAO,KAE5FqlB,GAAUvd,aAAajM,KAAK6oB,GAC5BY,GAAWxd,aAAajM,KAAK+oB,GAGzBW,IACAf,EACKjI,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAiB,IAAKpB,IAClDsX,UAAU6M,EAAkB,GACjC5R,GAAEjQ,OAAO,6BACJQ,KAAK,YAAa,eAAiB8iB,EAAG1d,QAAQ,GAAK,KACxDqK,GAAEjQ,OAAO,6BAA6B2G,aACjCjM,KAAK2oB,IAGVgB,IACAC,EACKnjB,MAAMmiB,GACNlI,OAAQyG,EAAmB,IAC3B7M,UAAWlW,EAAgB,GAChCylB,EACKpjB,MAAMqiB,GACNpI,OAAQyG,EAAmB,IAC3B7M,SAAS0N,EAAShnB,OAAS,GAAKoD,EAAgB,GAErDmR,GAAEjQ,OAAO,8BACJsD,MAAM,UAAWof,EAAShnB,OAAS,EAAI,GACvC8E,KAAK,YAAa,eAAiB2hB,EAAGvc,QAAQ,GAAK,KACxDqK,GAAEjQ,OAAO,8BACJsD,MAAM,UAAWuf,EAAUnnB,OAAS,EAAI,GACxC8E,KAAK,YAAa,aAAe2hB,EAAGvc,QAAQ,GAAK,OAEtDqK,GAAEjQ,OAAO,8BAA8B2G,aAClCjM,KAAK4pB,GACVrU,GAAEjQ,OAAO,8BAA8B2G,aAClCjM,KAAK6pB,IAIdxC,EAAMphB,EAAEwhB,GAAIlnB,GAAG,QAASqnB,GAEpBL,GAAaF,EAAM5L,OAAO8L,EAE9B,IAAIC,IAAUjS,GAAEjQ,OAAO,uBAAuBI,UAAU,KACnD1C,MAAMukB,GAAeF,EAAM5L,WAE5BqO,GAAetC,GAAQ5hB,QACtBC,OAAO,IAEZikB,IAAajkB,OAAO,QACfC,KAAK,QAAS,QACdA,KAAK,IAAK,GACVA,KAAK,IAAK,GACVA,KAAK,SAAUqhB,GAEpB2C,GAAajkB,OAAO,QACfC,KAAK,QAAS,SACdA,KAAK,IAAK,GACVA,KAAK,IAAK,GACVA,KAAK,SAAUqhB,EAEpB,IAAI4C,IAASxU,GAAEjQ,OAAO,kBACjBtF,KAAKqnB,EACV0C,IAAOrkB,UAAU,QAEZI,KAAK,SAAUqhB,GACpB4C,GAAOrkB,UAAU,WAAWG,OAAO,QAAQC,KAAK,IAAKohB,GAMrDxH,EAAOrgB,SAASkB,GAAG,cAAe,SAASogB,GACvC,IAAK,GAAI5V,KAAO4V,GACZxR,EAAMpE,GAAO4V,EAAS5V,EAC1B1L,GAASof,YAAYtP,GACrBzN,EAAM+P,WAIVpS,EAASkB,GAAG,cAAe,SAASC,GACN,mBAAfA,GAAE6Z,WACTrX,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,SAAW7Z,EAAE6Z,SAASzY,KAEjCuN,EAAMkL,SAAW7Z,EAAE6Z,UAEvB3Y,EAAM+P,WAwIVmW,MAIGlmB,EA7dX,GA2BM+Z,GAEAxV,EACAwhB,EACAf,EACA6B,EACAK,EACAE,EAlCF3K,EAAQtf,EAAGI,OAAOkH,OAChB4iB,EAASlqB,EAAGI,OAAOkH,OACnByb,EAAO/iB,EAAGI,OAAOomB,gBACjBwD,EAAQhqB,EAAGI,OAAOomB,gBAClB1L,EAAQ9a,EAAGI,OAAOqW,OAClBqT,EAAS9pB,EAAGI,OAAOqW,OACnB+S,EAASxpB,EAAGI,OAAOqW,OACnBgT,EAASzpB,EAAGI,OAAOqW,OACnBsU,EAAS/qB,EAAGI,OAAOqW,OACnBuU,EAAShrB,EAAGI,OAAOqW,OACnBoK,EAAS7gB,EAAGI,OAAOygB,SACnB2H,EAAQ/nB,GAAGoU,IAAI2T,QACftoB,EAAUF,EAAGI,OAAOF,UAGtBkF,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9CwkB,GAAWvkB,IAAK,EAAGmQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAChDqB,EAAQ,KACRC,EAAS,KACTiS,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9BnC,EAAQhM,EAAGG,MAAM6O,eACjB4R,GAAa,EACb+I,GAAc,EACdmB,GAAiB,EACjBD,GAAiB,EACjBjB,EAAc,GAEdlB,EAAc,KAOdhT,EAAS,KACTlV,EAAWC,GAAGD,SAAS,QAAS,cAAe,eAC/ComB,EAAqB,EACrBtW,EAAQtQ,EAAGG,MAAMmQ,QACjB4P,EAAe,KACfuK,EAAqB,eACrBC,EAAsB,eAG5BpL,GAAMd,UAAS,GACf0L,EAAOlL,aAAY,GAEnBkL,EAAOiB,YAAY,SAAS1jB,GAAK,OAAO,IACxCqT,EAAMlE,OAAO,UAAUY,YAAY,GACnCgS,EAAO5S,OAAO,QACd6S,EAAO7S,OAAO,SACdkT,EAAOlT,OAAO,UAAUY,YAAY,GACpCuT,EAAOnU,OAAO,QACdoU,EAAOpU,OAAO,SAEd1W,EAAQ6K,eAAc,GAAMK,gBAAgB,SAAS3D,EAAG1E,GACpD,MAAO+X,GAAM/D,aAAatP,EAAG1E,IAOjC,IAAIkd,GAAc,SAAS9b,GACvB,MAAO,YACH,OACIzB,OAAQyB,EAAK+O,IAAI,SAASzL,GAAK,OAAQA,EAAE+T,cAKjDwE,EAAc,SAAS7b,GACvB,MAAO,UAASmM,GACS1M,SAAjB0M,EAAM5N,QACNyB,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,UAAYlL,EAAM5N,OAAOK,OAK5CsmB,EAAc,SAASllB,GACzB,MAAOA,GAAK2N,MAAM,SAAShG,GACzB,MAAOA,GAAO0P,WAogBlB,OAlHA8D,GAAM9e,SAASkB,GAAG,2BAA4B,SAASia,GACnDzb,EACK4H,SAAS,KACTqD,eAAe,SAAS1D,EAAG1E,GACxB,MAAO0mB,GAAO1S,aAAatP,EAAG1E,KAEjCoB,KAAKwX,GACL7V,QAAO,KAGhBwZ,EAAM9e,SAASkB,GAAG,0BAA2B,SAASia,GAClDzb,EAAQ4F,QAAO,KAGnBid,EAAKviB,SAASkB,GAAG,2BAA4B,SAASia,GAClDA,EAAIjQ,MAAQ7I,EAAMuE,IAAIuU,EAAIxX,MAC1BwX,EAAY,QACRjQ,MAAO7I,EAAMsL,IAAIwN,EAAIxX,MACrB6H,MAAO2P,EAAI3P,OAEf9L,EACK4H,SAAS,GACTqD,eAAe,SAAS1D,EAAG1E,GACxB,MAAOymB,GAAOzS,aAAatP,EAAG1E,KAEjCoB,KAAKwX,GACL7V,QAAO,KAGhBid,EAAKviB,SAASkB,GAAG,0BAA2B,SAASia,GACjDzb,EAAQ4F,QAAO,KAGnBid,EAAKviB,SAASkB,GAAG,2BAA4B,SAASia,GAClDzb,MAWJ2C,EAAMrC,SAAWA,EACjBqC,EAAMge,OAASA,EACfhe,EAAMyc,MAAQA,EACdzc,EAAMqnB,OAASA,EACfrnB,EAAMkgB,KAAOA,EACblgB,EAAMmnB,MAAQA,EACdnnB,EAAMiY,MAAQA,EACdjY,EAAMinB,OAASA,EACfjnB,EAAM2mB,OAASA,EACf3mB,EAAM4mB,OAASA,EACf5mB,EAAMkoB,OAASA,EACfloB,EAAMmoB,OAASA,EACfnoB,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtE4Y,YAAa5S,IAAK,WAAW,MAAO4S,IAAc3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IAC9E0gB,aAAiB1a,IAAK,WAAW,MAAO0a,IAAeza,IAAK,SAASjG,GAAG0gB,EAAY1gB,IACpF0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IACrE2hB,aAAiB3b,IAAK,WAAW,MAAO2b,IAAe1b,IAAK,SAASjG,GAAG2hB,EAAY3hB,IACpF4hB,aAAiB5b,IAAK,WAAW,MAAO4b,IAAe3b,IAAK,SAASjG,GAAG4hB,EAAY5hB,IACpF6iB,gBAAoB7c,IAAK,WAAW,MAAO6c,IAAkB5c,IAAK,SAASjG,GAAG6iB,EAAe7iB,IAC7F8iB,gBAAoB9c,IAAK,WAAW,MAAO8c,IAAkB7c,IAAK,SAASjG,GAAG8iB,EAAe9iB,IAC7FyiB,oBAAwBzc,IAAK,WAAW,MAAOyc,IAAsBxc,IAAK,SAASjG,GAAGyiB,EAAmBziB,IACzG0iB,qBAAyB1c,IAAK,WAAW,MAAO0c,IAAuBzc,IAAK,SAASjG,GAAG0iB,EAAoB1iB,IAG5G5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D+lB,aAAcpd,IAAK,WAAW,MAAO6b,IAAW5b,IAAK,SAASjG,GAC1D6hB,EAAQvkB,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASukB,EAAQvkB,IAC7DukB,EAAQpU,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASoU,EAAQpU,MAC7DoU,EAAQrU,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASqU,EAAQrU,OAC7DqU,EAAQxkB,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASwkB,EAAQxkB,OAEjEyC,UAAWkG,IAAK,WAAW,MAAO4Y,IAAsB3Y,IAAK,SAASjG,GAClE4e,EAAqB5e,IAEzBgE,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1B6Y,EAAO7U,MAAMA,KAEjB5E,GAAI4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAC7C4Q,EAAO5Q,EACPsX,EAAMlY,EAAEY,GACRkiB,EAAO9iB,EAAEY,GACT+a,EAAK3b,EAAEY,GACPgiB,EAAM5iB,EAAEY,KAEZmG,GAAIH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAC7CyS,EAAOzS,EACPsX,EAAMnR,EAAEnG,GACRkiB,EAAO/b,EAAEnG,GACT+a,EAAK5U,EAAEnG,GACPgiB,EAAM7b,EAAEnG,OAIhBhI,EAAGG,MAAM6U,eAAenS,EAAOyc,GAC/Btf,EAAGG,MAAMiO,YAAYvL,GAEdA,GAEX7C,EAAGI,OAAOirB,mBAAqB,WAC3B,YA0EA,SAASxoB,GAAMoB,GAyWX,MAxWAA,GAAUC,KAAK,SAASC,GA8RpB,QAASkkB,GAAW5gB,GAChB,GAAI9F,KAAW,KAAL8F,GACNL,EAAIzF,EAAI,EAAI,GACZwM,EAAIma,EAAmB,CAC3B,OAAO,IAAO,GAAKlhB,EAAK,IAAM+G,EACxB,YAAcxM,EAAI,IAAO,IAAMyF,EAAK,KAAO+G,EAAI,GAC/C,KAAO,EAAIA,EAAI,GACf,YAAcxM,EAAI,IAAO,GAAKyF,EAAK,IAAO,EAAI+G,EAC9C,KACO,IAAM/G,EAAK,KAAO+G,EAAI,GAC7B,KAAO,EAAIA,EAAI,GACf,IAAO,IAAM/G,EAAK,KAAO+G,EAAI,GAC7B,KAAO,EAAIA,EAAI,GAIzB,QAASoa,KACAC,EAAMC,SAASD,EAAM5L,OAAO8L,GACjCC,EACKxkB,MAAMqkB,EAAMC,QAAUG,EAAGxc,SAAWsc,IACpCxkB,KAAK,SAASuD,EAAE1E,GACb,GAAI8lB,GAAYD,EAAGnhB,EAAE,IAAML,EAAEiF,QAAQ,GACjCyc,EAAavjB,EAAiBqjB,EAAGnhB,EAAE,GACvChH,IAAGgG,OAAO3F,MAAM2F,OAAO,SAClBQ,KAAK,QAAsB,EAAZ4hB,EAAgB,EAAIA,GAExCpoB,GAAGgG,OAAO3F,MAAM2F,OAAO,UAClBQ,KAAK,IAAK2hB,EAAGnhB,EAAE,KACfR,KAAK,QAAsB,EAAb6hB,EAAiB,EAAIA,KAKpD,QAASC,KACLL,EAAcF,EAAMC,QAAU,KAAOD,EAAM5L,QAC3C,IAAIA,GAAS4L,EAAMC,QAAUG,EAAGxc,SAAWoc,EAAM5L,QAGjD,MAAI5T,KAAKC,IAAI2T,EAAO,GAAKA,EAAO,KAAO,GAAvC,CAIApc,EAASgoB,OAAO5L,OAAQA,EAAQ4L,MAAOA,IAGvCD,GAGA,IAAIa,GAAiB1S,EAAEjQ,OAAO,2BACzB8U,MACDpX,EACKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAC/BtI,IAAI,SAASzL,EAAE1E,GACZ,OACImJ,IAAKzE,EAAEyE,IACPwb,KAAMjgB,EAAEigB,KACR1d,QAASvC,EAAEuC,QACX9B,OAAQT,EAAES,OAAOqM,OAAO,SAAS9M,EAAE1E,GAC/B,MAAOuc,GAAMlY,IAAIK,EAAE1E,IAAM6Z,EAAO,IAAM0C,EAAMlY,IAAIK,EAAE1E,IAAM6Z,EAAO,QAKnFwM,GAAehc,aAAatF,SAAS8e,GAAoBzlB,KAAKme,GAI9D5I,EAAEjQ,OAAO,2BAA2B2G,aAAatF,SAAS8e,GACrDzlB,KAAK2Z,GACVpE,EAAEjQ,OAAO,2BAA2B2G,aAAatF,SAAS8e,GACrDzlB,KAAK6Z,IAnWd,GAAIxU,GAAY/F,GAAGgG,OAAO3F,MACtBif,EAAOjf,IACXd,GAAGG,MAAMiV,QAAQ5O,EACjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3D4jB,EAAmBhpB,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,GAAUkmB,EACzEhD,EAAmBgD,EAAUzB,EAAQvkB,IAAMukB,EAAQrU,MAavD,IAXA3S,EAAM+P,OAAS,WAAapM,EAAU4G,aAAatF,SAAS8e,GAAoBzlB,KAAK0B,IACrFA,EAAM2D,UAAY1F,KAElBwP,EACKqC,OAAOqN,EAAY7b,GAAOtB,EAAM+P,QAChCH,OAAOwN,EAAY9b,IACnByO,SAGLtC,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,YAE9C0E,EAAc,CACf,GAAIhU,EACJgU,KACA,KAAKhU,IAAOoE,GACJA,EAAMpE,YAAgBjL,OACtBif,EAAahU,GAAOoE,EAAMpE,GAAKhL,MAAM,GAErCgf,EAAahU,GAAOoE,EAAMpE,GAKtC,KAAK/H,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAE9E,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,SAItCP,EAAIkY,EAAMtZ,SACVmI,EAAImR,EAAM5E,SACVkO,EAAKsB,EAAOlkB,SACZ0jB,EAAKQ,EAAOxP,QAGZ,IAAI9T,GAAOJ,EAAUK,UAAU,mCAAmC1C,MAAMA,IACpEgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,sCAAsCD,OAAO,KAC7F0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,gBAEjC,IAAIojB,GAAalP,EAAOnU,OAAO,KAAKC,KAAK,QAAS,WAClDojB,GAAWrjB,OAAO,KAAKC,KAAK,QAAS,gBACrCojB,EAAWrjB,OAAO,KAAKC,KAAK,QAAS,gBACrCojB,EAAWrjB,OAAO,KAAKC,KAAK,QAAS,gBACrCojB,EAAWrjB,OAAO,KAAKC,KAAK,QAAS,iBAErC,IAAIqjB,GAAenP,EAAOnU,OAAO,KAAKC,KAAK,QAAS,aACpDqjB,GAAatjB,OAAO,KAAKC,KAAK,QAAS,gBACvCqjB,EAAatjB,OAAO,KAAKC,KAAK,QAAS,gBACvCqjB,EAAatjB,OAAO,KAAKC,KAAK,QAAS,gBACvCqjB,EAAatjB,OAAO,KAAKC,KAAK,QAAS,sBACvCqjB,EAAatjB,OAAO,KAAKC,KAAK,QAAS,iBAGnC2Z,IACAC,EAAOna,MAAMnB,GAEbmR,EAAEjQ,OAAO,kBACJ8U,MAAMpX,GACNhD,KAAK0f,GAELzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SACpBqiB,EAAmBhpB,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,GAAUkmB,GAG7E5U,EAAEjQ,OAAO,kBACJQ,KAAK,YAAa,gBAAmB7B,EAAOE,IAAM,MAG3DsB,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAInE6b,IACAC,EACK1a,MAAMnB,GACNoB,OAAOqiB,GACP5jB,QAAQC,KAAKD,EAAOC,KAAMC,IAAIF,EAAOE,MACrC4B,aAAaV,GACbR,OAAOoB,GACZR,EAAKH,OAAO,mBAAmBtF,KAAKigB,IAIxC9B,EACK5Y,MAAMnB,GACNoB,OAAOqiB,GACPhd,MACD7H,EACK+O,IAAI,SAASzL,EAAE1E,GACZ,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAE9BwR,OAAO,SAAS9M,EAAE1E,GACf,OAAQoB,EAAKpB,GAAGyY,YAI5B0O,EACKtC,QAAQtI,EAAMsI,WACdlhB,MAAMnB,GACNoB,OAAO2hB,GACPtc,MACD7H,EACK+O,IAAI,SAASzL,EAAE1E,GACZ,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAE9BwR,OAAO,SAAS9M,EAAE1E,GACf,OAAQoB,EAAKpB,GAAGyY,YAI5B9E,EAAEjQ,OAAO,eACJQ,KAAK,YAAa,gBAAmB+hB,EAAmB5jB,EAAOoQ,OAASqU,EAAQvkB,KAAO,IAE5F,IAAIimB,GAAmB7U,EAAEjQ,OAAO,6BAC3B8U,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAE/C/a,IAAG2M,WAAWme,GAAkBpqB,KAAK+oB,GAGrCpP,EACKlT,MAAMR,GACNya,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAChDsX,UAAUuN,EAAkB,GAEjChO,EACKpT,MAAMuG,GACN0T,OAAQ7hB,EAAGG,MAAMoT,WAAWyV,EAAiB,GAAI7kB,IACjDsX,UAAWlW,EAAgB,GAEhCmR,EAAEjQ,OAAO,2BACJQ,KAAK,YAAa,eAAiB+hB,EAAmB,KAG3DR,EACKphB,EAAEwhB,GACFlnB,GAAG,QAAS,WACTqnB,MAGJL,GAAaF,EAAM5L,OAAO8L,EAE9B,IAAIC,GAAUjS,EAAEjQ,OAAO,uBAAuBI,UAAU,KACnD1C,MAAMukB,GAAeF,EAAM5L,WAE5BqO,EAAetC,EAAQ5hB,QACtBC,OAAO,IAEZikB,GAAajkB,OAAO,QACfC,KAAK,QAAS,QACdA,KAAK,IAAK,GACVA,KAAK,IAAK,GACVA,KAAK,SAAUqhB,GAEpB2C,EAAajkB,OAAO,QACfC,KAAK,QAAS,SACdA,KAAK,IAAK,GACVA,KAAK,IAAK,GACVA,KAAK,SAAUqhB,EAEpB,IAAI4C,GAASxU,EAAEjQ,OAAO,kBACjBtF,KAAKqnB,EACV0C,GAAOrkB,UAAU,QACZI,KAAK,SAAUqhB,GACpB4C,EAAOrkB,UAAU,WAAWG,OAAO,QAAQC,KAAK,IAAKohB,GAErDU,IAGAe,EACKliB,MAAMghB,GACN/G,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAChDsX,UAAU6M,EAAkB,GAEjC5R,EAAEjQ,OAAO,6BACJQ,KAAK,YAAa,eAAiByiB,EAAGrd,QAAQ,GAAK,KACxD5L,GAAG2M,WAAWsJ,EAAEjQ,OAAO,8BAClBtF,KAAK2oB,GAEVL,EACK7hB,MAAM8hB,GACN7H,OAAQ7hB,EAAGG,MAAMoT,WAAW+U,EAAiB,GAAInkB,IACjDsX,UAAWlW,EAAgB,GAEhC9E,GAAG2M,WAAWsJ,EAAEjQ,OAAO,8BAClBtF,KAAKsoB,GAEV/S,EAAEjQ,OAAO,6BACJQ,KAAK,YAAa,eAAiByiB,EAAGrd,QAAQ,GAAK,KAMxDwU,EAAOrgB,SAASkB,GAAG,cAAe,SAASogB,GACvC,IAAK,GAAI5V,KAAO4V,GACZxR,EAAMpE,GAAO4V,EAAS5V,EAC1B1L,GAASof,YAAYtP,GACrBzN,EAAM+P,WAGVwO,EAAiB5gB,SAASkB,GAAG,mBAAoB,SAASC,GACtD2d,EAAMF,iBACN,IAAI2C,GAAa7C,EAAY8C,EAAgBC,IA4B7C,IA3BA9d,EACKoQ,OAAO,SAASzI,EAAQ/I,GAErB,MADA+I,GAAOyV,YAAcxe,GACb+I,EAAO0P,WAElBjS,QAAQ,SAASuC,EAAO/I,GACjB,GAAI6Z,GAAS4L,EAAMC,QAAUG,EAAGxc,SAAWoc,EAAM5L,SAC7C4O,EAAgB1f,EAAO5D,OAAOqM,OAAO,SAAS9M,EAAE1E,GACpD,MAAOuc,GAAMlY,IAAIK,EAAE1E,IAAM6Z,EAAO,IAAM0C,EAAMlY,IAAIK,EAAE1E,IAAM6Z,EAAO,IAGnEsC,GAAalf,EAAGiI,kBAAkBujB,EAAe7pB,EAAEoE,YAAauZ,EAAMlY,IACtE,IAAI8G,GAAQsd,EAActM,GACtBgJ,EAAcrlB,EAAMsL,IAAID,EAAOgR,EAChB,OAAfgJ,GACA5I,EAAML,eAAelc,EAAGmc,GAAY,GAE1Btb,SAAVsK,IACgBtK,SAAhBme,IAA2BA,EAAc7T,GACtBtK,SAAnBoe,IAA8BA,EAAiBnf,EAAMmD,SAASnD,EAAMuE,IAAI8G,EAAMgR,KAClF+C,EAAQze,MACJ0I,IAAKJ,EAAOI,IACZR,MAAO7I,EAAMsL,IAAID,EAAOgR,GACxBlT,MAAOA,EAAMF,EAAOA,EAAOyV,kBAInCU,EAAQ9f,OAAS,EAAG,CACpB,GAAI+f,GAASrf,EAAM6X,SAASzU,OAAOtE,EAAE6C,QACjC2d,EAAenZ,KAAKC,IAAIpG,EAAM6X,SAAStO,SAAS,GAAKvJ,EAAM6X,SAAStO,SAAS,IAC7EjD,EAAY,IAAOgZ,EACnB7Y,EAAmBtJ,EAAGkJ,kBAAkB+Y,EAAQ/O,IAAI,SAASzL,GAAG,MAAOA,GAAEiE,QAAQwW,EAAO/Y,EACnE,QAArBG,IACA2Y,EAAQ3Y,GAAkByC,WAAY,GAG9C,GAAIqW,GAAStH,EAAM/D,aAAalU,EAAMuE,IAAI2a,EAAY7C,GACtDkC,GAAiBlhB,QACZwJ,eAAeqW,EAAK/P,YACpB7E,eAAe,SAAS1D,EAAE1E,GACvB,MAAY,OAAL0E,EAAY,MAAQuT,EAAMjE,aAAatP,KAEjDtD,MACGuH,MAAO0W,EACP1Z,MAAOwW,EACPpT,OAAQmW,MAGhBb,EAAiBvb,gBAAgBmc,KAIrCZ,EAAiB5gB,SAASkB,GAAG,kBAAkB,SAASC,GACpD2d,EAAMF,oBAGV5e,EAASkB,GAAG,cAAe,SAASC,GACN,mBAAfA,GAAE6Z,UACTrX,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,SAAW7Z,EAAE6Z,SAASzY,KAGrCF,EAAM+P,aAkFP/P,EA7aX,GAmBMuE,GACA+G,EACAya,EACAc,EAtBFpK,EAAQtf,EAAGI,OAAOkH,OAChB4iB,EAASlqB,EAAGI,OAAOkH,OACnBwT,EAAQ9a,EAAGI,OAAOqW,OAClBuE,EAAQhb,EAAGI,OAAOqW,OAClBqT,EAAS9pB,EAAGI,OAAOqW,OACnBgT,EAASzpB,EAAGI,OAAOqW,OACnBoK,EAAS7gB,EAAGI,OAAOygB,SACnB2H,EAAQ/nB,GAAGoU,IAAI2T,QACftoB,EAAUF,EAAGI,OAAOF,UACpBkhB,EAAmBphB,EAAG+D,uBAGxBqB,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9CwkB,GAAWvkB,IAAK,EAAGmQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAChD2G,EAAQhM,EAAGG,MAAM6O,eACjBtI,EAAQ,KACRC,EAAS,KACT2kB,EAAU,GACVnK,GAA0B,EAK1BP,GAAa,EACb8H,EAAc,KACdhT,EAAS,KACTlV,EAAWC,GAAGD,SAAS,QAAS,cAAe,eAC/ComB,EAAqB,IACrBtW,EAAQtQ,EAAGG,MAAMmQ,QACjB4P,EAAe,IAGrBZ,GAAMd,UAAS,GAAM1W,SAAS,GAC9BoiB,EAAOlL,aAAY,GAEnBkL,EAAOiB,YAAY,SAAS1jB,GAAK,OAAO,IACxCqT,EAAMlE,OAAO,UAAUY,YAAY,GACnCwD,EAAMpE,OAAO,QACbkT,EAAOlT,OAAO,UAAUY,YAAY,GACpCiS,EAAO7S,OAAO,QAEd1W,EAAQiL,eAAe,SAAS1D,EAAG1E,GAC/B,MAAOiY,GAAMjE,aAAatP,EAAG1E,KAC9BqI,gBAAgB,SAAS3D,EAAG1E,GAC3B,MAAO+X,GAAM/D,aAAatP,EAAG1E,IAOjC,IAAIkd,GAAc,SAAS9b,GACvB,MAAO,YACH,OACIzB,OAAQyB,EAAK+O,IAAI,SAASzL,GAAK,OAAQA,EAAE+T,cAKjDwE,EAAc,SAAS7b,GACvB,MAAO,UAASmM,GACS1M,SAAjB0M,EAAM5N,QACNyB,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,UAAYlL,EAAM5N,OAAOK,MAkdhD,OA7FAuc,GAAM9e,SAASkB,GAAG,2BAA4B,SAASia,GACnDzb,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7BwZ,EAAM9e,SAASkB,GAAG,0BAA2B,SAASia,GAClDzb,EAAQ4F,QAAO,KAQnBjD,EAAMrC,SAAWA,EACjBqC,EAAMge,OAASA,EACfhe,EAAMyc,MAAQA,EACdzc,EAAMqnB,OAASA,EACfrnB,EAAMiY,MAAQA,EACdjY,EAAMmY,MAAQA,EACdnY,EAAMinB,OAASA,EACfjnB,EAAM4mB,OAASA,EACf5mB,EAAMue,iBAAmBA,EACzBve,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtE4hB,aAAkB5b,IAAK,WAAW,MAAOsd,IAAWrd,IAAK,SAASjG,GAAGsjB,EAAQtjB,IAC7E4Y,YAAa5S,IAAK,WAAW,MAAO4S,IAAc3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IAC9E0gB,aAAc1a,IAAK,WAAW,MAAO0a,IAAeza,IAAK,SAASjG,GAAG0gB,EAAY1gB,IACjFkY,cAAkBlS,IAAK,WAAW,MAAOkS,IAAgBjS,IAAK,SAASjG,GAAGkY,EAAalY,IACvF0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IAGrE5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D+lB,aAAcpd,IAAK,WAAW,MAAO6b,IAAW5b,IAAK,SAASjG,GAC1D6hB,EAAQvkB,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASukB,EAAQvkB,IAC7DukB,EAAQpU,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASoU,EAAQpU,MAC7DoU,EAAQrU,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASqU,EAAQrU,OAC7DqU,EAAQxkB,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASwkB,EAAQxkB,OAEjE2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1B6Y,EAAO7U,MAAMA,KAGjB2b,aAAc3Z,IAAK,WAAW,MAAOsR,GAAMqI,eAAiB1Z,IAAK,SAASjG,GACtEsX,EAAMqI,YAAY3f,GAClBkiB,EAAOvC,YAAY3f,KAEvByjB,aAAczd,IAAK,WAAW,MAAO8M,GAAM/D,cAAgB9I,IAAK,SAASjG,GACrE8S,EAAM/D,WAAW/O,GACjB8hB,EAAO/S,WAAW/O,KAEtB0jB,aAAc1d,IAAK,WAAW,MAAOgN,GAAMjE,cAAgB9I,IAAK,SAASjG,GACrEgT,EAAMjE,WAAW/O,GACjByhB,EAAO1S,WAAW/O,KAEtBF,UAAckG,IAAK,WAAW,MAAO4Y,IAAsB3Y,IAAK,SAASjG,GACrE4e,EAAmB5e,EACnBgT,EAAMlT,SAAS8e,GACf6C,EAAO3hB,SAAS8e,GAChB9L,EAAMhT,SAAS8e,GACfkD,EAAOhiB,SAAS8e,KAEpBxf,GAAI4G,IAAK,WAAW,MAAOsR,GAAMlY,KAAO6G,IAAK,SAASjG,GAClDsX,EAAMlY,EAAEY,GACRkiB,EAAO9iB,EAAEY,KAEbmG,GAAIH,IAAK,WAAW,MAAOsR,GAAMnR,KAAOF,IAAK,SAASjG,GAClDsX,EAAMnR,EAAEnG,GACRkiB,EAAO/b,EAAEnG,KAEbmZ,yBAA0BnT,IAAK,WAAW,MAAOmT,IAA2BlT,IAAK,SAASjG,GACtFmZ,EAA0BnZ,EACtBmZ,IACA7B,EAAMN,aAAY,GAClBM,EAAMoD,YAAW,QAK7B1iB,EAAGG,MAAM6U,eAAenS,EAAOyc,GAC/Btf,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAOurB,SAAW,WACjB,YA0CA,SAAS9oB,GAAMoB,GAsUX,MArUAgN,GAAYW,QACZ3N,EAAUC,KAAK,SAASC,GACpB,GAAIoB,GAAiBmB,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAC9CjQ,EAAkBmB,EAASvB,EAAOE,IAAMF,EAAOoQ,MAEnDhP,GAAY/F,GAAGgG,OAAO3F,MACtBd,EAAGG,MAAMiV,QAAQ5O,EACjB,IAAIolB,GAAoB,CAkBxB,IAVGC,GAAY1nB,EAAKhC,SAAQ0pB,IACxB3jB,OAAQ/D,EAAK,GAAG+D,OAAOgL,IAAI,SAASzL,GAC5B,OACIL,EAAGK,EAAEL,EACL+G,EAAG,EACHrC,OAAQrE,EAAEqE,OACVwC,KAAM,UAIlBwd,EAAS,CACT,GAAIC,GAAStrB,GAAGurB,OAAOC,QAClBC,OAAOC,GACPjkB,OAAO,SAAST,GAAI,MAAOA,GAAES,SAC7BiG,EAAEsM,IACLtW,EAAKhC,QAAU0pB,EAAWA,EAAW1nB,EAEvC4nB,GAAOxiB,QAAQ,SAASuC,EAAQ/I,GAExB+I,EAAOsgB,cACPjoB,EAAKpB,GAAGspB,mBAAqBT,IAC7BG,EAAOhpB,GAAKoB,EAAKpB,IAGbA,EAAI,GAAKgpB,EAAOhpB,EAAI,GAAGqpB,cACvBL,EAAOhpB,GAAGmF,OAAOgL,IAAI,SAASzL,EAAEsS,GAC5BtS,EAAEmS,IAAMmS,EAAOhpB,EAAI,GAAGmF,OAAO6R,GAAG5L,EAChC1G,EAAEogB,GAAKpgB,EAAEmS,GAAKnS,EAAE0G,MAKhChK,EAAO4nB,EAGX5nB,EAAKoF,QAAQ,SAASuC,EAAQ/I,GAC1B+I,EAAO5D,OAAOqB,QAAQ,SAAS2E,GAC3BA,EAAMpC,OAAS/I,EACfmL,EAAMhC,IAAMJ,EAAOI,QAKvB4f,GACA3nB,EAAK,GAAG+D,OAAOgL,IAAI,SAASzL,EAAE1E,GAC1B,GAAIupB,GAAU,EAAGC,EAAU,CAC3BpoB,GAAK+O,IAAI,SAASzL,EAAG4a,GACjB,IAAKle,EAAKke,GAAK+J,aAAc,CACzB,GAAII,GAAI/kB,EAAES,OAAOnF,EACjBypB,GAAEle,KAAOtF,KAAKC,IAAIujB,EAAEre,GAChBqe,EAAEre,EAAE,GACJqe,EAAE3E,GAAK0E,EACPA,GAAoBC,EAAEle,OAGtBke,EAAE3E,GAAK2E,EAAEle,KAAOge,EAChBA,GAAoBE,EAAEle,UAS1C,IAAIsU,GAAcjK,GAAWI,KACzB5U,EAAK+O,IAAI,SAASzL,EAAG4a,GACjB,MAAO5a,GAAES,OAAOgL,IAAI,SAASzL,EAAE1E,GAC3B,OAASqE,EAAGwR,EAAKnR,EAAE1E,GAAIoL,EAAGsM,EAAKhT,EAAE1E,GAAI6W,GAAInS,EAAEmS,GAAIiO,GAAIpgB,EAAEogB,GAAIxF,IAAIA,MAIzEjb,GAAEgF,OAAOuM,GAAWlY,GAAGoc,MAAM+F,GAAY1P,IAAI,SAASzL,GAAK,MAAOA,GAAEL,KAC/DqR,WAAWI,IAAW,EAAGtT,GAAiBknB,GAE/Cte,EAAE/B,OAAO2M,GAAWtY,GAAGmc,OAAOnc,GAAGoc,MAAM+F,GAAY1P,IAAI,SAASzL,GAC5D,GAAI2E,GAAS3E,EAAE0G,CASf,OAPI2d,KAAY3nB,EAAKsD,EAAE4a,KAAK+J,eAEpBhgB,EADA3E,EAAE0G,EAAI,EACG1G,EAAEogB,GAEFpgB,EAAEogB,GAAKpgB,EAAE0G,GAGnB/B,IACR3K,OAAO4c,KACThS,MAAMqN,IAAWlU,EAAiB,IAG/B4B,EAAEgF,SAAS,KAAOhF,EAAEgF,SAAS,KAC7BhF,EAAEgF,SAAS,GACPhF,EAAEgF,QAAQhF,EAAEgF,SAAS,GAAqB,IAAhBhF,EAAEgF,SAAS,GAAWhF,EAAEgF,SAAS,GAAqB,IAAhBhF,EAAEgF,SAAS,KACzEhF,EAAEgF,QAAQ,GAAG,KAEnB+B,EAAE/B,SAAS,KAAO+B,EAAE/B,SAAS,KAC7B+B,EAAE/B,SAAS,GACP+B,EAAE/B,QAAQ+B,EAAE/B,SAAS,GAAqB,IAAhB+B,EAAE/B,SAAS,GAAW+B,EAAE/B,SAAS,GAAqB,IAAhB+B,EAAE/B,SAAS,KACzE+B,EAAE/B,QAAQ,GAAG,KAEvBuN,EAAKA,GAAMvS,EACXwS,EAAKA,GAAMzL,CAGX,IAAIvH,GAAOJ,EAAUK,UAAU,yBAAyB1C,MAAMA,IAC1D2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,4BACnDmU,EAAYtU,EAAUE,OAAO,QAC7BmU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,aACjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEvE8V,EAAUpU,OAAO,YACZC,KAAK,KAAM,gBAAkB6C,GAC7B9C,OAAO,QACZJ,EAAKH,OAAO,iBAAmBqD,EAAK,SAC/B7C,KAAK,QAAS1B,GACd0B,KAAK,SAAUzB,GAEpBkR,EAAEzP,KAAK,YAAauX,EAAW,qBAAuB1U,EAAK,IAAM,GAEjE,IAAIgZ,GAASlc,EAAKH,OAAO,cAAcI,UAAU,aAC5C1C,KAAK,SAASsD,GAAK,MAAOA,IAAK,SAASA,EAAE1E,GAAK,MAAOA,IAC3D+f,GAAO/b,QAAQC,OAAO,KACjB+C,MAAM,iBAAkB,MACxBA,MAAM,eAAgB,KAE3B,IAAI2iB,GAAiBzb,EAChB7D,WAAW0V,EAAOpb,OAAOb,UAAU,eAAgB,eAAgBmC,KAAKF,IAAI,IAAKhB,IACjFb,KAAK,IAAK,SAASQ,EAAG1E,EAAGgX,GACtB,GAAI6H,GAAOhI,EAAG,IAAM,CAMpB,OALIkS,IACI3nB,EAAKsD,EAAEqE,UAAY3H,EAAKsD,EAAEqE,QAAQsgB,eAClCxK,EAAOhI,EAAGnS,EAAEmS,KAGbgI,IAEV3a,KAAK,SAAU,GACfU,QACD+kB,GAAerf,OACfqf,EAAerf,MAAM,SAAS5F,EAAE1E,GAC5B,GAAIsK,GAAQtK,GAAK+E,GAAY6kB,EAAkB,IAAM5pB,CACrD,OAAOsK,KAEfyV,EACK7b,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO,sBAAwBA,IAC7DiH,QAAQ,QAAS,SAASvC,GAAK,MAAOA,GAAEuS,QACxCjQ,MAAM,OAAQ,SAAStC,EAAE1E,GAAI,MAAOiJ,GAAMvE,EAAG1E,KAC7CgH,MAAM,SAAU,SAAStC,EAAE1E,GAAI,MAAOiJ,GAAMvE,EAAG1E,KACpD+f,EACK/Y,MAAM,iBAAkB,GACxBA,MAAM,eAAgB,IAE3B,IAAIgZ,GAAOD,EAAOjc,UAAU,eACvB1C,KAAK,SAASsD,GAAK,MAAQokB,KAAa1nB,EAAKhC,OAAU0pB,EAAS3jB,OAAST,EAAES,QAChF6a,GAAKrb,OAAOC,QAEIob,GAAKhc,QAAQC,OAAO,QAC3BC,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO0X,GAAKhT,EAAE1E,GAAK,EAAI,kBAAoB,oBACzEkE,KAAK,IAAK,SAASQ,EAAE1E,EAAEgX,GACpB,MAAO+R,KAAY3nB,EAAK4V,GAAGqS,aAAe,EAAKrS,EAAI3S,EAAEkQ,YAAcnT,EAAKhC,SAE3E8E,KAAK,IAAK,SAASQ,EAAE1E,EAAEgX,GAAK,MAAOH,GAAGkS,IAAY3nB,EAAK4V,GAAGqS,aAAe3kB,EAAEmS,GAAK,IAAM,IACtF3S,KAAK,SAAU,GACfA,KAAK,QAAS,SAASQ,EAAE1E,EAAEgX,GAAK,MAAO3S,GAAEkQ,aAAewU,IAAY3nB,EAAK4V,GAAGqS,aAAe,EAAIjoB,EAAKhC,UACpG8E,KAAK,YAAa,SAASQ,EAAE1E,GAAK,MAAO,aAAeqE,EAAEwR,EAAKnR,EAAE1E,IAAM,OAEhFggB,GACKhZ,MAAM,OAAQ,SAAStC,EAAE1E,EAAEgX,GAAI,MAAO/N,GAAMvE,EAAGsS,EAAGhX,KAClDgH,MAAM,SAAU,SAAStC,EAAE1E,EAAEgX,GAAI,MAAO/N,GAAMvE,EAAGsS,EAAGhX,KACpDrB,GAAG,YAAa,SAAS+F,EAAE1E,GACxBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASyZ,kBACL9V,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,WAAY,SAAS+F,EAAE1E,GACvBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASoF,iBACLzB,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,YAAa,SAAS+F,EAAE1E,GACxBvC,EAAS0F,kBACL/B,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,QAAS,SAAS+F,EAAE1E,GACpBvC,EAAS6F,cACLlC,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,UAEjCtJ,GAAGmE,MAAMqe,oBAEZvhB,GAAG,WAAY,SAAS+F,EAAE1E,GACvBvC,EAAS0iB,iBACL/e,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,UAEjCtJ,GAAGmE,MAAMqe,oBAEjBF,EACK9b,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO0X,GAAKhT,EAAE1E,GAAK,EAAI,kBAAoB,oBACzEkE,KAAK,YAAa,SAASQ,EAAE1E,GAAK,MAAO,aAAeqE,EAAEwR,EAAKnR,EAAE1E,IAAM,QAExE6pB,IACKpR,IAAUA,EAAWrX,EAAK+O,IAAI,WAAa,OAAO,KACvD6P,EACKhZ,MAAM,OAAQ,SAAStC,EAAE1E,EAAEgX,GAAK,MAAOtZ,IAAGosB,IAAID,EAASnlB,EAAE1E,IAAI+pB,OAAStR,EAAStI,IAAI,SAASzL,EAAE1E,GAAK,MAAOA,KAAKwR,OAAO,SAAS9M,EAAE1E,GAAI,OAAQyY,EAASzY,KAAOgX,IAAOgT,aACpKhjB,MAAM,SAAU,SAAStC,EAAE1E,EAAEgX,GAAK,MAAOtZ,IAAGosB,IAAID,EAASnlB,EAAE1E,IAAI+pB,OAAStR,EAAStI,IAAI,SAASzL,EAAE1E,GAAK,MAAOA,KAAKwR,OAAO,SAAS9M,EAAE1E,GAAI,OAAQyY,EAASzY,KAAOgX,IAAOgT,aAG/K,IAAIC,GACAjK,EAAK/R,gBAAgBC,EAAa,WAAYjI,KAAKF,IAAI,IAAKhB,IACvDuF,MAAM,SAAS5F,EAAE1E,GACd,MAAOA,GAAI+E,EAAW3D,EAAK,GAAG+D,OAAO/F,QAE7C2pB,GACAkB,EACK/lB,KAAK,IAAK,SAASQ,EAAE1E,EAAEgX,GACpB,GAAI6H,GAAO,CAeX,OATQA,GAJHzd,EAAK4V,GAAGqS,aAGL3R,EAAKhT,EAAE1E,GAAK,EACLoL,EAAE,GAELA,EAAE,GAAKA,EAAEsM,EAAKhT,EAAE1E,IAAM,GACfoL,EAAE,GAAK,EAEPA,EAAEsM,EAAKhT,EAAG1E,KAAO,EARzBoL,EAAE1G,EAAEogB,MAclB5gB,KAAK,SAAU,SAASQ,EAAE1E,EAAEgX,GACzB,MAAK5V,GAAK4V,GAAGqS,aAGFpjB,KAAKL,IAAIK,KAAKC,IAAIkF,EAAEsM,EAAKhT,EAAE1E,IAAMoL,EAAE,IAAK,IAAM,EAF9CnF,KAAKL,IAAIK,KAAKC,IAAIkF,EAAE1G,EAAE0G,EAAE1G,EAAEmS,IAAMzL,EAAE1G,EAAEmS,KAAM,KAKxD3S,KAAK,IAAK,SAASQ,EAAE1E,EAAEgX,GACpB,GAAIrT,GAAQ,CAOZ,OANIvC,GAAK4V,GAAGqS,eACR1lB,EAAQe,EAAEqE,OAAS1E,EAAEkQ,YAAcnT,EAAKhC,OACpCgC,EAAKhC,SAAWypB,IAChBllB,EAAQvC,EAAK4V,GAAGsS,mBAAqBjlB,EAAEkQ,aAA+B,EAAlBsU,KAGrDllB,IAEVO,KAAK,QAAS,SAASQ,EAAE1E,EAAEgX,GACxB,GAAK5V,EAAK4V,GAAGqS,aAEN,CAEH,GAAI1lB,GAASU,EAAEkQ,YAAcsU,CAM7B,OAHIznB,GAAKhC,SAAWypB,IAChBllB,EAAQU,EAAEkQ,aAA+B,EAAlBsU,IAEpBllB,EATP,MAAOU,GAAEkQ,cAcrB0V,EACK/lB,KAAK,IAAK,SAASQ,EAAE1E,GAClB,MAAO0E,GAAEqE,OAAS1E,EAAEkQ,YAAcnT,EAAKhC,SAE1C8E,KAAK,QAASG,EAAEkQ,YAAcnT,EAAKhC,QACnC8E,KAAK,IAAK,SAASQ,EAAE1E,GAClB,MAAO0X,GAAKhT,EAAE1E,GAAK,EACfoL,EAAE,GACEA,EAAE,GAAKA,EAAEsM,EAAKhT,EAAE1E,IAAM,EAC1BoL,EAAE,GAAK,EACPA,EAAEsM,EAAKhT,EAAE1E,KAAO,IAEvBkE,KAAK,SAAU,SAASQ,EAAE1E,GACvB,MAAOiG,MAAKL,IAAIK,KAAKC,IAAIkF,EAAEsM,EAAKhT,EAAE1E,IAAMoL,EAAE,IAAI,IAAM,IAKhEwL,EAAKvS,EAAEoR,OACPoB,EAAKzL,EAAEqK,OAGHrU,EAAK,IAAMA,EAAK,GAAG+D,SACnBykB,EAAkBxoB,EAAK,GAAG+D,OAAO/F,UAKzC8O,EAAYS,UAAU,sBAEf7O,EA1WX,GAgBM2Y,GAEA7C,EACAI,EACAF,EACAa,EASFC,EAAIC,EA9BJxU,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACRC,EAAS,IACTS,EAAI3G,GAAGmH,MAAMuH,UACbhB,EAAI1N,GAAGmH,MAAMC,SACbiC,EAAKd,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UACrBlE,EAAY,KACZoS,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9BkQ,GAAU,GACVG,GAAW,EACXsN,GAAU,EACVK,EAAc,OACdngB,EAAQhM,EAAGG,MAAM6O,eACjB6c,GAAW,EACXe,EAAW,KAEX9kB,EAAW,IAKX2kB,EAAe,GACfjsB,EAAWC,GAAGD,SAAS,aAAc,eAAgB,kBAAmB,mBAAoB,kBAAmB,mBAAoB,aAQnIyQ,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,GAG/C6kB,EAAkB,CA6XtB,OA9CA9pB,GAAMrC,SAAWA,EAEjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAUsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACjErB,QAAUqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACnEZ,GAAU4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAK5Q,IAC/DmG,GAAUH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAAGyS,EAAKzS,IAC/DhC,QAAUgI,IAAK,WAAW,MAAO5G,IAAK6G,IAAK,SAASjG,GAAGZ,EAAEY,IACzD0S,QAAU1M,IAAK,WAAW,MAAOG,IAAKF,IAAK,SAASjG,GAAGmG,EAAEnG,IACzD2Q,SAAU3K,IAAK,WAAW,MAAO2K,IAAW1K,IAAK,SAASjG,GAAG2Q,EAAQ3Q,IACrE+Q,SAAU/K,IAAK,WAAW,MAAO+K,IAAW9K,IAAK,SAASjG,GAAG+Q,EAAQ/Q,IACrE6Q,QAAU7K,IAAK,WAAW,MAAO6K,IAAU5K,IAAK,SAASjG,GAAG6Q,EAAO7Q,IACnE0R,QAAU1L,IAAK,WAAW,MAAO0L,IAAUzL,IAAK,SAASjG,GAAG0R,EAAO1R,IACnEqW,QAAUrQ,IAAK,WAAW,MAAOqQ,IAAUpQ,IAAK,SAASjG,GAAGqW,EAAOrW,IACnE8jB,SAAU9d,IAAK,WAAW,MAAO8d,IAAW7d,IAAK,SAASjG,GAAG8jB,EAAQ9jB,IACrEmkB,aAAcne,IAAK,WAAW,MAAOme,IAAele,IAAK,SAASjG,GAAGmkB,EAAYnkB,IACjFwW,UAAcxQ,IAAK,WAAW,MAAOwQ,IAAYvQ,IAAK,SAASjG,GAAGwW,EAASxW,IAC3EwT,UAAcxN,IAAK,WAAW,MAAOwN,IAAYvN,IAAK,SAASjG,GAAGwT,EAASxT,IAC3E8B,IAAckE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,GAAG8B,EAAG9B,IAC/D6jB,UAAc7d,IAAK,WAAW,MAAO6d,IAAY5d,IAAK,SAASjG,GAAG6jB,EAAS7jB,IAC3EykB,cAAcze,IAAK,WAAW,MAAOye,IAAgBxe,IAAK,SAASjG,GAAGykB,EAAazkB,IAGnF5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,KAEtBkE,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,KAE9B4kB,UAAY5e,IAAK,WAAW,MAAO4e,IAAY3e,IAAK,SAASjG,GACzD4kB,EAAW5kB,EAAIhI,EAAGG,MAAM4O,SAAS/G,GAAK,SAI9ChI,EAAGG,MAAMiO,YAAYvL,GAEdA,GAEX7C,EAAGI,OAAO6sB,cAAgB,WACtB,YA0FA,SAASpqB,GAAMoB,GAiPX,MAhPAgN,GAAYW,QACZX,EAAY7Q,OAAO8sB,GACfrS,GAAW5J,EAAY7Q,OAAO0a,GAC9BC,GAAW9J,EAAY7Q,OAAO4a,GAElC/W,EAAUC,KAAK,SAASC,GACpB,GAAIqC,GAAY/F,GAAGgG,OAAO3F,KAE1Bd,GAAGG,MAAMiV,QAAQ5O,EACjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAoBlE,IAlBAvC,EAAM+P,OAAS,WACM,IAAb9K,EACAtB,EAAUrF,KAAK0B,GAEf2D,EAAU4G,aACLtF,SAASA,GACT3G,KAAK0B,IAElBA,EAAM2D,UAAY1F,KAElBwP,EACKqC,OAAOqN,EAAY7b,GAAOtB,EAAM+P,QAChCH,OAAOwN,EAAY9b,IACnByO,SAGLtC,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,YAE9C0E,EAAc,CACf,GAAIhU,EACJgU,KACA,KAAKhU,IAAOoE,GACJA,EAAMpE,YAAgBjL,OACtBif,EAAahU,GAAOoE,EAAMpE,GAAKhL,MAAM,GAErCgf,EAAahU,GAAOoE,EAAMpE,GAKtC,KAAK/H,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAE9E,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,SAItCP,EAAI8lB,EAASlnB,SACbmI,EAAI+e,EAASxS,QAGb,IAAI9T,GAAOJ,EAAUK,UAAU,mCAAmC1C,MAAMA,IACpEgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,sCAAsCD,OAAO,KAC7F0P,EAAI9P,EAAKH,OAAO,IA0BpB,IAxBA0U,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,eACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,mBAG7B2Z,IACAC,EAAOna,MAAMnB,EAAiB4nB,KAE9BzW,EAAEjQ,OAAO,kBACJ8U,MAAMpX,GACNhD,KAAK0f,GAELzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SACpBnB,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IAGlEsR,EAAEjQ,OAAO,kBACJQ,KAAK,YAAa,aAAekmB,IAAiB,KAAQ/nB,EAAOE,IAAM,MAI5Ewb,EAAc,CACd,GAAIC,KACE7U,IAAKkhB,EAAcC,SAAW,UAAW7R,SAAU0R,EAASpB,YAC5D5f,IAAKkhB,EAActB,SAAW,UAAWtQ,UAAW0R,EAASpB,WAGnE9K,GAASta,MAAMymB,KAAgBnhB,OAAO,OAAQ,OAAQ,SACtD0K,EAAEjQ,OAAO,oBACJ8U,MAAMwF,GACN9Z,KAAK,YAAa,gBAAmB7B,EAAOE,IAAM,KAClDnE,KAAK6f,GAGdpa,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KACnE+V,GACA3E,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,aAAe1B,EAAiB,OAI3D2nB,EACK1R,SAASrX,EAAK+O,IAAI,SAASpH,GAAU,MAAOA,GAAO0P,YACnD9U,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GACvB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,WAG9C,IAAIF,GAAW5E,EAAEjQ,OAAO,gBACnB8U,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAK/C,IAHAF,EAASna,KAAK+rB,GAGVrS,EAAW,CACXC,EACKlT,MAAMR,GACNya,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAChDsX,UAAUjW,EAAiB,GAEhCkR,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,eAAiBkH,EAAE9B,QAAQ,GAAK,KACvDqK,EAAEjQ,OAAO,iBACJtF,KAAK2Z,EAEV,IAAIlD,GAASlB,EAAEjQ,OAAO,qBAAqBI,UAAU;AAMrD,GAJA+Q,EACK/Q,UAAU,cACVkD,MAAM,UAAW,GAElBoO,EAAe,CACf,GAAImV,GAAe,SAASlmB,EAAE+G,GAC1B,MAAO,aAAe/G,EAAI,IAAM+G,EAAI,KAGpCof,EAAY,EAAGC,EAAc,EAEjC5V,GACK/Q,UAAU,QACVI,KAAK,YAAa,SAASQ,EAAE1E,EAAEgX,GAC5B,MAAQuT,GAAa,EAAIvT,EAAI,GAAK,EAAIwT,EAAYC,IAG1D,IAAIC,GAAsBhtB,GAAGoG,UAAU,mCAAmC,GAAG1E,MAC7EuU,GAAE7P,UAAU,qCACPI,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAOuqB,GAAa,EAAU,IAANvqB,GAAW0qB,EAAsB,IAAM,EAAKD,EAAcD,KAI1FhK,GACA7M,EAAE7P,UAAU,cACP1F,KAAKnB,EAAGG,MAAM0V,UAAWhT,EAAMiY,MAAMxD,aAG1CoW,GACA9V,EACKrD,OAAO,SAAS9M,EAAE1E,GACf,MAAOA,GAAIiG,KAAKmd,KAAKhiB,EAAK,GAAG+D,OAAO/F,QAAUoD,EAAiB,QAAU,IAE5EsB,UAAU,cACVkD,MAAM,UAAW,GAEvB+N,GACCF,EACK/Q,UAAU,cACVI,KAAK,YAAa,UAAY6Q,EAAe,SAC7C/N,MAAM,cAAe+N,EAAe,EAAI,QAAU,OAE3DpB,EAAEjQ,OAAO,iBAAiBI,UAAU,wBAC/BkD,MAAM,UAAW,GAGtBgR,IACAC,EACKpT,MAAMuG,GACN0T,OAAQ7hB,EAAGG,MAAMoT,WAAW/N,EAAgB,GAAIrB,IAChDsX,UAAWlW,EAAgB,GAEhCmR,EAAEjQ,OAAO,iBACJtF,KAAK6Z,IAOd6F,EAAOrgB,SAASkB,GAAG,cAAe,SAASogB,GACvC,IAAK,GAAI5V,KAAO4V,GACZxR,EAAMpE,GAAO4V,EAAS5V,EAC1B1L,GAASof,YAAYtP,GACrBzN,EAAM+P,WAGVoO,EAASxgB,SAASkB,GAAG,cAAe,SAAS+F,EAAE1E,GAC3C,GAAK0E,EAAE+T,SAAP,CAOA,OANAuF,EAAeA,EAAa7N,IAAI,SAAS0B,GAErC,MADAA,GAAE4G,UAAW,EACN5G,IAEXnN,EAAE+T,UAAW,EAEL/T,EAAEyE,KACN,IAAK,UACL,IAAKkhB,GAAcC,QACfH,EAASpB,SAAQ,EACjB,MACJ,KAAK,UACL,IAAKsB,GAActB,QACfoB,EAASpB,SAAQ,GAIzBxb,EAAMwb,QAAUoB,EAASpB,UACzBtrB,EAASof,YAAYtP,GACrBzN,EAAM+P,YAIVpS,EAASkB,GAAG,cAAe,SAASC,GACN,mBAAfA,GAAE6Z,WACTrX,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,SAAW7Z,EAAE6Z,SAASzY,KAEjCuN,EAAMkL,SAAW7Z,EAAE6Z,UAEE,mBAAd7Z,GAAEmqB,UACToB,EAASpB,QAAQnqB,EAAEmqB,SACnBxb,EAAMwb,QAAUnqB,EAAEmqB,QAClBA,EAAUnqB,EAAEmqB,SAEhBjpB,EAAM+P,aAId3B,EAAYS,UAAU,2BACf7O,EArUX,GAsBMuE,GACA+G,EAvBF+e,EAAWltB,EAAGI,OAAOurB,WACnB7Q,EAAQ9a,EAAGI,OAAOqW,OAClBuE,EAAQhb,EAAGI,OAAOqW,OAClBoK,EAAS7gB,EAAGI,OAAOygB,SACnBG,EAAWhhB,EAAGI,OAAOygB,SACrB3gB,EAAUF,EAAGI,OAAOF,UAGtBkF,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9CqB,EAAQ,KACRC,EAAS,KACTqF,EAAQhM,EAAGG,MAAM6O,eACjB8R,GAAe,EACfsM,KACAxM,GAAa,EACb/F,GAAY,EACZE,GAAY,EACZM,GAAkB,EAClBqS,GAAe,EACfvV,GAAgB,EAChBoL,GAAa,EACbzL,EAAe,EAGfxH,EAAQtQ,EAAGG,MAAMmQ,QACjB4P,EAAe,KACfxK,EAAS,KACTlV,EAAWC,GAAGD,SAAS,cAAe,cAAe,aACrD2sB,EAAe,WAAa,MAAOrM,GAAe,IAAM,GACxDhZ,EAAW,GAGjBwI,GAAMwb,SAAU,EAEhBoB,EAASpB,SAAQ,GACjBhR,EACKlE,OAAO,UACPY,YAAY,GACZD,YAAW,GACXR,WAAW,SAAStP,GAAK,MAAOA,KAErCuT,EACKpE,OAAO,EAAoB,QAAU,QACrCG,WAAWtW,GAAGib,OAAO,SAG1Bxb,EACK4H,SAAS,GACTqD,eAAe,SAAS1D,EAAG1E,GACxB,MAAOiY,GAAMjE,aAAatP,EAAG1E,KAEhCqI,gBAAgB,SAAS3D,EAAG1E,GACzB,MAAO+X,GAAM/D,aAAatP,EAAG1E,KAGrCie,EAASyB,aAAY,EAMrB,IAAIxR,GAAcjR,EAAGG,MAAM8Q,YAAYzQ,GACnCsrB,GAAU,EAEV7L,EAAc,SAAS9b,GACvB,MAAO,YACH,OACIzB,OAAQyB,EAAK+O,IAAI,SAASzL,GAAK,OAAQA,EAAE+T,WACzCsQ,QAASA,KAKjB9L,EAAc,SAAS7b,GACvB,MAAO,UAASmM,GACU1M,SAAlB0M,EAAMwb,UACNA,EAAUxb,EAAMwb,SACCloB,SAAjB0M,EAAM5N,QACNyB,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,UAAYlL,EAAM5N,OAAOK,MA8UhD,OAjFAmqB,GAAS1sB,SAASkB,GAAG,2BAA4B,SAASia,GACtDA,EAAIjQ,MAAQ7I,EAAMuE,IAAIuU,EAAIxX,MAC1BwX,EAAY,QACRzP,IAAKyP,EAAIxX,KAAK+H,IACdR,MAAO7I,EAAMsL,IAAIwN,EAAIxX,MACrB6H,MAAO2P,EAAI3P,OAEf9L,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7BonB,EAAS1sB,SAASkB,GAAG,0BAA2B,SAASia,GACrDzb,EAAQ4F,QAAO,KAGnBonB,EAAS1sB,SAASkB,GAAG,2BAA4B,SAASia,GACtDzb,MAQJ2C,EAAMrC,SAAWA,EACjBqC,EAAMqqB,SAAWA,EACjBrqB,EAAMge,OAASA,EACfhe,EAAMme,SAAWA,EACjBne,EAAMiY,MAAQA,EACdjY,EAAMmY,MAAQA,EACdnY,EAAMyN,MAAQA,EACdzN,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtE4Y,YAAa5S,IAAK,WAAW,MAAO4S,IAAc3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IAC9E8Y,cAAe9S,IAAK,WAAW,MAAO8S,IAAgB7S,IAAK,SAASjG,GAAG8Y,EAAa9Y,IACpFolB,eAAgBpf,IAAK,WAAW,MAAOof,IAAiBnf,IAAK,SAASjG,GAAGolB,EAAcplB,IACvF6S,WAAiB7M,IAAK,WAAW,MAAO6M,IAAa5M,IAAK,SAASjG,GAAG6S,EAAU7S,IAChF+S,WAAe/M,IAAK,WAAW,MAAO+M,IAAa9M,IAAK,SAASjG,GAAG+S,EAAU/S,IAC9EkY,cAAkBlS,IAAK,WAAW,MAAOkS,IAAgBjS,IAAK,SAASjG,GAAGkY,EAAalY,IACvF0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IACrE0lB,cAAkB1f,IAAK,WAAW,MAAO0f,IAAgBzf,IAAK,SAASjG,GAAG0lB,EAAa1lB,IACvF8P,cAAkB9J,IAAK,WAAW,MAAO8J,IAAgB7J,IAAK,SAASjG,GAAG8P,EAAa9P,IACvFmQ,eAAmBnK,IAAK,WAAW,MAAOmK,IAAiBlK,IAAK,SAASjG,GAAGmQ,EAAcnQ,IAC1Fub,YAAevV,IAAK,WAAW,MAAOuV,IAActV,IAAK,SAASjG,GAAGub,IAAavb,IAGlF5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXklB,EAASplB,SAASA,GAClBgT,EAAMhT,SAASA,GACfkT,EAAMlT,SAASA,GACfmJ,EAAYW,MAAM9J,KAEtBkE,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1B6Y,EAAO7U,MAAMA,KAEjBqP,iBAAkBrN,IAAK,WAAW,MAAOqN,IAAmBpN,IAAK,SAASjG,GACtEqT,EAAkBrT,EAClBgT,EAAMpE,OAAQyE,EAAkB,QAAU,UAE9CuR,UAAY5e,IAAK,WAAW,MAAOkf,GAASN,UAAY3e,IAAK,SAASjG,GAClEklB,EAASN,SAAS5kB,GAClB6Y,EAAO7U,MAAM,SAASvE,EAAE1E,GAAI,MAAOtC,IAAGosB,IAAI,QAAQC,OAAW,IAAJ/pB,GAASgqB,iBAI1E/sB,EAAGG,MAAM6U,eAAenS,EAAOqqB,GAC/BltB,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAOutB,mBAAqB,WAC3B,YA0CA,SAAS9qB,GAAMoB,GA+PX,MA9PAgN,GAAYW,QACZ3N,EAAUC,KAAK,SAASC,GACpB,GAAIoB,GAAiBmB,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAC9CjQ,EAAkBmB,EAASvB,EAAOE,IAAMF,EAAOoQ,MAEnDhP,GAAY/F,GAAGgG,OAAO3F,MACtBd,EAAGG,MAAMiV,QAAQ5O,GAEbslB,IACA3nB,EAAO1D,GAAGurB,OAAOC,QACZC,OAAO,QACPhkB,OAAO,SAAST,GAAI,MAAOA,GAAES,SAC7BiG,EAAEsM,GACNtW,IAGLA,EAAKoF,QAAQ,SAASuC,EAAQ/I,GAC1B+I,EAAO5D,OAAOqB,QAAQ,SAAS2E,GAC3BA,EAAMpC,OAAS/I,EACfmL,EAAMhC,IAAMJ,EAAOI,QAKvB4f,GACA3nB,EAAK,GAAG+D,OAAOgL,IAAI,SAASzL,EAAE1E,GAC1B,GAAIupB,GAAU,EAAGC,EAAU,CAC3BpoB,GAAK+O,IAAI,SAASzL,GACd,GAAI+kB,GAAI/kB,EAAES,OAAOnF,EACjBypB,GAAEle,KAAOtF,KAAKC,IAAIujB,EAAEre,GAChBqe,EAAEre,EAAE,GACJqe,EAAE3E,GAAK0E,EAAUC,EAAEle,KACnBie,GAAoBC,EAAEle,OAGtBke,EAAE3E,GAAKyE,EACPA,GAAoBE,EAAEle,SAOtC,IAAIsU,GAAcjK,GAAWI,KACzB5U,EAAK+O,IAAI,SAASzL,GACd,MAAOA,GAAES,OAAOgL,IAAI,SAASzL,EAAE1E,GAC3B,OAASqE,EAAGwR,EAAKnR,EAAE1E,GAAIoL,EAAGsM,EAAKhT,EAAE1E,GAAI6W,GAAInS,EAAEmS,GAAIiO,GAAIpgB,EAAEogB,OAIjEzgB,GAAEgF,OAAOuM,GAAWlY,GAAGoc,MAAM+F,GAAY1P,IAAI,SAASzL,GAAK,MAAOA,GAAEL,KAC/DqR,WAAWI,IAAW,EAAGrT,GAAkBinB,GAEhDte,EAAE/B,OAAO2M,GAAWtY,GAAGmc,OAAOnc,GAAGoc,MAAM+F,GAAY1P,IAAI,SAASzL,GAAK,MAAOqkB,GAAWrkB,EAAE0G,EAAI,EAAI1G,EAAEogB,GAAKpgB,EAAE0G,EAAI1G,EAAEogB,GAAOpgB,EAAE0G,IAAK1M,OAAO4c,KAEjIwE,IAAeiJ,EACf3d,EAAE9B,MAAMqN,IAAYvL,EAAE/B,SAAS,GAAK,EAAIwhB,EAAe,EAAIroB,GAAkB4I,EAAE/B,SAAS,GAAK,EAAIwhB,EAAe,KAEhHzf,EAAE9B,MAAMqN,IAAW,EAAGnU,IAE1BoU,EAAKA,GAAMvS,EACXwS,EAAKA,GAAMnZ,GAAGmH,MAAMC,SAASuE,OAAO+B,EAAE/B,UAAUC,OAAO8B,EAAE,GAAGA,EAAE,IAG9D,IAAIvH,GAAOnG,GAAGgG,OAAO3F,MAAM+F,UAAU,mCAAmC1C,MAAMA,IAC1E2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,sCAEnDkU,GADYrU,EAAUE,OAAO,QACpBF,EAAUE,OAAO,KACtBJ,GAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,aACjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAEvE,IAAIwd,GAASlc,EAAKH,OAAO,cAAcI,UAAU,aAC5C1C,KAAK,SAASsD,GAAK,MAAOA,IAAK,SAASA,EAAE1E,GAAK,MAAOA,IAC3D+f,GAAO/b,QAAQC,OAAO,KACjB+C,MAAM,iBAAkB,MACxBA,MAAM,eAAgB,MAC3B+Y,EAAOpb,OAAOsJ,gBAAgBC,EAAa,mCACtClH,MAAM,iBAAkB,MACxBA,MAAM,eAAgB,MACtBpC,SACLmb,EACK7b,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO,sBAAwBA,IAC7DiH,QAAQ,QAAS,SAASvC,GAAK,MAAOA,GAAEuS,QACxCjQ,MAAM,OAAQ,SAAStC,EAAE1E,GAAI,MAAOiJ,GAAMvE,EAAG1E,KAC7CgH,MAAM,SAAU,SAAStC,EAAE1E,GAAI,MAAOiJ,GAAMvE,EAAG1E,KACpD+f,EAAO9R,gBAAgBC,EAAa,8BAC/BlH,MAAM,iBAAkB,GACxBA,MAAM,eAAgB,IAE3B,IAAIgZ,GAAOD,EAAOjc,UAAU,YACvB1C,KAAK,SAASsD,GAAK,MAAOA,GAAES,QACjC6a,GAAKrb,OAAOC,QAEZ,IAAIqb,GAAYD,EAAKhc,QAAQC,OAAO,KAC/BC,KAAK,YAAa,SAASQ,EAAE1E,EAAEgX,GAC5B,MAAO,aAAeH,EAAGkS,EAAUrkB,EAAEmS,GAAK,GAAK,KAAOkS,EAAU,EAAK/R,EAAI3S,EAAEkQ,YAAcnT,EAAKhC,OAAWiF,EAAEwR,EAAKnR,EAAE1E,KAAO,KAGjIigB,GAAUhc,OAAO,QACZC,KAAK,QAAS,GACdA,KAAK,SAAUG,EAAEkQ,aAAewU,EAAU,EAAI3nB,EAAKhC,SAExD4gB,EACKrhB,GAAG,YAAa,SAAS+F,EAAE1E,GACxBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASyZ,kBACL9V,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,WAAY,SAAS+F,EAAE1E,GACvBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASoF,iBACLzB,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,WAAY,SAAS+F,EAAE1E,GACvBvC,EAASoF,iBACLzB,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,YAAa,SAAS+F,EAAE1E,GACxBvC,EAAS0F,kBACL/B,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,QAAS,SAAS+F,EAAE1E,GACpBvC,EAAS6F,cACLlC,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,UAEjCtJ,GAAGmE,MAAMqe,oBAEZvhB,GAAG,WAAY,SAAS+F,EAAE1E,GACvBvC,EAAS0iB,iBACL/e,KAAMsD,EACNiB,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,UAEjCtJ,GAAGmE,MAAMqe,oBAGb4K,EAAQ1pB,EAAK,GAAG,KAChB6e,EAAUhc,OAAO,YAEjB+b,EAAKtc,OAAO,YACPQ,KAAK,OAAQ,QACbA,KAAK,SAAU,SAASQ,EAAE1E,GACvB,GAAI+qB,GAAOD,EAAQpmB,EAAE1E,GACfgrB,EAAM,GAAM3mB,EAAEkQ,aAA6C,GAA7BwU,EAAU,EAAI3nB,EAAKhC,QACvD2rB,GAAOA,EAAK3rB,OAAS2rB,IAAS9kB,KAAKC,IAAI6kB,GAAO9kB,KAAKC,IAAI6kB,IACvDA,EAAOA,EAAK5a,IAAI,SAASvR,GAAK,MAAOwM,GAAExM,GAAKwM,EAAE,IAC9C,IAAIkG,KAAMyZ,EAAK,IAAIC,IAAOD,EAAK,GAAGC,IAAOD,EAAK,GAAG,IAAKA,EAAK,GAAG,IAAKA,EAAK,IAAIC,IAAOD,EAAK,GAAGC,GAC3F,OAAO1Z,GAAEnB,IAAI,SAAU8a,GAAQ,MAAOA,GAAKzX,KAAK,OAAQA,KAAK,OAEhEtP,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,GAAIgrB,GAAM3mB,EAAEkQ,aAA6C,GAA7BwU,EAAU,EAAI3nB,EAAKhC,QAC/C,OAAO,cAAgBsY,EAAKhT,EAAE1E,GAAK,EAAI,EAAIoL,EAAEsM,EAAKhT,EAAE1E,IAAMoL,EAAE,IAAM,KAAO4f,EAAM,OAI3F/K,EAAUhc,OAAO,QAEb6b,IAAeiJ,GACf/I,EAAKtc,OAAO,QACPQ,KAAK,cAAe,SAASQ,EAAE1E,GAAK,MAAO0X,GAAKhT,EAAE1E,GAAK,EAAI,MAAQ,UACnEkE,KAAK,IAAKG,EAAEkQ,aAA6B,EAAdnT,EAAKhC,SAChC8E,KAAK,KAAM,SACXwJ,KAAK,SAAShJ,EAAE1E,GACb,GAAI4R,GAAIwO,EAAY1I,EAAKhT,EAAE1E,IACrBkrB,EAAOJ,EAAQpmB,EAAE1E,EACvB,OAAaa,UAATqqB,EACOtZ,EACNsZ,EAAK9rB,OAEHwS,EAAI,IAAMwO,EAAYna,KAAKC,IAAIglB,EAAK,KAAO,IAAM9K,EAAYna,KAAKC,IAAIglB,EAAK,KADvEtZ,EAAI,IAAMwO,EAAYna,KAAKC,IAAIglB,MAGlDlL,EAAK/R,gBAAgBC,EAAa,4BAC7BxK,OAAO,QACPQ,KAAK,IAAK,SAASQ,EAAE1E,GAAK,MAAO0X,GAAKhT,EAAE1E,GAAK,EAAI,GAAKoL,EAAEsM,EAAKhT,EAAE1E,IAAMoL,EAAE,GAAK,KAEjF4U,EAAKlc,UAAU,QAAQ4J,KAAK,IAG5Byd,IAAkBpC,GAClB9I,EAAUhc,OAAO,QAAQgD,QAAQ,gBAAe,GAChD+Y,EAAKtc,OAAO,qBACPQ,KAAK,cAAe,SAASQ,EAAE1E,GAAK,MAAO0X,GAAKhT,EAAE1E,GAAK,EAAI,QAAU,QACrEkE,KAAK,IAAKG,EAAEkQ,aAA6B,EAAdnT,EAAKhC,SAChC8E,KAAK,KAAM,SACXwJ,KAAK,SAAShJ,EAAE1E,GAAK,MAAO6V,GAAKnR,EAAE1E,KACxCggB,EAAK/R,gBAAgBC,EAAa,4BAC7BxK,OAAO,qBACPQ,KAAK,IAAK,SAASQ,EAAE1E,GAAK,MAAO0X,GAAKhT,EAAE1E,GAAK,EAAIoL,EAAE,GAAKA,EAAEsM,EAAKhT,EAAE1E,IAAM,EAAI,MAGhFggB,EAAKlc,UAAU,qBAAqB4J,KAAK,IAG7CsS,EACK9b,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO0X,GAAKhT,EAAE1E,GAAK,EAAI,kBAAoB,oBAE1E6pB,IACKpR,IAAUA,EAAWrX,EAAK+O,IAAI,WAAa,OAAO,KACvD6P,EACKhZ,MAAM,OAAQ,SAAStC,EAAE1E,EAAEgX,GAAK,MAAOtZ,IAAGosB,IAAID,EAASnlB,EAAE1E,IAAI+pB,OAAStR,EAAStI,IAAI,SAASzL,EAAE1E,GAAK,MAAOA,KAAKwR,OAAO,SAAS9M,EAAE1E,GAAI,OAAQyY,EAASzY,KAAOgX,IAAOgT,aACpKhjB,MAAM,SAAU,SAAStC,EAAE1E,EAAEgX,GAAK,MAAOtZ,IAAGosB,IAAID,EAASnlB,EAAE1E,IAAI+pB,OAAStR,EAAStI,IAAI,SAASzL,EAAE1E,GAAK,MAAOA,KAAKwR,OAAO,SAAS9M,EAAE1E,GAAI,OAAQyY,EAASzY,KAAOgX,IAAOgT,cAG3KjB,EACA/I,EAAK/R,gBAAgBC,EAAa,4BAC7BhK,KAAK,YAAa,SAASQ,EAAE1E,GAC1B,MAAO,aAAeoL,EAAE1G,EAAEogB,IAAM,IAAMzgB,EAAEwR,EAAKnR,EAAE1E,IAAM,MAExD0D,OAAO,QACPQ,KAAK,QAAS,SAASQ,EAAE1E,GACtB,MAAOiG,MAAKC,IAAIkF,EAAEsM,EAAKhT,EAAE1E,GAAK0E,EAAEmS,IAAMzL,EAAE1G,EAAEmS,MAAQ,IAErD3S,KAAK,SAAUG,EAAEkQ,aAEtByL,EAAK/R,gBAAgBC,EAAa,4BAC7BhK,KAAK,YAAa,SAASQ,EAAE1E,GAE1B,MAAO,aACcoL,EAAhBsM,EAAKhT,EAAE1E,GAAK,EAAM0X,EAAKhT,EAAE1E,GAAQ,GAChC,KACD0E,EAAEqE,OAAS1E,EAAEkQ,YAAcnT,EAAKhC,OAE7BiF,EAAEwR,EAAKnR,EAAE1E,KACX,MAET0D,OAAO,QACPQ,KAAK,SAAUG,EAAEkQ,YAAcnT,EAAKhC,QACpC8E,KAAK,QAAS,SAASQ,EAAE1E,GACtB,MAAOiG,MAAKL,IAAIK,KAAKC,IAAIkF,EAAEsM,EAAKhT,EAAE1E,IAAMoL,EAAE,IAAI,IAAM,IAIhEwL,EAAKvS,EAAEoR,OACPoB,EAAKzL,EAAEqK,SAIXvH,EAAYS,UAAU,gCACf7O,EAnSX,GAaM2Y,GAQA7C,EACAI,EACAF,EACAa,EASFC,EAAIC,EAjCJxU,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACRC,EAAS,IACTmD,EAAKd,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UACrBlE,EAAY,KACZY,EAAI3G,GAAGmH,MAAMuH,UACbhB,EAAI1N,GAAGmH,MAAMC,SACb+Q,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9B0f,EAAU,SAASpmB,GAAK,MAAOA,GAAE0mB,MACjC9P,GAAU,GACVrS,EAAQhM,EAAGG,MAAM6O,eACjB4d,EAAW,KAEXd,GAAU,EACVjJ,GAAa,EACbqL,GAAgB,EAChBN,EAAe,GACfnB,EAAe,GACftJ,EAAc1iB,GAAGib,OAAO,QAMxB5T,EAAW,IACXtH,EAAWC,GAAGD,SAAS,aAAc,eAAgB,kBAAmB,mBAAoB,kBAAmB,mBAAoB,aAQrIyQ,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,EAyTjD,OAjDAjF,GAAMrC,SAAWA,EAEjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAUsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACjErB,QAAUqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACnEZ,GAAU4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAK5Q,IAC/DmG,GAAUH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAAGyS,EAAKzS,IAC/DmmB,MAAangB,IAAK,WAAW,MAAO6f,IAAW5f,IAAK,SAASjG,GAAG6lB,EAAQ7lB,IACxEhC,QAAUgI,IAAK,WAAW,MAAO5G,IAAK6G,IAAK,SAASjG,GAAGZ,EAAEY,IACzD0S,QAAU1M,IAAK,WAAW,MAAOG,IAAKF,IAAK,SAASjG,GAAGmG,EAAEnG,IACzD2Q,SAAU3K,IAAK,WAAW,MAAO2K,IAAW1K,IAAK,SAASjG,GAAG2Q,EAAQ3Q,IACrE+Q,SAAU/K,IAAK,WAAW,MAAO+K,IAAW9K,IAAK,SAASjG,GAAG+Q,EAAQ/Q,IACrE6Q,QAAU7K,IAAK,WAAW,MAAO6K,IAAU5K,IAAK,SAASjG,GAAG6Q,EAAO7Q,IACnE0R,QAAU1L,IAAK,WAAW,MAAO0L,IAAUzL,IAAK,SAASjG,GAAG0R,EAAO1R,IACnEqW,QAAUrQ,IAAK,WAAW,MAAOqQ,IAAUpQ,IAAK,SAASjG,GAAGqW,EAAOrW,IACnE8jB,SAAU9d,IAAK,WAAW,MAAO8d,IAAW7d,IAAK,SAASjG,GAAG8jB,EAAQ9jB,IACrE6a,YAAa7U,IAAK,WAAW,MAAO6U,IAAc5U,IAAK,SAASjG,GAAG6a,EAAW7a,IAG9EwT,UAAexN,IAAK,WAAW,MAAOwN,IAAYvN,IAAK,SAASjG,GAAGwT,EAASxT,IAC5E8B,IAAekE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,GAAG8B,EAAG9B,IAChEmb,aAAenV,IAAK,WAAW,MAAOmV,IAAelV,IAAK,SAASjG,GAAGmb,EAAYnb,IAClF4lB,cAAe5f,IAAK,WAAW,MAAO4f,IAAgB3f,IAAK,SAASjG,GAAG4lB,EAAa5lB,IACpFykB,cAAcze,IAAK,WAAW,MAAOye,IAAgBxe,IAAK,SAASjG,GAAGykB,EAAazkB,IAGnF5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,KAEtBkE,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,KAE9B4kB,UAAY5e,IAAK,WAAW,MAAO4e,IAAY3e,IAAK,SAASjG,GACzD4kB,EAAW5kB,EAAIhI,EAAGG,MAAM4O,SAAS/G,GAAK,SAI9ChI,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAOguB,wBAA0B,WAChC,YAsFA,SAASvrB,GAAMoB,GAuMX,MAtMAgN,GAAYW,QACZX,EAAY7Q,OAAO8sB,GACfrS,GAAW5J,EAAY7Q,OAAO0a,GAC9BC,GAAW9J,EAAY7Q,OAAO4a,GAElC/W,EAAUC,KAAK,SAASC,GACpB,GAAIqC,GAAY/F,GAAGgG,OAAO3F,KAE1Bd,GAAGG,MAAMiV,QAAQ5O,EACjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAelE,IAbAvC,EAAM+P,OAAS,WAAapM,EAAU4G,aAAatF,SAASA,GAAU3G,KAAK0B,IAC3EA,EAAM2D,UAAY1F,KAElBgrB,EAAUoB,EAASpB,UAEnBxb,EACKqC,OAAOqN,EAAY7b,GAAOtB,EAAM+P,QAChCH,OAAOwN,EAAY9b,IACnByO,SAGLtC,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,YAE9C0E,EAAc,CACf,GAAIhU,EACJgU,KACA,KAAKhU,IAAOoE,GACJA,EAAMpE,YAAgBjL,OACtBif,EAAahU,GAAOoE,EAAMpE,GAAKhL,MAAM,GAErCgf,EAAahU,GAAOoE,EAAMpE,GAKtC,KAAK/H,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAE9E,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,SAItCP,EAAI8lB,EAASlnB,SACbmI,EAAI+e,EAASxS,QAGb,IAAI9T,GAAOJ,EAAUK,UAAU,wCAAwC1C,MAAMA,IACzEgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,2CAA2CD,OAAO,KAClG0P,EAAI9P,EAAKH,OAAO,IA4BpB,IA1BA0U,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBAC5BD,OAAO,KAAKC,KAAK,QAAS,eAC1BD,OAAO,QACZmU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,eACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,mBAG7B2Z,IACAC,EAAOna,MAAMnB,EAAiB4nB,KAE9BzW,EAAEjQ,OAAO,kBACJ8U,MAAMpX,GACNhD,KAAK0f,GAELzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SACpBnB,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IAGlEsR,EAAEjQ,OAAO,kBACJQ,KAAK,YAAa,aAAekmB,IAAiB,KAAQ/nB,EAAOE,IAAM,MAI5Ewb,EAAc,CACd,GAAIC,KACE7U,IAAKkhB,EAAcC,SAAW,UAAW7R,SAAU0R,EAASpB,YAC5D5f,IAAKkhB,EAActB,SAAW,UAAWtQ,UAAW0R,EAASpB,WAGnE9K,GAASta,MAAMymB,KAAgBnhB,OAAO,OAAQ,OAAQ,SACtD0K,EAAEjQ,OAAO,oBACJ8U,MAAMwF,GACN9Z,KAAK,YAAa,gBAAmB7B,EAAOE,IAAM,KAClDnE,KAAK6f,GAGdpa,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAGvE4nB,EACK1R,SAASrX,EAAK+O,IAAI,SAASpH,GAAU,MAAOA,GAAO0P,YACnD9U,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GACvB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,WAE9C,IAAIF,GAAW5E,EAAEjQ,OAAO,gBACnB8U,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAK/C,IAHAF,EAASlO,aAAajM,KAAK+rB,GAGvBrS,EAAW,CACXC,EACKlT,MAAMR,GACNya,OAAQ7hB,EAAGG,MAAMoT,WAAW/N,EAAgB,GAAIrB,IAChDsX,UAAUlW,EAAgB,GAE/BmR,EAAEjQ,OAAO,iBAAiBtF,KAAK2Z,EAE/B,IAAIlD,GAASlB,EAAEjQ,OAAO,iBAAiBI,UAAU,IAEjD+Q,GACK/Q,UAAU,cAGfkU,IACAC,EACKpT,MAAMuG,GACN0T,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAChDsX,UAAWjW,EAAiB,GAEjCkR,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,eAAiBzB,EAAkB,KAC1DkR,EAAEjQ,OAAO,iBAAiBtF,KAAK6Z,IAInCtE,EAAEjQ,OAAO,qBACJQ,KAAK,KAAMkH,EAAE,IACblH,KAAK,KAAMkH,EAAE,IACblH,KAAK,KAAM,GACXA,KAAK,MAAOzB,GAOjBqb,EAAOrgB,SAASkB,GAAG,cAAe,SAASogB,GACvC,IAAK,GAAI5V,KAAO4V,GACZxR,EAAMpE,GAAO4V,EAAS5V,EAC1B1L,GAASof,YAAYtP,GACrBzN,EAAM+P,WAGVoO,EAASxgB,SAASkB,GAAG,cAAe,SAAS+F,EAAE1E,GAC3C,GAAK0E,EAAE+T,SAAP,CAOA,OANAuF,EAAeA,EAAa7N,IAAI,SAAS0B,GAErC,MADAA,GAAE4G,UAAW,EACN5G,IAEXnN,EAAE+T,UAAW,EAEL/T,EAAEyE,KACN,IAAK,UACDghB,EAASpB,SAAQ,EACjB,MACJ,KAAK,UACDoB,EAASpB,SAAQ,GAIzBxb,EAAMwb,QAAUoB,EAASpB,UACzBtrB,EAASof,YAAYtP,GACrBwb,EAAUoB,EAASpB,UAEnBjpB,EAAM+P,YAIVpS,EAASkB,GAAG,cAAe,SAASC,GAEN,mBAAfA,GAAE6Z,WACTrX,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,SAAW7Z,EAAE6Z,SAASzY,KAGjCuN,EAAMkL,SAAW7Z,EAAE6Z,UAGE,mBAAd7Z,GAAEmqB,UACToB,EAASpB,QAAQnqB,EAAEmqB,SACnBxb,EAAMwb,QAAUnqB,EAAEmqB,QAClBA,EAAUnqB,EAAEmqB,SAGhBjpB,EAAM+P,aAGd3B,EAAYS,UAAU,uCACf7O,EAvRX,GAkBMuE,GACA+G,EAnBF+e,EAAWltB,EAAGI,OAAOutB,qBACnB7S,EAAQ9a,EAAGI,OAAOqW,OAClBuE,EAAQhb,EAAGI,OAAOqW,OAClBoK,EAAS7gB,EAAGI,OAAOygB,SAASla,OAAO,IACnCqa,EAAWhhB,EAAGI,OAAOygB,SAASla,OAAO,IACrCzG,EAAUF,EAAGI,OAAOF,UAGtBkF,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9CqB,EAAQ,KACRC,EAAS,KACTqF,EAAQhM,EAAGG,MAAM6O,eACjB8R,GAAe,EACfsM,KACAxM,GAAa,EACb/F,GAAY,EACZE,GAAY,EACZ+Q,GAAU,EAGVxb,EAAQtQ,EAAGG,MAAMmQ,QACjB4P,EAAe,KACfxK,EAAS,KACTlV,EAAWC,GAAGD,SAAS,cAAe,cAAc,aACpD2sB,EAAe,WAAa,MAAOrM,GAAe,IAAM,GACxDhZ,EAAW,GAGjBwI,GAAMwb,SAAU,EAEhBoB,EAASpB,QAAQA,GAEjBhR,EACKlE,OAAO,QACPY,YAAY,GACZD,YAAW,GACXR,WAAW,SAAStP,GAAK,MAAOA,KAErCuT,EACKpE,OAAO,UACPG,WAAWtW,GAAGib,OAAO,SAG1Bxb,EACK4H,SAAS,GACTqD,eAAe,SAAS1D,EAAG1E,GACxB,MAAOiY,GAAMjE,aAAatP,EAAG1E,KAEhCqI,gBAAgB,SAAS3D,EAAG1E,GACzB,MAAO+X,GAAM/D,aAAatP,EAAG1E,KAGrCie,EAASyB,aAAY,EAMrB,IAAIxC,GAAc,SAAS9b,GACvB,MAAO,YACH,OACIzB,OAAQyB,EAAK+O,IAAI,SAASzL,GAAK,OAAQA,EAAE+T,WACzCsQ,QAASA,KAKjB9L,EAAc,SAAS7b,GACvB,MAAO,UAASmM,GACU1M,SAAlB0M,EAAMwb,UACNA,EAAUxb,EAAMwb,SACCloB,SAAjB0M,EAAM5N,QACNyB,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,UAAYlL,EAAM5N,OAAOK,OAK5CkO,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,EAyRjD,OAzEAolB,GAAS1sB,SAASkB,GAAG,2BAA4B,SAASia,GACtDA,EAAIjQ,MAAQ7I,EAAMuE,IAAIuU,EAAIxX,MAC1BwX,EAAY,QACRzP,IAAKyP,EAAIxX,KAAK+H,IACdR,MAAO7I,EAAMsL,IAAIwN,EAAIxX,MACrB6H,MAAO2P,EAAI3P,OAEf9L,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7BonB,EAAS1sB,SAASkB,GAAG,0BAA2B,SAASia,GACrDzb,EAAQ4F,QAAO,KAGnBonB,EAAS1sB,SAASkB,GAAG,2BAA4B,SAASia,GACtDzb,MAQJ2C,EAAMrC,SAAWA,EACjBqC,EAAMqqB,SAAWA,EACjBrqB,EAAMge,OAASA,EACfhe,EAAMme,SAAWA,EACjBne,EAAMiY,MAAQA,EACdjY,EAAMmY,MAAQA,EACdnY,EAAMyN,MAAQA,EACdzN,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtE4Y,YAAa5S,IAAK,WAAW,MAAO4S,IAAc3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IAC9E8Y,cAAe9S,IAAK,WAAW,MAAO8S,IAAgB7S,IAAK,SAASjG,GAAG8Y,EAAa9Y,IACpFolB,eAAgBpf,IAAK,WAAW,MAAOof,IAAiBnf,IAAK,SAASjG,GAAGolB,EAAcplB,IACvF6S,WAAiB7M,IAAK,WAAW,MAAO6M,IAAa5M,IAAK,SAASjG,GAAG6S,EAAU7S,IAChF+S,WAAe/M,IAAK,WAAW,MAAO+M,IAAa9M,IAAK,SAASjG,GAAG+S,EAAU/S,IAC9EkY,cAAkBlS,IAAK,WAAW,MAAOkS,IAAgBjS,IAAK,SAASjG,GAAGkY,EAAalY,IACvF0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IAGrE5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,GAClBolB,EAASplB,SAASA,GAClBgT,EAAMhT,SAASA,GACfkT,EAAMlT,SAASA,KAEnBkE,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1B6Y,EAAO7U,MAAMA,KAEjB4gB,UAAY5e,IAAK,WAAW,MAAOkf,GAASN,UAAY3e,IAAK,SAASjG,GAClEklB,EAASN,SAAS5kB,GAClB6Y,EAAO7U,MAAM,SAASvE,EAAE1E,GAAI,MAAOtC,IAAGosB,IAAI,QAAQC,OAAW,IAAJ/pB,GAASgqB,iBAI1E/sB,EAAGG,MAAM6U,eAAenS,EAAOqqB,GAC/BltB,EAAGG,MAAMiO,YAAYvL,GAEdA,GAEX7C,EAAGI,OAAOiuB,WAAa,WACnB,YAgDA,SAASxrB,GAAMoB,GA2UX,MA1UAA,GAAUC,KAAK,SAASC,GA4NpB,QAASmqB,GAAe3S,GACpB,GAAI4S,GAAwC,IAAhCpqB,EAAKwX,EAAI4F,aAAavG,MAAcwT,EAASC,CACzD9S,GAAIjQ,MAAQiQ,EAAIzN,MAAM9G,EACtBuU,EAAI7P,QACAJ,MAAOiQ,EAAIzN,MAAMC,EACjBnC,MAAO2P,EAAIzN,MAAMlC,MACjBE,IAAKyP,EAAI7P,OAAOI,KAEpBhM,EACK4H,SAAS,GACTqD,eAAe,SAAS1D,EAAG1E,GACxB,MAAOwrB,GAAMxX,aAAatP,EAAG1E,KAEhCoB,KAAKwX,GACL7V,QAAO,GAGhB,QAAS4oB,GAAkB/S,GACvB,GAAI4S,GAAwC,IAAhCpqB,EAAKwX,EAAI4F,aAAavG,MAAcwT,EAASC,CACzD9S,GAAIjQ,MAAQiQ,EAAIzN,MAAM9G,EACtBuU,EAAI7P,QACAJ,MAAOiQ,EAAIzN,MAAMC,EACjBnC,MAAO2P,EAAIzN,MAAMlC,MACjBE,IAAKyP,EAAI7P,OAAOI,KAEpBhM,EACK4H,SAAS,KACTqD,eAAe,SAAS1D,EAAG1E,GACxB,MAAOwrB,GAAMxX,aAAatP,EAAG1E,KAEhCoB,KAAKwX,GACL7V,QAAO,GAGhB,QAAS6oB,GAAgBhT,GACrB,GAAI4S,GAAwC,IAAhCpqB,EAAKwX,EAAI4F,aAAavG,MAAcwT,EAASC,CACzD9S,GAAIzN,MAAS,EAAI0gB,EAAOxnB,IAAIuU,EAAIzN,OAChCyN,EAAIzN,MAAS,EAAI0gB,EAAOzgB,IAAIwN,EAAIzN,OAChChO,EACK4H,SAAS,GACTqD,eAAe,SAAS1D,EAAG1E,GACxB,MAAOwrB,GAAMxX,aAAatP,EAAG1E,KAEhCoB,KAAKwX,GACL7V,QAAO,GAGhB,QAAS+oB,GAAclT,GACnB,GAAI4S,GAAwC,IAAhCpqB,EAAKwX,EAAIxX,KAAK2H,QAAQkP,MAAcwT,EAASC,CAEzD9S,GAAIjQ,MAAQojB,EAAM1nB,IAAIuU,EAAIxX,MAC1BwX,EAAY,QACRjQ,MAAOojB,EAAM3gB,IAAIwN,EAAIxX,MACrB6H,MAAO2P,EAAI3P,MACXE,IAAKyP,EAAIxX,KAAK+H,KAElBhM,EACK4H,SAAS,GACTqD,eAAe,SAAS1D,EAAG1E,GACxB,MAAOwrB,GAAMxX,aAAatP,EAAG1E,KAEhCoB,KAAKwX,GACL7V,QAAO,GAzRhB,GAAIU,GAAY/F,GAAGgG,OAAO3F,KAE1Bd,GAAGG,MAAMiV,QAAQ5O,GAEjB3D,EAAM+P,OAAS,WAAapM,EAAU4G,aAAajM,KAAK0B,IACxDA,EAAM2D,UAAY1F,IAElB,IAAIyE,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,GAE9D2pB,EAAa5qB,EAAKoQ,OAAO,SAAS9M,GAAI,MAAiB,QAAVA,EAAEtB,MAA6B,GAAXsB,EAAEuT,QACnEgU,EAAa7qB,EAAKoQ,OAAO,SAAS9M,GAAI,MAAiB,QAAVA,EAAEtB,MAA6B,GAAXsB,EAAEuT,QACnEiU,EAAgB9qB,EAAKoQ,OAAO,SAAS9M,GAAI,MAAiB,WAAVA,EAAEtB,MAAgC,GAAXsB,EAAEuT,QACzEkU,EAAgB/qB,EAAKoQ,OAAO,SAAS9M,GAAI,MAAiB,WAAVA,EAAEtB,MAAgC,GAAXsB,EAAEuT,QACzEmU,EAAahrB,EAAKoQ,OAAO,SAAS9M,GAAI,MAAiB,OAAVA,EAAEtB,MAA6B,GAAXsB,EAAEuT,QACnEoU,EAAajrB,EAAKoQ,OAAO,SAAS9M,GAAI,MAAiB,OAAVA,EAAEtB,MAA6B,GAAXsB,EAAEuT,QACnEqU,EAAalrB,EAAKoQ,OAAO,SAAS9M,GAAI,MAAiB,QAAVA,EAAEtB,MAA6B,GAAXsB,EAAEuT,QACnEsU,EAAanrB,EAAKoQ,OAAO,SAAS9M,GAAI,MAAiB,QAAVA,EAAEtB,MAA6B,GAAXsB,EAAEuT,OAGvE,MAAK7W,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAE9E,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,QAGtC,IAAIwiB,GAAUhmB,EAAKoQ,OAAO,SAAS9M,GAAI,OAAQA,EAAE+T,UAAuB,GAAX/T,EAAEuT,QAC1D9H,IAAI,SAASzL,GACV,MAAOA,GAAES,OAAOgL,IAAI,SAASzL,EAAE1E,GAC3B,OAASqE,EAAGwR,EAAKnR,GAAI0G,EAAGsM,EAAKhT,QAIrC2iB,EAAUjmB,EAAKoQ,OAAO,SAAS9M,GAAI,OAAQA,EAAE+T,UAAuB,GAAX/T,EAAEuT,QAC1D9H,IAAI,SAASzL,GACV,MAAOA,GAAES,OAAOgL,IAAI,SAASzL,EAAE1E,GAC3B,OAASqE,EAAGwR,EAAKnR,GAAI0G,EAAGsM,EAAKhT,OAIzCL,GAAKgF,OAAO3L,GAAGmc,OAAOnc,GAAGoc,MAAMsN,EAAQ1oB,OAAO2oB,IAAW,SAAS3iB,GAAK,MAAOmR,GAAKnR,MAC9E4E,OAAO,EAAG9G,GAEf,IAAIqB,GAAOJ,EAAUK,UAAU,qBAAqB1C,MAAMA,IACtDgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,wBAAwBD,OAAO,IAEnFmU,GAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,cACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,cACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,aACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,aACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,cACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,cACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,aAEjC,IAAIyP,GAAI9P,EAAKH,OAAO,KAEhB8oB,EAAcprB,EAAK+O,IAAI,SAASzL,EAAE1E,GAClC,MAAOoB,GAAKpB,GAAGiJ,OAASA,EAAMvE,EAAG1E,IAGrC,IAAI6d,EAAY,CACZ,GAAI8E,GAAc7E,EAAOmE,QAAUzf,EAAiB,EAAIA,EACpDglB,EAAkB1J,EAAOmE,QAAUU,EAAc,CAErD7E,GAAOna,MAAMgf,GACb7E,EAAO7U,MAAMujB,GAEb7Y,EAAEjQ,OAAO,eACJ8U,MAAMpX,EAAK+O,IAAI,SAASpH,GAGrB,MAFAA,GAAO0e,YAAqC5mB,SAAvBkI,EAAO0e,YAA4B1e,EAAOI,IAAMJ,EAAO0e,YAC5E1e,EAAOI,IAAMJ,EAAO0e,aAA+B,GAAhB1e,EAAOkP,MAAa,GAAK,iBACrDlP,KAEV3K,KAAK0f,GAELzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SACpBnB,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IAGlEsR,EAAEjQ,OAAO,eACJQ,KAAK,YAAa,aAAesjB,EAAkB,KAAQnlB,EAAOE,IAAM,KAGjFkqB,EACK9oB,MAAMnB,GACNoB,OAAOnB,GACPmiB,YAAYA,GACZ3b,MAAMujB,EAAYhb,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,UAA6B,GAAjBrX,EAAKpB,GAAGiY,OAA8B,QAAhB7W,EAAKpB,GAAGoD,QACxG+jB,EACKxjB,MAAMnB,GACNoB,OAAOnB,GACPmiB,YAAYA,GACZ3b,MAAMujB,EAAYhb,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,UAA6B,GAAjBrX,EAAKpB,GAAGiY,OAA8B,QAAhB7W,EAAKpB,GAAGoD,QACxGspB,EACK/oB,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAMujB,EAAYhb,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,UAA6B,GAAjBrX,EAAKpB,GAAGiY,OAA8B,WAAhB7W,EAAKpB,GAAGoD,QACxGupB,EACKhpB,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAMujB,EAAYhb,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,UAA6B,GAAjBrX,EAAKpB,GAAGiY,OAA8B,WAAhB7W,EAAKpB,GAAGoD,QACxG2oB,EACKpoB,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAMujB,EAAYhb,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,UAA6B,GAAjBrX,EAAKpB,GAAGiY,OAA8B,OAAhB7W,EAAKpB,GAAGoD,QACxG6jB,EACKtjB,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAMujB,EAAYhb,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,UAA6B,GAAjBrX,EAAKpB,GAAGiY,OAA8B,OAAhB7W,EAAKpB,GAAGoD,QACxGyoB,EACKloB,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAMujB,EAAYhb,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,UAA6B,GAAjBrX,EAAKpB,GAAGiY,OAA8B,QAAhB7W,EAAKpB,GAAGoD,QACxGwpB,EACKjpB,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAMujB,EAAYhb,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,UAA6B,GAAjBrX,EAAKpB,GAAGiY,OAA8B,QAAhB7W,EAAKpB,GAAGoD,QAExGuQ,EAAEzP,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAEpE,IAAIsqB,GAAalZ,EAAEjQ,OAAO,eACrB8U,MAAMwT,EAAWxa,OAAO,SAAS9M,GAAG,OAAQA,EAAE+T,YAC/CqU,EAAgBnZ,EAAEjQ,OAAO,kBACxB8U,MAAM0T,EAAc1a,OAAO,SAAS9M,GAAG,OAAQA,EAAE+T,YAClDsU,GAAYpZ,EAAEjQ,OAAO,cACpB8U,MAAM4T,EAAU5a,OAAO,SAAS9M,GAAG,OAAQA,EAAE+T,YAC9CuU,GAAarZ,EAAEjQ,OAAO,eACrB8U,MAAM8T,EAAW9a,OAAO,SAAS9M,GAAG,OAAQA,EAAE+T,YAC/CoP,GAAalU,EAAEjQ,OAAO,eACrB8U,MAAMyT,EAAWza,OAAO,SAAS9M,GAAG,OAAQA,EAAE+T,YAC/CwU,GAAgBtZ,EAAEjQ,OAAO,kBACxB8U,MAAM2T,EAAc3a,OAAO,SAAS9M,GAAG,OAAQA,EAAE+T,YAClDmP,GAAYjU,EAAEjQ,OAAO,cACpB8U,MAAM6T,EAAU7a,OAAO,SAAS9M,GAAG,OAAQA,EAAE+T,YAC9CyU,GAAavZ,EAAEjQ,OAAO,eACrB8U,MAAM+T,EAAW/a,OAAO,SAAS9M,GAAG,OAAQA,EAAE+T,YAE/C0U,GAAcb,EAAWltB,OAASktB,EAAWnc,IAAI,SAASmB,GAAG,MAAOA,GAAEnM,SAAS2d,OAAO,SAASxR,EAAE8b,GACjG,MAAO9b,GAAEnB,IAAI,SAASkd,EAAKrtB,GAAG,OAAQqE,EAAGgpB,EAAKhpB,EAAG+G,EAAGiiB,EAAKjiB,EAAIgiB,EAAEptB,GAAGoL,OACnE1M,SAAS2F,EAAE,EAAG+G,EAAE,QACfkiB,GAAcf,EAAWntB,OAASmtB,EAAWpc,IAAI,SAASmB,GAAG,MAAOA,GAAEnM,SAAS2d,OAAO,SAASxR,EAAE8b,GACjG,MAAO9b,GAAEnB,IAAI,SAASkd,EAAKrtB,GAAG,OAAQqE,EAAGgpB,EAAKhpB,EAAG+G,EAAGiiB,EAAKjiB,EAAIgiB,EAAEptB,GAAGoL,OACnE1M,SAAS2F,EAAE,EAAG+G,EAAE,OAEnBmiB,GAASlkB,OAAOmkB,GAAY9vB,GAAGmc,OAAOnc,GAAGoc,MAAMsN,GAAS1oB,OAAOyuB,IAAc,SAASzoB,GAAK,MAAOA,GAAE0G,KAC/F9B,OAAO,EAAG7G,IAEfgrB,EAASpkB,OAAOqkB,GAAYhwB,GAAGmc,OAAOnc,GAAGoc,MAAMuN,GAAS3oB,OAAO4uB,IAAc,SAAS5oB,GAAK,MAAOA,GAAE0G,KAC/F9B,OAAO,EAAG7G,IAEfgqB,EAAOzW,QAAQuX,EAAQlkB,UACvBqjB,EAAU1W,QAAQuX,EAAQlkB,UAC1B0iB,EAAM/V,QAAQuX,EAAQlkB,UACtBwiB,EAAO7V,QAAQuX,EAAQlkB,UAEvB8d,EAAOnR,QAAQyX,EAAQpkB,UACvBsjB,EAAU3W,QAAQyX,EAAQpkB,UAC1B4d,EAAMjR,QAAQyX,EAAQpkB,UACtBujB,EAAO5W,QAAQyX,EAAQpkB,UAEpBijB,EAAWltB,QAAQ1B,GAAG2M,WAAW2iB,IAAY5uB,KAAKytB,GAClDU,EAAWntB,QAAQ1B,GAAG2M,WAAW6iB,IAAY9uB,KAAKwuB,GAElDR,EAAUhtB,QAAQ1B,GAAG2M,WAAW0iB,IAAW3uB,KAAK2tB,GAChDM,EAAUjtB,QAAQ1B,GAAG2M,WAAWud,IAAWxpB,KAAK6oB,GAEhD+E,EAAW5sB,QAAQ1B,GAAG2M,WAAWwiB,GAAYzuB,KAAKquB,GAClDR,EAAW7sB,QAAQ1B,GAAG2M,WAAWwd,IAAYzpB,KAAK+oB,GAElD+E,EAAc9sB,QAAQ1B,GAAG2M,WAAWyiB,GAAe1uB,KAAKsuB,GACxDP,EAAc/sB,QAAQ1B,GAAG2M,WAAW4iB,IAAe7uB,KAAKuuB,GAE3D5U,EACK+G,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAChDsX,UAAUjW,EAAiB,GAEhCkR,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,eAAiBzB,EAAkB,KAC1D/E,GAAG2M,WAAWsJ,EAAEjQ,OAAO,kBAClBtF,KAAK2Z,GAEV2T,EACK5M,OAAQ7hB,EAAGG,MAAMoT,WAAW/N,EAAgB,GAAIrB,IAChDsX,UAAWlW,EAAgB,GAGhC9E,GAAG2M,WAAWsJ,EAAEjQ,OAAO,mBAClBtF,KAAKstB,GAEVD,EACK3M,OAAQ7hB,EAAGG,MAAMoT,WAAW/N,EAAgB,GAAIrB,IAChDsX,UAAWlW,EAAgB,GAEhC9E,GAAG2M,WAAWsJ,EAAEjQ,OAAO,mBAClBtF,KAAKqtB,GAEV9X,EAAEjQ,OAAO,kBACJuD,QAAQ,cAAemgB,EAAQhoB,QAAS,GAAQ,GAChD8E,KAAK,YAAa,aAAeG,EAAEiF,QAAQ,GAAK,OAErDqK,EAAEjQ,OAAO,kBACJuD,QAAQ,cAAeogB,EAAQjoB,QAAS,GAAQ,GAChD8E,KAAK,YAAa,aAAeG,EAAEiF,QAAQ,GAAK,OAErDwU,EAAOrgB,SAASkB,GAAG,cAAe,SAASogB,GACvCjf,EAAM+P,WAwEV4c,EAAOhvB,SAASkB,GAAG,2BAA4B4sB,GAC/CpE,EAAO1pB,SAASkB,GAAG,2BAA4B4sB,GAC/CkB,EAAOhvB,SAASkB,GAAG,0BAA2B,SAASia,GACnDzb,EAAQ4F,QAAO,KAEnBokB,EAAO1pB,SAASkB,GAAG,0BAA2B,SAASia,GACnDzb,EAAQ4F,QAAO,KAGnB2pB,EAAUjvB,SAASkB,GAAG,2BAA4BgtB,GAClDgB,EAAUlvB,SAASkB,GAAG,2BAA4BgtB,GAClDe,EAAUjvB,SAASkB,GAAG,0BAA2B,SAASia,GACtDzb,EAAQ4F,QAAO,KAEnB4pB,EAAUlvB,SAASkB,GAAG,0BAA2B,SAASia,GACtDzb,EAAQ4F,QAAO,KAGnB8oB,EAAOpuB,SAASkB,GAAG,2BAA4BitB,GAC/CgB,EAAOnvB,SAASkB,GAAG,2BAA4BitB,GAC/CC,EAAOpuB,SAASkB,GAAG,0BAA2B,SAASia,GACnDzb,EAAQ4F,QAAO,KAEnB6pB,EAAOnvB,SAASkB,GAAG,0BAA2B,SAASia,GACnDzb,EAAQ4F,QAAO,KAGnBgpB,EAAMtuB,SAASkB,GAAG,2BAA4BmtB,GAC9C7E,EAAMxpB,SAASkB,GAAG,2BAA4BmtB,GAE9CC,EAAMtuB,SAASkB,GAAG,0BAA2B,SAASia,GAClDzb,EAAQ4F,QAAO,KAEnBkkB,EAAMxpB,SAASkB,GAAG,0BAA2B,SAASia,GAClDzb,EAAQ4F,QAAO,KAEnBgpB,EAAMtuB,SAASkB,GAAG,2BAA4B,SAASia,GACnDzb,MAEJ8pB,EAAMxpB,SAASkB,GAAG,2BAA4B,SAASia,GACnDzb,QAKD2C,EArXX,GAMI0tB,GACAE,EAPArrB,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAChD2G,EAAQhM,EAAGG,MAAM6O,eACjBtI,EAAQ,KACRC,EAAS,KACTia,GAAa,EACblL,EAAS,KAGTkD,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9BwZ,EAAc,WACdjF,GAAa,EAObtb,EAAI3G,GAAGmH,MAAMC,SACbyoB,EAAU7vB,GAAGmH,MAAMC,SACnB2oB,EAAU/vB,GAAGmH,MAAMC,SAEnB2nB,EAASxvB,EAAGI,OAAOkH,OAAOoT,OAAO4V,GACjCpG,EAASlqB,EAAGI,OAAOkH,OAAOoT,OAAO8V,GAEjCf,EAAYzvB,EAAGI,OAAOgnB,UAAU1M,OAAO4V,GACvCZ,EAAY1vB,EAAGI,OAAOgnB,UAAU1M,OAAO8V,GAEvC1B,EAAQ9uB,EAAGI,OAAOurB,WAAWG,SAAQ,GAAOpR,OAAO4V,GACnDtG,EAAQhqB,EAAGI,OAAOurB,WAAWG,SAAQ,GAAOpR,OAAO8V,GAEnD5B,EAAS5uB,EAAGI,OAAOswB,cAAchW,OAAO4V,GACxCX,EAAS3vB,EAAGI,OAAOswB,cAAchW,OAAO8V,GAExC1V,EAAQ9a,EAAGI,OAAOqW,OAAO7O,MAAMR,GAAGwP,OAAO,UAAUY,YAAY,GAC/DiX,EAASzuB,EAAGI,OAAOqW,OAAO7O,MAAM0oB,GAAS1Z,OAAO,QAChD4X,EAASxuB,EAAGI,OAAOqW,OAAO7O,MAAM4oB,GAAS5Z,OAAO,SAEhDiK,EAAS7gB,EAAGI,OAAOygB,SAASla,OAAO,IACnCzG,EAAUF,EAAGI,OAAOF,UACpBM,EAAWC,GAAGD,UA0ZlB,OAtEAqC,GAAMrC,SAAWA,EACjBqC,EAAMge,OAASA,EACfhe,EAAM2sB,OAASA,EACf3sB,EAAMqnB,OAASA,EACfrnB,EAAM4sB,UAAYA,EAClB5sB,EAAM6sB,UAAYA,EAClB7sB,EAAMisB,MAAQA,EACdjsB,EAAMmnB,MAAQA,EACdnnB,EAAM+rB,OAASA,EACf/rB,EAAM8sB,OAASA,EACf9sB,EAAMiY,MAAQA,EACdjY,EAAM4rB,OAASA,EACf5rB,EAAM2rB,OAASA,EACf3rB,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtE4Y,YAAa5S,IAAK,WAAW,MAAO4S,IAAc3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IAC9EuoB,UAAgBviB,IAAK,WAAW,MAAOuiB,IAAYtiB,IAAK,SAASjG,GAAGuoB,EAASvoB,IAC7EyoB,UAAcziB,IAAK,WAAW,MAAOyiB,IAAYxiB,IAAK,SAASjG,GAAGyoB,EAASzoB,IAC3E0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IACrE2f,aAAiB3Z,IAAK,WAAW,MAAO2Z,IAAe1Z,IAAK,SAASjG,GAAG2f,EAAY3f,IAGpF5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,KAE9BZ,GAAI4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAC7C4Q,EAAO5Q,EACPwnB,EAAOpoB,EAAEY,GACTkiB,EAAO9iB,EAAEY,GACTynB,EAAUroB,EAAEY,GACZ0nB,EAAUtoB,EAAEY,GACZ8mB,EAAM1nB,EAAEY,GACRgiB,EAAM5iB,EAAEY,GACR4mB,EAAOxnB,EAAEY,GACT2nB,EAAOvoB,EAAEY,KAEbmG,GAAIH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAC7CyS,EAAOzS,EACPwnB,EAAOrhB,EAAEnG,GACTkiB,EAAO/b,EAAEnG,GACTynB,EAAUthB,EAAEnG,GACZ0nB,EAAUvhB,EAAEnG,GACZ4mB,EAAOzgB,EAAEnG,GACT2nB,EAAOxhB,EAAEnG,GACT8mB,EAAM3gB,EAAEnG,GACRgiB,EAAM7b,EAAEnG,KAEZ0a,YAAa1U,IAAK,WAAW,MAAO0U,IAAczU,IAAK,SAASjG,GAC5D0a,EAAW1a,EACXwnB,EAAO9M,WAAW1a,GAClBkiB,EAAOxH,WAAW1a,GAClB4mB,EAAOlM,WAAW1a,GAClB2nB,EAAOjN,WAAW1a,OAI1BhI,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAO2mB,QAAU,WAChB,YAoCA,SAASlkB,GAAMoB,GAiIX,MAhIAA,GAAUC,KAAK,SAASC,GACpBqC,EAAY/F,GAAGgG,OAAO3F,KACtB,IAAIyE,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAElEpF,GAAGG,MAAMiV,QAAQ5O,EAGjB,IAAI4Q,GAAK7R,EAAiBpB,EAAK,GAAG+D,OAAO/F,OAAU,EAGnDiF,GAAEgF,OAAOuM,GAAWlY,GAAGmc,OAAOzY,EAAK,GAAG+D,OAAOgL,IAAI0F,GAAMnX,OAAOqb,KAE1DqB,EACA/W,EAAEiF,MAAMwM,IAA4B,GAAjBtT,EAAsBpB,EAAK,GAAG+D,OAAO/F,OAAQoD,GAAkBpB,EAAK,GAAG+D,OAAO/F,OAAS,IAAOgC,EAAK,GAAG+D,OAAO/F,SAEhIiF,EAAEiF,MAAMwM,IAAW,EAAIzB,EAAE,EAAG7R,EAAiB6R,EAAE,EAAI,IAEvDjJ,EAAE/B,OAAO2M,IACDtY,GAAGqI,IAAI3E,EAAK,GAAG+D,OAAOgL,IAAIkL,GAAQ3c,OAAO4c,IACzC5d,GAAGkI,IAAIxE,EAAK,GAAG+D,OAAOgL,IAAIoL,GAAS7c,OAAO4c,MAEhDhS,MAAMqN,IAAWlU,EAAiB,IAGhC4B,EAAEgF,SAAS,KAAOhF,EAAEgF,SAAS,KAC7BhF,EAAEgF,SAAS,GACPhF,EAAEgF,QAAQhF,EAAEgF,SAAS,GAAqB,IAAhBhF,EAAEgF,SAAS,GAAWhF,EAAEgF,SAAS,GAAqB,IAAhBhF,EAAEgF,SAAS,KACzEhF,EAAEgF,QAAQ,GAAG,KAEnB+B,EAAE/B,SAAS,KAAO+B,EAAE/B,SAAS,KAC7B+B,EAAE/B,SAAS,GACP+B,EAAE/B,QAAQ+B,EAAE/B,SAAS,GAAqB,IAAhB+B,EAAE/B,SAAS,GAAW+B,EAAE/B,SAAS,GAAqB,IAAhB+B,EAAE/B,SAAS,KACzE+B,EAAE/B,QAAQ,GAAG,IAGvB,IAAIxF,GAAOnG,GAAGgG,OAAO3F,MAAM+F,UAAU,wBAAwB1C,MAAMA,EAAK,GAAG+D,SACvEpB,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,2BACnDmU,EAAYtU,EAAUE,OAAO,QAC7BmU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,YAEjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEvEkB,EACK9E,GAAG,QAAS,SAAS+F,EAAE1E,GACpBvC,EAAS+d,YACLpa,KAAMsD,EACNiB,MAAO3F,EACP4J,IAAKlM,GAAGmE,MACRkF,GAAIA,MAIhBsR,EAAUpU,OAAO,YACZC,KAAK,KAAM,sBAAwB6C,GACnC9C,OAAO,QAEZJ,EAAKH,OAAO,uBAAyBqD,EAAK,SACrC7C,KAAK,QAAS1B,GACd0B,KAAK,SAAUzB,GAEpBkR,EAAKzP,KAAK,YAAauX,EAAW,2BAA6B1U,EAAK,IAAM,GAE1E,IAAI6M,GAAQ/P,EAAKH,OAAO,aAAaI,UAAU,YAC1C1C,KAAK,SAASsD,GAAK,MAAOA,IAC/BkP,GAAMjP,OAAOC,SAEbgP,EAAM5P,QAAQC,OAAO,QAChBC,KAAK,QAAS,SAASQ,EAAE1E,EAAEgX,GAAK,OAAQ2E,EAAQjX,EAAE1E,GAAK4b,EAASlX,EAAE1E,GAAK,mBAAqB,oBAAsB,YAAcgX,EAAI,IAAMhX,IAC1IkE,KAAK,IAAK,SAASQ,EAAE1E,GAClB,MAAO,WACAoL,EAAEuQ,EAAQjX,EAAE1E,IACToL,EAAEmQ,EAAQ7W,EAAE1E,KAChB,KACEqU,EAAE,EACJ,MACCA,EAAE,EACH,SACCjJ,EAAEiQ,EAAO3W,EAAE1E,IAAMoL,EAAEuQ,EAAQjX,EAAE1E,KAC9B,OACCoL,EAAEwQ,EAASlX,EAAE1E,IACVoL,EAAEiQ,EAAO3W,EAAE1E,KACf,IACCqU,EAAE,EACH,OACEA,EAAE,EACJ,QAETnQ,KAAK,YAAa,SAASQ,EAAE1E,GAAK,MAAO,aAAeqE,EAAEwR,EAAKnR,EAAE1E,IAAM,IAAMoL,EAAEmQ,EAAQ7W,EAAE1E,IAAM,MAC/FkE,KAAK,OAAQ,SAASQ,EAAE1E,GAAK,MAAOiJ,GAAM,KAC1C/E,KAAK,SAAU,SAASQ,EAAE1E,GAAK,MAAOiJ,GAAM,KAC5C/E,KAAK,IAAK,GACVA,KAAK,IAAK,SAASQ,EAAE1E,GAAM,MAAOoL,GAAEnF,KAAKL,IAAI,EAAG8R,EAAKhT,EAAE1E,OACvDkE,KAAK,SAAU,SAASQ,EAAE1E,GAAK,MAAOiG,MAAKC,IAAIkF,EAAEsM,EAAKhT,EAAE1E,IAAMoL,EAAE,MAGrEwI,EAAM1P,KAAK,QAAS,SAASQ,EAAE1E,EAAEgX,GAC7B,OAAQ2E,EAAQjX,EAAE1E,GAAK4b,EAASlX,EAAE1E,GAAK,mBAAqB,oBAAsB,YAAcgX,EAAI,IAAMhX,IAG9GtC,GAAG2M,WAAWuJ,GACT1P,KAAK,YAAa,SAASQ,EAAE1E,GAAK,MAAO,aAAeqE,EAAEwR,EAAKnR,EAAE1E,IAAM,IAAMoL,EAAEmQ,EAAQ7W,EAAE1E,IAAM,MAC/FkE,KAAK,IAAK,SAASQ,EAAE1E,GAClB,GAAIqU,GAAK7R,EAAiBpB,EAAK,GAAG+D,OAAO/F,OAAU,EACnD,OAAO,WACAgM,EAAEuQ,EAAQjX,EAAE1E,IACToL,EAAEmQ,EAAQ7W,EAAE1E,KAChB,KACEqU,EAAE,EACJ,MACCA,EAAE,EACH,SACCjJ,EAAEiQ,EAAO3W,EAAE1E,IACRoL,EAAEuQ,EAAQjX,EAAE1E,KAChB,OACCoL,EAAEwQ,EAASlX,EAAE1E,IACVoL,EAAEiQ,EAAO3W,EAAE1E,KACf,IACCqU,EAAE,EACH,OACEA,EAAE,EACJ,UAIXvU,EA/JX,GAmBM8V,GACAI,EACAF,EACAa,EAtBFtU,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,KACRC,EAAS,KACTmD,EAAKd,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UACrBlE,EAAY,KACZY,EAAI3G,GAAGmH,MAAMC,SACbsG,EAAI1N,GAAGmH,MAAMC,SACb+Q,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9BuQ,EAAU,SAASjX,GAAK,MAAOA,GAAEmX,MACjCD,EAAW,SAASlX,GAAK,MAAOA,GAAEoX,OAClCP,EAAU,SAAS7W,GAAK,MAAOA,GAAEqX,MACjCV,EAAS,SAAS3W,GAAK,MAAOA,GAAEsX,KAChCjC,KACAuB,KACAF,GAAc,EACdK,GAAW,EACXxS,EAAQhM,EAAGG,MAAM6O,eACjBgQ,GAAc,EAKdxe,EAAWC,GAAGD,SAAS,cAAe,cAAe,YAAa,aAAc,eAAgB,kBAAmB,mBAAoB,kBAAmB,mBAsMhK,OAzDAqC,GAAMoc,eAAiB,SAASC,EAAYC,GACxCtc,EAAMuc,kBACN5Y,EAAUC,OAAO,0BAA4ByY,GACxClV,QAAQ,QAASmV,IAI1Btc,EAAMuc,gBAAkB,WACpB5Y,EAAUC,OAAO,8BACZuD,QAAQ,SAAS,IAQ1BnH,EAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAWsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IAClErB,QAAWqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACpEhC,QAAWgI,IAAK,WAAW,MAAO5G,IAAK6G,IAAK,SAASjG,GAAGZ,EAAEY,IAC1D0S,QAAW1M,IAAK,WAAW,MAAOG,IAAKF,IAAK,SAASjG,GAAGmG,EAAEnG,IAC1D2Q,SAAW3K,IAAK,WAAW,MAAO2K,IAAW1K,IAAK,SAASjG,GAAG2Q,EAAQ3Q,IACtE+Q,SAAW/K,IAAK,WAAW,MAAO+K,IAAW9K,IAAK,SAASjG,GAAG+Q,EAAQ/Q,IACtE6Q,QAAW7K,IAAK,WAAW,MAAO6K,IAAU5K,IAAK,SAASjG,GAAG6Q,EAAO7Q,IACpE0R,QAAW1L,IAAK,WAAW,MAAO0L,IAAUzL,IAAK,SAASjG,GAAG0R,EAAO1R,IACpE8U,QAAW9O,IAAK,WAAW,MAAO8O,IAAU7O,IAAK,SAASjG,GAAG8U,EAAO9U,IACpEqW,QAAWrQ,IAAK,WAAW,MAAOqQ,IAAUpQ,IAAK,SAASjG,GAAGqW,EAAOrW,IACpEmW,SAAWnQ,IAAK,WAAW,MAAOmQ,IAAWlQ,IAAK,SAASjG,GAAGmW,EAAQnW,IACtEwW,UAAWxQ,IAAK,WAAW,MAAOwQ,IAAYvQ,IAAK,SAASjG,GAAGwW,EAASxW,IACxE8B,IAAWkE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,GAAG8B,EAAG9B,IAC5DgX,aAAchR,IAAK,WAAW,MAAOgR,IAAe/Q,IAAK,SAASjG,GAAGgX,EAAYhX,IAEjFZ,GAAQ4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAK5Q,IAC7DmG,GAAQH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAAGyS,EAAKzS,IAC7D4W,MAAQ5Q,IAAK,WAAW,MAAO0Q,MAAazQ,IAAK,SAASjG,GAAG0W,EAAQ1W,IACrE6W,OAAQ7Q,IAAK,WAAW,MAAO2Q,MAAc1Q,IAAK,SAASjG,GAAG2W,EAAS3W,IACvE8W,MAAQ9Q,IAAK,WAAW,MAAOsQ,IAAWrQ,IAAK,SAASjG,GAAGsW,EAAQtW,IACnE+W,KAAQ/Q,IAAK,WAAW,MAAOoQ,IAAUnQ,IAAK,SAASjG,GAAGoW,EAAOpW,IAGjE5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAqB1B,QAAZoE,EAAE1C,IAAsB0C,EAAE1C,IAASF,EAAOE,IAC1DF,EAAOqQ,MAAqB7R,QAAZoE,EAAEyN,MAAsBzN,EAAEyN,MAASrQ,EAAOqQ,MAC1DrQ,EAAOoQ,OAAqB5R,QAAZoE,EAAEwN,OAAsBxN,EAAEwN,OAASpQ,EAAOoQ,OAC1DpQ,EAAOC,KAAqBzB,QAAZoE,EAAE3C,KAAsB2C,EAAE3C,KAASD,EAAOC,OAE9D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,OAIlChI,EAAGG,MAAMiO,YAAYvL,GACdA,GAIX7C,EAAGI,OAAOuwB,oBAAsB,WAC5B,YAyBA,SAAS9tB,GAAMoB,GAyPX,MAxPAA,GAAUC,KAAK,SAASC,GA2JpB,QAAS6pB,GAAKvmB,GACV,MAAOH,GAAKspB,EAAe1d,IAAI,SAAUrH,GAErC,GAAGkF,MAAMtJ,EAAEoE,KAAOkF,MAAMsF,WAAW5O,EAAEoE,KAAM,CACvC,GAAIO,GAAS+B,EAAEtC,GAAGO,SACdC,EAAQ8B,EAAEtC,GAAGQ,QACbvD,EAAMsD,EAAO,IAAMA,EAAO,GAAKA,EAAO,IAAM,CAGhD,IAAGykB,EAAsBlf,QAAQ9F,GAAK,EAAG,CAErC,GAAIilB,GAAWrwB,GAAGmH,MAAMC,SAASuE,QAAQtD,EAAKsD,EAAO,KAAKC,OAAO7G,EAAkB,GAAI6G,EAAM,IAC7F8B,GAAEtC,GAAG2c,MAAMra,EAAE2iB,GACbD,EAAsBrtB,KAAKqI,GAG/B,OAAQzE,EAAEyE,GAAIsC,EAAEtC,GAAG/C,IAYtB,MARE+nB,GAAsB1uB,OAAS,GAC9B4uB,EAAkBhnB,MAAM,UAAW,UACnCinB,EAAsBjnB,MAAM,UAAW,YAEvCgnB,EAAkBhnB,MAAM,UAAW,QACnCinB,EAAsBjnB,MAAM,UAAW,UAGlC3C,EAAEyE,GAAIsC,EAAEtC,GAAGpE,EAAEoE,QAK9B,QAAS2c,KACL,GAAIyI,GAAUL,EAAerc,OAAO,SAAS1I,GAAK,OAAQsC,EAAEtC,GAAG2c,MAAMC,UACjEyI,EAAUD,EAAQ/d,IAAI,SAASrH,GAAK,MAAOsC,GAAEtC,GAAG2c,MAAM5L,UAE1DuU,MACAF,EAAQ1nB,QAAQ,SAAS9B,EAAE1E,GACvBouB,EAAQpuB,IACJquB,UAAW3pB,EACXmV,OAAQsU,EAAQnuB,MAIxBL,KACA2uB,EAAWtnB,MAAM,UAAW,SAAStC,GACjC,GAAI6pB,GAAWL,EAAQnf,MAAM,SAASjG,EAAG9I,GACrC,MAAGgO,OAAMtJ,EAAEoE,KAAOqlB,EAAQnuB,GAAG,IAAMoL,EAAEtC,GAAG2c,MAAMra,IAAI/B,SAAS,IAAW,EAC/D8kB,EAAQnuB,GAAG,IAAM0E,EAAEoE,IAAMpE,EAAEoE,IAAMqlB,EAAQnuB,GAAG,IAGvD,OADIuuB,IAAU5uB,EAAOc,KAAKiE,GACnB6pB,EAAW,KAAO;GAG7B9wB,EAASgoB,OACL2I,QAASA,EACTzuB,OAAQA,IAIhB,QAAS6c,GAAU9X,EAAG1E,GAClBwuB,EAAS9pB,GAAK3G,KAAKkP,WAAWwhB,WAAapqB,EAAEK,GAC7CgqB,EAAWxqB,KAAK,aAAc,UAIlC,QAASuY,GAAS/X,EAAG1E,GACjBwuB,EAAS9pB,GAAKuB,KAAKF,IAAIvD,EAAgByD,KAAKL,IAAI,EAAG7H,KAAKkP,WAAWwhB,YAAc/wB,GAAGmE,MAAMwC,IAC1FiqB,EAAWpqB,KAAK,IAAK+mB,GACrB4C,EAAetc,KAAK,SAAUD,EAAG8b,GAAK,MAAOnlB,GAASqJ,GAAKrJ,EAASmlB,KACpE/oB,EAAEgF,OAAOwkB,GACTc,EAAWzqB,KAAK,YAAa,SAASQ,GAAK,MAAO,aAAeuD,EAASvD,GAAK,MAGnF,QAASkY,GAAQlY,EAAG1E,SACTjC,MAAKkP,WAAWwhB,iBAChBD,GAAS9pB,GAChBhH,GAAGgG,OAAO3F,KAAKkP,YAAY/I,KAAK,YAAa,aAAeG,EAAEK,GAAK,KACnE4pB,EACGpqB,KAAK,IAAK+mB,GACbyD,EACGxqB,KAAK,IAAK+mB,GACV/mB,KAAK,aAAc,MAI1B,QAAS+D,GAASvD,GACd,GAAIc,GAAIgpB,EAAS9pB,EACjB,OAAY,OAALc,EAAYnB,EAAEK,GAAKc,EAnP9B,GAAI/B,GAAY/F,GAAGgG,OAAO3F,MACtByE,EAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAElEpF,GAAGG,MAAMiV,QAAQ5O,GAEjB9D,EAASyB,EAGTiD,EAAEuqB,aAAa,EAAGpsB,GAAiB,GAAG6G,OAAOwkB,EAG7C,IAAIgB,KAEJhB,GAAernB,QAAQ,SAAS9B,GAC5B,GAAImV,GAASnc,GAAGmc,OAAOzY,EAAM,SAAS0H,GAAK,OAAQA,EAAEpE,IAqBrD,OApBAmqB,GAAcnqB,IAAK,EAED7D,SAAdgZ,EAAO,KACPgV,EAAcnqB,IAAK,EACnBmV,EAAO,GAAK,EACZA,EAAO,GAAK,GAGZA,EAAO,KAAOA,EAAO,KACrBA,EAAO,GAAKA,EAAO,GAAK,EACxBA,EAAO,GAAKA,EAAO,GAAK,GAI5BzO,EAAE1G,GAAKhH,GAAGmH,MAAMC,SACXuE,OAAOwQ,GACPvQ,OAAgC,IAAxB7G,EAAkB,IAAW,IAE1C2I,EAAE1G,GAAG+gB,MAAQ/nB,GAAGoU,IAAI2T,QAAQra,EAAEA,EAAE1G,IAAI/F,GAAG,QAAS8mB,GAEpC,QAAL/gB,GAIX,IAAIb,GAAOJ,EAAUK,UAAU,oCAAoC1C,MAAMA,IACrE2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,uCACnDkU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,qCACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,qCACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,4CAEjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAEvE,IAQIyrB,GAAmBC,EARnB1pB,EAAO7G,GAAGoU,IAAIvN,OAAOqgB,YAAY,YAAYkK,QAAQC,GACrDrb,EAAOhW,GAAGoU,IAAI4B,OAAOG,OAAO,QAC5Bmb,EAAWtxB,GAAG2f,SAASC,OACd3e,GAAG,YAAa6d,GAChB7d,GAAG,OAAQ8d,GACX9d,GAAG,UAAWie,GAIvBld,EAAO2E,EAAEiF,QAAQ,GAAKjF,EAAEiF,QAAQ,GAChCwkB,KACAmB,GAAY,EAAIvvB,EAAO,EAAG+C,EAAkB,GAAID,EAAiB9C,EAAO,EAAG+C,EAAkB,GACjGurB,GAAoBnqB,EAAKH,OAAO,sBAAsBI,UAAU,QAAQ1C,MAAM6tB,IAC9EjB,EAAkBhqB,QAAQC,OAAO,QACjC+pB,EAAkBrpB,OAAOC,SACzBopB,EAAkB9pB,KAAK,KAAM,SAASQ,GAAK,MAAOA,GAAE,KAC3CR,KAAK,KAAM,SAASQ,GAAK,MAAOA,GAAE,KAClCR,KAAK,KAAM,SAASQ,GAAK,MAAOA,GAAE,KAClCR,KAAK,KAAM,SAASQ,GAAK,MAAOA,GAAE,KAG3CupB,EAAwBpqB,EAAKH,OAAO,sBAAsBI,UAAU,QAAQ1C,MAAM,qBAClF6sB,EAAsBhqB,OAAO,QAAQ7C,MAAM,qBAC3C6sB,EAAsBjqB,QAAQC,OAAO,QACrCgqB,EAAsBtpB,OAAOC,SAC7BqpB,EAAsB/pB,KAAK,IAAKzB,GAEvByB,KAAK,IAAK1B,EAAiB,GAAK9C,EAAO,GACvCgO,KAAK,SAAShJ,GAAK,MAAOA,IAGnC,IAAIgqB,GAAa7qB,EAAKH,OAAO,eAAeI,UAAU,QAAQ1C,KAAKA,EACnEstB,GAAW1qB,QAAQC,OAAO,QAC1ByqB,EAAW/pB,OAAOC,SAClB8pB,EAAWxqB,KAAK,IAAK+mB,EAGrB,IAAIqD,GAAazqB,EAAKH,OAAO,eAAeI,UAAU,QAAQ1C,KAAKA,EACnEktB,GAAWtqB,QAAQC,OAAO,QAC1BqqB,EAAW3pB,OAAOC,SAClB0pB,EAAWpqB,KAAK,IAAK+mB,GAAM/mB,KAAK,SAAU+E,GAC1CqlB,EAAW3vB,GAAG,YAAa,SAAU+F,EAAG1E,GACpCtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASyZ,kBACLM,MAAO9S,EAAEpF,KACT8B,KAAMsD,EAAEtD,KACRuE,MAAO3F,EACP4J,KAAMlM,GAAG6D,MAAMxD,KAAKkP,YAAY,GAAIvP,GAAG6D,MAAMxD,KAAKkP,YAAY,QAItEqhB,EAAW3vB,GAAG,WAAY,SAAU+F,EAAG1E,GACnCtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASoF,iBACL2U,MAAO9S,EAAEpF,KACT8B,KAAMsD,EAAEtD,KACRuE,MAAO3F,KAKf,IAAI2uB,GAAahb,EAAE7P,UAAU,cAAc1C,KAAKysB,GAC5CqB,EAAkBP,EAAW3qB,QAAQC,OAAO,KAAKC,KAAK,QAAS,mCACnEgrB,GAAgBjrB,OAAO,KAAKC,KAAK,QAAS,kCAC1CgrB,EAAgBjrB,OAAO,KAAKC,KAAK,QAAS,gCAC1CgrB,EAAgBjrB,OAAO,QAAQC,KAAK,QAAS,mCAE7CyqB,EAAWzqB,KAAK,YAAa,SAASQ,GAAK,MAAO,aAAeL,EAAEK,GAAK,QACxEiqB,EAAWhqB,OAAOC,SAGlB+pB,EAAWjrB,OAAO,aACbsD,MAAM,SAAU,QAChB9C,KAAK,KAAM,QACXA,KAAK,cAAe,UACpBwJ,KAAKjJ,QACL9F,GAAG,YAAa,SAAS+F,EAAG1E,GACzBvC,EAASyZ,kBACLiY,IAAKzqB,EACLkF,KAAMlM,GAAG6D,MAAMxD,KAAKkP,WAAWA,YAAY,GAAIvP,GAAG6D,MAAMxD,KAAKkP,WAAWA,YAAY,QAG3FtO,GAAG,WAAY,SAAS+F,EAAG1E,GACxBvC,EAASoF,iBACLssB,IAAKzqB,MAGZtG,KAAK4wB,GAEVL,EAAWjrB,OAAO,YACbvC,KAAK,SAAUuD,EAAG1E,GACftC,GAAGgG,OAAO3F,MAAMK,KAAKsV,EAAK7O,MAAMuG,EAAE1G,IAAIsP,WAAWtW,GAAGib,OAAOyW,EAAiBpvB,QAGhF2uB,EAAWjrB,OAAO,iCACjBvC,KAAK,SAAUuD,GACZhH,GAAGgG,OAAO3F,MAAMK,KAAKgN,EAAE1G,GAAG+gB,SAE7B3hB,UAAU,QACVI,KAAK,IAAK,IACVA,KAAK,QAAS,MAgGhBpE,EA5QX,GAAIuC,IAAUE,IAAK,GAAImQ,MAAO,EAAGD,OAAQ,GAAInQ,KAAM,GAC7CqB,EAAQ,KACRC,EAAS,KACTS,EAAI3G,GAAGmH,MAAMuH,UACbhB,KACAyiB,KACAuB,KACAnmB,EAAQhM,EAAGG,MAAM6O,eACjBmiB,KACAzuB,KACA6uB,KACAO,EAAc,EACdtxB,EAAWC,GAAGD,SAAS,QAAS,mBAAoB,kBAsS1D,OA/BAqC,GAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAgBsH,IAAK,WAAW,MAAOtH,IAAmBuH,IAAK,SAASjG,GAAGtB,EAAOsB,IAClFrB,QAAgBqH,IAAK,WAAW,MAAOrH,IAAmBsH,IAAK,SAASjG,GAAGrB,EAAQqB,IACnF4oB,gBAAiB5iB,IAAK,WAAa,MAAO4iB,IAAkB3iB,IAAK,SAASjG,GAAG4oB,EAAgB5oB,IAC7FmqB,kBAAoBnkB,IAAK,WAAW,MAAOmkB,IAAoBlkB,IAAK,SAAUjG,GAAGmqB,EAAiBnqB,IAClG8pB,aAAgB9jB,IAAK,WAAW,MAAO8jB,IAAmB7jB,IAAK,SAASjG,GAAG8pB,EAAc9pB,IAGzF0pB,YAAa1jB,IAAK,WAAY,MAAO4iB,IAAkB3iB,IAAK,SAASjG,GAEjEhI,EAAGoC,WAAW,aAAc,8BAC5BwuB,EAAiB5oB,IAIrB5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAuB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC5DF,EAAOqQ,MAAuB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC5DrQ,EAAOoQ,OAAuB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC5DpQ,EAAOC,KAAuBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAEhE2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,OAIlChI,EAAGG,MAAMiO,YAAYvL,GACdA,GAEX7C,EAAGI,OAAOgyB,IAAM,WACZ,YA0CA,SAASvvB,GAAMoB,GAgTX,MA/SAgN,GAAYW,QACZ3N,EAAUC,KAAK,SAASC,GAiSpB,QAASkuB,GAAShe,EAAGgO,GACjBhO,EAAEie,SAAWvhB,MAAMsD,EAAEie,UAAY,EAAIje,EAAEie,SACvCje,EAAEke,WAAaxhB,MAAMsD,EAAEke,YAAc,EAAIle,EAAEke,WACtCC,IAAOne,EAAEoe,YAAc,EAC5B,IAAI1vB,GAAItC,GAAGknB,YAAY7mB,KAAK4xB,SAAUre,EAEtC,OADAvT,MAAK4xB,SAAW3vB,EAAE,GACX,SAAU4R,GACb,MAAOge,GAAKtQ,GAAKtf,EAAE4R,KAvS3B,GAAIpP,GAAiBmB,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAC5CjQ,EAAkBmB,EAASvB,EAAOE,IAAMF,EAAOoQ,OAC/Cod,EAAS5pB,KAAKF,IAAIvD,EAAgBC,GAAmB,EACrDqtB,KACAC,IAIN,IADAtsB,EAAY/F,GAAGgG,OAAO3F,MACI,IAAtBiyB,EAAW5wB,OAGX,IAAK,GAFD6wB,GAAQJ,EAASA,EAAS,EAC1BK,EAAQC,EAAaN,EAChB7vB,EAAI,EAAGA,EAAIoB,EAAK,GAAGhC,OAAQY,IAChC8vB,EAAgBrvB,KAAKwvB,GACrBF,EAAgBtvB,KAAKyvB,OAGzBJ,GAAkBE,EAAW7f,IAAI,SAAUzL,GAAK,OAAQA,EAAEurB,MAAQvrB,EAAEurB,MAAQ,GAAKJ,IACjFE,EAAkBC,EAAW7f,IAAI,SAAUzL,GAAK,OAAQA,EAAEwrB,MAAQxrB,EAAEwrB,MAAQ,GAAKL,IACjFM,EAAazyB,GAAGqI,IAAIiqB,EAAW7f,IAAI,SAAUzL,GAAK,MAAQA,GAAEwrB,MAAQxrB,EAAEwrB,MAAQ,IAElFjzB,GAAGG,MAAMiV,QAAQ5O,EAGjB,IAAII,GAAOJ,EAAUK,UAAU,mBAAmB1C,KAAKA,GACnD2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAQ,gCAAkC6C,GACpFqR,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,KAChB0sB,EAAQhY,EAAOnU,OAAO,KAAKC,KAAK,QAAS,SAC7CkU,GAAOnU,OAAO,KAAKC,KAAK,QAAS,gBAEjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KACvEoR,EAAEjQ,OAAO,WAAWQ,KAAK,YAAa,aAAe1B,EAAiB,EAAI,IAAMC,EAAkB,EAAI,KACtGkR,EAAEjQ,OAAO,iBAAiBQ,KAAK,YAAa,aAAe1B,EAAiB,EAAI,IAAMC,EAAkB,EAAI,KAG5GgB,EAAU9E,GAAG,QAAS,SAAS+F,EAAE1E,GAC7BvC,EAAS+d,YACLpa,KAAMsD,EACNiB,MAAO3F,EACP4J,IAAKlM,GAAGmE,MACRkF,GAAIA,MAIZ6oB,KACAS,IACA,KAAK,GAAIrwB,GAAI,EAAGA,EAAIoB,EAAK,GAAGhC,OAAQY,IAAK,CAErC,GAAIswB,GAAM5yB,GAAGoU,IAAIwe,MAAMC,YAAYT,EAAgB9vB,IAC/CwwB,EAAU9yB,GAAGoU,IAAIwe,MAAMC,YAAYT,EAAgB9vB,GAAK,EAExDwvB,MAAe,IACfc,EAAId,WAAWA,GACfgB,EAAQhB,WAAWA,IAEnBD,KAAa,IACbe,EAAIf,SAASA,GACbiB,EAAQjB,SAASA,IAEjBE,IACAa,EAAIZ,YAAYK,EAAgB/vB,IAChCwwB,EAAQd,YAAYK,EAAgB/vB,KAGpCswB,EAAIG,cAAgBA,IACpBH,EAAIG,aAAaA,GACjBD,EAAQC,aAAaA,IAGzBb,EAAKnvB,KAAK6vB,GACVD,EAAS5vB,KAAK+vB,GAIlB,GAAInB,GAAM3xB,GAAGurB,OAAOoG,MACf9d,KAAK,MACL5I,MAAM,SAASjE,GAAK,MAAOA,GAAE+T,SAAW,EAAIf,EAAKhT,IAGlD2qB,GAAIqB,UAAYA,GAChBrB,EAAIqB,SAASA,GAIbjB,GAAS/U,IACT0V,EAAMnsB,OAAO,QAAQC,KAAK,QAAS,gBAEnCL,EAAKH,OAAO,iBACPsD,MAAM,cAAe,UACrB0G,KAAK,SAAUhJ,GACZ,MAAOgW,KAEV1T,MAAM,YAAcf,KAAKF,IAAIvD,EAAgBC,GAAoB0tB,EAAa,GAAKzV,EAAMtb,OAAS,GAAK,MACvG8E,KAAK,KAAM,UACXA,KAAK,YAAa,SAASQ,EAAG1E,GAC3B,MAAO,gBAAiB2wB,EAAc,MAIlD,IAAIC,GAAS/sB,EAAKH,OAAO,WAAWI,UAAU,aAAa1C,KAAKiuB,GAC5DwB,EAAYhtB,EAAKH,OAAO,iBAAiBI,UAAU,aAAa1C,KAAKiuB,EAEzEuB,GAAOjsB,OAAOC,SACdisB,EAAUlsB,OAAOC,QAEjB,IAAIksB,GAAKF,EAAO5sB,QAAQC,OAAO,IAC/B6sB,GAAG5sB,KAAK,QAAS,YACjB4sB,EAAGnyB,GAAG,YAAa,SAAS+F,EAAG1E,GAC3BtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GAC7B8pB,GACArzB,GAAGgG,OAAO3F,MAAM2F,OAAO,QAAQ2G,aAC1BtF,SAAS,IACTb,KAAK,IAAKmsB,EAASrwB,IAE5BvC,EAASyZ,kBACL9V,KAAMsD,EAAEtD,KACRuE,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGrC8pB,EAAGnyB,GAAG,WAAY,SAAS+F,EAAG1E,GAC1BtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GAC7B8pB,GACArzB,GAAGgG,OAAO3F,MAAM2F,OAAO,QAAQ2G,aAC1BtF,SAAS,IACTb,KAAK,IAAK0rB,EAAK5vB,IAExBvC,EAASoF,iBAAiBzB,KAAMsD,EAAEtD,KAAMuE,MAAO3F,MAEnD8wB,EAAGnyB,GAAG,YAAa,SAAS+F,EAAG1E,GAC3BvC,EAAS0F,kBAAkB/B,KAAMsD,EAAEtD,KAAMuE,MAAO3F,MAEpD8wB,EAAGnyB,GAAG,QAAS,SAAS+F,EAAG1E,GACvBvC,EAAS6F,cACLlC,KAAMsD,EAAEtD,KACRuE,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGrC8pB,EAAGnyB,GAAG,WAAY,SAAS+F,EAAG1E,GAC1BvC,EAAS0iB,iBACL/e,KAAMsD,EAAEtD,KACRuE,MAAO3F,EACPiJ,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAIrC4pB,EAAO1sB,KAAK,OAAQ,SAASQ,EAAE1E,GAAK,MAAOiJ,GAAMvE,EAAEtD,KAAMpB,KACzD4wB,EAAO1sB,KAAK,SAAU,SAASQ,EAAE1E,GAAK,MAAOiJ,GAAMvE,EAAEtD,KAAMpB,IAE/C8wB,GAAG7sB,OAAO,QAAQ9C,KAAK,SAASuD,GACxC3G,KAAK4xB,SAAWjrB,GAQpB,IALAksB,EAAOltB,OAAO,QACT2G,aACAnG,KAAK,IAAK,SAAUQ,EAAG1E,GAAK,MAAO4vB,GAAK5vB,GAAG0E,KAC3CssB,UAAU,IAAK1B,GAEhB2B,EAAY,CAGZ,IAAK,GADDC,MACKlxB,EAAI,EAAGA,EAAIoB,EAAK,GAAGhC,OAAQY,IAChCkxB,EAAUzwB,KAAKmvB,EAAK5vB,IAEhBmxB,EACI1B,IACAyB,EAAUlxB,GAAKtC,GAAGoU,IAAIwe,MAAMC,YAAYX,EAAK5vB,GAAGuwB,eAC5Cf,KAAe,GAAO0B,EAAUlxB,GAAGwvB,WAAWA,GAC9CD,KAAa,GAAO2B,EAAUlxB,GAAGuvB,SAASA,IAE1CE,GACJyB,EAAUlxB,GAAG0vB,YAAY,EAIrCmB,GAAU7sB,QAAQC,OAAO,KAAKgD,QAAQ,YAAW,GAAM9F,KAAK,SAASuD,EAAE1E,GACnE,GAAIoxB,GAAQ1zB,GAAGgG,OAAO3F,KAEtBqzB,GAAMltB,KAAK,YAAa,SAAUQ,EAAG1E,GACjC,GAAIqxB,EAAoB,CACpB3sB,EAAE6rB,YAAcT,EAAgB9vB,GAAK,GACrC0E,EAAEgrB,YAAcI,EAAgB9vB,GAAK,EACrC,IAAIsxB,IAAe5sB,EAAE8qB,WAAa9qB,EAAE6qB,UAAY,GAAK,IAAMtpB,KAAKkP,GAMhE,QALKzQ,EAAE8qB,WAAa9qB,EAAE6qB,UAAY,EAAItpB,KAAKkP,GACvCmc,GAAe,GAEfA,GAAe,GAEZ,aAAeJ,EAAUlxB,GAAGuxB,SAAS7sB,GAAK,YAAc4sB,EAAc,IAI7E,MAFA5sB,GAAE6rB,YAAcV,EAAS,GACzBnrB,EAAEgrB,YAAcG,EAAS,GAClB,aAAeqB,EAAUlxB,GAAGuxB,SAAS7sB,GAAK,MAIzD0sB,EAAMntB,OAAO,QACR+C,MAAM,SAAU,QAChBA,MAAM,OAAQ,QACd9C,KAAK,KAAM,GACXA,KAAK,KAAM,GAEhBktB,EAAMntB,OAAO,QACR+C,MAAM,cAAeqqB,GAAuB3sB,EAAE8qB,WAAa9qB,EAAE6qB,UAAY,EAAItpB,KAAKkP,GAAK,QAAU,MAAS,UAC1GnO,MAAM,OAAQ,SAGvB,IAAIwqB,MACAC,EAAY,GACZC,EAAW,IACXC,GAAgB,SAASC,GACzB,MAAO3rB,MAAKyB,MAAMkqB,EAAY,GAAGF,GAAYA,EAAW,IAAMzrB,KAAKyB,MAAMkqB,EAAY,GAAGH,GAAaA,EAGzGZ,GAAU5iB,gBAAgBC,EAAa,cAAchK,KAAK,YAAa,SAAUQ,EAAG1E,GAChF,GAAIqxB,EAAoB,CACpB3sB,EAAE6rB,YAAcT,EAAgB9vB,GAAK,GACrC0E,EAAEgrB,YAAcI,EAAgB9vB,GAAK,EACrC,IAAIsxB,IAAe5sB,EAAE8qB,WAAa9qB,EAAE6qB,UAAY,GAAK,IAAMtpB,KAAKkP,GAMhE,QALKzQ,EAAE8qB,WAAa9qB,EAAE6qB,UAAY,EAAItpB,KAAKkP,GACvCmc,GAAe,GAEfA,GAAe,GAEZ,aAAeJ,EAAUlxB,GAAGuxB,SAAS7sB,GAAK,YAAc4sB,EAAc,IAE7E5sB,EAAE6rB,YAAcV,EAAS,GACzBnrB,EAAEgrB,YAAcG,EAAS,EAOzB,IAAIgC,GAASX,EAAUlxB,GAAGuxB,SAAS7sB,EACnC,IAAIA,EAAEiE,MAAO,CACT,GAAImpB,GAAUH,GAAcE,EACxBL,GAAkBM,KAClBD,EAAO,IAAMJ,GAEjBD,EAAkBG,GAAcE,KAAW,EAE/C,MAAO,aAAeA,EAAS,MAIvChB,EAAUntB,OAAO,kBACZsD,MAAM,cAAe,SAAStC,EAAE1E,GAE7B,MAAOqxB,IAAuB3sB,EAAE8qB,WAAa9qB,EAAE6qB,UAAY,EAAItpB,KAAKkP,GAAK,QAAU,MAAS,WAE/FzH,KAAK,SAAShJ,EAAG1E,GACd,GAAI+xB,IAAWrtB,EAAE6qB,SAAW7qB,EAAE8qB,aAAe,EAAIvpB,KAAKkP,IAClDqC,EAAQ,EACZ,KAAK9S,EAAEiE,OAAmBqpB,EAAVD,EAA0B,MAAO,EAEjD,IAAwB,kBAAdE,GACNza,EAAQya,EAAUvtB,EAAG1E,GACjBmJ,IAAO0M,EAAKnR,EAAEtD,MACduH,MAAS+O,EAAKhT,EAAEtD,MAChB2wB,QAAW3R,EAAY2R,SAG3B,QAAQE,GACJ,IAAK,MACDza,EAAQ3B,EAAKnR,EAAEtD,KACf,MACJ,KAAK,QACDoW,EAAQ4I,EAAY1I,EAAKhT,EAAEtD,MAC3B,MACJ,KAAK,UACDoW,EAAQ9Z,GAAGib,OAAO,KAAKoZ,GAInC,MAAOva,QAwBvBtJ,EAAYS,UAAU,iBACf7O,EApVX,GAAIuC,IAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACRC,EAAS,IACTiS,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9BrE,EAAKd,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UACrBlE,EAAY,KACZwF,EAAQhM,EAAGG,MAAM6O,eACjBmU,EAAc1iB,GAAGib,OAAO,QACxBsY,GAAa,EACbE,GAAgB,EAChBc,EAAY,MACZD,EAAiB,IACjBvC,GAAQ,EACR/U,GAAQ,EACRqW,GAAc,EACdJ,EAAc,EACdU,GAAqB,EACrB7B,GAAa,EACbkB,GAAW,EACXnB,GAAW,EACXkB,EAAe,EACfN,EAAa,GACbH,KACAvyB,EAAWC,GAAGD,SAAS,aAAc,eAAgB,kBAAmB,mBAAoB,kBAAmB,mBAAoB,aAGrImyB,KACAS,KAMAniB,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAqXvC,OA5DAqC,GAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBglB,YAAc/kB,IAAK,WAAc,MAAO+kB,IAAe9kB,IAAK,SAAUjG,GAAK+qB,EAAa/qB,IACxFtB,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtEgsB,YAAahmB,IAAK,WAAW,MAAOgmB,IAAc/lB,IAAK,SAASjG,GAAGgsB,EAAWhsB,IAC9EyV,OAAazP,IAAK,WAAW,MAAOyP,IAASxP,IAAK,SAASjG,GAAGyV,EAAMzV,IACpE0rB,aAAiB1lB,IAAK,WAAW,MAAO0lB,IAAezlB,IAAK,SAASjG,GAAG0rB,EAAY1rB,IACpF+sB,gBAAiB/mB,IAAK,WAAW,MAAO+mB,IAAkB9mB,IAAK,SAASjG,GAAG+sB,EAAe/sB,IAC1Fmb,aAAiBnV,IAAK,WAAW,MAAOmV,IAAelV,IAAK,SAASjG,GAAGmb,EAAYnb,IACpFZ,GAAa4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAK5Q,IAClE8B,IAAakE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,GAAG8B,EAAG9B,IAC9DsqB,UAAatkB,IAAK,WAAW,MAAOskB,IAAYrkB,IAAK,SAASjG,GAAGsqB,EAAStqB,IAC1EuqB,YAAavkB,IAAK,WAAW,MAAOukB,IAActkB,IAAK,SAASjG,GAAGuqB,EAAWvqB,IAC9EyrB,UAAazlB,IAAK,WAAW,MAAOylB,IAAYxlB,IAAK,SAASjG,GAAGyrB,EAASzrB,IAC1EwrB,cAAexlB,IAAK,WAAW,MAAOwlB,IAAgBvlB,IAAK,SAASjG,GAAGwrB,EAAaxrB,IACpFkrB,YAAellB,IAAK,WAAW,MAAOklB,IAAcjlB,IAAK,SAASjG,GAAGkrB,EAAWlrB,IAChFksB,eAAgBlmB,IAAK,WAAW,MAAOkmB,IAAiBjmB,IAAK,SAASjG,GAAGksB,EAAclsB,IACvFosB,oBAAqBpmB,IAAK,WAAW,MAAOomB,IAAsBnmB,IAAK,SAASjG,GAAGosB,EAAmBpsB,IACtGwqB,OAAqBxkB,IAAK,WAAW,MAAOwkB,IAASvkB,IAAK,SAASjG,GAAGwqB,EAAMxqB,IAC5E8rB,aAAqB9lB,IAAK,WAAW,MAAO8lB,IAAe7lB,IAAK,SAASjG,GAAG8rB,EAAY9rB,IAGxFitB,kBAAmBjnB,IAAK,WAAW,MAAOkmB,IAAiBjmB,IAAK,SAASjG,GACrEksB,EAAclsB,EACdhI,EAAGoC,WAAW,mBAAoB,+BAGtC8yB,oBAAqBlnB,IAAK,WAAW,MAAOkmB,IAAiBjmB,IAAK,SAASjG,GACvEksB,EAAclsB,EACdhI,EAAGoC,WAAW,qBAAsB,+BAGxC+yB,aAAcnnB,IAAK,WAAY,MAAOmV,IAAelV,IAAK,SAASjG,GAC/Dmb,EAAYnb,EACZhI,EAAGoC,WAAW,cAAc,6BAIhCgD,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAA4B,mBAAZ0C,GAAE1C,IAAwB0C,EAAE1C,IAASF,EAAOE,IACnEF,EAAOqQ,MAA4B,mBAAZzN,GAAEyN,MAAwBzN,EAAEyN,MAASrQ,EAAOqQ,MACnErQ,EAAOoQ,OAA4B,mBAAZxN,GAAEwN,OAAwBxN,EAAEwN,OAASpQ,EAAOoQ,OACnEpQ,EAAOC,KAA4B,mBAAZ2C,GAAE3C,KAAwB2C,EAAE3C,KAASD,EAAOC,OAEvE8I,GAAIH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAC7CyS,EAAKha,GAAGsU,QAAQ/M,KAEpBgE,OAAQgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GAClDgE,EAAMhM,EAAGG,MAAM4O,SAAS/G,KAE5BgtB,WAAqBhnB,IAAK,WAAW,MAAOgnB,IAAa/mB,IAAK,SAASjG,GACnEgtB,EAAWhtB,GAAK,UAIxBhI,EAAGG,MAAMiO,YAAYvL,GACdA,GAEX7C,EAAGI,OAAOg1B,SAAW,WACjB,YA0DA,SAASvyB,GAAMoB,GAgHX,MA/GAgN,GAAYW,QACZX,EAAY7Q,OAAOgyB,GAEnBnuB,EAAUC,KAAK,SAASC,GACpB,GAAIqC,GAAY/F,GAAGgG,OAAO3F,KAC1Bd,GAAGG,MAAMiV,QAAQ5O,EAEjB,IACIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAYlE,IAVAvC,EAAM+P,OAAS,WAAapM,EAAU4G,aAAajM,KAAK0B,IACxDA,EAAM2D,UAAY1F,KAElBwP,EAAMqC,OAAOqN,EAAY7b,GAAOtB,EAAM+P,QACjCH,OAAOwN,EAAY9b,IACnByO,SAGLtC,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,YAE9C0E,EAAc,CACf,GAAIhU,EACJgU,KACA,KAAKhU,IAAOoE,GACJA,EAAMpE,YAAgBjL,OACtBif,EAAahU,GAAOoE,EAAMpE,GAAKhL,MAAM,GAErCgf,EAAahU,GAAOoE,EAAMpE,GAKtC,IAAK/H,IAASA,EAAKhC,OAEf,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,QAItC,IAAIf,GAAOJ,EAAUK,UAAU,yBAAyB1C,MAAMA,IAC1DgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,4BAA4BD,OAAO,KACnF0P,EAAI9P,EAAKH,OAAO,IAMpB,IAJA0U,EAAOnU,OAAO,KAAKC,KAAK,QAAS,cACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBAG7B2Z,EACA,GAAuB,QAAnByU,EACAxU,EAAOna,MAAOnB,GAAiB2G,IAAIkmB,EAAIhrB,KAEvCR,EAAKH,OAAO,kBACP8U,MAAMpX,GACNhD,KAAK0f,GAELzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SACpBnB,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IAGlEwB,EAAKH,OAAO,kBACPQ,KAAK,YAAa,gBAAmB7B,EAAOE,IAAM,SACpD,IAAuB,UAAnB+vB,EAA4B,CACnC,GAAI3P,GAAc1lB,EAAGI,OAAOygB,SAASna,OACZgf,GAArBngB,EAAiB,IACjBmgB,EAAengB,EAAiB,GAEpCsb,EAAOla,OAAOnB,GAAiB0G,IAAIkmB,EAAIhrB,KACvCyZ,EAAOna,MAAMgf,GACbngB,GAAkBsb,EAAOna,QAEzBE,EAAKH,OAAO,kBACP8U,MAAMpX,GACNhD,KAAK0f,GACL5Z,KAAK,YAAa,aAAe,EAAkB,OAGhEL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAGvE8sB,EAAI1rB,MAAMnB,GAAgBoB,OAAOnB,EACjC,IAAI8vB,GAAU5e,EAAEjQ,OAAO,eAAe8U,OAAOpX,GAC7C1D,IAAG2M,WAAWkoB,GAASn0B,KAAKixB,GAM5BvR,EAAOrgB,SAASkB,GAAG,cAAe,SAASogB,GACvC,IAAK,GAAI5V,KAAO4V,GACZxR,EAAMpE,GAAO4V,EAAS5V,EAE1B1L,GAASof,YAAYtP,GACrBzN,EAAM+P,WAIVpS,EAASkB,GAAG,cAAe,SAASC,GACN,mBAAfA,GAAE6Z,WACTrX,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,SAAW7Z,EAAE6Z,SAASzY,KAEjCuN,EAAMkL,SAAW7Z,EAAE6Z,UAEvB3Y,EAAM+P,aAId3B,EAAYS,UAAU,sBACf7O,EApKX,GAAIuvB,GAAMpyB,EAAGI,OAAOgyB,MAChBvR,EAAS7gB,EAAGI,OAAOygB,SACnB3gB,EAAUF,EAAGI,OAAOF,UAEpBkF,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9CqB,EAAQ,KACRC,EAAS,KACTia,GAAa,EACbyU,EAAiB,MACjBrpB,EAAQhM,EAAGG,MAAM6O,eACjBsB,EAAQtQ,EAAGG,MAAMmQ,QACjB4P,EAAe,KACfxK,EAAS,KACT5N,EAAW,IACXtH,EAAWC,GAAGD,SAAS,cAAe,cAAc,YAG1DN,GACK4H,SAAS,GACTiD,eAAc,GACdI,eAAe,SAAS1D,EAAG1E,GACxB,MAAOqvB,GAAIjP,cAAc1b,EAAG1E,IAOpC,IAAIkO,GAAcjR,EAAGG,MAAM8Q,YAAYzQ,GAEnCyf,EAAc,SAAS9b,GACvB,MAAO,YACH,OACIzB,OAAQyB,EAAK+O,IAAI,SAASzL,GAAK,OAAQA,EAAE+T,cAKjDwE,EAAc,SAAS7b,GACvB,MAAO,UAASmM,GACS1M,SAAjB0M,EAAM5N,QACNyB,EAAKoF,QAAQ,SAAUuC,EAAQ/I,GAC3B+I,EAAO0P,UAAYlL,EAAM5N,OAAOK,MAwLhD,OAvDAqvB,GAAI5xB,SAASkB,GAAG,2BAA4B,SAASia,GACjDA,EAAY,QACRzP,IAAKrJ,EAAMuE,IAAIuU,EAAIxX,MACnBuH,MAAO7I,EAAMsL,IAAIwN,EAAIxX,MACrB6H,MAAO2P,EAAI3P,OAEf9L,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7BssB,EAAI5xB,SAASkB,GAAG,0BAA2B,SAASia,GAChDzb,EAAQ4F,QAAO,KAGnBssB,EAAI5xB,SAASkB,GAAG,2BAA4B,SAASia,GACjDzb,MAQJ2C,EAAMge,OAASA,EACfhe,EAAMrC,SAAWA,EACjBqC,EAAMuvB,IAAMA,EACZvvB,EAAM3C,QAAUA,EAChB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAG1CA,EAAMiL,SAAWrB,OAAOsB,WAEpB2H,QAAiB1H,IAAK,WAAW,MAAO0H,IAAkBzH,IAAK,SAASjG,GAAG0N,EAAO1N,IAClF4Y,YAAiB5S,IAAK,WAAW,MAAO4S,IAAkB3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IACtFqtB,gBAAiBrnB,IAAK,WAAW,MAAOqnB,IAAkBpnB,IAAK,SAASjG,GAAGqtB,EAAertB,IAC1FkY,cAAiBlS,IAAK,WAAW,MAAOkS,IAAkBjS,IAAK,SAASjG,GAAGkY,EAAalY,IAGxFgE,OAAQgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GAClDgE,EAAQhE,EACR6Y,EAAO7U,MAAMA,GACbomB,EAAIpmB,MAAMA,KAEdlE,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,KAEtB1C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,SAGnErF,EAAGG,MAAM6U,eAAenS,EAAOuvB,GAC/BpyB,EAAGG,MAAMiO,YAAYvL,GACdA,GAGX7C,EAAGI,OAAOgnB,QAAU,WAChB,YAsDA,SAASvkB,GAAMoB,GAuXX,MAtXAgN,GAAYW,QACZ3N,EAAUC,KAAK,SAASC,GAwFpB,QAASoxB,KAKL,GAFAC,GAAc,GAETxW,EAAa,OAAO,CAGzB,IAAI0D,KAAe,EAAM,CACrB,GAAI+S,GAAWh1B,GAAGoc,MAAM1Y,EAAK+O,IAAI,SAASihB,EAAOuB,GACzC,MAAOvB,GAAMjsB,OACRgL,IAAI,SAAShF,EAAOgR,GAKjB,GAAIyW,GAAK/c,EAAK1K,EAAMgR,GAChB0W,EAAKnb,EAAKvM,EAAMgR,EAEpB,QAAQ9X,EAAEuuB,GAAqB,KAAhB3sB,KAAK0B,SACZyD,EAAEynB,GAAqB,KAAhB5sB,KAAK0B,SAChBgrB,EACAxW,EAAYhR,KAEnBqG,OAAO,SAASshB,EAAY3W,GACzB,MAAOiM,GAAY0K,EAAW,GAAI3W,OAKlD,IAAuB,GAAnBuW,EAAStzB,OAAa,OAAO,CAC7BszB,GAAStzB,OAAS,IAElBszB,EAASjyB,MAAM4D,EAAEiF,QAAQ,GAAK,GAAI8B,EAAE9B,QAAQ,GAAK,GAAI,KAAM,OAC3DopB,EAASjyB,MAAM4D,EAAEiF,QAAQ,GAAK,GAAI8B,EAAE9B,QAAQ,GAAK,GAAI,KAAM,OAC3DopB,EAASjyB,MAAM4D,EAAEiF,QAAQ,GAAK,GAAI8B,EAAE9B,QAAQ,GAAK,GAAI,KAAM,OAC3DopB,EAASjyB,MAAM4D,EAAEiF,QAAQ,GAAK,GAAI8B,EAAE9B,QAAQ,GAAK,GAAI,KAAM,OAK/D,IAAIypB,GAASr1B,GAAGs1B,KAAKC,UAChB,IAAI,MACJ,IAAIrvB,EAAS,KACbD,EAAQ,GAAGC,EAAS,KACpBD,EAAQ,GAAG,OAGZuvB,EAAUx1B,GAAGs1B,KAAKE,QAAQR,GAAUviB,IAAI,SAASzL,EAAG1E,GACpD,OACIoB,KAAQ2xB,EAAOI,KAAKzuB,GACpBqE,OAAU2pB,EAAS1yB,GAAG,GACtBmL,MAASunB,EAAS1yB,GAAG,KAK7B6D,GAAKH,OAAO,mBAAmBI,UAAU,QAAQc,QACjD,IAAIwuB,GAAavvB,EAAKH,OAAO,mBAAmBI,UAAU,QAAQ1C,KAAK8xB,GACnEG,EAAcD,EACbpvB,QAAQC,OAAO,YACfC,KAAK,IAAK,SAASQ,GAChB,MAAKA,IAAMA,EAAEtD,MAA0B,IAAlBsD,EAAEtD,KAAKhC,OAGjB,IAAMsF,EAAEtD,KAAKoS,KAAK,KAAO,IAFzB,UAIdtP,KAAK,KAAM,SAASQ,EAAE1E,GACnB,MAAO,WAAWA,IACrBkE,KAAK,YAAa,SAASQ,EAAE1E,GAAK,MAAO,gBAAgB+G,EAAG,IAAI/G,EAAE,KAWvE,IAPIszB,GACAD,EAAYrsB,MAAM,OAAQtJ,GAAGosB,IAAI,IAAK,IAAK,MACtC9iB,MAAM,eAAgB,IACtBA,MAAM,iBAAkB,GACxBA,MAAM,SAAUtJ,GAAGosB,IAAI,IAAI,IAAI,MAGpCyJ,EAAa,CAGb1vB,EAAKH,OAAO,mBAAmBI,UAAU,KAAKc,QAC9C,IAAI4uB,GAAa3vB,EAAKH,OAAO,mBAAmBI,UAAU,YAAY1C,KAAKsxB,EACzDc,GACbxvB,QAAQC,OAAO,gBACfC,KAAK,KAAM,SAASQ,EAAG1E,GAAK,MAAO,WAAW+G,EAAG,IAAI/G,IACrDiE,OAAO,cACPC,KAAK,KAAM,SAASQ,GAAK,MAAOA,GAAE,KAClCR,KAAK,KAAM,SAASQ,GAAK,MAAOA,GAAE,KAClCR,KAAK,IAAKuvB,GAGnB,GAAIC,GAAqB,SAAShvB,EAAGivB,GACjC,GAAIlB,EAAa,MAAO,EACxB,IAAI1pB,GAAS3H,EAAKsD,EAAEqE,OACpB,IAAelI,SAAXkI,EAAJ,CACA,GAAIoC,GAASpC,EAAO5D,OAAOT,EAAEyG,MAC7BA,GAAa,MAAIlC,EAAMF,EAAQrE,EAAEqE,QAGjCoC,EAAS,EAAI0K,EAAK1K,GAClBA,EAAS,EAAIuM,EAAKvM,EAGlB,IAAI6J,GAAMvR,EAAU8D,OAAO0N,wBACvB2e,EAAa10B,OAAO20B,aAAejtB,SAASqD,gBAAgB2pB,UAC5DE,EAAa50B,OAAO60B,aAAentB,SAASqD,gBAAgB6pB,WAE5DlqB,GACAtH,KAAM+B,EAAEwR,EAAK1K,EAAOzG,EAAEyG,QAAU6J,EAAI1S,KAAOwxB,EAAazxB,EAAOC,KAAO,GACtEC,IAAK6I,EAAEsM,EAAKvM,EAAOzG,EAAEyG,QAAU6J,EAAIzS,IAAMqxB,EAAYvxB,EAAOE,IAAM,GAGtEoxB,IACIxoB,MAAOA,EACPpC,OAAQA,EACRa,IAAKA,EACLoqB,aAAc3vB,EAAEwR,EAAK1K,EAAOzG,EAAEyG,QAAU9I,EAAOC,KAAM8I,EAAEsM,EAAKvM,EAAOzG,EAAEyG,QAAU9I,EAAOE,KACtFic,YAAa9Z,EAAEqE,OACfoT,WAAYzX,EAAEyG,SAItBioB,GACKz0B,GAAG,QAAS,SAAS+F,GAClBgvB,EAAmBhvB,EAAGjH,EAAS6F,gBAElC3E,GAAG,WAAY,SAAS+F,GACrBgvB,EAAmBhvB,EAAGjH,EAAS0iB,mBAElCxhB,GAAG,YAAa,SAAS+F,GACtBgvB,EAAmBhvB,EAAGjH,EAASyZ,oBAElCvY,GAAG,WAAY,SAAS+F,EAAG1E,GACxB0zB,EAAmBhvB,EAAGjH,EAASoF,uBAKvCgB,GAAKH,OAAO,cAAcI,UAAU,aAC/BA,UAAU,aAGVnF,GAAG,QAAS,SAAS+F,EAAE1E,GAEpB,GAAIyyB,IAAgBrxB,EAAKsD,EAAEqE,QAAS,MAAO,EAC3C,IAAIA,GAAS3H,EAAKsD,EAAEqE,QAChBoC,EAASpC,EAAO5D,OAAOnF,EAE3BvC,GAAS6F,cACL6H,MAAOA,EACPpC,OAAQA,EACRa,KAAMvF,EAAEwR,EAAK1K,EAAOnL,IAAMqC,EAAOC,KAAM8I,EAAEsM,EAAKvM,EAAOnL,IAAMqC,EAAOE,KAClEyxB,aAAc3vB,EAAEwR,EAAK1K,EAAOnL,IAAMqC,EAAOC,KAAM8I,EAAEsM,EAAKvM,EAAOnL,IAAMqC,EAAOE,KAC1Eic,YAAa9Z,EAAEqE,OACfoT,WAAYnc,MAGnBrB,GAAG,WAAY,SAAS+F,EAAE1E,GACvB,GAAIyyB,IAAgBrxB,EAAKsD,EAAEqE,QAAS,MAAO,EAC3C,IAAIA,GAAS3H,EAAKsD,EAAEqE,QAChBoC,EAASpC,EAAO5D,OAAOnF,EAE3BvC,GAAS0iB,iBACLhV,MAAOA,EACPpC,OAAQA,EACRa,KAAMvF,EAAEwR,EAAK1K,EAAOnL,IAAMqC,EAAOC,KAAM8I,EAAEsM,EAAKvM,EAAOnL,IAAMqC,EAAOE,KAClEyxB,aAAc3vB,EAAEwR,EAAK1K,EAAOnL,IAAMqC,EAAOC,KAAM8I,EAAEsM,EAAKvM,EAAOnL,IAAMqC,EAAOE,KAC1Eic,YAAa9Z,EAAEqE,OACfoT,WAAYnc,MAGnBrB,GAAG,YAAa,SAAS+F,EAAE1E,GACxB,GAAIyyB,IAAgBrxB,EAAKsD,EAAEqE,QAAS,MAAO,EAC3C,IAAIA,GAAS3H,EAAKsD,EAAEqE,QAChBoC,EAASpC,EAAO5D,OAAOnF,EAE3BvC,GAASyZ,kBACL/L,MAAOA,EACPpC,OAAQA,EACRa,KAAMvF,EAAEwR,EAAK1K,EAAOnL,IAAMqC,EAAOC,KAAM8I,EAAEsM,EAAKvM,EAAOnL,IAAMqC,EAAOE,KAClEyxB,aAAc3vB,EAAEwR,EAAK1K,EAAOnL,IAAMqC,EAAOC,KAAM8I,EAAEsM,EAAKvM,EAAOnL,IAAMqC,EAAOE,KAC1Eic,YAAa9Z,EAAEqE,OACfoT,WAAYnc,EACZiJ,MAAOA,EAAMvE,EAAG1E,OAGvBrB,GAAG,WAAY,SAAS+F,EAAE1E,GACvB,GAAIyyB,IAAgBrxB,EAAKsD,EAAEqE,QAAS,MAAO,EAC3C,IAAIA,GAAS3H,EAAKsD,EAAEqE,QAChBoC,EAASpC,EAAO5D,OAAOnF,EAE3BvC,GAASoF,iBACLsI,MAAOA,EACPpC,OAAQA,EACRa,KAAMvF,EAAEwR,EAAK1K,EAAOnL,IAAMqC,EAAOC,KAAM8I,EAAEsM,EAAKvM,EAAOnL,IAAMqC,EAAOE,KAClEyxB,aAAc3vB,EAAEwR,EAAK1K,EAAOnL,IAAMqC,EAAOC,KAAM8I,EAAEsM,EAAKvM,EAAOnL,IAAMqC,EAAOE,KAC1Eic,YAAa9Z,EAAEqE,OACfoT,WAAYnc,EACZiJ,MAAOA,EAAMvE,EAAG1E,OAhSpCyD,EAAY/F,GAAGgG,OAAO3F,KACtB,IAAIyE,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAElEpF,GAAGG,MAAMiV,QAAQ5O,GAGjBrC,EAAKoF,QAAQ,SAASuC,EAAQ/I,GAC1B+I,EAAO5D,OAAOqB,QAAQ,SAAS2E,GAC3BA,EAAMpC,OAAS/I,KAMvB,IAAI6f,GAAcjK,GAAWI,GAAWie,KACpCv2B,GAAGoc,MACC1Y,EAAK+O,IAAI,SAASzL,GACd,MAAOA,GAAES,OAAOgL,IAAI,SAASzL,EAAE1E,GAC3B,OAASqE,EAAGwR,EAAKnR,EAAE1E,GAAIoL,EAAGsM,EAAKhT,EAAE1E,GAAIuL,KAAM2oB,EAAQxvB,EAAE1E,QAKrEqE,GAAKgF,OAAOuM,GAAWlY,GAAGmc,OAAOgG,EAAW1P,IAAI,SAASzL,GAAK,MAAOA,GAAEL,IAAM3F,OAAOqb,KAEhFqB,GAAWha,EAAK,GAChBiD,EAAEiF,MAAMwM,KAAYtT,EAAiB2xB,EAAgB3xB,IAAmB,EAAGpB,EAAK,GAAG+D,OAAO/F,QAASoD,EAAiBA,GAAkB,EAAI2xB,IAAiB,EAAI/yB,EAAK,GAAG+D,OAAO/F,UAG9KiF,EAAEiF,MAAMwM,IAAW,EAAGtT,IAE1B4I,EAAK/B,OAAO2M,GAAWtY,GAAGmc,OAAOgG,EAAW1P,IAAI,SAASzL,GAAK,MAAOA,GAAE0G,IAAK1M,OAAO4c,KAC9EhS,MAAMqN,IAAWlU,EAAiB,IAEvC2xB,EAAK/qB,OAAO4qB,GAAcv2B,GAAGmc,OAAOgG,EAAW1P,IAAI,SAASzL,GAAK,MAAOA,GAAE6G,OAAQ7M,OAAO21B,KACpF/qB,MAAMgrB,GAAaC,GAGxBvV,EAAc3a,EAAEgF,SAAS,KAAOhF,EAAEgF,SAAS,IAAM+B,EAAE/B,SAAS,KAAO+B,EAAE/B,SAAS,GAE1EhF,EAAEgF,SAAS,KAAOhF,EAAEgF,SAAS,KAC7BhF,EAAEgF,SAAS,GACPhF,EAAEgF,QAAQhF,EAAEgF,SAAS,GAAqB,IAAhBhF,EAAEgF,SAAS,GAAWhF,EAAEgF,SAAS,GAAqB,IAAhBhF,EAAEgF,SAAS,KACzEhF,EAAEgF,QAAQ,GAAG,KAEnB+B,EAAE/B,SAAS,KAAO+B,EAAE/B,SAAS,KAC7B+B,EAAE/B,SAAS,GACP+B,EAAE/B,QAAQ+B,EAAE/B,SAAS,GAAqB,IAAhB+B,EAAE/B,SAAS,GAAW+B,EAAE/B,SAAS,GAAqB,IAAhB+B,EAAE/B,SAAS,KACzE+B,EAAE/B,QAAQ,GAAG,KAElB2E,MAAM3J,EAAEgF,SAAS,KAClBhF,EAAEgF,QAAQ,GAAG,IAGZ2E,MAAM5C,EAAE/B,SAAS,KAClB+B,EAAE/B,QAAQ,GAAG,IAGjBuN,EAAKA,GAAMvS,EACXwS,EAAKA,GAAMzL,EACXopB,EAAKA,GAAMJ,CAGX,IAAIvwB,GAAOJ,EAAUK,UAAU,wBAAwB1C,MAAMA,IACzD2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,oCAAsC6C,GACzFsR,EAAYtU,EAAUE,OAAO,QAC7BmU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpBG,GAAKoD,QAAQ,kBAAmB+X,GAChC5G,EAAOnU,OAAO,KAAKC,KAAK,QAAS,aACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,kBACjCH,EAAUE,OAAO,KAAKC,KAAK,QAAS,kBAEpCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEvE8V,EAAUpU,OAAO,YACZC,KAAK,KAAM,gBAAkB6C,GAC7B9C,OAAO,QAEZJ,EAAKH,OAAO,iBAAmBqD,EAAK,SAC/B7C,KAAK,QAAS1B,GACd0B,KAAK,SAAWzB,EAAkB,EAAKA,EAAkB,GAE9DkR,EAAEzP,KAAK,YAAauX,EAAW,qBAAuB1U,EAAK,IAAM,IAiNjE0rB,GAAc,CACd,IAAI1S,GAASlc,EAAKH,OAAO,cAAcI,UAAU,aAC5C1C,KAAK,SAASsD,GAAK,MAAOA,IAAK,SAASA,GAAK,MAAOA,GAAEyE,KAC3D4W,GAAO/b,QAAQC,OAAO,KACjB+C,MAAM,iBAAkB,MACxBA,MAAM,eAAgB,MAC3B+Y,EAAOpb,OACFC,SACLmb,EACK7b,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO,sBAAwBA,IAC7DiH,QAAQ,QAAS,SAASvC,GAAK,MAAOA,GAAEuS,QAC7C8I,EAAO9R,gBAAgBC,EAAa,mBAC/BlH,MAAM,OAAQ,SAAStC,EAAE1E,GAAK,MAAOiJ,GAAMvE,EAAG1E,KAC9CgH,MAAM,SAAU,SAAStC,EAAE1E,GAAK,MAAOiJ,GAAMvE,EAAG1E,KAChDgH,MAAM,iBAAkB,GACxBA,MAAM,eAAgB,GAG3B,IAAIytB,GAAS1U,EAAOjc,UAAU,iBACzB1C,KAAK,SAASsD,GACX,MAAOA,GAAES,OAAOgL,IACZ,SAAUhF,EAAOgR,GACb,OAAQhR,EAAOgR,KAChB3K,OACC,SAASshB,EAAY3W,GACjB,MAAOiM,GAAY0K,EAAW,GAAI3W,MAGtDsY,GAAOzwB,QAAQC,OAAO,QACjB+C,MAAM,OAAQ,SAAUtC,GAAK,MAAOA,GAAEuE,QACtCjC,MAAM,SAAU,SAAUtC,GAAK,MAAOA,GAAEuE,QACxC/E,KAAK,YAAa,SAASQ,GACxB,MAAO,aAAekS,EAAGf,EAAKnR,EAAE,GAAGA,EAAE,KAAO,IAAMmS,EAAGa,EAAKhT,EAAE,GAAGA,EAAE,KAAO,MAE3ER,KAAK,IACFjH,EAAGG,MAAMuU,SACRvO,KAAK,SAASsB,GAAK,MAAOgwB,GAAShwB,EAAE,MACrC6G,KAAK,SAAS7G,GAAK,MAAO0vB,GAAEF,EAAQxvB,EAAE,GAAGA,EAAE,QAEpD+vB,EAAO9vB,OAAOC,SACdmb,EAAOpb,OAAOb,UAAU,iBACnBmK,gBAAgBC,EAAa,gBAC7BhK,KAAK,YAAa,SAASQ,GACxB,MAAO,aAAeL,EAAEwR,EAAKnR,EAAE,GAAGA,EAAE,KAAO,IAAM0G,EAAEsM,EAAKhT,EAAE,GAAGA,EAAE,KAAO,MAEzEE,SACL6vB,EAAOtzB,KAAK,SAASuD,GACjBhH,GAAGgG,OAAO3F,MACLkJ,QAAQ,YAAY,GACpBA,QAAQ,YAAcvC,EAAE,IAAI,GAC5BuC,QAAQ,qBAAsBgV,GAC9BhV,QAAQ,SAAQ,KAGzBwtB,EACKxmB,gBAAgBC,EAAa,kBAC7BhK,KAAK,YAAa,SAASQ,GAExB,MAAO,aAAeL,EAAEwR,EAAKnR,EAAE,GAAGA,EAAE,KAAO,IAAM0G,EAAEsM,EAAKhT,EAAE,GAAGA,EAAE,KAAO,MAEzER,KAAK,IACFjH,EAAGG,MAAMuU,SACRvO,KAAK,SAASsB,GAAK,MAAOgwB,GAAShwB,EAAE,MACrC6G,KAAK,SAAS7G,GAAK,MAAO0vB,GAAEF,EAAQxvB,EAAE,GAAGA,EAAE,QAIpDiwB,aAAaC,GACbA,EAAYv0B,WAAWmyB,EAAwB,KAI/C5b,EAAKvS,EAAEoR,OACPoB,EAAKzL,EAAEqK,OACP+e,EAAKJ,EAAE3e,SAGXvH,EAAYS,UAAU,qBACf7O,EAvaX,GAyCI8W,GAAIC,EAAI2d,EACNI,EA1CFvyB,GAAgBE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GACjDqB,EAAe,KACfC,EAAe,KACfqF,EAAehM,EAAGG,MAAM6O,eACxBlF,EAAed,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UAC/BlE,EAAe,KACfY,EAAe3G,GAAGmH,MAAMC,SACxBsG,EAAe1N,GAAGmH,MAAMC,SACxBsvB,EAAe12B,GAAGmH,MAAMC,SACxB+Q,EAAe,SAASnR,GAAK,MAAOA,GAAEL,GACtCqT,EAAe,SAAShT,GAAK,MAAOA,GAAE0G,GACtC8oB,EAAe,SAASxvB,GAAK,MAAOA,GAAE6G,MAAQ,GAC9CmpB,EAAe,SAAShwB,GAAK,MAAOA,GAAEmwB,OAAS,UAC/C9a,KACAuB,KACA+Y,KACApY,GAAe,EACfmM,EAAe,SAAS1jB,GAAK,OAAQA,EAAEowB,WACvC1Z,GAAe,EACf+Y,EAAe,GACf1Y,GAAe,EACf8X,GAAe,EACfD,GAAe,EACfG,EAAe,WAAa,MAAO,KACnC7d,EAAe,KACfI,EAAe,KACfF,EAAe,KACfa,EAAe,KACfsd,EAAe,KACfK,EAAe,KACftV,GAAe,EACfvhB,EAAeC,GAAGD,SAAS,eAAgB,kBAAmB,mBAAoB,kBAAmB,aACrGkiB,GAAe,EACf5a,EAAe,IAUf0tB,GAAc,EACdvkB,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,GAC7CwvB,GAAkB,GAAI,IAud5B,OAtFAz0B,GAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAG1CA,EAAM4Q,OAAS,GAAI,YACf3S,KAAKse,gBAAkB,WAInB,MAHApf,GAAGO,IAAIoD,MAAM,WACT6C,EAAUK,UAAU,mBAAmBmD,QAAQ,SAAS,KAErD,MAEXlJ,KAAKme,eAAiB,SAAUsC,EAAarC,EAAYC,GACrDnf,EAAGO,IAAIoD,MAAM,WACT6C,EAAUC,OAAO,cACdI,UAAU,cAAgB0a,GAC1B1a,UAAU,aAAeqY,GACzBlV,QAAQ,QAASmV,OAMhC3e,EAASkB,GAAG,yBAA0B,SAAS+F,GACvCuX,GAAanc,EAAM4Q,OAAOwL,eAAexX,EAAE8Z,YAAY9Z,EAAEyX,YAAW,KAG5E1e,EAASkB,GAAG,wBAAyB,SAAS+F,GACtCuX,GAAanc,EAAM4Q,OAAOwL,eAAexX,EAAE8Z,YAAY9Z,EAAEyX,YAAW,KAG5Erc,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAesH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACtErB,QAAeqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACxEhC,QAAegI,IAAK,WAAW,MAAO5G,IAAK6G,IAAK,SAASjG,GAAGZ,EAAEY,IAC9D0S,QAAe1M,IAAK,WAAW,MAAOG,IAAKF,IAAK,SAASjG,GAAGmG,EAAEnG,IAC9D8vB,YAAe9pB,IAAK,WAAW,MAAOmpB,IAAKlpB,IAAK,SAASjG,GAAGmvB,EAAEnvB,IAC9D2Q,SAAe3K,IAAK,WAAW,MAAO2K,IAAW1K,IAAK,SAASjG,GAAG2Q,EAAQ3Q,IAC1E+Q,SAAe/K,IAAK,WAAW,MAAO+K,IAAW9K,IAAK,SAASjG,GAAG+Q,EAAQ/Q,IAC1EggB,aAAeha,IAAK,WAAW,MAAOgpB,IAAc/oB,IAAK,SAASjG,GAAGgvB,EAAWhvB,IAChF6Q,QAAe7K,IAAK,WAAW,MAAO6K,IAAU5K,IAAK,SAASjG,GAAG6Q,EAAO7Q,IACxE0R,QAAe1L,IAAK,WAAW,MAAO0L,IAAUzL,IAAK,SAASjG,GAAG0R,EAAO1R,IACxE+vB,YAAe/pB,IAAK,WAAW,MAAOqpB,IAAappB,IAAK,SAASjG,GAAGqvB,EAAUrvB,IAC9E8U,QAAe9O,IAAK,WAAW,MAAO8O,IAAU7O,IAAK,SAASjG,GAAG8U,EAAO9U,IACxEqW,QAAerQ,IAAK,WAAW,MAAOqQ,IAAUpQ,IAAK,SAASjG,GAAGqW,EAAOrW,IACxEgwB,YAAehqB,IAAK,WAAW,MAAOopB,IAAanpB,IAAK,SAASjG,GAAGovB,EAAUpvB,IAC9EgX,aAAehR,IAAK,WAAW,MAAOgR,IAAe/Q,IAAK,SAASjG,GAAGgX,EAAYhX,IAClFmjB,aAAend,IAAK,WAAW,MAAOmd,IAAeld,IAAK,SAASjG,GAAGmjB,EAAYnjB,IAClFkvB,cAAelpB,IAAK,WAAW,MAAOkpB,IAAgBjpB,IAAK,SAASjG,GAAGkvB,EAAalvB,IACpFmW,SAAenQ,IAAK,WAAW,MAAOmQ,IAAWlQ,IAAK,SAASjG,GAAGmW,EAAQnW,IAC1EwW,UAAexQ,IAAK,WAAW,MAAOwQ,IAAYvQ,IAAK,SAASjG,GAAGwW,EAASxW,IAC5EsuB,aAAetoB,IAAK,WAAW,MAAOsoB,IAAeroB,IAAK,SAASjG,GAAGsuB,EAAYtuB,IAClFwuB,YAAexoB,IAAK,WAAW,MAAOwoB,IAAcvoB,IAAK,SAASjG,GAAGwuB,EAAWxuB,IAChFquB,aAAgBroB,IAAK,WAAW,MAAOqoB,IAAepoB,IAAK,SAASjG,GAAGquB,EAAYruB,IACnF8B,IAAekE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,GAAG8B,EAAG9B,IAIhEZ,GAAQ4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAOnY,GAAGsU,QAAQ/M,KAC1EmG,GAAQH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAAGyS,EAAOha,GAAGsU,QAAQ/M,KAC1E+f,WAAY/Z,IAAK,WAAW,MAAOipB,IAAWhpB,IAAK,SAASjG,GAAGivB,EAAUx2B,GAAGsU,QAAQ/M,KACpFiwB,YAAajqB,IAAK,WAAW,MAAOypB,IAAYxpB,IAAK,SAASjG,GAAGyvB,EAAWh3B,GAAGsU,QAAQ/M,KAGvF5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,KAEtBkE,OAAQgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GAClDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,KAE9B0a,YAAa1U,IAAK,WAAW,MAAO0U,IAAczU,IAAK,SAASjG,GAC5D0a,EAAa1a,EACT0a,KAAe,IACf4T,GAAc,OAK1Bt2B,EAAGG,MAAMiO,YAAYvL,GACdA,GAGX7C,EAAGI,OAAO83B,aAAe,WACrB,YA2EA,SAASr1B,GAAMoB,GA4PX,MA3PAgN,GAAYW,QACZX,EAAY7Q,OAAOgnB,GACfvM,GAAW5J,EAAY7Q,OAAO0a,GAC9BC,GAAW9J,EAAY7Q,OAAO4a,GAC9Bmd,GAAWlnB,EAAY7Q,OAAOg4B,GAC9BC,GAAWpnB,EAAY7Q,OAAOk4B,GAElCr0B,EAAUC,KAAK,SAASC,GAGpBqC,EAAY/F,GAAGgG,OAAO3F,MACtBd,EAAGG,MAAMiV,QAAQ5O,EAEjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAkBlE,IAhBAvC,EAAM+P,OAAS,WACM,IAAb9K,EACAtB,EAAUrF,KAAK0B,GAEf2D,EAAU4G,aAAatF,SAASA,GAAU3G,KAAK0B,IAEvDA,EAAM2D,UAAY1F,KAElBwP,EACKqC,OAAOqN,EAAY7b,GAAOtB,EAAM+P,QAChCH,OAAOwN,EAAY9b,IACnByO,SAGLtC,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,YAE9C0E,EAAc,CACf,GAAIhU,EACJgU,KACA,KAAKhU,IAAOoE,GACJA,EAAMpE,YAAgBjL,OACtBif,EAAahU,GAAOoE,EAAMpE,GAAKhL,MAAM,GAErCgf,EAAahU,GAAOoE,EAAMpE,GAKtC,KAAK/H,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAG9E,MAFAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GACvByK,EAAYS,UAAU,qBACf7O,CAEP2D,GAAUK,UAAU,cAAcc,SAItCP,EAAIggB,EAAQphB,SACZmI,EAAIiZ,EAAQ1M,QAGZ,IAAI9T,GAAOJ,EAAUK,UAAU,6BAA6B1C,MAAMA,IAC9D2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,yCAA2CmgB,EAAQtd,MACtGqR,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAkBpB,IAfA0U,EAAOnU,OAAO,QAAQC,KAAK,QAAS,sBAAsB8C,MAAM,iBAAiB,QAEjFoR,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,kBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,0BACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,eACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBAE7BoU,GACA3E,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,aAAe1B,EAAiB,OAIvDqb,EAAY,CACZ,GAAI8E,GAAcngB,CAClBsb,GAAOna,MAAMgf,GAEb9e,EAAKH,OAAO,kBACP8U,MAAMpX,GACNhD,KAAK0f,GAELzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SACpBnB,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IAGlEwB,EAAKH,OAAO,kBACPQ,KAAK,YAAa,gBAAwB7B,EAAOE,IAAM,KAGhEsB,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAGvE8hB,EACK1gB,MAAMnB,GACNoB,OAAOnB,GACPwG,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GAEvB,MADA0E,GAAEuE,MAAQvE,EAAEuE,OAASA,EAAMvE,EAAG1E,GACvB0E,EAAEuE,QACVuI,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,YAE9C5U,EAAKH,OAAO,mBACP8U,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,YAC1Cra,KAAKimB,GAGVxgB,EAAKH,OAAO,2BACPQ,KAAK,YAAa,qBAAuBmgB,EAAQtd,KAAO,IAE7D,IAAIyuB,GAAU3xB,EAAKH,OAAO,2BAA2BI,UAAU,gBAC1D1C,KAAK,SAAUsD,GACZ,MAAOA,IAGf8wB,GAAQxxB,QAAQC,OAAO,KAAKC,KAAK,QAAS,cAE1C,IAAIuxB,GAAUD,EAAQ1xB,UAAU,eAC3B1C,KAAK,SAAUsD,GACZ,OAAQA,IAGhB+wB,GAAQzxB,QACHC,OAAO,QAAQC,KAAK,QAAS,cAC7B8C,MAAM,iBAAkB,GAG7ByuB,EAAQjkB,OAAO,SAAS9M,GACpB,MAAOA,GAAEgxB,WAAahxB,EAAEixB,QAEvB1nB,gBAAgBC,EAAa,iCAC7BhK,KAAK,KAAMG,EAAEiF,QAAQ,IACrBpF,KAAK,KAAMG,EAAEiF,QAAQ,IACrBpF,KAAK,KAAM,SAAUQ,EAAG1E,GACrB,MAAOoL,GAAE/G,EAAEgF,SAAS,GAAK3E,EAAEixB,MAAQjxB,EAAEgxB,aAExCxxB,KAAK,KAAM,SAAUQ,EAAG1E,GACrB,MAAOoL,GAAE/G,EAAEgF,SAAS,GAAK3E,EAAEixB,MAAQjxB,EAAEgxB,aAExC1uB,MAAM,SAAU,SAAUtC,EAAG1E,EAAGgX,GAC7B,MAAO/N,GAAMvE,EAAGsS,KAEnBhQ,MAAM,iBAAkB,SAAUtC,EAAG1E,GAClC,MAAQ0E,GAAE+T,UAA+B,mBAAZ/T,GAAEixB,OAAgD,mBAAhBjxB,GAAEgxB,UAA6B,EAAI,IAItG5d,IACAC,EACKlT,MAAMR,GACNya,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAChDsX,UAAWjW,EAAkB,GAElCkR,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,eAAiBkH,EAAE9B,QAAQ,GAAK,KAClDlL,KAAK2Z,IAGVC,IACAC,EACKpT,MAAMuG,GACN0T,OAAQ7hB,EAAGG,MAAMoT,WAAW/N,EAAgB,GAAIrB,IAChDsX,UAAWlW,EAAgB,GAEhCmR,EAAEjQ,OAAO,iBACJtF,KAAK6Z,IAIVmd,IACAC,EACKxU,QAAQwD,EAAQhgB,KAChBQ,MAAMR,GACNV,MAAMnB,GACNyG,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GACvB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,YAC9CL,EAAO1U,OAAO,gBAAgBO,OAAO,KAChCC,KAAK,QAAS,oBACnByP,EAAEjQ,OAAO,qBACJQ,KAAK,YAAa,eAAiBkH,EAAE9B,QAAQ,GAAK,KAClDkP,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,YAC1Cra,KAAKi3B,IAGVC,IACAC,EACK1U,QAAQwD,EAAQjZ,KAChBvG,MAAMuG,GACNzH,MAAMlB,GACNwG,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GACvB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC5BwR,OAAO,SAAS9M,EAAE1E,GAAK,OAAQoB,EAAKpB,GAAGyY,YAC9CL,EAAO1U,OAAO,gBAAgBO,OAAO,KAChCC,KAAK,QAAS,oBACnByP,EAAEjQ,OAAO,qBACJQ,KAAK,YAAa,cAAgBoU,EAAkB9V,GAAkB+yB,EAAMhqB,QAAW,OACvFiN,MAAMpX,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,YAC1Cra,KAAKm3B,IAOdzX,EAAOrgB,SAASkB,GAAG,cAAe,SAASogB,GACvC,IAAK,GAAI5V,KAAO4V,GACZxR,EAAMpE,GAAO4V,EAAS5V,EAC1B1L,GAASof,YAAYtP,GACrBzN,EAAM+P,WAIVpS,EAASkB,GAAG,cAAe,SAASC,GACN,mBAAfA,GAAE6Z,WACTrX,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,SAAW7Z,EAAE6Z,SAASzY,KAEjCuN,EAAMkL,SAAW7Z,EAAE6Z,UAEvB3Y,EAAM+P,WAIVwU,EAAQ5mB,SAASkB,GAAG,0BAA2B,SAASia,GACpDzb,EAAQ4F,QAAO,GACfU,EAAUC,OAAO,aAAe2gB,EAAQtd,KAAO,eAAiB6R,EAAI4F,YAAc,cAAgB5F,EAAIuD,YACjGjY,KAAK,KAAM,GAChBT,EAAUC,OAAO,aAAe2gB,EAAQtd,KAAO,eAAiB6R,EAAI4F,YAAc,cAAgB5F,EAAIuD,YACjGjY,KAAK,KAAMqxB,EAAMhqB,UAG1B8Y,EAAQ5mB,SAASkB,GAAG,2BAA4B,SAASia,GACrDnV,EAAUC,OAAO,cAAgBkV,EAAI4F,YAAc,cAAgB5F,EAAIuD,YAClEjY,KAAK,KAAM0U,EAAIob,YAAY,GAAKvxB,GACrCgB,EAAUC,OAAO,cAAgBkV,EAAI4F,YAAc,cAAgB5F,EAAIuD,YAClEjY,KAAK,KAAM0U,EAAIob,YAAY,GAAKqB,EAAM9pB,QAC3CpO,EAAQiE,KAAKwX,GAAK7V,QAAO,KAI7B6T,EAAKvS,EAAEoR,OACPoB,EAAKzL,EAAEqK,SAIXvH,EAAYS,UAAU,+BACf7O,EAjUX,GAAIukB,GAAepnB,EAAGI,OAAOgnB,UACvBtM,EAAe9a,EAAGI,OAAOqW,OACzBuE,EAAehb,EAAGI,OAAOqW,OACzBoK,EAAe7gB,EAAGI,OAAOygB,SACzBuX,EAAep4B,EAAGI,OAAOojB,eACzB8U,EAAet4B,EAAGI,OAAOojB,eACzBtjB,EAAeF,EAAGI,OAAOF,UAG3BkF,GAAgBE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IACpDqB,EAAe,KACfC,EAAe,KACfH,EAAe,KACfwF,EAAehM,EAAGG,MAAM6O,eACxB5H,EAAeggB,EAAQphB,SACvBmI,EAAeiZ,EAAQ1M,SACvByd,GAAe,EACfE,GAAe,EACfzX,GAAe,EACf/F,GAAe,EACfE,GAAe,EACfM,GAAkB,EAClB/K,EAAQtQ,EAAGG,MAAMmQ,QACjB4P,EAAe,KACf1f,EAAWC,GAAGD,SAAS,cAAe,cAAe,aACrDkV,EAAe,KACf5N,EAAW,GAGjBsf,GAAQphB,OAAOoB,GAAGsT,OAAOvM,GACzB2M,EAAMlE,OAAO,UAAUY,YAAY,IACnCwD,EACKpE,OAAO,EAAoB,QAAU,QACrCY,YAAY,IAEjB4gB,EAAM3hB,KAAK,KACX6hB,EAAM7hB,KAAK,KACXvW,EACKkL,gBAAgB,SAAS3D,EAAG1E,GACzB,MAAO+X,GAAM/D,aAAatP,EAAG1E,KAEhCoI,eAAe,SAAS1D,EAAG1E,GACxB,MAAOiY,GAAMjE,aAAatP,EAAG1E,IAOrC,IAAI4W,GAAIC,EACF3I,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,GAE/CmY,EAAc,SAAS9b,GACvB,MAAO,YACH,OACIzB,OAAQyB,EAAK+O,IAAI,SAASzL,GAAK,OAAQA,EAAE+T,cAKjDwE,EAAc,SAAS7b,GACvB,MAAO,UAASmM,GACS1M,SAAjB0M,EAAM5N,QACNyB,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,UAAYlL,EAAM5N,OAAOK,MAsThD,OA7CAF,GAAMrC,SAAWA,EACjBqC,EAAMukB,QAAUA,EAChBvkB,EAAMge,OAASA,EACfhe,EAAMiY,MAAQA,EACdjY,EAAMmY,MAAQA,EACdnY,EAAMu1B,MAAQA,EACdv1B,EAAMy1B,MAAQA,EACdz1B,EAAM3C,QAAUA,EAEhB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAC1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtExB,WAAawH,IAAK,WAAW,MAAOxH,IAAayH,IAAK,SAASjG,GAAGxB,EAAUwB,IAC5EmwB,WAAanqB,IAAK,WAAW,MAAOmqB,IAAalqB,IAAK,SAASjG,GAAGmwB,EAAUnwB,IAC5EqwB,WAAarqB,IAAK,WAAW,MAAOqqB,IAAapqB,IAAK,SAASjG,GAAGqwB,EAAUrwB,IAC5E4Y,YAAa5S,IAAK,WAAW,MAAO4S,IAAc3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IAC9E6S,WAAa7M,IAAK,WAAW,MAAO6M,IAAa5M,IAAK,SAASjG,GAAG6S,EAAU7S,IAC5E+S,WAAa/M,IAAK,WAAW,MAAO+M,IAAa9M,IAAK,SAASjG,GAAG+S,EAAU/S,IAC5EkY,cAAmBlS,IAAK,WAAW,MAAOkS,IAAgBjS,IAAK,SAASjG,GAAGkY,EAAalY,IACxF0N,QAAa1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IACtEF,UAAakG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GAAGF,EAASE,IAG1E5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DgW,iBAAkBrN,IAAK,WAAW,MAAOqN,IAAmBpN,IAAK,SAASjG,GACtEqT,EAAkBrT,EAClBgT,EAAMpE,OAAQ,EAAM,QAAU,UAElC5K,OAAQgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GAClDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1B6Y,EAAO7U,MAAMA,GACbosB,EAAMpsB,MAAMA,GACZssB,EAAMtsB,MAAMA,OAIpBhM,EAAGG,MAAM6U,eAAenS,EAAOukB,GAC/BpnB,EAAGG,MAAMiO,YAAYvL,GACdA,GAGX7C,EAAGI,OAAOu4B,UAAY,WAClB,YAsBA,SAAS91B,GAAMoB,GAgEX,MA/DAA,GAAUC,KAAK,SAASC,GACpB,GAAIoB,GAAiBmB,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAC9CjQ,EAAkBmB,EAASvB,EAAOE,IAAMF,EAAOoQ,MAEnDhP,GAAY/F,GAAGgG,OAAO3F,MACtBd,EAAGG,MAAMiV,QAAQ5O,GAGjBY,EAAKgF,OAAOuM,GAAWlY,GAAGmc,OAAOzY,EAAMyU,IAClCvM,MAAMwM,IAAW,EAAGtT,IAEzB4I,EAAK/B,OAAO2M,GAAWtY,GAAGmc,OAAOzY,EAAMsW,IAClCpO,MAAMqN,IAAWlU,EAAiB,GAGvC,IAAIoB,GAAOJ,EAAUK,UAAU,0BAA0B1C,MAAMA,IAC3D2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,4BAC1CH,GAAUE,OAAO,KACtBJ,EAAKH,OAAO,IAEpBG,GAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAEvE,IAAIszB,GAAQhyB,EAAKC,UAAU,QACtB1C,KAAK,SAASsD,GAAK,OAAQA,IAChCmxB,GAAM7xB,QAAQC,OAAO,QACrB4xB,EAAMlxB,OAAOC,SACbixB,EACK7uB,MAAM,SAAU,SAAStC,EAAE1E,GAAK,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAG1E,KAC3DkE,KAAK,IAAKxG,GAAGoU,IAAIvN,OACbF,EAAE,SAASK,EAAE1E,GAAK,MAAOqE,GAAEwR,EAAKnR,EAAE1E;GAClCoL,EAAE,SAAS1G,EAAE1E,GAAK,MAAOoL,GAAEsM,EAAKhT,EAAE1E,MAI3C,IAAIy0B,GAAS5wB,EAAKC,UAAU,mBACvB1C,KAAK,SAASA,GAEX,QAAS+a,GAAWxW,GAChB,GAAa,IAATA,EAAa,CACb,GAAImwB,GAAS10B,EAAKuE,EAElB,OADAmwB,GAAO3Z,WAAaxW,EACbmwB,EAEP,MAAO,MAPf,GAAIC,GAAU30B,EAAK+O,IAAI,SAASzL,EAAG1E,GAAK,MAAO0X,GAAKhT,EAAE1E,KAUlDg2B,EAAW7Z,EAAW4Z,EAAQE,YAAY7qB,EAAE/B,SAAS,KACrD6sB,EAAW/Z,EAAW4Z,EAAQnnB,QAAQxD,EAAE/B,SAAS,KACjD8sB,EAAeha,EAAW4Z,EAAQ32B,OAAS,EAC/C,QAAQ82B,EAAUF,EAAUG,GAAc3kB,OAAO,SAAU9M,GAAI,MAAY,OAALA,KAE9E+vB,GAAOzwB,QAAQC,OAAO,UACtBwwB,EAAO9vB,OAAOC,SACd6vB,EACKvwB,KAAK,KAAM,SAASQ,EAAE1E,GAAK,MAAOqE,GAAEwR,EAAKnR,EAAEA,EAAEyX,eAC7CjY,KAAK,KAAM,SAASQ,EAAE1E,GAAK,MAAOoL,GAAEsM,EAAKhT,EAAEA,EAAEyX,eAC7CjY,KAAK,IAAK,GACVA,KAAK,QAAS,SAASQ,EAAE1E,GACtB,MAAO6V,GAAKnR,EAAGA,EAAEyX,aAAe9X,EAAEgF,SAAS,GAAK,2BACxCqO,EAAKhT,EAAGA,EAAEyX,aAAe/Q,EAAE/B,SAAS,GAAK,uBAAyB,2BAI/EvJ,EAhFX,GAUM8V,GACAI,EACAF,EACAa,EAbFtU,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACRC,EAAS,GACTH,EAAY,KACZ2yB,GAAU,EACV/xB,EAAI3G,GAAGmH,MAAMC,SACbsG,EAAI1N,GAAGmH,MAAMC,SACb+Q,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9BnC,EAAQhM,EAAGG,MAAM4O,UAAU,QA6GjC,OA/BAlM,GAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAYsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACnErB,QAAYqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACrE2Q,SAAY3K,IAAK,WAAW,MAAO2K,IAAW1K,IAAK,SAASjG,GAAG2Q,EAAQ3Q,IACvE+Q,SAAY/K,IAAK,WAAW,MAAO+K,IAAW9K,IAAK,SAASjG,GAAG+Q,EAAQ/Q,IACvE6Q,QAAY7K,IAAK,WAAW,MAAO6K,IAAU5K,IAAK,SAASjG,GAAG6Q,EAAO7Q,IACrE0R,QAAY1L,IAAK,WAAW,MAAO0L,IAAUzL,IAAK,SAASjG,GAAG0R,EAAO1R,IACrEhC,QAAYgI,IAAK,WAAW,MAAO5G,IAAK6G,IAAK,SAASjG,GAAGZ,EAAEY,IAC3D0S,QAAY1M,IAAK,WAAW,MAAOG,IAAKF,IAAK,SAASjG,GAAGmG,EAAEnG,IAC3DmxB,SAAYnrB,IAAK,WAAW,MAAOmrB,IAAWlrB,IAAK,SAASjG,GAAGmxB,EAAQnxB,IAGvEZ,GAAI4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAKnY,GAAGsU,QAAQ/M,KACpEmG,GAAIH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAAGyS,EAAKha,GAAGsU,QAAQ/M,KAGpE5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,OAIlChI,EAAGG,MAAMiO,YAAYvL,GACdA,GAGX7C,EAAGI,OAAOg5B,cAAgB,WACtB,YAuBA,SAASv2B,GAAMoB,GAiJX,MAhJAA,GAAUC,KAAK,SAASC,GAwEpB,QAASk1B,KACL,IAAIC,EAAJ,CAEA,GAAIC,GAAa7iB,EAAE7P,UAAU,kBAAkB1C,KAAKuE,GAEhD8wB,EAAaD,EAAWxyB,QACvBC,OAAO,KAAKC,KAAK,QAAS,iBAC1B8C,MAAM,iBAAkB,GACxBA,MAAM,eAAgB,EAE3BwvB,GAAW7xB,OACN0F,aAAatF,SAAS,KACtBiC,MAAM,iBAAkB,GACxBA,MAAM,eAAgB,GACtBpC,SAEL4xB,EACKtyB,KAAK,YAAa,SAASQ,GAAK,MAAO,aAAeL,EAAEuxB,EAAUvxB,IAAIjD,EAAKsD,GAAGA,IAAM,QACpF2F,aAAatF,SAAS,KACtBiC,MAAM,iBAAkB,GACxBA,MAAM,eAAgB,GAEtBrB,EAAMvG,SAEXq3B,EAAWxyB,OAAO,QACbC,KAAK,KAAM,GACXA,KAAK,MAAO7B,EAAOE,KACnB2B,KAAK,KAAM,GACXA,KAAK,KAAMzB,GAEhBg0B,EAAWxyB,OAAO,QAAQC,KAAK,QAAS,aACnCA,KAAK,IAAK,IACVA,KAAK,KAAM7B,EAAOE,KAClB2B,KAAK,cAAe,OACpBA,KAAK,KAAM,QAEhByP,EAAEjQ,OAAO,6BACJgK,KAAKgb,EAAYkN,EAAUvxB,IAAIjD,EAAKuE,EAAM,IAAKA,EAAM,MAE1D8wB,EAAWxyB,OAAO,QAAQC,KAAK,QAAS,aACnCA,KAAK,IAAK,GACVA,KAAK,KAAM7B,EAAOE,KAClB2B,KAAK,cAAe,SACpBA,KAAK,KAAM,QAEhByP,EAAEjQ,OAAO,6BACJgK,KAAKib,EAAYiN,EAAUxqB,IAAIhK,EAAKuE,EAAM,IAAKA,EAAM,QAG9D,QAAS+wB,KAKL,QAASC,GAAgBv1B,EAAMiD,GAG3B,IAAK,GAFDwD,GAAW5B,KAAKC,IAAI0vB,EAAUvxB,IAAIjD,EAAK,GAAI,GAAKiD,GAChDuyB,EAAe,EACV52B,EAAI,EAAGA,EAAIoB,EAAKhC,OAAQY,IACzBiG,KAAKC,IAAI0vB,EAAUvxB,IAAIjD,EAAKpB,GAAIA,GAAKqE,GAAKwD,IAC1CA,EAAW5B,KAAKC,IAAI0vB,EAAUvxB,IAAIjD,EAAKpB,GAAIA,GAAKqE,GAChDuyB,EAAe52B,EAGvB,OAAO42B,GAbX,IAAIL,EAAJ,CAEA,GAAI3sB,GAAMlM,GAAG6D,MAAMxD,MAAM,GAAKsE,EAAOC,IAcrCqD,IAASgxB,EAAgBv1B,EAAM6E,KAAKuP,MAAMnR,EAAEnB,OAAO0G,MACnD0sB,KA1IJ,GAAI7yB,GAAY/F,GAAGgG,OAAO3F,KAC1Bd,GAAGG,MAAMiV,QAAQ5O,EAEjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAMlE,IAJAvC,EAAM+P,OAAS,WAAapM,EAAUrF,KAAK0B,IAC3CA,EAAM2D,UAAY1F,MAGbqD,IAASA,EAAKhC,OAEf,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,QAGtC,IAAIiB,GAAe+vB,EAAUxqB,IAAIhK,EAAKA,EAAKhC,OAAO,GAAIgC,EAAKhC,OAAO,EAGlEiF,GAAIuxB,EAAU3yB,SACdmI,EAAIwqB,EAAUje,QAGd,IAAI9T,GAAOJ,EAAUK,UAAU,8BAA8B1C,MAAMA,IAC/D2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,iCACnDkU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,oBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBAEjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,IAGvE,IAAIs0B,GAAgBljB,EAAEjQ,OAAO,oBAK7B,IAHAkyB,EAAUjyB,MAAMnB,GAAgBoB,OAAOnB,GACvCo0B,EAAcz4B,KAAKw3B,GAEfkB,EAAe,CACf,GAAIC,GAAYpjB,EAAEjQ,OAAO,iBACrBiF,EAAQouB,EAAUjzB,UAAU,oBAC3B1C,MAAMyE,GAEX8C,GAAM3E,QAAQC,OAAO,QAAQC,KAAK,QAAS,mBACtCA,KAAK,KAAM8yB,EAAkB,GAAK,GAClC9yB,KAAK,KAAM,QACX8C,MAAM,cAAegwB,EAAkB,MAAQ,SAEpDruB,EACKzE,KAAK,IAAK1B,GAAkBw0B,EAAkB30B,EAAOqQ,MAAQ,IAC7DxO,KAAK,IAAK+yB,EAAa,SAAUvyB,GAC9B,MAAO0G,GAAE1G,IACT,GACHsC,MAAM,OAAQ4uB,EAAU3sB,QAAQ7H,EAAKA,EAAKhC,OAAS,GAAIgC,EAAKhC,OAAS,IACrEsO,KAAKib,EAAY9iB,IAG1BuS,EAAO1U,OAAO,iBAAiBO,OAAO,QACjCtF,GAAG,YAAa+3B,GAChB/3B,GAAG,QAAS,WAAa43B,GAAUA,IACnC53B,GAAG,WAAY,WAAagH,KAAY2wB,MAE7C3iB,EAAEjQ,OAAO,sBACJQ,KAAK,YAAa,SAASQ,GAAK,MAAO,cAAgBrC,EAAOC,KAAO,KAAOD,EAAOE,IAAM,MACzF2B,KAAK,QAAS1B,EAAiBH,EAAOC,KAAOD,EAAOqQ,OACpDxO,KAAK,SAAUzB,EAAkBJ,EAAOE,OA2E1CzC,EAlKX,GAKMuE,GACA+G,EANFwqB,EAAY34B,EAAGI,OAAOu4B,YAEtBvzB,GAAUE,IAAK,GAAImQ,MAAO,IAAKD,OAAQ,GAAInQ,KAAM,IAC/CqB,EAAQ,KACRC,EAAS,KAGT+B,KACA4wB,GAAS,EACT7N,EAAchrB,GAAGib,OAAO,MACxBgQ,EAAcjrB,GAAGib,OAAO,QACxBme,GAAgB,EAChBG,GAAa,EACbD,GAAkB,EAClBrkB,EAAS,IAuLf,OA3BA7S,GAAM81B,UAAYA,EAElB91B,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAkBsH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACzErB,QAAkBqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IAC3EyjB,aAAkBzd,IAAK,WAAW,MAAOyd,IAAexd,IAAK,SAASjG,GAAGyjB,EAAYzjB,IACrF0jB,aAAkB1d,IAAK,WAAW,MAAO0d,IAAezd,IAAK,SAASjG,GAAG0jB,EAAY1jB,IACrF6xB,eAAkB7rB,IAAK,WAAW,MAAO6rB,IAAiB5rB,IAAK,SAASjG,GAAG6xB,EAAc7xB,IACzFgyB,YAAkBhsB,IAAK,WAAW,MAAOgsB,IAAc/rB,IAAK,SAASjG,GAAGgyB,EAAWhyB,IACnF+xB,iBAAkB/rB,IAAK,WAAW,MAAO+rB,IAAmB9rB,IAAK,SAASjG,GAAG+xB,EAAgB/xB,IAC7F0N,QAAkB1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IAG3E5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,SAInErF,EAAGG,MAAM6U,eAAenS,EAAO81B,GAC/B34B,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAOswB,YAAc,WACpB,YA6CA,SAAS7tB,GAAMoB,GA4LX,MA3LAgN,GAAYW,QACZX,EAAY7Q,OAAOgnB,GACnBnjB,EAAUC,KAAK,SAASC,GACpB,GAAIoB,GAAiBmB,EAAQtB,EAAOC,KAAOD,EAAOqQ,MAC9CjQ,EAAkBmB,EAASvB,EAAOE,IAAMF,EAAOoQ,MAEnDhP,GAAY/F,GAAGgG,OAAO3F,MACtBd,EAAGG,MAAMiV,QAAQ5O,GAGjBY,EAAIggB,EAAQphB,SACZmI,EAAIiZ,EAAQ1M,QAEZ,IAAIuf,GAAU91B,CAEdA,GAAKoF,QAAQ,SAAS2wB,EAASn3B,GAC3Bm3B,EAAQ3Y,YAAcxe,EACtBm3B,EAAQhyB,OAASgyB,EAAQhyB,OAAOgL,IAAI,SAASzL,EAAGsS,GAG5C,MAFAtS,GAAEiB,MAAQqR,EACVtS,EAAE8Z,YAAcxe,EACT0E,KAIf,IAAI0yB,GAAeh2B,EAAKoQ,OAAO,SAASzI,GACpC,OAAQA,EAAO0P,UAGnBrX,GAAO1D,GAAGurB,OAAOC,QACZmO,MAAMA,GACNlO,OAAOA,GACPhkB,OAAO,SAAST,GAAK,MAAOA,GAAES,SAC9Bd,EAAEwR,GACFzK,EAAEsM,GACF4f,IAAI,SAAS5yB,EAAGmS,EAAIzL,GACjB1G,EAAE4Z,SACElT,EAAGA,EACHyL,GAAIA,KAGfugB,EAGD,IAAIvzB,GAAOJ,EAAUK,UAAU,4BAA4B1C,MAAMA,IAC7D2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,+BACnDmU,EAAYtU,EAAUE,OAAO,QAC7BmU,EAASrU,EAAUE,OAAO,KAC1B0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,eACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,kBAEjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAIxC,GAA3B8hB,EAAQ/I,SAASlc,QACjBilB,EAAQ/I,SAAS7a,KAAK,GAG1B4jB,EACK1gB,MAAMnB,GACNoB,OAAOnB,GACP4B,EAAEwR,GACFzK,EAAE,SAAS1G,GACR,MAAkB7D,UAAd6D,EAAE4Z,QAAgC5Z,EAAE4Z,QAAQlT,EAAI1G,EAAE4Z,QAAQzH,GAA9D,SAEHyE,QAAQ,IACRrS,MAAM7H,EAAK+O,IAAI,SAASzL,EAAE1E,GACvB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAGA,EAAE8Z,eAGrC,IAAI8F,GAAc3Q,EAAEjQ,OAAO,mBACtB8U,MAAMpX,EAEXkjB,GAAYlmB,KAAKimB,GAEjBhM,EAAUpU,OAAO,YACZC,KAAK,KAAM,gBAAkB6C,GAC7B9C,OAAO,QAEZJ,EAAKH,OAAO,iBAAmBqD,EAAK,SAC/B7C,KAAK,QAAS1B,GACd0B,KAAK,SAAUzB,GAEpBkR,EAAEzP,KAAK,YAAauX,EAAW,qBAAuB1U,EAAK,IAAM,GAEjE,IAAI4d,GAAOjnB,GAAGoU,IAAI6S,OACbtgB,EAAE,SAASK,EAAE1E,GAAM,MAAOqE,GAAEwR,EAAKnR,EAAE1E,MACnC6W,GAAG,SAASnS,GACT,MAAO0G,GAAE1G,EAAE4Z,QAAQzH,MAEtBiO,GAAG,SAASpgB,GACT,MAAO0G,GAAE1G,EAAE4Z,QAAQlT,EAAI1G,EAAE4Z,QAAQzH,MAEpC+N,YAAYA,GAEb2S,EAAW75B,GAAGoU,IAAI6S,OACjBtgB,EAAE,SAASK,EAAE1E,GAAM,MAAOqE,GAAEwR,EAAKnR,EAAE1E,MACnC6W,GAAG,SAASnS,GAAK,MAAO0G,GAAE1G,EAAE4Z,QAAQzH,MACpCiO,GAAG,SAASpgB,GAAK,MAAO0G,GAAE1G,EAAE4Z,QAAQzH,MAErCoU,EAAOtX,EAAEjQ,OAAO,gBAAgBI,UAAU,gBACzC1C,KAAK,SAASsD,GAAK,MAAOA,IAE/BumB,GAAKjnB,QAAQC,OAAO,QAAQC,KAAK,QAAS,SAASQ,EAAE1E,GAAK,MAAO,mBAAqBA,IACjFkE,KAAK,IAAK,SAASQ,EAAE1E,GAClB,MAAOu3B,GAAS7yB,EAAES,OAAQT,EAAE8Z,eAE/B7f,GAAG,YAAa,SAAS+F,EAAE1E,GACxBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAAS+5B,eACLrsB,MAAOzG,EACPqE,OAAQrE,EAAEyE,IACVS,KAAMlM,GAAGmE,MAAM41B,MAAO/5B,GAAGmE,MAAM61B,OAC/BlZ,YAAa9Z,EAAE8Z,gBAGtB7f,GAAG,WAAY,SAAS+F,EAAE1E,GACvBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASk6B,cACLxsB,MAAOzG,EACPqE,OAAQrE,EAAEyE,IACVS,KAAMlM,GAAGmE,MAAM41B,MAAO/5B,GAAGmE,MAAM61B,OAC/BlZ,YAAa9Z,EAAE8Z,gBAGtB7f,GAAG,QAAS,SAAS+F,EAAE1E,GACpBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GACjCxJ,EAASm6B,WACLzsB,MAAOzG,EACPqE,OAAQrE,EAAEyE,IACVS,KAAMlM,GAAGmE,MAAM41B,MAAO/5B,GAAGmE,MAAM61B,OAC/BlZ,YAAa9Z,EAAE8Z,gBAI3ByM,EAAKtmB,OAAOC,SACZqmB,EAAKjkB,MAAM,OAAQ,SAAStC,EAAE1E,GACtB,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAGA,EAAE8Z,eAEhCxX,MAAM,SAAU,SAAStC,EAAE1E,GAAI,MAAO0E,GAAEuE,OAASA,EAAMvE,EAAGA,EAAE8Z,eACjEyM,EAAKhd,gBAAgBC,EAAY,oBAC5BhK,KAAK,IAAK,SAASQ,EAAE1E,GAClB,MAAO2kB,GAAKjgB,EAAES,OAAOnF,KAO7BqkB,EAAQ5mB,SAASkB,GAAG,wBAAyB,SAASC,GAClD+U,EAAEjQ,OAAO,aAAeqD,EAAK,aAAenI,EAAE4f,aAAavX,QAAQ,SAAS,KAEhFod,EAAQ5mB,SAASkB,GAAG,uBAAwB,SAASC,GACjD+U,EAAEjQ,OAAO,aAAeqD,EAAK,aAAenI,EAAE4f,aAAavX,QAAQ,SAAS,KAIhFnH,EAAM+3B,8BAAgC,SAASC,GAC3C,GAEI93B,GACAgX,EACA+gB,EAJAhqB,EAAI+pB,EAAU14B,OACdqP,EAAIqpB,EAAU,GAAG14B,OAIjByX,IAEJ,KAAKG,EAAI,EAAOvI,EAAJuI,IAASA,EAAG,CACpB,IAAKhX,EAAI,EAAG+3B,EAAI,EAAG/3B,EAAIk3B,EAAQ93B,OAAQY,IACnC+3B,GAAKrgB,EAAKwf,EAAQl3B,GAAGmF,OAAO6R,GAGhC,IAAI+gB,EAAG,IAAK/3B,EAAI,EAAO+N,EAAJ/N,EAAOA,IACtB83B,EAAU93B,GAAGgX,GAAG,IAAM+gB,MAEtB,KAAK/3B,EAAI,EAAO+N,EAAJ/N,EAAOA,IACf83B,EAAU93B,GAAGgX,GAAG,GAAK,EAIjC,IAAKA,EAAI,EAAOvI,EAAJuI,IAASA,EAAGH,EAAGG,GAAK,CAChC,OAAOH,MAKf3I,EAAYS,UAAU,yBACf7O,EAnOX,GAaMuE,GACA+G,EAdF/I,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,IACRC,EAAS,IACTqF,EAAQhM,EAAGG,MAAM6O,eACjBlF,EAAKd,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UACrBlE,EAAY,KACZoS,EAAO,SAASnR,GAAK,MAAOA,GAAEL,GAC9BqT,EAAO,SAAShT,GAAK,MAAOA,GAAE0G,GAC9BpE,EAAQ,QACRmiB,EAAS,OACTkO,EAAQ,UACRzS,EAAc,SACdnJ,GAAW,EAGX4I,EAAUpnB,EAAGI,OAAOgnB,UACpBtf,EAAW,IACXtH,EAAYC,GAAGD,SAAS,YAAa,gBAAiB,eAAe,YAAa,eAAgB,mBAAoB,kBAG5H4mB,GACKW,UAAU,KACVC,aAAa,IAAK,KAevB,IAAI/W,GAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAAUsH,EAwRjD,OAnFAjF,GAAMrC,SAAWA,EACjBqC,EAAMukB,QAAUA,EAEhBA,EAAQ5mB,SAASkB,GAAG,eAAgB,WAAYlB,EAAS6F,aAAa7E,MAAMV,KAAMM,aAClFgmB,EAAQ5mB,SAASkB,GAAG,mBAAoB,WAAYlB,EAASyZ,iBAAiBzY,MAAMV,KAAMM,aAC1FgmB,EAAQ5mB,SAASkB,GAAG,kBAAmB,WAAYlB,EAASoF,gBAAgBpE,MAAMV,KAAMM,aAExFyB,EAAM8kB,YAAc,SAAS3f,GACzB,MAAK5G,WAAUe,QACfwlB,EAAc3f,EACPnF,GAFuB8kB,GAKlC9kB,EAAMiF,SAAW,SAASE,GACtB,MAAK5G,WAAUe,QACf2F,EAAWE,EACXiJ,EAAYW,MAAM9J,GAClBsf,EAAQtf,SAASA,GACVjF,GAJuBiF,GAOlCjF,EAAMrC,SAAWA,EACjBqC,EAAMukB,QAAUA,EAChBvkB,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtEwW,UAAWxQ,IAAK,WAAW,MAAOwQ,IAAYvQ,IAAK,SAASjG,GAAGwW,EAASxW,IACxEkkB,QAAcle,IAAK,WAAW,MAAOke,IAAUje,IAAK,SAASjG,GAAGkkB,EAAOlkB,IACvEoyB,OAAWpsB,IAAK,WAAW,MAAOosB,IAASnsB,IAAK,SAASjG,GAAGoyB,EAAMpyB,IAClE2f,aAAiB3Z,IAAK,WAAW,MAAO2Z,IAAe1Z,IAAK,SAASjG,GAAG2f,EAAY3f,IAGpFZ,GAAQ4G,IAAK,WAAW,MAAO4K,IAAQ3K,IAAK,SAASjG,GAAG4Q,EAAOnY,GAAGsU,QAAQ/M,KAC1EmG,GAAQH,IAAK,WAAW,MAAOyM,IAAQxM,IAAK,SAASjG,GAAGyS,EAAOha,GAAGsU,QAAQ/M,KAG1E5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/D2G,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,KAE9B+B,OAAQiE,IAAK,WAAW,MAAOjE,IAASkE,IAAK,SAASjG,GAElD,OADA+B,EAAQ/B,GAEJ,IAAK,QACDnF,EAAMqpB,OAAO,QACbrpB,EAAMu3B,MAAM,UACZ,MACJ,KAAK,SACDv3B,EAAMqpB,OAAO,UACbrpB,EAAMu3B,MAAM,aACZ,MACJ,KAAK,gBACDv3B,EAAMqpB,OAAO,cACbrpB,EAAMu3B,MAAM,aACZ,MACJ,KAAK,SACDv3B,EAAMqpB,OAAO,UACbrpB,EAAMu3B,MAAM,UACZ,MACJ,KAAK,gBACDv3B,EAAMqpB,OAAOrpB,EAAM+3B,+BACnB/3B,EAAMu3B,MAAM,cAIxBtyB,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,GAClBsf,EAAQtf,SAASA,OAIzB9H,EAAGG,MAAM6U,eAAenS,EAAOukB,GAC/BpnB,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAO26B,iBAAmB,WACzB,YA6FA,SAASl4B,GAAMoB,GAoXX,MAnXAgN,GAAYW,QACZX,EAAY7Q,OAAO0rB,GACfjR,GAAW5J,EAAY7Q,OAAO0a,GAC9BC,GAAW9J,EAAY7Q,OAAO4a,GAElC/W,EAAUC,KAAK,SAASC,GACpB,GAAIqC,GAAY/F,GAAGgG,OAAO3F,MACtBif,EAAOjf,IACXd,GAAGG,MAAMiV,QAAQ5O,EAEjB,IAAIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAalE,IAXAvC,EAAM+P,OAAS,WAAapM,EAAU4G,aAAatF,SAASA,GAAU3G,KAAK0B,IAC3EA,EAAM2D,UAAY1F,KAElBwP,EACKqC,OAAOqN,EAAY7b,GAAOtB,EAAM+P,QAChCH,OAAOwN,EAAY9b,IACnByO,SAGLtC,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,YAE9C0E,EAAc,CACf,GAAIhU,EACJgU,KACA,KAAKhU,IAAOoE,GACJA,EAAMpE,YAAgBjL,OACtBif,EAAahU,GAAOoE,EAAMpE,GAAKhL,MAAM,GAErCgf,EAAahU,GAAOoE,EAAMpE,GAKtC,KAAK/H,GAASA,EAAKhC,QAAWgC,EAAKoQ,OAAO,SAAS9M,GAAK,MAAOA,GAAES,OAAO/F,SAAUA,QAE9E,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,SAItCP,EAAI0kB,EAAQ9lB,SACZmI,EAAI2d,EAAQpR,QAGZ,IAAI9T,GAAOJ,EAAUK,UAAU,iCAAiC1C,MAAMA,IAClEgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,oCAAoCD,OAAO,KAC3F0P,EAAI9P,EAAKH,OAAO,IAapB,IAXA0U,EAAOnU,OAAO,QAAQ+C,MAAM,UAAU,GACtCoR,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,gBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,kBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,iBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,mBACjCkU,EAAOnU,OAAO,KAAKC,KAAK,QAAS,kBAEjCyP,EAAEjQ,OAAO,QAAQQ,KAAK,QAAQ1B,GAAgB0B,KAAK,SAASzB,GAGxDob,EAAY,CACZ,GAAI8E,GAAc,EAAiBngB,EAAiB4nB,EAAe5nB,CAEnEsb,GAAOna,MAAMgf,GACbhP,EAAEjQ,OAAO,kBAAkB8U,MAAMpX,GAAMhD,KAAK0f,GAEvCzb,EAAOE,KAAOub,EAAOla,WACtBvB,EAAOE,IAAMub,EAAOla,SACpBnB,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IAGlEsR,EAAEjQ,OAAO,kBACJQ,KAAK,YAAa,cAAgB1B,EAAemgB,GAAe,KAAQtgB,EAAOE,IAAM,KAI9F,GAAIwb,EAAc,CACd,GAAIC,KAEI7U,IAAKkhB,EAActB,SAAW,UAC9BkP,QAAS,UACTxf,SAA6B,SAAnBsQ,EAAQ/hB,QAClBA,MAAO,UAGPmC,IAAKkhB,EAAc6N,QAAU,SAC7BD,QAAS,SACTxf,SAA6B,UAAnBsQ,EAAQ/hB,QAClBA,MAAO,WAGPmC,IAAKkhB,EAAcpJ,UAAY,WAC/BgX,QAAS,WACTxf,SAA6B,UAAnBsQ,EAAQ/hB,QAClBA,MAAO,WAGPmC,IAAKkhB,EAAc8N,eAAiB,UACpCF,QAAS,gBACTxf,SAA6B,iBAAnBsQ,EAAQ/hB,QAClBA,MAAO,iBAIfojB,GAAgBgO,EAAeh5B,OAAO,EAAK,IAC3C4e,EAAeA,EAAaxM,OAAO,SAAS9M,GACxC,MAA6C,KAAtC0zB,EAAexpB,QAAQlK,EAAEuzB,WAGpCha,EACKta,MAAOymB,GACPnhB,OAAO,OAAQ,OAAQ,SAE5B0K,EAAEjQ,OAAO,oBACJ8U,MAAMwF,GACN5f,KAAK6f,GAEL5b,EAAOE,KAAO0D,KAAKL,IAAIqY,EAASra,SAAUka,EAAOla,YAClDvB,EAAOE,IAAM0D,KAAKL,IAAIqY,EAASra,SAAUka,EAAOla,UAChDnB,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,IAGlEsR,EAAEjQ,OAAO,oBACJQ,KAAK,YAAa,gBAAmB7B,EAAOE,IAAM,KAG3DsB,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAEnE+V,GACA3E,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,aAAe1B,EAAiB,OAIvD4b,IACAC,EACK1a,MAAMnB,GACNoB,OAAOnB,GACPJ,QAAQC,KAAMD,EAAOC,KAAMC,IAAKF,EAAOE,MACvC4B,aAAaV,GACbR,OAAOoB,GACZR,EAAKH,OAAO,mBAAmBtF,KAAKigB,IAGxC0K,EACKplB,MAAMnB,GACNoB,OAAOnB,EAEZ,IAAI41B,GAAc1kB,EAAEjQ,OAAO,mBACtB8U,MAAMpX,EAkBX,IAhBAi3B,EAAYhuB,aAAajM,KAAK2qB,GAG1BjR,IACAC,EAAMlT,MAAMR,GACPya,OAAQ7hB,EAAGG,MAAMgT,WAAW5N,EAAe,IAAKpB,IAChDsX,UAAWjW,EAAiB,GAEjCkR,EAAEjQ,OAAO,iBACJQ,KAAK,YAAa,eAAiBzB,EAAkB,KAE1DkR,EAAEjQ,OAAO,iBACJ2G,aAAatF,SAAS,GACtB3G,KAAK2Z,IAGVC,EAAW,CACX,GAAIpE,EAWA,IATAA,EADqB,WAArBmV,EAAQI,SACA,EAGAlsB,EAAGG,MAAMoT,WAAW/N,EAAgB,GAAIrB,GAEpD6W,EAAMpT,MAAMuG,GACP0T,OAAOlL,GACP8E,UAAUlW,EAAgB,GAEH,WAApBumB,EAAQ/hB,SAA4C,kBAApB+hB,EAAQ/hB,QAA6B,CACrE,GAAIsxB,GAAgBrgB,EAAMjE,YAEpBukB,IAAkBD,IAAkBE,IACtCD,EAAiBD,GAGrBrgB,EAAMjE,WAAWwkB,OAGbD,KACAtgB,EAAMjE,WAAWukB,GACjBA,EAAiB,KAI7B5kB,GAAEjQ,OAAO,iBACJ2G,aAAatF,SAAS,GACtB3G,KAAK6Z,GAOd8Q,EAAQtrB,SAASkB,GAAG,mBAAoB,SAASC,GACkB,IAA3DwC,EAAKoQ,OAAO,SAAS9M,GAAK,OAAQA,EAAE+T,WAAYrZ,OAChDgC,EAAKoF,QAAQ,SAAS9B,GAClBA,EAAE+T,UAAW,IAGjBrX,EAAKoF,QAAQ,SAAS9B,EAAE1E,GACpB0E,EAAE+T,SAAYzY,GAAKpB,EAAE4f,cAG7BjR,EAAMkL,SAAWrX,EAAK+O,IAAI,SAASzL,GAAK,QAASA,EAAE+T,WACnDhb,EAASof,YAAYtP,GAErBzN,EAAM+P,WAGViO,EAAOrgB,SAASkB,GAAG,cAAe,SAASogB,GACvC,IAAK,GAAI5V,KAAO4V,GACZxR,EAAMpE,GAAO4V,EAAS5V,EAC1B1L,GAASof,YAAYtP,GACrBzN,EAAM+P,WAGVoO,EAASxgB,SAASkB,GAAG,cAAe,SAAS+F,EAAE1E,GACtC0E,EAAE+T,WAEPuF,EAAeA,EAAa7N,IAAI,SAAS0B,GAErC,MADAA,GAAE4G,UAAW,EACN5G,IAEXnN,EAAE+T,UAAW,EAEbsQ,EAAQ/hB,MAAMtC,EAAEsC,OAGhBuG,EAAMvG,MAAQ+hB,EAAQ/hB,QACtBvJ,EAASof,YAAYtP,GAErBzN,EAAM+P,YAGVwO,EAAiB5gB,SAASkB,GAAG,mBAAoB,SAASC,GACtDmqB,EAAQ1M,iBACR,IAAI2C,GAAa7C,EAAY8C,EAAgBC,KAAcuZ,EAAW,CAkCtE,IAjCAr3B,EACKoQ,OAAO,SAASzI,EAAQ/I,GAErB,MADA+I,GAAOyV,YAAcxe,GACb+I,EAAO0P,WAElBjS,QAAQ,SAASuC,EAAO/I,GACrBmc,EAAalf,EAAGiI,kBAAkB6D,EAAO5D,OAAQvG,EAAEoE,YAAalD,EAAMuE,IACtE,IAAI8G,GAAQpC,EAAO5D,OAAOgX,GACtBgJ,EAAcrlB,EAAMsL,IAAID,EAAOgR,EAInC,IAHmB,MAAfgJ,GACA4D,EAAQ7M,eAAelc,EAAGmc,GAAY,GAErB,mBAAVhR,GAAX,CAC2B,mBAAhB6T,KAA6BA,EAAc7T,GACxB,mBAAnB8T,KAAgCA,EAAiBnf,EAAMmD,SAASnD,EAAMuE,IAAI8G,EAAMgR,IAG3F,IAAIuc,GAAmC,UAAnB3P,EAAQ/hB,QAAuBmE,EAAMmT,QAAQlT,EAAItL,EAAMsL,IAAID,EAAMgR,EACrF+C,GAAQze,MACJ0I,IAAKJ,EAAOI,IACZR,MAAO+vB,EACPzvB,MAAOA,EAAMF,EAAOA,EAAOyV,aAC3Bma,aAAcxtB,EAAMmT,UAGpBsa,GAAyC,UAAnB7P,EAAQ/hB,UAChCyxB,GAAYC,MAItBxZ,EAAQhM,UAGJgM,EAAQ9f,OAAS,EAAG,CACpB,GAAI+f,GAASrf,EAAM6X,SAASzU,OAAOtE,EAAE6C,QACZ8E,EAAmB,IAC5C2Y,GAAQ1Y,QAAQ,SAASuC,EAAO/I,GAI5Bmf,EAASlZ,KAAKC,IAAIiZ,EAClB,IAAI0Z,GAAY5yB,KAAKC,IAAI6C,EAAO4vB,aAAa9hB,IACzCiiB,EAAW7yB,KAAKC,IAAI6C,EAAO4vB,aAAavtB,EAC5C,OAAK+T,IAAU0Z,GAAwBC,EAAWD,GAAtB1Z,OAExB5Y,EAAmBvG,GAFvB,SAMoB,MAApBuG,IACA2Y,EAAQ3Y,GAAkByC,WAAY,GAI1C4vB,GAAyC,UAAnB7P,EAAQ/hB,SAAuBkY,EAAQ9f,QAAU,GACvE8f,EAAQze,MACJ0I,IAAK4vB,EACLpwB,MAAO8vB,EACPvvB,OAAO,GAIf,IAAImW,GAAStH,EAAM/D,aAAalU,EAAMuE,IAAI2a,EAAY7C,IAElD/T,EAAiBiW,EAAiBlhB,QAAQiL,gBAEtB,YAApB2gB,EAAQ/hB,SAA4C,kBAApB+hB,EAAQ/hB,SAClCgyB,IACFA,EAAoB5wB,GAGxBA,EAAiB1K,GAAGib,OAAO,QAGvBqgB,IACA5wB,EAAiB4wB,EACjBA,EAAoB,MAI5B3a,EAAiBlhB,QACZwJ,eAAeqW,EAAK/P,YACpB7E,eAAeA,GACfhH,MAEGuH,MAAO0W,EACPtW,OAAQmW,MAIhBb,EAAiBvb,gBAAgBmc,KAIrCZ,EAAiB5gB,SAASkB,GAAG,kBAAkB,SAASC,GACpDmqB,EAAQ1M,oBAIZ5e,EAASkB,GAAG,cAAe,SAASC,GAEN,mBAAfA,GAAE6Z,UAA4BrX,EAAKhC,SAAWR,EAAE6Z,SAASrZ,SAChEgC,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,SAAW7Z,EAAE6Z,SAASzY,KAGjCuN,EAAMkL,SAAW7Z,EAAE6Z,UAGA,mBAAZ7Z,GAAEoI,QACT+hB,EAAQ/hB,MAAMpI,EAAEoI,OAChBA,EAAQpI,EAAEoI,OAGdlH,EAAM+P,aAKd3B,EAAYS,UAAU,gCACf7O,EA3cX,GAqBMuE,GACA+G,EAtBF2d,EAAU9rB,EAAGI,OAAOswB,cAClB5V,EAAQ9a,EAAGI,OAAOqW,OAClBuE,EAAQhb,EAAGI,OAAOqW,OAClBoK,EAAS7gB,EAAGI,OAAOygB,SACnBG,EAAWhhB,EAAGI,OAAOygB,SACrBO,EAAmBphB,EAAG+D,uBACtB7D,EAAUF,EAAGI,OAAOF,UAGtBkF,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9CqB,EAAQ,KACRC,EAAS,KACTqF,EAAQhM,EAAGG,MAAM6O,eACjB8R,GAAe,EACfF,GAAa,EACb/F,GAAY,EACZE,GAAY,EACZM,GAAkB,EAClB8F,GAA0B,EAC1Bwa,GAAqB,EACrBG,EAAa,QAGbxrB,EAAQtQ,EAAGG,MAAMmQ,QACjB4P,EAAe,KACfxK,EAAS,KACTlV,EAAWC,GAAGD,SAAS,cAAe,cAAc,aACpD2sB,EAAe,IACfgO,GAAkB,UAAU,SAAS,YACrC/N,KACAtlB,EAAW,GAGjBwI,GAAMvG,MAAQ+hB,EAAQ/hB,QACtB+Q,EAAMlE,OAAO,UAAUY,YAAY,GACnCwD,EAAMpE,OAAO,EAAoB,QAAU,QAE3C1W,EACKkL,gBAAgB,SAAS3D,EAAG1E,GACzB,MAAO+X,GAAM/D,aAAatP,EAAG1E,KAEhCoI,eAAe,SAAS1D,EAAG1E,GACxB,MAAOiY,GAAMjE,aAAatP,EAAG1E,KAGrCqe,EAAiBlhB,QACZkL,gBAAgB,SAAS3D,EAAG1E,GACzB,MAAO+X,GAAM/D,aAAatP,EAAG1E,KAEhCoI,eAAe,SAAS1D,EAAG1E,GACxB,MAAOiY,GAAMjE,aAAatP,EAAG1E,IAGrC,IAAIu4B,GAAiB,KACjBS,EAAoB,IAExB/a,GAASyB,aAAY,EAMrB,IAAIxR,GAAcjR,EAAGG,MAAM8Q,YAAYzQ,GACnCuJ,EAAQ+hB,EAAQ/hB,QAEhBkW,EAAc,SAAS9b,GACvB,MAAO,YACH,OACIzB,OAAQyB,EAAK+O,IAAI,SAASzL,GAAK,OAAQA,EAAE+T,WACzCzR,MAAO+hB,EAAQ/hB,WAKvBiW,EAAc,SAAS7b,GACvB,MAAO,UAASmM,GACQ1M,SAAhB0M,EAAMvG,QACNA,EAAQuG,EAAMvG,OACGnG,SAAjB0M,EAAM5N,QACNyB,EAAKoF,QAAQ,SAASuC,EAAO/I,GACzB+I,EAAO0P,UAAYlL,EAAM5N,OAAOK,OAK5Cw4B,EAAmB96B,GAAGib,OAAO,IAycjC,OA5EAoQ,GAAQtrB,SAASkB,GAAG,2BAA4B,SAASia,GACrDA,EAAIzN,MAAS,EAAI4d,EAAQ1kB,IAAIuU,EAAIzN,OACjCyN,EAAIzN,MAAS,EAAI4d,EAAQ3d,IAAIwN,EAAIzN,OACjChO,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7BgmB,EAAQtrB,SAASkB,GAAG,0BAA2B,SAASia,GACpDzb,EAAQ4F,QAAO,KAQnBjD,EAAMrC,SAAWA,EACjBqC,EAAMipB,QAAUA,EAChBjpB,EAAMge,OAASA,EACfhe,EAAMme,SAAWA,EACjBne,EAAMiY,MAAQA,EACdjY,EAAMmY,MAAQA,EACdnY,EAAMue,iBAAmBA,EACzBve,EAAM3C,QAAUA,EAEhB2C,EAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtE4Y,YAAa5S,IAAK,WAAW,MAAO4S,IAAc3S,IAAK,SAASjG,GAAG4Y,EAAW5Y,IAC9E6S,WAAiB7M,IAAK,WAAW,MAAO6M,IAAa5M,IAAK,SAASjG,GAAG6S,EAAU7S,IAChF+S,WAAe/M,IAAK,WAAW,MAAO+M,IAAa9M,IAAK,SAASjG,GAAG+S,EAAU/S,IAC9EkY,cAAkBlS,IAAK,WAAW,MAAOkS,IAAgBjS,IAAK,SAASjG,GAAGkY,EAAalY,IACvF0N,QAAY1H,IAAK,WAAW,MAAO0H,IAAUzH,IAAK,SAASjG,GAAG0N,EAAO1N,IACrE8Y,cAAkB9S,IAAK,WAAW,MAAO8S,IAAgB7S,IAAK,SAASjG,GAAG8Y,EAAa9Y,IACvFolB,eAAmBpf,IAAK,WAAW,MAAOof,IAAiBnf,IAAK,SAASjG,GAAGolB,EAAcplB,IAC1FmzB,gBAAoBntB,IAAK,WAAW,MAAOmtB,IAAkBltB,IAAK,SAASjG,GAAGmzB,EAAenzB,IAC7F2zB,oBAA0B3tB,IAAK,WAAW,MAAO2tB,IAAsB1tB,IAAK,SAASjG,GAAG2zB,EAAmB3zB,IAC3G8zB,YAAkB9tB,IAAK,WAAW,MAAO8tB,IAAc7tB,IAAK,SAASjG,GAAG8zB,EAAW9zB,IAGnF5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,OAE/DyC,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,GAClBgkB,EAAQhkB,SAASA,GACjBgT,EAAMhT,SAASA,GACfkT,EAAMlT,SAASA,KAEnBkE,OAASgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GACnDgE,EAAQhM,EAAGG,MAAM4O,SAAS/G,GAC1B6Y,EAAO7U,MAAMA,GACb8f,EAAQ9f,MAAMA,KAElBqP,iBAAkBrN,IAAK,WAAW,MAAOqN,IAAmBpN,IAAK,SAASjG,GACtEqT,EAAkBrT,EAClBgT,EAAMpE,OAAQyE,EAAkB,QAAU,UAE9C8F,yBAA0BnT,IAAK,WAAW,MAAOmT,IAA2BlT,IAAK,SAASjG,GACtFmZ,IAA4BnZ,EAC5BnF,EAAMmc,aAAahX,GACnBnF,EAAM6f,YAAY1a,GAClB8jB,EAAQ1E,QAAQpI,aAAahX,OAIrChI,EAAGG,MAAM6U,eAAenS,EAAOipB,GAC/B9rB,EAAGG,MAAMiO,YAAYvL,GAEdA,GAGX7C,EAAGI,OAAO47B,SAAW,WACjB,YA0CA,SAASn5B,GAAMoB,GAgIX,MA/HAgN,GAAYW,QACZ3N,EAAUC,KAAK,SAASC,GA4EpB,QAAS83B,GAAMx0B,GACXA,EAAEkS,GAAKlS,EAAEL,EACTK,EAAEy0B,IAAMz0B,EAAEgY,GA4Bd,QAAS0c,GAAa10B,GAClB,GAAI20B,GAAK37B,GAAGknB,YAAYvgB,EAAEgF,UAAW3E,EAAEL,EAAGK,EAAEL,EAAIK,EAAEgY,KAC9C4c,EAAK57B,GAAGknB,YAAYxZ,EAAE/B,UAAW3E,EAAE0G,EAAG,IACtCmuB,EAAK77B,GAAGknB,YAAYxZ,EAAE9B,SAAU5E,EAAE0G,EAAI,GAAK,EAAGykB,GAClD,OAAO,UAAUnrB,EAAG1E,GAChB,MAAOA,GACD,SAAU4R,GACZ,MAAO0e,GAAI5rB,IAET,SAAUkN,GAGZ,MAFAvN,GAAEgF,OAAOgwB,EAAGznB,IACZxG,EAAE/B,OAAOiwB,EAAG1nB,IAAItI,MAAMiwB,EAAG3nB,IAClB0e,EAAI5rB,KArHvBjB,EAAY/F,GAAGgG,OAAO3F,KACtB,IAGIktB,GAHAzoB,EAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,GAC9DwtB,EAAS5pB,KAAKF,IAAIvD,EAAgBC,GAAmB,CAGzDxF,GAAGG,MAAMiV,QAAQ5O,EAGjB,IAAII,GAAOJ,EAAUK,UAAU,wBAAwB1C,KAAKA,GACxD2C,EAAYF,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,qCAAuC6C,GAE1F4M,EAAI5P,EAAUD,UAAU,cAE5BD,GAAKK,KAAK,YAAa,aAAe1B,EAAiB,EAAI,IAAMC,EAAkB,EAAI,KAEvFgB,EAAU9E,GAAG,QAAS,SAAU+F,EAAG1E,GAC/BvC,EAAS+d,YACLpa,KAAMsD,EACNiB,MAAO3F,EACP4J,IAAKlM,GAAGmE,MACRkF,GAAIA,MAIZqE,EAAE9B,OAAO,EAAGumB,IAEZtoB,EAAOA,GAAQnG,EACfo4B,EAAWp4B,EAAK,GAChBq4B,EAAU9wB,MAAM+wB,EAAMC,IAASD,EAAa,OAC5CzO,EAAOtX,EAAEvS,KAAKq4B,EAAUG,OAAO51B,QAC1BC,OAAO,QACPC,KAAK,IAAKosB,GACVtpB,MAAM,OAAQ,SAAUtC,GACrB,MAAOuE,IAAOvE,EAAEm1B,SAAWn1B,EAAIA,EAAEo1B,QAAQx6B,QAE5C0H,MAAM,SAAU,QAChBrI,GAAG,QAAS,SAAS+F,GACdq1B,IAAaxyB,GAAQA,IAAS7C,IAAGq1B,EAAWxyB,GAChDA,EAAO7C,EACPumB,EAAK5gB,aACAtF,SAASA,GACTisB,UAAU,IAAKoI,EAAa10B,MAEpCvD,KAAK+3B,GACLv6B,GAAG,WAAY,SAAS+F,GACjBq1B,EAASD,QAAUp1B,GACnBumB,EAAK5gB,aACAtF,SAASA,GACTisB,UAAU,IAAKoI,EAAaI,MAGxCr4B,KAAK+3B,GACLv6B,GAAG,YAAa,SAAS+F,EAAE1E,GACxBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GAAMD,MAAM,UAAW,IACxDvJ,EAASyZ,kBACL9V,KAAMsD,EACNuE,MAAOvL,GAAGgG,OAAO3F,MAAMiJ,MAAM,YAGpCrI,GAAG,WAAY,SAAS+F,EAAE1E,GACvBtC,GAAGgG,OAAO3F,MAAMkJ,QAAQ,SAAS,GAAOD,MAAM,UAAW,GACzDvJ,EAASoF,iBACLzB,KAAMsD,MAGb/F,GAAG,YAAa,SAAS+F,EAAE1E,GACxBvC,EAAS0F,kBACL/B,KAAMsD,QAwDtBwJ,EAAYS,UAAU,sBACf7O,EApKX,GA0BIyH,GAAMwyB,EAENP,EA5BAn3B,GAAUE,IAAK,EAAGmQ,MAAO,EAAGD,OAAQ,EAAGnQ,KAAM,GAC3CqB,EAAQ,KACRC,EAAS,KACT+1B,EAAO,QACPD,GAASM,MAAO,SAASt1B,GAAK,MAAO,IAAM6G,KAAM,SAAS7G,GAAK,MAAOA,GAAE6G,OACxExE,EAAKd,KAAKyB,MAAsB,IAAhBzB,KAAK0B,UACrBlE,EAAY,KACZwF,EAAQhM,EAAGG,MAAM6O,eACjBlH,EAAW,IACXtH,EAAWC,GAAGD,SAAS,aAAc,eAAgB,kBAAmB,mBAAoB,mBAAoB,kBAAmB,aAGrI4G,EAAI3G,GAAGmH,MAAMC,SAASwE,OAAO,EAAG,EAAIrD,KAAKkP,KACzC/J,EAAI1N,GAAGmH,MAAMo1B,OAEbR,EAAY/7B,GAAGurB,OAAOwQ,YACrBloB,KAAK,MACL5I,MAAM,SAASjE,GAAK,MAAO,KAE5B4rB,EAAM5yB,GAAGoU,IAAIwe,MACZd,WAAW,SAAS9qB,GAAK,MAAOuB,MAAKL,IAAI,EAAGK,KAAKF,IAAI,EAAIE,KAAKkP,GAAI9Q,EAAEK,EAAEL,OACtEkrB,SAAS,SAAS7qB,GAAK,MAAOuB,MAAKL,IAAI,EAAGK,KAAKF,IAAI,EAAIE,KAAKkP,GAAI9Q,EAAEK,EAAEL,EAAIK,EAAEgY,QAC1EgT,YAAY,SAAShrB,GAAK,MAAOuB,MAAKL,IAAI,EAAGwF,EAAE1G,EAAE0G,MACjDmlB,YAAY,SAAS7rB,GAAK,MAAOuB,MAAKL,IAAI,EAAGwF,EAAE1G,EAAE0G,EAAI1G,EAAE2O,OAWxDnF,EAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAiKvC,OAxBAqC,GAAMrC,SAAWA,EACjBqC,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAE1CA,EAAMiL,SAAWrB,OAAOsB,WAEpBrH,OAAasH,IAAK,WAAW,MAAOtH,IAASuH,IAAK,SAASjG,GAAGtB,EAAMsB,IACpErB,QAAaqH,IAAK,WAAW,MAAOrH,IAAUsH,IAAK,SAASjG,GAAGrB,EAAOqB,IACtE00B,MAAa1uB,IAAK,WAAW,MAAO0uB,IAAQzuB,IAAK,SAASjG,GAAG00B,EAAK10B,IAClE8B,IAAakE,IAAK,WAAW,MAAOlE,IAAMmE,IAAK,SAASjG,GAAG8B,EAAG9B,IAC9DF,UAAakG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GAAGF,EAASE,IAG1E5C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAqB1B,QAAZoE,EAAE1C,IAAsB0C,EAAE1C,IAASF,EAAOE,IAC1DF,EAAOqQ,MAAqB7R,QAAZoE,EAAEyN,MAAsBzN,EAAEyN,MAASrQ,EAAOqQ,MAC1DrQ,EAAOoQ,OAAqB5R,QAAZoE,EAAEwN,OAAsBxN,EAAEwN,OAASpQ,EAAOoQ,OAC1DpQ,EAAOC,KAAqBzB,QAAZoE,EAAE3C,KAAsB2C,EAAE3C,KAASD,EAAOC,OAE9D2G,OAAQgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GAClDgE,EAAMhM,EAAGG,MAAM4O,SAAS/G,OAIhChI,EAAGG,MAAMiO,YAAYvL,GACdA,GAEX7C,EAAGI,OAAO68B,cAAgB,WACtB,YAqCA,SAASp6B,GAAMoB,GA6CX,MA5CAgN,GAAYW,QACZX,EAAY7Q,OAAO47B,GAEnB/3B,EAAUC,KAAK,SAASC,GACpB,GAAIqC,GAAY/F,GAAGgG,OAAO3F,KAC1Bd,GAAGG,MAAMiV,QAAQ5O,EAEjB,IACIjB,GAAiBvF,EAAGG,MAAMoF,eAAemB,EAAOF,EAAWpB,GAC3DI,EAAkBxF,EAAGG,MAAMqF,gBAAgBmB,EAAQH,EAAWpB,EAWlE,IATAvC,EAAM+P,OAAS,WACM,IAAb9K,EACAtB,EAAUrF,KAAK0B,GAEf2D,EAAU4G,aAAatF,SAASA,GAAU3G,KAAK0B,IAEvDA,EAAM2D,UAAY1F,MAGbqD,IAASA,EAAKhC,OAEf,MADAnC,GAAGG,MAAMuV,OAAO7S,EAAO2D,GAChB3D,CAEP2D,GAAUK,UAAU,cAAcc,QAItC,IAAIf,GAAOJ,EAAUK,UAAU,8BAA8B1C,KAAKA,GAC9DgX,EAASvU,EAAKG,QAAQC,OAAO,KAAKC,KAAK,QAAS,iCAAiCD,OAAO,KACxF0P,EAAI9P,EAAKH,OAAO,IAEpB0U,GAAOnU,OAAO,KAAKC,KAAK,QAAS,mBAEjCL,EAAKK,KAAK,YAAa,aAAe7B,EAAOC,KAAO,IAAMD,EAAOE,IAAM,KAGvE02B,EAASt1B,MAAMnB,GAAgBoB,OAAOnB,EACtC,IAAI03B,GAAUxmB,EAAEjQ,OAAO,oBAAoB8U,MAAMpX,EACjD1D,IAAG2M,WAAW8vB,GAAS/7B,KAAK66B,KAIhC/qB,EAAYS,UAAU,2BACf7O,EA5EX,GAAIm5B,GAAWh8B,EAAGI,OAAO47B,WACrB97B,EAAUF,EAAGI,OAAOF,UAEpBkF,GAAUE,IAAK,GAAImQ,MAAO,GAAID,OAAQ,GAAInQ,KAAM,IAC9CqB,EAAQ,KACRC,EAAS,KACTqF,EAAQhM,EAAGG,MAAM6O,eAEjBkR,GADKlX,KAAKuP,MAAsB,IAAhBvP,KAAK0B,UACN,MACfgL,EAAS,KACT5N,EAAW,IACXtH,EAAWC,GAAGD,SAAS,cAAe,cAAc,YAG1DN,GAAQ4H,SAAS,EAMjB,IAAImJ,GAAcjR,EAAGG,MAAM8Q,YAAYzQ,EAmHvC,OAlHAN,GACK6K,eAAc,GACdI,eAAe,SAAS1D,EAAG1E,GACxB,MAAO0E,KA2Dfu0B,EAASx7B,SAASkB,GAAG,2BAA4B,SAASia,GACtDA,EAAY,QACRzP,IAAKyP,EAAIxX,KAAK9B,KACdqJ,MAAOiQ,EAAIxX,KAAKmK,KAChBtC,MAAO2P,EAAI3P,OAEf9L,EAAQiE,KAAKwX,GAAK7V,QAAO,KAG7Bk2B,EAASx7B,SAASkB,GAAG,0BAA2B,SAASia,GACrDzb,EAAQ4F,QAAO,KAGnBk2B,EAASx7B,SAASkB,GAAG,2BAA4B,SAASia,GACtDzb,MAQJ2C,EAAMrC,SAAWA,EACjBqC,EAAMm5B,SAAWA,EACjBn5B,EAAM3C,QAAUA,EAChB2C,EAAM+K,QAAU5N,EAAGG,MAAM0N,YAAYjN,KAAKiC,GAG1CA,EAAMiL,SAAWrB,OAAOsB,WAEpB2H,QAAiB1H,IAAK,WAAW,MAAO0H,IAAkBzH,IAAK,SAASjG,GAAG0N,EAAO1N,IAClFkY,cAAiBlS,IAAK,WAAW,MAAOkS,IAAkBjS,IAAK,SAASjG,GAAGkY,EAAalY,IAGxFgE,OAAQgC,IAAK,WAAW,MAAOhC,IAASiC,IAAK,SAASjG,GAClDgE,EAAQhE,EACRg0B,EAAShwB,MAAMA,KAEnBlE,UAAWkG,IAAK,WAAW,MAAOlG,IAAYmG,IAAK,SAASjG,GACxDF,EAAWE,EACXiJ,EAAYW,MAAM9J,GAClBk0B,EAASl0B,SAASA,KAEtB1C,QAAS4I,IAAK,WAAW,MAAO5I,IAAU6I,IAAK,SAASjG,GACpD5C,EAAOE,IAAsB1B,SAAboE,EAAE1C,IAAuB0C,EAAE1C,IAASF,EAAOE,IAC3DF,EAAOqQ,MAAsB7R,SAAboE,EAAEyN,MAAuBzN,EAAEyN,MAASrQ,EAAOqQ,MAC3DrQ,EAAOoQ,OAAsB5R,SAAboE,EAAEwN,OAAuBxN,EAAEwN,OAASpQ,EAAOoQ,OAC3DpQ,EAAOC,KAAsBzB,SAAboE,EAAE3C,KAAuB2C,EAAE3C,KAASD,EAAOC,SAGnErF,EAAGG,MAAM6U,eAAenS,EAAOm5B,GAC/Bh8B,EAAGG,MAAMiO,YAAYvL,GACdA,GAGX7C,EAAGm9B,QAAU"} \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 000000000..e7e19e6d6 --- /dev/null +++ b/composer.json @@ -0,0 +1,32 @@ +{ + "name": "novus/nvd3", + "description": "A reusable charting library written in d3.js", + "keywords": [ + "nvd3", + "d3", + "chart", + "graph" + ], + "homepage": "https://github.com/novus/nvd3", + "license": "Apache-2.0", + "authors": [ + { + "name": "Bob Monteverde" + }, + { + "name": "Tyler Wolf" + }, + { + "name": "Robin Hu" + }, + { + "name": "Frank Shao" + }, + { + "name": "liquidpele" + } + ], + "require": { + "mbostock/d3": "@stable" + } +} \ No newline at end of file diff --git a/examples/TimeSeries.html b/examples/TimeSeries.html new file mode 100644 index 000000000..c7fc946f8 --- /dev/null +++ b/examples/TimeSeries.html @@ -0,0 +1,236 @@ + + + + + + + + + + + + + + +
(affects the x axis ticks and the bar spacing)
+ +
+ +
+ +
+
+ +
+ + + + \ No newline at end of file diff --git a/examples/boxPlot.html b/examples/boxPlot.html new file mode 100644 index 000000000..0c7f15cb0 --- /dev/null +++ b/examples/boxPlot.html @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/bulletChart.html b/examples/bulletChart.html index 7a96c220d..09ee731d1 100644 --- a/examples/bulletChart.html +++ b/examples/bulletChart.html @@ -54,10 +54,10 @@ "subtitle":"US$, in thousands", "ranges":[150,225,300], "measures":[220], - "markers":[250], + "markers":[250, 100], + "markerLabels":['Target Inventory', 'Low Inventory'], "rangeLabels":['Maximum Inventory','Average Inventory','Minimum Inventory'], - "measureLabels":['Current Inventory'], - "markerLabels":['Target Inventory'] + "measureLabels":['Current Inventory'] }]; //TODO: to be consistent with other models, should be appending a g to an already made svg, not creating the svg element diff --git a/examples/candlestick.html b/examples/candlestick.html new file mode 100644 index 000000000..a40dcd6a1 --- /dev/null +++ b/examples/candlestick.html @@ -0,0 +1,121 @@ + + + + + + + + + + + + +
+ +
+ + + + diff --git a/examples/candlestickChart.html b/examples/candlestickChart.html new file mode 100644 index 000000000..7035d8fc9 --- /dev/null +++ b/examples/candlestickChart.html @@ -0,0 +1,139 @@ + + + + + + + + + + + + +
+ +
+ + + + diff --git a/examples/discreteBarChart.html b/examples/discreteBarChart.html index b377c1a26..b238763cf 100644 --- a/examples/discreteBarChart.html +++ b/examples/discreteBarChart.html @@ -75,7 +75,6 @@ .y(function(d) { return d.value }) .staggerLabels(true) //.staggerLabels(historicalBarChart[0].values.length > 8) - .tooltips(false) .showValues(true) .duration(250) ; diff --git a/examples/documentation.html b/examples/documentation.html index 69b11005f..9d745b427 100644 --- a/examples/documentation.html +++ b/examples/documentation.html @@ -17,7 +17,7 @@ - \ No newline at end of file + diff --git a/examples/donutChart.html b/examples/donutChart.html index 90045a967..1ba8c523a 100644 --- a/examples/donutChart.html +++ b/examples/donutChart.html @@ -3,7 +3,7 @@ - + @@ -15,9 +15,16 @@ svg { display: block; float: left; - height: 350px; - width: 350px; } + #test2 { + height: 350px !important; + width: 350px !important; + } + #test1 { + height: 350px !important; + width: 350px !important; + } + html, body { margin: 0px; padding: 0px; @@ -30,7 +37,6 @@ } .nvd3.nv-pie.nv-chart-donut1 .nv-pie-title { - font-size: 45px; opacity: 0.4; fill: rgba(224, 116, 76, 0.91); } @@ -43,6 +49,8 @@ + + - \ No newline at end of file + diff --git a/examples/furiousLegend.html b/examples/furiousLegend.html new file mode 100644 index 000000000..107191246 --- /dev/null +++ b/examples/furiousLegend.html @@ -0,0 +1,110 @@ + + + + + + + + + + + +

Legend 1

+ + + +

Legend 2

+

Setting align(false)

+ + +

Legend 3

+

Setting legend padding distance

+ + + + + \ No newline at end of file diff --git a/examples/index.html b/examples/index.html index e82851ccc..d24da6930 100644 --- a/examples/index.html +++ b/examples/index.html @@ -104,6 +104,7 @@

NVD3 Examples List

  • Horizon
  • Indentedtree
  • Legend +
  • Furious Legend
  • Line
  • LineChart
  • LineChartSVGResize diff --git a/examples/legend.html b/examples/legend.html index d4f0f932b..106898005 100644 --- a/examples/legend.html +++ b/examples/legend.html @@ -12,61 +12,95 @@ } svg { display: block; + } html, body, svg { margin: 0px; padding: 0px; - height: 100%; width: 100%; } +

    Legend 1

    + + + +

    Legend 2

    +

    Setting align(false)

    + - +

    Legend 3

    +

    Setting legend padding distance

    + \ No newline at end of file diff --git a/examples/line.html b/examples/line.html index c0ee22cb4..c2e1a3e4f 100644 --- a/examples/line.html +++ b/examples/line.html @@ -89,7 +89,8 @@ { values: cos, key: "Cosine Wave", - color: "#2ca02c" + color: "#2ca02c", + strokeWidth: 3 } ]; } diff --git a/examples/lineChart.html b/examples/lineChart.html index 2a43d87d3..edda830fe 100644 --- a/examples/lineChart.html +++ b/examples/lineChart.html @@ -19,15 +19,39 @@ height: 100%; width: 100%; } + + .dashed { + stroke-dasharray: 5,5; + } - +
    + + + +
    - \ No newline at end of file + diff --git a/examples/lineWithFocusChart_x2AxisLabel.html b/examples/lineWithFocusChart_x2AxisLabel.html new file mode 100644 index 000000000..3c7dcc846 --- /dev/null +++ b/examples/lineWithFocusChart_x2AxisLabel.html @@ -0,0 +1,67 @@ + + + + + + + + + + + + + +
    + +
    + + + + diff --git a/examples/monitoringChart.html b/examples/monitoringChart.html new file mode 100644 index 000000000..38d60b204 --- /dev/null +++ b/examples/monitoringChart.html @@ -0,0 +1,182 @@ + + + + + + + + + + + + + + + + + + diff --git a/examples/multiBarChart2.html b/examples/multiBarChart2.html index 98ab489c4..b63f4f85f 100644 --- a/examples/multiBarChart2.html +++ b/examples/multiBarChart2.html @@ -33,11 +33,11 @@ //var test_data = stream_layers(3,128,.1).map(function(data, i) { var test_data = stream_layers(3,128,.1).map(function(data, i) { return { - key: 'Stream' + i, + key: (i == 1) ? 'Non-stackable Stream' + i: 'Stream' + i, + nonStackable: (i == 1), values: data }; }); - nv.addGraph({ generate: function() { var width = nv.utils.windowSize().width, diff --git a/examples/multiBarHorizontalChart.html b/examples/multiBarHorizontalChart.html index 2b3ec1c63..f223a4095 100644 --- a/examples/multiBarHorizontalChart.html +++ b/examples/multiBarHorizontalChart.html @@ -33,7 +33,6 @@ var long_short_data = [ { key: 'Series1', - color: '#d62728', values: [ { "label" : "Group A" , @@ -57,25 +56,24 @@ } , { "label" : "Group F" , - "value" : -0.77154485523777 + "value" : -2.77154485523777 } , { "label" : "Group G" , - "value" : -0.90152097798131 + "value" : -9.90152097798131 } , { "label" : "Group H" , - "value" : -0.91445417330854 + "value" : 14.91445417330854 } , { "label" : "Group I" , - "value" : -0.055746319141851 + "value" : -3.055746319141851 } ] }, { key: 'Series2', - color: '#1f77b4', values: [ { "label" : "Group A" , @@ -103,25 +101,24 @@ } , { "label" : "Group G" , - "value" : 0.30947953487127 + "value" : 7.0947953487127 } , { "label" : "Group H" , - "value" : 0 + "value" : 8 } , { "label" : "Group I" , - "value" : 0 + "value" : 21 } ] }, { key: 'Series3', - color: '#2ca02c', values: [ { "label" : "Group A" , - "value" : -25.307646510375 + "value" : -14.307646510375 } , { "label" : "Group B" , @@ -141,7 +138,7 @@ } , { "label" : "Group F" , - "value" : 5.259101026956 + "value" : 15.259101026956 } , { "label" : "Group G" , @@ -168,10 +165,14 @@ .yErr(function(d) { return [-Math.abs(d.value * Math.random() * 0.3), Math.abs(d.value * Math.random() * 0.3)] }) .barColor(d3.scale.category20().range()) .duration(250) + .margin({left: 100}) .stacked(true); chart.yAxis.tickFormat(d3.format(',.2f')); + chart.yAxis.axisLabel('Y Axis'); + chart.xAxis.axisLabel('X Axis').axisLabelDistance(20); + d3.select('#chart1 svg') .datum(long_short_data) .call(chart); diff --git a/examples/multiChart.html b/examples/multiChart.html index 7a29e857e..451d3dec9 100644 --- a/examples/multiChart.html +++ b/examples/multiChart.html @@ -30,7 +30,7 @@ - \ No newline at end of file + diff --git a/examples/parallelCoordinates.html b/examples/parallelCoordinates.html index abe5eaf50..f54f9f093 100644 --- a/examples/parallelCoordinates.html +++ b/examples/parallelCoordinates.html @@ -34,10 +34,10 @@ nv.addGraph(function() { chart = nv.models.parallelCoordinates() - .dimensions(["economy (mpg)", "cylinders", "displacement (cc)", "power (hp)", "weight (lb)", "0-60 mph (s)", "year"]); - - // make all lines the same color like this - //chart.color(['steelblue']); + .dimensionNames(["economy (mpg)", "cylinders", "displacement (cc)", "power (hp)", "weight (lb)", "0-60 mph (s)", "year"]) + .dimensionFormats(["0.5f", "e", "g", "d", "", "%", "p"]) + .lineTension(0.85); + d3.select('#chart1 svg') .datum(data()) diff --git a/examples/parallelCoordinatesChart.html b/examples/parallelCoordinatesChart.html new file mode 100644 index 000000000..a24f5513a --- /dev/null +++ b/examples/parallelCoordinatesChart.html @@ -0,0 +1,231 @@ + + + + + + + + + + + +
    + + +
    + + + + + + diff --git a/examples/pie.html b/examples/pie.html index 754f81371..781320a25 100644 --- a/examples/pie.html +++ b/examples/pie.html @@ -11,7 +11,7 @@ text { font: 12px sans-serif; } - svg { + .testBlock { display: block; float: left; height: 300px; @@ -27,8 +27,8 @@ - - +
    +
    \ No newline at end of file diff --git a/examples/stylesheets/styles.css b/examples/stylesheets/styles.css index 8fba3d546..8570a335c 100644 --- a/examples/stylesheets/styles.css +++ b/examples/stylesheets/styles.css @@ -553,6 +553,7 @@ h3.option { padding-left: 10px; border-top: 5px solid #CCC; margin-top: 10px; + min-height: 24px; } h3 .expand { font-size: 14px; diff --git a/examples/sunburst.html b/examples/sunburst.html new file mode 100644 index 000000000..431cbeab8 --- /dev/null +++ b/examples/sunburst.html @@ -0,0 +1,426 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/tooltip.html b/examples/tooltip.html new file mode 100644 index 000000000..b701a9087 --- /dev/null +++ b/examples/tooltip.html @@ -0,0 +1,112 @@ + + + + + + + + + + + + +
    +
    +
    +
    + + + + + +
    +
    +
    +
    +
    +
    +
    + + +
    +
    +
    + + + \ No newline at end of file diff --git a/index.html b/index.html index 786e2efe1..d404e2004 100644 --- a/index.html +++ b/index.html @@ -12,8 +12,8 @@ // force https to avoid stupid mixed content stuff. // don't force just http because http-everywhere plugins cause infinite redirect loop // can't use relative links because they break when loading the site locally on disk (browsers suck) - if (window.location.protocol == "http:") - window.location.href = "https:" + window.location.href.substring(window.location.protocol.length); + // if (window.location.protocol == "http:") + // window.location.href = "https:" + window.location.href.substring(window.location.protocol.length); diff --git a/meteor/export.js b/meteor/export.js new file mode 100644 index 000000000..dc7387f62 --- /dev/null +++ b/meteor/export.js @@ -0,0 +1,4 @@ +/*global nv:true*/ // Meteor creates a file-scope global for exporting. This comment prevents a potential JSHint warning. +nv = window.nv; +delete window.nv; + diff --git a/package.js b/package.js new file mode 100644 index 000000000..5938969ba --- /dev/null +++ b/package.js @@ -0,0 +1,24 @@ +// Package metadata for Meteor.js full stack web framework +// This file is defined in Meteor documentation at http://docs.meteor.com/#/full/packagejs +// and used by Meteor https://www.meteor.com/ and its package repository Atmosphere https://atmospherejs.com + +Package.describe({ + "name": 'nvd3:nvd3', + summary: 'Nvd3.org charts.', + version: '1.8.1-dev', + git: "https://github.com/novus/nvd3.git" +}); +Package.on_use(function (api) { + api.versionsFrom("METEOR@1.0"); + api.use('d3js:d3@3.5.5', 'client'); + api.add_files('build/nv.d3.js', 'client'); + api.add_files('build/nv.d3.css', 'client'); + api.add_files('meteor/export.js', 'client'); + api.export("nv"); +}); +Package.onTest(function(api) { + api.use(['tinytest', 'test-helpers']); + api.use('d3js:d3', 'client'); + api.addFiles(['build/nv.d3.js', 'meteor/export.js'], "client"); + api.addFiles('test/tinytest/nv-is-defined-test.js', "client"); +}); diff --git a/package.json b/package.json index e8970c208..b28c8202e 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,22 @@ { "name": "nvd3", - "version": "1.7.1", + "version": "1.8.1-dev", + "description": "A reusable charting library written in d3.js", + "url": "https://github.com/novus/nvd3", + "main": "build/nv.d3.js", "scripts": { "test": "grunt" }, + "repository": { + "type": "git", + "url": "https://github.com/novus/nvd3" + }, + "keywords": ["nvd3", "d3", "chart", "graph"], + "readmeFilename": "README.md", + "license": "Apache-2.0", + "peerDependencies": { + "d3": "^3.4.4" + }, "devDependencies": { "grunt": "~0.4.1", "grunt-contrib-uglify": "~0.2.0" diff --git a/src/core.js b/src/core.js index b0b69a5f4..2dbd40a85 100755 --- a/src/core.js +++ b/src/core.js @@ -1,7 +1,6 @@ -// set up main nv object on window -var nv = window.nv || {}; -window.nv = nv; +// set up main nv object +var nv = {}; // the major global objects under the nv namespace nv.dev = false; //set false when in production @@ -9,8 +8,8 @@ nv.tooltip = nv.tooltip || {}; // For the tooltip system nv.utils = nv.utils || {}; // Utility subsystem nv.models = nv.models || {}; //stores all the possible models/components nv.charts = {}; //stores all the ready to use charts -nv.graphs = []; //stores all the graphs currently on the page nv.logs = {}; //stores some statistics and potential error messages +nv.dom = {}; //DOM manipulation functions nv.dispatch = d3.dispatch('render_start', 'render_end'); @@ -70,14 +69,15 @@ nv.log = function() { }; // print console warning, should be used by deprecated functions -nv.deprecated = function(name) { - if (nv.dev && console && console.warn) { - console.warn('`' + name + '` has been deprecated.'); +nv.deprecated = function(name, info) { + if (console && console.warn) { + console.warn('nvd3 warning: `' + name + '` has been deprecated. ', info || ''); } }; -// render function is used to queue up chart rendering -// in non-blocking timeout functions +// The nv.render function is used to queue up chart rendering +// in non-blocking async functions. +// When all queued charts are done rendering, nv.dispatch.render_end is invoked. nv.render = function render(step) { // number of graphs to generate in each timeout loop step = step || 1; @@ -85,29 +85,48 @@ nv.render = function render(step) { nv.render.active = true; nv.dispatch.render_start(); - setTimeout(function() { + var renderLoop = function() { var chart, graph; for (var i = 0; i < step && (graph = nv.render.queue[i]); i++) { chart = graph.generate(); if (typeof graph.callback == typeof(Function)) graph.callback(chart); - nv.graphs.push(chart); } nv.render.queue.splice(0, i); - if (nv.render.queue.length) setTimeout(arguments.callee, 0); + if (nv.render.queue.length) { + setTimeout(renderLoop); + } else { nv.dispatch.render_end(); nv.render.active = false; } - }, 0); + }; + + setTimeout(renderLoop); }; nv.render.active = false; nv.render.queue = []; -// main function to use when adding a new graph, see examples +/* +Adds a chart to the async rendering queue. This method can take arguments in two forms: +nv.addGraph({ + generate: + callback: +}) + +or + +nv.addGraph(, ) + +The generate function should contain code that creates the NVD3 model, sets options +on it, adds data to an SVG element, and invokes the chart model. The generate function +should return the chart model. See examples/lineChart.html for a usage example. + +The callback function is optional, and it is called when the generate function completes. +*/ nv.addGraph = function(obj) { if (typeof arguments[0] === typeof(Function)) { obj = {generate: arguments[0], callback: arguments[1]}; @@ -118,4 +137,13 @@ nv.addGraph = function(obj) { if (!nv.render.active) { nv.render(); } -}; \ No newline at end of file +}; + +// Node/CommonJS exports +if (typeof(module) !== 'undefined' && typeof(exports) !== 'undefined') { + module.exports = nv; +} + +if (typeof(window) !== 'undefined') { + window.nv = nv; +} diff --git a/src/css/axis.css b/src/css/axis.css new file mode 100644 index 000000000..676f61ee8 --- /dev/null +++ b/src/css/axis.css @@ -0,0 +1,44 @@ +.nvd3 .nv-axis { + pointer-events:none; + opacity: 1; +} + +.nvd3 .nv-axis path { + fill: none; + stroke: #000; + stroke-opacity: .75; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis path.domain { + stroke-opacity: .75; +} + +.nvd3 .nv-axis.nv-x path.domain { + stroke-opacity: 0; +} + +.nvd3 .nv-axis line { + fill: none; + stroke: #e5e5e5; + shape-rendering: crispEdges; +} + +.nvd3 .nv-axis .zero line, + /*this selector may not be necessary*/ .nvd3 .nv-axis line.zero { + stroke-opacity: .75; +} + +.nvd3 .nv-axis .nv-axisMaxMin text { + font-weight: bold; +} + +.nvd3 .x .nv-axis .nv-axisMaxMin text, +.nvd3 .x2 .nv-axis .nv-axisMaxMin text, +.nvd3 .x3 .nv-axis .nv-axisMaxMin text { + text-anchor: middle +} + +.nvd3 .nv-axis.nv-disabled { + opacity: 0; +} diff --git a/src/css/bars.css b/src/css/bars.css new file mode 100644 index 000000000..ee440fe40 --- /dev/null +++ b/src/css/bars.css @@ -0,0 +1,47 @@ +.nvd3 .nv-bars rect { + fill-opacity: .75; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-bars rect.hover { + fill-opacity: 1; +} + +.nvd3 .nv-bars .hover rect { + fill: lightblue; +} + +.nvd3 .nv-bars text { + fill: rgba(0,0,0,0); +} + +.nvd3 .nv-bars .hover text { + fill: rgba(0,0,0,1); +} + +.nvd3 .nv-multibar .nv-groups rect, +.nvd3 .nv-multibarHorizontal .nv-groups rect, +.nvd3 .nv-discretebar .nv-groups rect { + stroke-opacity: 0; + + transition: fill-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear; +} + +.nvd3 .nv-multibar .nv-groups rect:hover, +.nvd3 .nv-multibarHorizontal .nv-groups rect:hover, +.nvd3 .nv-candlestickBar .nv-ticks rect:hover, +.nvd3 .nv-discretebar .nv-groups rect:hover { + fill-opacity: 1; +} + +.nvd3 .nv-discretebar .nv-groups text, +.nvd3 .nv-multibarHorizontal .nv-groups text { + font-weight: bold; + fill: rgba(0,0,0,1); + stroke: rgba(0,0,0,0); +} diff --git a/src/css/boxplot.css b/src/css/boxplot.css new file mode 100644 index 000000000..70f42e75a --- /dev/null +++ b/src/css/boxplot.css @@ -0,0 +1,20 @@ +/* boxplot CSS */ +.nvd3 .nv-boxplot circle { + fill-opacity: 0.5; +} + +.nvd3 .nv-boxplot circle:hover { + fill-opacity: 1; +} + +.nvd3 .nv-boxplot rect:hover { + fill-opacity: 1; +} + +.nvd3 line.nv-boxplot-median { + stroke: black; +} + +.nv-boxplot-tick:hover { + stroke-width: 2.5px; +} \ No newline at end of file diff --git a/src/css/bullet.css b/src/css/bullet.css new file mode 100644 index 000000000..70c9ab1ec --- /dev/null +++ b/src/css/bullet.css @@ -0,0 +1,21 @@ +/* bullet */ +.nvd3.nv-bullet { font: 10px sans-serif; } +.nvd3.nv-bullet .nv-measure { fill-opacity: .8; } +.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } +.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } +.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } +.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } +.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } +.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } +.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } +.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } +.nvd3.nv-bullet .nv-subtitle { fill: #999; } + + +.nvd3.nv-bullet .nv-range { + fill: #bababa; + fill-opacity: .4; +} +.nvd3.nv-bullet .nv-range:hover { + fill-opacity: .7; +} diff --git a/src/css/candlestick.css b/src/css/candlestick.css new file mode 100644 index 000000000..2a25ed785 --- /dev/null +++ b/src/css/candlestick.css @@ -0,0 +1,29 @@ +.nvd3.nv-candlestickBar .nv-ticks .nv-tick { + stroke-width: 1px; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.hover { + stroke-width: 2px; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.positive rect { + stroke: #2ca02c; + fill: #2ca02c; +} + +.nvd3.nv-candlestickBar .nv-ticks .nv-tick.negative rect { + stroke: #d62728; + fill: #d62728; +} + +.with-transitions .nv-candlestickBar .nv-ticks .nv-tick { + transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-candlestickBar .nv-ticks line { + stroke: #333; +} + diff --git a/src/css/furiousLegend.css b/src/css/furiousLegend.css new file mode 100644 index 000000000..9ddf5ebfb --- /dev/null +++ b/src/css/furiousLegend.css @@ -0,0 +1,22 @@ +.nvd3 .nv-legend .nv-disabled rect { + /*fill-opacity: 0;*/ +} + +.nvd3 .nv-check-box .nv-box { + fill-opacity:0; + stroke-width:2; +} + +.nvd3 .nv-check-box .nv-check { + fill-opacity:0; + stroke-width:4; +} + +.nvd3 .nv-series.nv-disabled .nv-check-box .nv-check { + fill-opacity:0; + stroke-opacity:0; +} + +.nvd3 .nv-controlsWrap .nv-legend .nv-check-box .nv-check { + opacity: 0; +} diff --git a/src/css/lineplusbar.css b/src/css/lineplusbar.css new file mode 100644 index 000000000..84b06356f --- /dev/null +++ b/src/css/lineplusbar.css @@ -0,0 +1,8 @@ +/* line plus bar */ +.nvd3.nv-linePlusBar .nv-bar rect { + fill-opacity: .75; +} + +.nvd3.nv-linePlusBar .nv-bar rect:hover { + fill-opacity: 1; +} \ No newline at end of file diff --git a/src/css/lines.css b/src/css/lines.css new file mode 100644 index 000000000..6db5b1ed3 --- /dev/null +++ b/src/css/lines.css @@ -0,0 +1,46 @@ +.nvd3 .nv-groups path.nv-line { + fill: none; +} + +.nvd3 .nv-groups path.nv-area { + stroke: none; +} + +.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { + fill-opacity: .5 !important; + stroke-opacity: .5 !important; +} + + +.with-transitions .nvd3 .nv-groups .nv-point { + transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-scatter .nv-groups .nv-point.hover, +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 7px; + fill-opacity: .95 !important; + stroke-opacity: .95 !important; +} + + +.nvd3 .nv-point-paths path { + stroke: #aaa; + stroke-opacity: 0; + fill: #eee; + fill-opacity: 0; +} + + + +.nvd3 .nv-indexLine { + cursor: ew-resize; +} diff --git a/src/css/main.css b/src/css/main.css new file mode 100644 index 000000000..d96eacb0c --- /dev/null +++ b/src/css/main.css @@ -0,0 +1,91 @@ +/******************** + * SVG CSS + */ + +/******************** + Default CSS for an svg element nvd3 used +*/ +svg.nvd3-svg { + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -ms-user-select: none; + -moz-user-select: none; + user-select: none; + display: block; + width:100%; + height:100%; +} + +/******************** + Box shadow and border radius styling +*/ +.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip { + -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); + -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); + box-shadow: 0 5px 10px rgba(0,0,0,.2); + + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} + + +.nvd3 text { + font: normal 12px Arial; +} + +.nvd3 .title { + font: bold 14px Arial; +} + +.nvd3 .nv-background { + fill: white; + fill-opacity: 0; +} + +.nvd3.nv-noData { + font-size: 18px; + font-weight: bold; +} + + +/********** +* Brush +*/ + +.nv-brush .extent { + fill-opacity: .125; + shape-rendering: crispEdges; +} + +.nv-brush .resize path { + fill: #eee; + stroke: #666; +} + + +/********** +* Legend +*/ + +.nvd3 .nv-legend .nv-series { + cursor: pointer; +} + +.nvd3 .nv-legend .nv-disabled circle { + fill-opacity: 0; +} + +/* focus */ +.nvd3 .nv-brush .extent { + fill-opacity: 0 !important; +} + +.nvd3 .nv-brushBackground rect { + stroke: #000; + stroke-width: .4; + fill: #fff; + fill-opacity: .7; +} + diff --git a/src/css/ohlc.css b/src/css/ohlc.css new file mode 100644 index 000000000..8ed864b1c --- /dev/null +++ b/src/css/ohlc.css @@ -0,0 +1,16 @@ +.nvd3.nv-ohlcBar .nv-ticks .nv-tick { + stroke-width: 1px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { + stroke-width: 2px; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { + stroke: #2ca02c; +} + +.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { + stroke: #d62728; +} + diff --git a/src/css/parallelcoordinates.css b/src/css/parallelcoordinates.css new file mode 100644 index 000000000..146ae34d3 --- /dev/null +++ b/src/css/parallelcoordinates.css @@ -0,0 +1,33 @@ +.nvd3 .background path { + fill: none; + stroke: #EEE; + stroke-opacity: .4; + shape-rendering: crispEdges; +} + +.nvd3 .foreground path { + fill: none; + stroke-opacity: .7; +} + +.nvd3 .nv-parallelCoordinates-brush .extent +{ + fill: #fff; + fill-opacity: .6; + stroke: gray; + shape-rendering: crispEdges; +} + +.nvd3 .nv-parallelCoordinates .hover { + fill-opacity: 1; + stroke-width: 3px; +} + + +.nvd3 .missingValuesline line { + fill: none; + stroke: black; + stroke-width: 1; + stroke-opacity: 1; + stroke-dasharray: 5, 5; +} \ No newline at end of file diff --git a/src/css/pie.css b/src/css/pie.css new file mode 100644 index 000000000..5c8473e08 --- /dev/null +++ b/src/css/pie.css @@ -0,0 +1,37 @@ +.nvd3.nv-pie path { + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; + +} + +.nvd3.nv-pie .nv-pie-title { + font-size: 24px; + fill: rgba(19, 196, 249, 0.59); +} + +.nvd3.nv-pie .nv-slice text { + stroke: #000; + stroke-width: 0; +} + +.nvd3.nv-pie path { + stroke: #fff; + stroke-width: 1px; + stroke-opacity: 1; +} + +.nvd3.nv-pie path { + fill-opacity: .7; +} +.nvd3.nv-pie .hover path { + fill-opacity: 1; +} +.nvd3.nv-pie .nv-label { + pointer-events: none; +} +.nvd3.nv-pie .nv-label rect { + fill-opacity: 0; + stroke-opacity: 0; +} diff --git a/src/css/scatter.css b/src/css/scatter.css new file mode 100644 index 000000000..75d33b894 --- /dev/null +++ b/src/css/scatter.css @@ -0,0 +1,16 @@ +/* scatter */ +.nvd3 .nv-groups .nv-point.hover { + stroke-width: 20px; + stroke-opacity: .5; +} + +.nvd3 .nv-scatter .nv-point.hover { + fill-opacity: 1; +} +.nv-noninteractive { + pointer-events: none; +} + +.nv-distx, .nv-disty { + pointer-events: none; +} diff --git a/src/css/sparkline.css b/src/css/sparkline.css new file mode 100644 index 000000000..6c5c1cc48 --- /dev/null +++ b/src/css/sparkline.css @@ -0,0 +1,49 @@ +/* sparkline */ +.nvd3.nv-sparkline path { + fill: none; +} + +.nvd3.nv-sparklineplus g.nv-hoverValue { + pointer-events: none; +} + +.nvd3.nv-sparklineplus .nv-hoverValue line { + stroke: #333; + stroke-width: 1.5px; +} + +.nvd3.nv-sparklineplus, +.nvd3.nv-sparklineplus g { + pointer-events: all; +} + +.nvd3 .nv-hoverArea { + fill-opacity: 0; + stroke-opacity: 0; +} + +.nvd3.nv-sparklineplus .nv-xValue, +.nvd3.nv-sparklineplus .nv-yValue { + stroke-width: 0; + font-size: .9em; + font-weight: normal; +} + +.nvd3.nv-sparklineplus .nv-yValue { + stroke: #f66; +} + +.nvd3.nv-sparklineplus .nv-maxValue { + stroke: #2ca02c; + fill: #2ca02c; +} + +.nvd3.nv-sparklineplus .nv-minValue { + stroke: #d62728; + fill: #d62728; +} + +.nvd3.nv-sparklineplus .nv-currentValue { + font-weight: bold; + font-size: 1.1em; +} \ No newline at end of file diff --git a/src/css/stackedarea.css b/src/css/stackedarea.css new file mode 100644 index 000000000..cbf4bcc67 --- /dev/null +++ b/src/css/stackedarea.css @@ -0,0 +1,18 @@ +/* stacked area */ +.nvd3.nv-stackedarea path.nv-area { + fill-opacity: .7; + stroke-opacity: 0; + transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; + -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; +} + +.nvd3.nv-stackedarea path.nv-area.hover { + fill-opacity: .9; +} + + +.nvd3.nv-stackedarea .nv-groups .nv-point { + stroke-opacity: 0; + fill-opacity: 0; +} \ No newline at end of file diff --git a/src/css/tooltip.css b/src/css/tooltip.css new file mode 100644 index 000000000..daffa6368 --- /dev/null +++ b/src/css/tooltip.css @@ -0,0 +1,139 @@ + + +.nvtooltip { + position: absolute; + background-color: rgba(255,255,255,1.0); + color: rgba(0,0,0,1.0); + padding: 1px; + border: 1px solid rgba(0,0,0,.2); + z-index: 10000; + display: block; + + font-family: Arial; + font-size: 13px; + text-align: left; + pointer-events: none; + + white-space: nowrap; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.nvtooltip { + background: rgba(255,255,255, 0.8); + border: 1px solid rgba(0,0,0,0.5); + border-radius: 4px; +} + +/*Give tooltips that old fade in transition by + putting a "with-transitions" class on the container div. +*/ +.nvtooltip.with-transitions, .with-transitions .nvtooltip { + transition: opacity 50ms linear; + -moz-transition: opacity 50ms linear; + -webkit-transition: opacity 50ms linear; + + transition-delay: 200ms; + -moz-transition-delay: 200ms; + -webkit-transition-delay: 200ms; +} + +.nvtooltip.x-nvtooltip, +.nvtooltip.y-nvtooltip { + padding: 8px; +} + +.nvtooltip h3 { + margin: 0; + padding: 4px 14px; + line-height: 18px; + font-weight: normal; + background-color: rgba(247,247,247,0.75); + color: rgba(0,0,0,1.0); + text-align: center; + + 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; +} + +.nvtooltip p { + margin: 0; + padding: 5px 14px; + text-align: center; +} + +.nvtooltip span { + display: inline-block; + margin: 2px 0; +} + +.nvtooltip table { + margin: 6px; + border-spacing:0; +} + + +.nvtooltip table td { + padding: 2px 9px 2px 0; + vertical-align: middle; +} + +.nvtooltip table td.key { + font-weight: normal; +} +.nvtooltip table td.key.total { + font-weight: bold; +} +.nvtooltip table td.value { + text-align: right; + font-weight: bold; +} + +.nvtooltip table tr.highlight td { + padding: 1px 9px 1px 0; + border-bottom-style: solid; + border-bottom-width: 1px; + border-top-style: solid; + border-top-width: 1px; +} + +.nvtooltip table td.legend-color-guide div { + width: 8px; + height: 8px; + vertical-align: middle; +} + +.nvtooltip table td.legend-color-guide div { + width: 12px; + height: 12px; + border: 1px solid #999; +} + +.nvtooltip .footer { + padding: 3px; + text-align: center; +} + +.nvtooltip-pending-removal { + pointer-events: none; + display: none; +} + + +/**** +Interactive Layer +*/ +.nvd3 .nv-interactiveGuideLine { + pointer-events:none; +} +.nvd3 line.nv-guideline { + stroke: #ccc; +} diff --git a/src/dom.js b/src/dom.js new file mode 100644 index 000000000..b1cbb933b --- /dev/null +++ b/src/dom.js @@ -0,0 +1,25 @@ +/* Facade for queueing DOM write operations + * with Fastdom (https://github.com/wilsonpage/fastdom) + * if available. + * This could easily be extended to support alternate + * implementations in the future. + */ +nv.dom.write = function(callback) { + if (window.fastdom !== undefined) { + return fastdom.write(callback); + } + return callback(); +}; + +/* Facade for queueing DOM read operations + * with Fastdom (https://github.com/wilsonpage/fastdom) + * if available. + * This could easily be extended to support alternate + * implementations in the future. + */ +nv.dom.read = function(callback) { + if (window.fastdom !== undefined) { + return fastdom.read(callback); + } + return callback(); +}; \ No newline at end of file diff --git a/src/interactiveLayer.js b/src/interactiveLayer.js index 72ad5a5db..c73ff6631 100644 --- a/src/interactiveLayer.js +++ b/src/interactiveLayer.js @@ -9,26 +9,21 @@ nv.interactiveGuideline = function() { "use strict"; - var tooltip = nv.models.tooltip(); - - //Public settings - var width = null; - var height = null; - - //Please pass in the bounding chart's top and left margins - //This is important for calculating the correct mouseX/Y positions. - var margin = {left: 0, top: 0} - , xScale = d3.scale.linear() - , yScale = d3.scale.linear() - , dispatch = d3.dispatch('elementMousemove', 'elementMouseout', 'elementClick', 'elementDblclick') - , showGuideLine = true; - //Must pass in the bounding chart's container. - //The mousemove event is attached to this container. - var svgContainer = null; - - // check if IE by looking for activeX - var isMSIE = "ActiveXObject" in window; - + var margin = { left: 0, top: 0 } //Pass the chart's top and left magins. Used to calculate the mouseX/Y. + , width = null + , height = null + , xScale = d3.scale.linear() + , dispatch = d3.dispatch('elementMousemove', 'elementMouseout', 'elementClick', 'elementDblclick', 'elementMouseDown', 'elementMouseUp') + , showGuideLine = true + , svgContainer = null // Must pass the chart's svg, we'll use its mousemove event. + , tooltip = nv.models.tooltip() + , isMSIE = "ActiveXObject" in window // Checkt if IE by looking for activeX. + ; + + tooltip + .duration(0) + .hideDelay(0) + .hidden(false); function layer(selection) { selection.each(function(data) { @@ -97,7 +92,8 @@ nv.interactiveGuideline = function() { if (isMSIE) { if (d3.event.relatedTarget && d3.event.relatedTarget.ownerSVGElement === undefined - && d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass)) { + && (d3.event.relatedTarget.className === undefined + || d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass))) { return; } @@ -107,7 +103,10 @@ nv.interactiveGuideline = function() { mouseY: mouseY }); layer.renderGuideLine(null); //hide the guideline + tooltip.hidden(true); return; + } else { + tooltip.hidden(false); } var pointXValue = xScale.invert(mouseX); @@ -134,32 +133,54 @@ nv.interactiveGuideline = function() { pointXValue: pointXValue }); } + + // if user presses mouse down the layer, fire elementMouseDown + if (d3.event.type === 'mousedown') { + dispatch.elementMouseDown({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + } + + // if user presses mouse down the layer, fire elementMouseUp + if (d3.event.type === 'mouseup') { + dispatch.elementMouseUp({ + mouseX: mouseX, + mouseY: mouseY, + pointXValue: pointXValue + }); + } } svgContainer + .on("touchmove",mouseHandler) .on("mousemove",mouseHandler, true) .on("mouseout" ,mouseHandler,true) + .on("mousedown" ,mouseHandler,true) + .on("mouseup" ,mouseHandler,true) .on("dblclick" ,mouseHandler) .on("click", mouseHandler) ; + layer.guideLine = null; //Draws a vertical guideline at the given X postion. layer.renderGuideLine = function(x) { if (!showGuideLine) return; - var line = wrap.select(".nv-interactiveGuideLine") - .selectAll("line") - .data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String); - - line.enter() - .append("line") - .attr("class", "nv-guideline") - .attr("x1", function(d) { return d;}) - .attr("x2", function(d) { return d;}) - .attr("y1", availableHeight) - .attr("y2",0) - ; - line.exit().remove(); - + if (layer.guideLine && layer.guideLine.attr("x1") === x) return; + nv.dom.write(function() { + var line = wrap.select(".nv-interactiveGuideLine") + .selectAll("line") + .data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String); + line.enter() + .append("line") + .attr("class", "nv-guideline") + .attr("x1", function(d) { return d;}) + .attr("x2", function(d) { return d;}) + .attr("y1", availableHeight) + .attr("y2",0); + line.exit().remove(); + }); } }); } @@ -225,15 +246,30 @@ nv.interactiveBisect = function (values, searchVal, xAccessor) { if (! (values instanceof Array)) { return null; } + var _xAccessor; if (typeof xAccessor !== 'function') { - xAccessor = function(d,i) { + _xAccessor = function(d) { return d.x; } + } else { + _xAccessor = xAccessor; } + var _cmp = function(d, v) { + // Accessors are no longer passed the index of the element along with + // the element itself when invoked by d3.bisector. + // + // Starting at D3 v3.4.4, d3.bisector() started inspecting the + // function passed to determine if it should consider it an accessor + // or a comparator. This meant that accessors that take two arguments + // (expecting an index as the second parameter) are treated as + // comparators where the second argument is the search value against + // which the first argument is compared. + return _xAccessor(d) - v; + }; - var bisect = d3.bisector(xAccessor).left; + var bisect = d3.bisector(_cmp).left; var index = d3.max([0, bisect(values,searchVal) - 1]); - var currentValue = xAccessor(values[index], index); + var currentValue = _xAccessor(values[index]); if (typeof currentValue === 'undefined') { currentValue = index; @@ -244,7 +280,7 @@ nv.interactiveBisect = function (values, searchVal, xAccessor) { } var nextIndex = d3.min([index+1, values.length - 1]); - var nextValue = xAccessor(values[nextIndex], nextIndex); + var nextValue = _xAccessor(values[nextIndex]); if (typeof nextValue === 'undefined') { nextValue = nextIndex; @@ -267,7 +303,7 @@ nv.nearestValueIndex = function (values, searchVal, threshold) { var yDistMax = Infinity, indexToHighlight = null; values.forEach(function(d,i) { var delta = Math.abs(searchVal - d); - if ( delta <= yDistMax && delta < threshold) { + if ( d != null && delta <= yDistMax && delta < threshold) { yDistMax = delta; indexToHighlight = i; } diff --git a/src/models/axis.js b/src/models/axis.js index 32bc11993..145ba0c32 100644 --- a/src/models/axis.js +++ b/src/models/axis.js @@ -13,7 +13,6 @@ nv.models.axis = function() { , height = 60 //only used for tickLabel currently , axisLabelText = null , showMaxMin = true //TODO: showMaxMin should be disabled on all ordinal scaled axes - , highlightZero = true , rotateLabels = 0 , rotateYLabel = true , staggerLabels = false @@ -22,8 +21,6 @@ nv.models.axis = function() { , axisLabelDistance = 0 , duration = 250 , dispatch = d3.dispatch('renderEnd') - , axisRendered = false - , maxMinRendered = false ; axis .scale(scale) @@ -48,7 +45,7 @@ nv.models.axis = function() { var wrap = container.selectAll('g.nv-wrap.nv-axis').data([data]); var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-axis'); var gEnter = wrapEnter.append('g'); - var g = wrap.select('g') + var g = wrap.select('g'); if (ticks !== null) axis.ticks(ticks); @@ -69,25 +66,30 @@ nv.models.axis = function() { .data([axisLabelText || null]); axisLabel.exit().remove(); + var xLabelMargin; + var axisMaxMin; + var w; switch (axis.orient()) { case 'top': axisLabel.enter().append('text').attr('class', 'nv-axislabel'); - var w; - if (scale.range().length < 2) { - w = 0; - } else if (scale.range().length === 2) { - w = scale.range()[1]; - } else { - w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]); - } + w = 0; + if (scale.range().length === 1) { + w = isOrdinal ? scale.range()[0] * 2 + scale.rangeBand() : 0; + } else if (scale.range().length === 2) { + w = isOrdinal ? scale.range()[0] + scale.range()[1] + scale.rangeBand() : scale.range()[1]; + } else if ( scale.range().length > 2){ + w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]); + }; axisLabel .attr('text-anchor', 'middle') .attr('y', 0) .attr('x', w/2); if (showMaxMin) { - var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') .data(scale.domain()); - axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text'); + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ') + }).append('text'); axisMaxMin.exit().remove(); axisMaxMin .attr('transform', function(d,i) { @@ -108,42 +110,49 @@ nv.models.axis = function() { } break; case 'bottom': - var xLabelMargin = axisLabelDistance + 36; + xLabelMargin = axisLabelDistance + 36; var maxTextWidth = 30; + var textHeight = 0; var xTicks = g.selectAll('g').select("text"); + var rotateLabelsRule = ''; if (rotateLabels%360) { //Calculate the longest xTick width xTicks.each(function(d,i){ - var width = this.getBoundingClientRect().width; + var box = this.getBoundingClientRect(); + var width = box.width; + textHeight = box.height; if(width > maxTextWidth) maxTextWidth = width; }); + rotateLabelsRule = 'rotate(' + rotateLabels + ' 0,' + (textHeight/2 + axis.tickPadding()) + ')'; //Convert to radians before calculating sin. Add 30 to margin for healthy padding. var sin = Math.abs(Math.sin(rotateLabels*Math.PI/180)); - var xLabelMargin = (sin ? sin*maxTextWidth : maxTextWidth)+30; + xLabelMargin = (sin ? sin*maxTextWidth : maxTextWidth)+30; //Rotate all xTicks xTicks - .attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' }) + .attr('transform', rotateLabelsRule) .style('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end'); } axisLabel.enter().append('text').attr('class', 'nv-axislabel'); - var w; - if (scale.range().length < 2) { - w = 0; + w = 0; + if (scale.range().length === 1) { + w = isOrdinal ? scale.range()[0] * 2 + scale.rangeBand() : 0; } else if (scale.range().length === 2) { - w = scale.range()[1]; - } else { + w = isOrdinal ? scale.range()[0] + scale.range()[1] + scale.rangeBand() : scale.range()[1]; + } else if ( scale.range().length > 2){ w = scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]); - } + }; axisLabel .attr('text-anchor', 'middle') .attr('y', xLabelMargin) .attr('x', w/2); if (showMaxMin) { //if (showMaxMin && !isOrdinal) { - var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') //.data(scale.domain()) .data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]); - axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text'); + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-x',(i == 0 ? 'nv-axisMin-x':'nv-axisMax-x')].join(' ') + }).append('text'); axisMaxMin.exit().remove(); axisMaxMin .attr('transform', function(d,i) { @@ -152,7 +161,7 @@ nv.models.axis = function() { .select('text') .attr('dy', '.71em') .attr('y', axis.tickPadding()) - .attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' }) + .attr('transform', rotateLabelsRule) .style('text-anchor', rotateLabels ? (rotateLabels%360 > 0 ? 'start' : 'end') : 'middle') .text(function(d,i) { var v = fmt(d); @@ -175,12 +184,14 @@ nv.models.axis = function() { axisLabel .style('text-anchor', rotateYLabel ? 'middle' : 'begin') .attr('transform', rotateYLabel ? 'rotate(90)' : '') - .attr('y', rotateYLabel ? (-Math.max(margin.right,width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart - .attr('x', rotateYLabel ? (scale.range()[0] / 2) : axis.tickPadding()); + .attr('y', rotateYLabel ? (-Math.max(margin.right, width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart + .attr('x', rotateYLabel ? (d3.max(scale.range()) / 2) : axis.tickPadding()); if (showMaxMin) { - var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') .data(scale.domain()); - axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text') + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ') + }).append('text') .style('opacity', 0); axisMaxMin.exit().remove(); axisMaxMin @@ -192,7 +203,7 @@ nv.models.axis = function() { .attr('y', 0) .attr('x', axis.tickPadding()) .style('text-anchor', 'start') - .text(function(d,i) { + .text(function(d, i) { var v = fmt(d); return ('' + v).match('NaN') ? '' : v; }); @@ -217,12 +228,14 @@ nv.models.axis = function() { axisLabel .style('text-anchor', rotateYLabel ? 'middle' : 'end') .attr('transform', rotateYLabel ? 'rotate(-90)' : '') - .attr('y', rotateYLabel ? (-Math.max(margin.left,width) + 25 - (axisLabelDistance || 0)) : -10) - .attr('x', rotateYLabel ? (-scale.range()[0] / 2) : -axis.tickPadding()); + .attr('y', rotateYLabel ? (-Math.max(margin.left, width) + 25 - (axisLabelDistance || 0)) : -10) + .attr('x', rotateYLabel ? (-d3.max(scale.range()) / 2) : -axis.tickPadding()); if (showMaxMin) { - var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') + axisMaxMin = wrap.selectAll('g.nv-axisMaxMin') .data(scale.domain()); - axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text') + axisMaxMin.enter().append('g').attr('class',function(d,i){ + return ['nv-axisMaxMin','nv-axisMaxMin-y',(i == 0 ? 'nv-axisMin-y':'nv-axisMax-y')].join(' ') + }).append('text') .style('opacity', 0); axisMaxMin.exit().remove(); axisMaxMin @@ -276,7 +289,7 @@ nv.models.axis = function() { .each(function(d,i) { try { if (i) // i== 1, max position - maxMinRange.push(scale(d) - this.getBoundingClientRect().width - 4) //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case) + maxMinRange.push(scale(d) - this.getBoundingClientRect().width - 4); //assuming the max and min labels are as wide as the next tick (with an extra 4 pixels just in case) else // i==0, min position maxMinRange.push(scale(d) + this.getBoundingClientRect().width + 4) }catch (err) { @@ -287,7 +300,7 @@ nv.models.axis = function() { } }); // the g's wrapping each tick - g.selectAll('g').each(function(d,i) { + g.selectAll('g').each(function(d, i) { if (scale(d) < maxMinRange[0] || scale(d) > maxMinRange[1]) { if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL d3.select(this).remove(); @@ -297,14 +310,18 @@ nv.models.axis = function() { }); } - //highlight zero line ... Maybe should not be an option and should just be in CSS? - if (highlightZero) { - g.selectAll('.tick') - .filter(function (d) { - return !parseFloat(Math.round(this.__data__ * 100000) / 1000000) && (this.__data__ !== undefined) - }) //this is because sometimes the 0 tick is a very small fraction, TODO: think of cleaner technique - .classed('zero', true); - } + //Highlight zero tick line + g.selectAll('.tick') + .filter(function (d) { + /* + The filter needs to return only ticks at or near zero. + Numbers like 0.00001 need to count as zero as well, + and the arithmetic trick below solves that. + */ + return !parseFloat(Math.round(d * 100000) / 1000000) && (d !== undefined) + }) + .classed('zero', true); + //store old scales for use in transitions on update scale0 = scale.copy(); @@ -329,7 +346,6 @@ nv.models.axis = function() { staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, rotateYLabel: {get: function(){return rotateYLabel;}, set: function(_){rotateYLabel=_;}}, - highlightZero: {get: function(){return highlightZero;}, set: function(_){highlightZero=_;}}, showMaxMin: {get: function(){return showMaxMin;}, set: function(_){showMaxMin=_;}}, axisLabel: {get: function(){return axisLabelText;}, set: function(_){axisLabelText=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, diff --git a/src/models/boxPlot.js b/src/models/boxPlot.js new file mode 100644 index 000000000..6f85b912e --- /dev/null +++ b/src/models/boxPlot.js @@ -0,0 +1,312 @@ +nv.models.boxPlot = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = 960 + , height = 500 + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , x = d3.scale.ordinal() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , color = nv.utils.defaultColor() + , container = null + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') + , duration = 250 + , maxBoxWidth = null + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var x0, y0; + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup Scales + x .domain(xDomain || data.map(function(d,i) { return getX(d,i); })) + .rangeBands(xRange || [0, availableWidth], .1); + + // if we know yDomain, no need to calculate + var yData = [] + if (!yDomain) { + // (y-range is based on quartiles, whiskers and outliers) + + // lower values + var yMin = d3.min(data.map(function(d) { + var min_arr = []; + + min_arr.push(d.values.Q1); + if (d.values.hasOwnProperty('whisker_low') && d.values.whisker_low !== null) { min_arr.push(d.values.whisker_low); } + if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { min_arr = min_arr.concat(d.values.outliers); } + + return d3.min(min_arr); + })); + + // upper values + var yMax = d3.max(data.map(function(d) { + var max_arr = []; + + max_arr.push(d.values.Q3); + if (d.values.hasOwnProperty('whisker_high') && d.values.whisker_high !== null) { max_arr.push(d.values.whisker_high); } + if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { max_arr = max_arr.concat(d.values.outliers); } + + return d3.max(max_arr); + })); + + yData = [ yMin, yMax ] ; + } + + y.domain(yDomain || yData); + y.range(yRange || [availableHeight, 0]); + + //store old scales if they exist + x0 = x0 || x; + y0 = y0 || y.copy().range([y(0),y(0)]); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap').data([data]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap'); + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var boxplots = wrap.selectAll('.nv-boxplot').data(function(d) { return d }); + var boxEnter = boxplots.enter().append('g').style('stroke-opacity', 1e-6).style('fill-opacity', 1e-6); + boxplots + .attr('class', 'nv-boxplot') + .attr('transform', function(d,i,j) { return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05) + ', 0)'; }) + .classed('hover', function(d) { return d.hover }); + boxplots + .watchTransition(renderWatch, 'nv-boxplot: boxplots') + .style('stroke-opacity', 1) + .style('fill-opacity', .75) + .delay(function(d,i) { return i * duration / data.length }) + .attr('transform', function(d,i) { + return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05) + ', 0)'; + }); + boxplots.exit().remove(); + + // ----- add the SVG elements for each boxPlot ----- + + // conditionally append whisker lines + boxEnter.each(function(d,i) { + var box = d3.select(this); + + ['low', 'high'].forEach(function(key) { + if (d.values.hasOwnProperty('whisker_' + key) && d.values['whisker_' + key] !== null) { + box.append('line') + .style('stroke', (d.color) ? d.color : color(d,i)) + .attr('class', 'nv-boxplot-whisker nv-boxplot-' + key); + + box.append('line') + .style('stroke', (d.color) ? d.color : color(d,i)) + .attr('class', 'nv-boxplot-tick nv-boxplot-' + key); + } + }); + }); + + // outliers + // TODO: support custom colors here + var outliers = boxplots.selectAll('.nv-boxplot-outlier').data(function(d) { + if (d.values.hasOwnProperty('outliers') && d.values.outliers !== null) { return d.values.outliers; } + else { return []; } + }); + outliers.enter().append('circle') + .style('fill', function(d,i,j) { return color(d,j) }).style('stroke', function(d,i,j) { return color(d,j) }) + .on('mouseover', function(d,i,j) { + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + series: { key: d, color: color(d,j) }, + e: d3.event + }); + }) + .on('mouseout', function(d,i,j) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + series: { key: d, color: color(d,j) }, + e: d3.event + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({e: d3.event}); + }); + + outliers.attr('class', 'nv-boxplot-outlier'); + outliers + .watchTransition(renderWatch, 'nv-boxplot: nv-boxplot-outlier') + .attr('cx', x.rangeBand() * .45) + .attr('cy', function(d,i,j) { return y(d); }) + .attr('r', '3'); + outliers.exit().remove(); + + var box_width = function() { return (maxBoxWidth === null ? x.rangeBand() * .9 : Math.min(75, x.rangeBand() * .9)); }; + var box_left = function() { return x.rangeBand() * .45 - box_width()/2; }; + var box_right = function() { return x.rangeBand() * .45 + box_width()/2; }; + + // update whisker lines and ticks + ['low', 'high'].forEach(function(key) { + var endpoint = (key === 'low') ? 'Q1' : 'Q3'; + + boxplots.select('line.nv-boxplot-whisker.nv-boxplot-' + key) + .watchTransition(renderWatch, 'nv-boxplot: boxplots') + .attr('x1', x.rangeBand() * .45 ) + .attr('y1', function(d,i) { return y(d.values['whisker_' + key]); }) + .attr('x2', x.rangeBand() * .45 ) + .attr('y2', function(d,i) { return y(d.values[endpoint]); }); + + boxplots.select('line.nv-boxplot-tick.nv-boxplot-' + key) + .watchTransition(renderWatch, 'nv-boxplot: boxplots') + .attr('x1', box_left ) + .attr('y1', function(d,i) { return y(d.values['whisker_' + key]); }) + .attr('x2', box_right ) + .attr('y2', function(d,i) { return y(d.values['whisker_' + key]); }); + }); + + ['low', 'high'].forEach(function(key) { + boxEnter.selectAll('.nv-boxplot-' + key) + .on('mouseover', function(d,i,j) { + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + series: { key: d.values['whisker_' + key], color: color(d,j) }, + e: d3.event + }); + }) + .on('mouseout', function(d,i,j) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + series: { key: d.values['whisker_' + key], color: color(d,j) }, + e: d3.event + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({e: d3.event}); + }); + }); + + // boxes + boxEnter.append('rect') + .attr('class', 'nv-boxplot-box') + // tooltip events + .on('mouseover', function(d,i) { + d3.select(this).classed('hover', true); + dispatch.elementMouseover({ + key: d.label, + value: d.label, + series: [ + { key: 'Q3', value: d.values.Q3, color: d.color || color(d,i) }, + { key: 'Q2', value: d.values.Q2, color: d.color || color(d,i) }, + { key: 'Q1', value: d.values.Q1, color: d.color || color(d,i) } + ], + data: d, + index: i, + e: d3.event + }); + }) + .on('mouseout', function(d,i) { + d3.select(this).classed('hover', false); + dispatch.elementMouseout({ + key: d.label, + value: d.label, + series: [ + { key: 'Q3', value: d.values.Q3, color: d.color || color(d,i) }, + { key: 'Q2', value: d.values.Q2, color: d.color || color(d,i) }, + { key: 'Q1', value: d.values.Q1, color: d.color || color(d,i) } + ], + data: d, + index: i, + e: d3.event + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({e: d3.event}); + }); + + // box transitions + boxplots.select('rect.nv-boxplot-box') + .watchTransition(renderWatch, 'nv-boxplot: boxes') + .attr('y', function(d,i) { return y(d.values.Q3); }) + .attr('width', box_width) + .attr('x', box_left ) + + .attr('height', function(d,i) { return Math.abs(y(d.values.Q3) - y(d.values.Q1)) || 1 }) + .style('fill', function(d,i) { return d.color || color(d,i) }) + .style('stroke', function(d,i) { return d.color || color(d,i) }); + + // median line + boxEnter.append('line').attr('class', 'nv-boxplot-median'); + + boxplots.select('line.nv-boxplot-median') + .watchTransition(renderWatch, 'nv-boxplot: boxplots line') + .attr('x1', box_left) + .attr('y1', function(d,i) { return y(d.values.Q2); }) + .attr('x2', box_right) + .attr('y2', function(d,i) { return y(d.values.Q2); }); + + //store old scales for use in transitions on update + x0 = x.copy(); + y0 = y.copy(); + }); + + renderWatch.renderEnd('nv-boxplot immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + maxBoxWidth: {get: function(){return maxBoxWidth;}, set: function(_){maxBoxWidth=_;}}, + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + // rectClass: {get: function(){return rectClass;}, set: function(_){rectClass=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; diff --git a/src/models/boxPlotChart.js b/src/models/boxPlotChart.js new file mode 100644 index 000000000..9912cb87b --- /dev/null +++ b/src/models/boxPlotChart.js @@ -0,0 +1,242 @@ +nv.models.boxPlotChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var boxplot = nv.models.boxPlot() + , xAxis = nv.models.axis() + , yAxis = nv.models.axis() + ; + + var margin = {top: 15, right: 10, bottom: 50, left: 60} + , width = null + , height = null + , color = nv.utils.getColor() + , showXAxis = true + , showYAxis = true + , rightAlignYAxis = false + , staggerLabels = false + , tooltip = nv.models.tooltip() + , x + , y + , noData = "No Data Available." + , dispatch = d3.dispatch('beforeUpdate', 'renderEnd') + , duration = 250 + ; + + xAxis + .orient('bottom') + .showMaxMin(false) + .tickFormat(function(d) { return d }) + ; + yAxis + .orient((rightAlignYAxis) ? 'right' : 'left') + .tickFormat(d3.format(',.1f')) + ; + + tooltip.duration(0); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch, duration); + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(boxplot); + if (showXAxis) renderWatch.models(xAxis); + if (showYAxis) renderWatch.models(yAxis); + + selection.each(function(data) { + var container = d3.select(this), + that = this; + nv.utils.initSVG(container); + var availableWidth = (width || parseInt(container.style('width')) || 960) + - margin.left - margin.right, + availableHeight = (height || parseInt(container.style('height')) || 400) + - margin.top - margin.bottom; + + chart.update = function() { + dispatch.beforeUpdate(); + container.transition().duration(duration).call(chart); + }; + chart.container = this; + + // Display No Data message if there's nothing to show. (quartiles required at minimum) + if (!data || !data.length || + !data.filter(function(d) { return d.values.hasOwnProperty("Q1") && d.values.hasOwnProperty("Q2") && d.values.hasOwnProperty("Q3"); }).length) { + var noDataText = container.selectAll('.nv-noData').data([noData]); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', margin.left + availableWidth / 2) + .attr('y', margin.top + availableHeight / 2) + .text(function(d) { return d }); + + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup Scales + x = boxplot.xScale(); + y = boxplot.yScale().clamp(true); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-boxPlotWithAxes').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-boxPlotWithAxes').append('g'); + var defsEnter = gEnter.append('defs'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y nv-axis') + .append('g').attr('class', 'nv-zeroLine') + .append('line'); + + gEnter.append('g').attr('class', 'nv-barsWrap'); + + g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } + + // Main Chart Component(s) + boxplot + .width(availableWidth) + .height(availableHeight); + + var barsWrap = g.select('.nv-barsWrap') + .datum(data.filter(function(d) { return !d.disabled })) + + barsWrap.transition().call(boxplot); + + + defsEnter.append('clipPath') + .attr('id', 'nv-x-label-clip-' + boxplot.id()) + .append('rect'); + + g.select('#nv-x-label-clip-' + boxplot.id() + ' rect') + .attr('width', x.rangeBand() * (staggerLabels ? 2 : 1)) + .attr('height', 16) + .attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 )); + + // Setup Axes + if (showXAxis) { + xAxis + .scale(x) + .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight, 0); + + g.select('.nv-x.nv-axis').attr('transform', 'translate(0,' + y.range()[0] + ')'); + g.select('.nv-x.nv-axis').call(xAxis); + + var xTicks = g.select('.nv-x.nv-axis').selectAll('g'); + if (staggerLabels) { + xTicks + .selectAll('text') + .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' }) + } + } + + if (showYAxis) { + yAxis + .scale(y) + .ticks( Math.floor(availableHeight/36) ) // can't use nv.utils.calcTicksY with Object data + .tickSize( -availableWidth, 0); + + g.select('.nv-y.nv-axis').call(yAxis); + } + + // Zero line + g.select(".nv-zeroLine line") + .attr("x1",0) + .attr("x2",availableWidth) + .attr("y1", y(0)) + .attr("y2", y(0)) + ; + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + }); + + renderWatch.renderEnd('nv-boxplot chart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + boxplot.dispatch.on('elementMouseover.tooltip', function(evt) { + tooltip.data(evt).hidden(false); + }); + + boxplot.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.data(evt).hidden(true); + }); + + boxplot.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.boxplot = boxplot; + chart.xAxis = xAxis; + chart.yAxis = yAxis; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, + showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, + tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + boxplot.duration(duration); + xAxis.duration(duration); + yAxis.duration(duration); + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + boxplot.color(color); + }}, + rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ + rightAlignYAxis = _; + yAxis.orient( (_) ? 'right' : 'left'); + }} + }); + + nv.utils.inheritOptions(chart, boxplot); + nv.utils.initOptions(chart); + + return chart; +} diff --git a/src/models/bullet.js b/src/models/bullet.js index 475db4950..8decbd68d 100644 --- a/src/models/bullet.js +++ b/src/models/bullet.js @@ -22,16 +22,18 @@ nv.models.bullet = function() { , forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.) , width = 380 , height = 30 + , container = null , tickFormat = null , color = nv.utils.getColor(['#1f77b4']) - , dispatch = d3.dispatch('elementMouseover', 'elementMouseout') + , dispatch = d3.dispatch('elementMouseover', 'elementMouseout', 'elementMousemove') ; function chart(selection) { selection.each(function(d, i) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); nv.utils.initSVG(container); var rangez = ranges.call(this, d, i).slice().sort(d3.descending), @@ -69,7 +71,6 @@ nv.models.bullet = function() { gEnter.append('rect').attr('class', 'nv-range nv-rangeAvg'); gEnter.append('rect').attr('class', 'nv-range nv-rangeMin'); gEnter.append('rect').attr('class', 'nv-measure'); - gEnter.append('path').attr('class', 'nv-markerTriangle'); wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -110,54 +111,83 @@ nv.models.bullet = function() { dispatch.elementMouseover({ value: measurez[0], label: measureLabelz[0] || 'Current', - pos: [x1(measurez[0]), availableHeight/2] + color: d3.select(this).style("fill") + }) + }) + .on('mousemove', function() { + dispatch.elementMousemove({ + value: measurez[0], + label: measureLabelz[0] || 'Current', + color: d3.select(this).style("fill") }) }) .on('mouseout', function() { dispatch.elementMouseout({ value: measurez[0], - label: measureLabelz[0] || 'Current' + label: measureLabelz[0] || 'Current', + color: d3.select(this).style("fill") }) }); var h3 = availableHeight / 6; - if (markerz[0]) { - g.selectAll('path.nv-markerTriangle') - .attr('transform', function(d) { return 'translate(' + x1(markerz[0]) + ',' + (availableHeight / 2) + ')' }) - .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z') - .on('mouseover', function() { - dispatch.elementMouseover({ - value: markerz[0], - label: markerLabelz[0] || 'Previous', - pos: [x1(markerz[0]), availableHeight/2] - }) - }) - .on('mouseout', function() { - dispatch.elementMouseout({ - value: markerz[0], - label: markerLabelz[0] || 'Previous' - }) - }); - } else { - g.selectAll('path.nv-markerTriangle').remove(); - } + + var markerData = markerz.map( function(marker, index) { + return {value: marker, label: markerLabelz[index]} + }); + gEnter + .selectAll("path.nv-markerTriangle") + .data(markerData) + .enter() + .append('path') + .attr('class', 'nv-markerTriangle') + .attr('transform', function(d) { return 'translate(' + x1(d.value) + ',' + (availableHeight / 2) + ')' }) + .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z') + .on('mouseover', function(d) { + dispatch.elementMouseover({ + value: d.value, + label: d.label || 'Previous', + color: d3.select(this).style("fill"), + pos: [x1(d.value), availableHeight/2] + }) + + }) + .on('mousemove', function(d) { + dispatch.elementMousemove({ + value: d.value, + label: d.label || 'Previous', + color: d3.select(this).style("fill") + }) + }) + .on('mouseout', function(d, i) { + dispatch.elementMouseout({ + value: d.value, + label: d.label || 'Previous', + color: d3.select(this).style("fill") + }) + }); wrap.selectAll('.nv-range') .on('mouseover', function(d,i) { var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum"); - dispatch.elementMouseover({ value: d, label: label, - pos: [x1(d), availableHeight/2] + color: d3.select(this).style("fill") + }) + }) + .on('mousemove', function() { + dispatch.elementMousemove({ + value: measurez[0], + label: measureLabelz[0] || 'Previous', + color: d3.select(this).style("fill") }) }) .on('mouseout', function(d,i) { var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum"); - dispatch.elementMouseout({ value: d, - label: label + label: label, + color: d3.select(this).style("fill") }) }); }); diff --git a/src/models/bulletChart.js b/src/models/bulletChart.js index f7a75cf61..d6678a0ec 100644 --- a/src/models/bulletChart.js +++ b/src/models/bulletChart.js @@ -9,8 +9,8 @@ nv.models.bulletChart = function() { // Public Variables with Default Settings //------------------------------------------------------------ - var bullet = nv.models.bullet() - ; + var bullet = nv.models.bullet(); + var tooltip = nv.models.tooltip(); var orient = 'left' // TODO top & bottom , reverse = false @@ -21,34 +21,21 @@ nv.models.bulletChart = function() { , width = null , height = 55 , tickFormat = null - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

    ' + x + '

    ' + - '

    ' + y + '

    ' - } - , noData = 'No Data Available.' - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide') + , ticks = null + , noData = null + , dispatch = d3.dispatch() ; - //============================================================ - // Private Variables - //------------------------------------------------------------ - - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ) + margin.left, - top = e.pos[1] + ( offsetElement.offsetTop || 0) + margin.top, - content = tooltip(e.key, e.label, e.value, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'e' : 'w', null, offsetElement); - }; + tooltip + .duration(0) + .headerEnabled(false); function chart(selection) { selection.each(function(d, i) { var container = d3.select(this); nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, + var availableWidth = nv.utils.availableWidth(width, container, margin), availableHeight = height - margin.top - margin.bottom, that = this; @@ -57,18 +44,7 @@ nv.models.bulletChart = function() { // Display No Data message if there's nothing to show. if (!d || !ranges.call(this, d, i)) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', 18 + margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -129,7 +105,7 @@ nv.models.bulletChart = function() { // Update the tick groups. var tick = g.selectAll('g.nv-tick') - .data(x1.ticks( availableWidth / 50 ), function(d) { + .data(x1.ticks( ticks ? ticks : (availableWidth / 50) ), function(d) { return this.textContent || format(d); }); @@ -166,16 +142,6 @@ nv.models.bulletChart = function() { .attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' }) .style('opacity', 1e-6) .remove(); - - //============================================================ - // Event Handling/Dispatching (in chart's scope) - //------------------------------------------------------------ - - dispatch.on('tooltipShow', function(e) { - e.key = d.title; - if (tooltips) showTooltip(e, that.parentNode); - }); - }); d3.timer.flush(); @@ -186,16 +152,21 @@ nv.models.bulletChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - bullet.dispatch.on('elementMouseover.tooltip', function(e) { - dispatch.tooltipShow(e); + bullet.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: evt.label, + value: evt.value, + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - bullet.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + bullet.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + bullet.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -204,6 +175,8 @@ nv.models.bulletChart = function() { chart.bullet = bullet; chart.dispatch = dispatch; + chart.tooltip = tooltip; + chart.options = nv.utils.optionsFunc.bind(chart); chart._options = Object.create({}, { @@ -214,8 +187,7 @@ nv.models.bulletChart = function() { width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, tickFormat: {get: function(){return tickFormat;}, set: function(_){tickFormat=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + ticks: {get: function(){return ticks;}, set: function(_){ticks=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, // options that require extra logic in the setter diff --git a/src/models/candlestickBar.js b/src/models/candlestickBar.js new file mode 100644 index 000000000..dd0278eb5 --- /dev/null +++ b/src/models/candlestickBar.js @@ -0,0 +1,226 @@ + +nv.models.candlestickBar = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container + , x = d3.scale.linear() + , y = d3.scale.linear() + , getX = function(d) { return d.x } + , getY = function(d) { return d.y } + , getOpen = function(d) { return d.open } + , getClose = function(d) { return d.close } + , getHigh = function(d) { return d.high } + , getLow = function(d) { return d.low } + , forceX = [] + , forceY = [] + , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart + , clipEdge = true + , color = nv.utils.defaultColor() + , interactive = false + , xDomain + , yDomain + , xRange + , yRange + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove') + ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + function chart(selection) { + selection.each(function(data) { + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + nv.utils.initSVG(container); + + // Width of the candlestick bars. + var barWidth = (availableWidth / data[0].values.length) * .45; + + // Setup Scales + x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) )); + + if (padData) + x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); + else + x.range(xRange || [5 + barWidth / 2, availableWidth - barWidth / 2 - 5]); + + y.domain(yDomain || [ + d3.min(data[0].values.map(getLow).concat(forceY)), + d3.max(data[0].values.map(getHigh).concat(forceY)) + ] + ).range(yRange || [availableHeight, 0]); + + // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point + if (x.domain()[0] === x.domain()[1]) + x.domain()[0] ? + x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) + : x.domain([-1,1]); + + if (y.domain()[0] === y.domain()[1]) + y.domain()[0] ? + y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01]) + : y.domain([-1,1]); + + // Setup containers and skeleton of chart + var wrap = d3.select(this).selectAll('g.nv-wrap.nv-candlestickBar').data([data[0].values]); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-candlestickBar'); + var defsEnter = wrapEnter.append('defs'); + var gEnter = wrapEnter.append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-ticks'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + container + .on('click', function(d,i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + defsEnter.append('clipPath') + .attr('id', 'nv-chart-clip-path-' + id) + .append('rect'); + + wrap.select('#nv-chart-clip-path-' + id + ' rect') + .attr('width', availableWidth) + .attr('height', availableHeight); + + g .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : ''); + + var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick') + .data(function(d) { return d }); + ticks.exit().remove(); + + var tickGroups = ticks.enter().append('g'); + + // The colors are currently controlled by CSS. + ticks + .attr('class', function(d, i, j) { return (getOpen(d, i) > getClose(d, i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i}); + + var lines = tickGroups.append('line') + .attr('class', 'nv-candlestick-lines') + .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; }) + .attr('x1', 0) + .attr('y1', function(d, i) { return y(getHigh(d, i)); }) + .attr('x2', 0) + .attr('y2', function(d, i) { return y(getLow(d, i)); }); + + var rects = tickGroups.append('rect') + .attr('class', 'nv-candlestick-rects nv-bars') + .attr('transform', function(d, i) { + return 'translate(' + (x(getX(d, i)) - barWidth/2) + ',' + + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0)) + + ')'; + }) + .attr('x', 0) + .attr('y', 0) + .attr('width', barWidth) + .attr('height', function(d, i) { + var open = getOpen(d, i); + var close = getClose(d, i); + return open > close ? y(close) - y(open) : y(open) - y(close); + }); + + ticks.select('.nv-candlestick-lines').transition() + .attr('transform', function(d, i) { return 'translate(' + x(getX(d, i)) + ',0)'; }) + .attr('x1', 0) + .attr('y1', function(d, i) { return y(getHigh(d, i)); }) + .attr('x2', 0) + .attr('y2', function(d, i) { return y(getLow(d, i)); }); + + ticks.select('.nv-candlestick-rects').transition() + .attr('transform', function(d, i) { + return 'translate(' + (x(getX(d, i)) - barWidth/2) + ',' + + (y(getY(d, i)) - (getOpen(d, i) > getClose(d, i) ? (y(getClose(d, i)) - y(getOpen(d, i))) : 0)) + + ')'; + }) + .attr('x', 0) + .attr('y', 0) + .attr('width', barWidth) + .attr('height', function(d, i) { + var open = getOpen(d, i); + var close = getClose(d, i); + return open > close ? y(close) - y(open) : y(open) - y(close); + }); + }); + + return chart; + } + + + //Create methods to allow outside functions to highlight a specific bar. + chart.highlightPoint = function(pointIndex, isHoverOver) { + chart.clearHighlights(); + container.select(".nv-candlestickBar .nv-tick-0-" + pointIndex) + .classed("hover", isHoverOver) + ; + }; + + chart.clearHighlights = function() { + container.select(".nv-candlestickBar .nv-tick.hover") + .classed("hover", false) + ; + }; + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + xScale: {get: function(){return x;}, set: function(_){x=_;}}, + yScale: {get: function(){return y;}, set: function(_){y=_;}}, + xDomain: {get: function(){return xDomain;}, set: function(_){xDomain=_;}}, + yDomain: {get: function(){return yDomain;}, set: function(_){yDomain=_;}}, + xRange: {get: function(){return xRange;}, set: function(_){xRange=_;}}, + yRange: {get: function(){return yRange;}, set: function(_){yRange=_;}}, + forceX: {get: function(){return forceX;}, set: function(_){forceX=_;}}, + forceY: {get: function(){return forceY;}, set: function(_){forceY=_;}}, + padData: {get: function(){return padData;}, set: function(_){padData=_;}}, + clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + interactive: {get: function(){return interactive;}, set: function(_){interactive=_;}}, + + x: {get: function(){return getX;}, set: function(_){getX=_;}}, + y: {get: function(){return getY;}, set: function(_){getY=_;}}, + open: {get: function(){return getOpen();}, set: function(_){getOpen=_;}}, + close: {get: function(){return getClose();}, set: function(_){getClose=_;}}, + high: {get: function(){return getHigh;}, set: function(_){getHigh=_;}}, + low: {get: function(){return getLow;}, set: function(_){getLow=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top != undefined ? _.top : margin.top; + margin.right = _.right != undefined ? _.right : margin.right; + margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom; + margin.left = _.left != undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; diff --git a/src/models/cumulativeLineChart.js b/src/models/cumulativeLineChart.js index 001db0ab4..00ac5185e 100644 --- a/src/models/cumulativeLineChart.js +++ b/src/models/cumulativeLineChart.js @@ -12,6 +12,7 @@ nv.models.cumulativeLineChart = function() { , legend = nv.models.legend() , controls = nv.models.legend() , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 30, bottom: 50, left: 60} @@ -22,22 +23,17 @@ nv.models.cumulativeLineChart = function() { , showXAxis = true , showYAxis = true , rightAlignYAxis = false - , tooltips = true , showControls = true , useInteractiveGuideline = false , rescaleY = true - , tooltip = function(key, x, y, e, graph) { - return '

    ' + key + '

    ' + - '

    ' + y + ' at ' + x + '

    ' - } , x //can be accessed via chart.xScale() , y //can be accessed via chart.yScale() , id = lines.id() , state = nv.utils.state() , defaultState = null - , noData = 'No Data Available.' + , noData = null , average = function(d) { return d.average } - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd') , transitionDuration = 250 , duration = 250 , noErrorCheck = false //if set to TRUE, will bypass an error check in the indexify function. @@ -46,13 +42,14 @@ nv.models.cumulativeLineChart = function() { state.index = 0; state.rescaleY = rescaleY; - xAxis - .orient('bottom') - .tickPadding(7) - ; - yAxis - .orient((rightAlignYAxis) ? 'right' : 'left') - ; + xAxis.orient('bottom').tickPadding(7); + yAxis.orient((rightAlignYAxis) ? 'right' : 'left'); + + tooltip.valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); controls.updateState(false); @@ -65,16 +62,6 @@ nv.models.cumulativeLineChart = function() { , renderWatch = nv.utils.renderWatch(dispatch, duration) ; - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, null, null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -109,10 +96,8 @@ nv.models.cumulativeLineChart = function() { container.classed('nv-chart-' + id, true); var that = this; - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { if (duration === 0) @@ -169,18 +154,7 @@ nv.models.cumulativeLineChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -246,8 +220,7 @@ nv.models.cumulativeLineChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.nv-legendWrap') @@ -389,7 +362,7 @@ nv.models.cumulativeLineChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/70, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/70, data) ) .tickSize(-availableHeight, 0); g.select('.nv-x.nv-axis') @@ -401,7 +374,7 @@ nv.models.cumulativeLineChart = function() { if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis') @@ -498,9 +471,7 @@ nv.models.cumulativeLineChart = function() { var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex), pointIndex); interactiveLayer.tooltip - .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) .chartContainer(that.parentNode) - .enabled(tooltips) .valueFormatter(function(d,i) { return yAxis.tickFormat()(d); }) @@ -515,17 +486,11 @@ nv.models.cumulativeLineChart = function() { }); interactiveLayer.dispatch.on("elementMouseout",function(e) { - dispatch.tooltipHide(); lines.clearHighlights(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined') { data.forEach(function(series,i) { series.disabled = e.disabled[i]; @@ -562,17 +527,18 @@ nv.models.cumulativeLineChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - lines.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - lines.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + lines.dispatch.on('elementMouseover.tooltip', function(evt) { + var point = { + x: chart.x()(evt.point), + y: chart.y()(evt.point), + color: evt.point.color + }; + evt.point = point; + tooltip.data(evt).hidden(false); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + lines.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) }); //============================================================ @@ -620,10 +586,12 @@ nv.models.cumulativeLineChart = function() { chart.dispatch = dispatch; chart.lines = lines; chart.legend = legend; + chart.controls = controls; chart.xAxis = xAxis; chart.yAxis = yAxis; chart.interactiveLayer = interactiveLayer; chart.state = state; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -635,8 +603,6 @@ nv.models.cumulativeLineChart = function() { showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, average: {get: function(){return average;}, set: function(_){average=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, @@ -678,4 +644,4 @@ nv.models.cumulativeLineChart = function() { nv.utils.initOptions(chart); return chart; -}; \ No newline at end of file +}; diff --git a/src/models/discreteBar.js b/src/models/discreteBar.js index 44a1f7aab..fcf364401 100644 --- a/src/models/discreteBar.js +++ b/src/models/discreteBar.js @@ -10,6 +10,7 @@ nv.models.discreteBar = function() { , width = 960 , height = 500 , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container , x = d3.scale.ordinal() , y = d3.scale.linear() , getX = function(d) { return d.x } @@ -22,7 +23,7 @@ nv.models.discreteBar = function() { , yDomain , xRange , yRange - , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout','renderEnd') + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') , rectClass = 'discreteBar' , duration = 250 ; @@ -38,8 +39,9 @@ nv.models.discreteBar = function() { renderWatch.reset(); selection.each(function(data) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); nv.utils.initSVG(container); //add series index to each data point for reference @@ -109,47 +111,42 @@ nv.models.discreteBar = function() { .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here d3.select(this).classed('hover', true); dispatch.elementMouseover({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('mouseout', function(d,i) { d3.select(this).classed('hover', false); dispatch.elementMouseout({ - value: getY(d,i), - point: d, - series: data[d.series], - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('click', function(d,i) { + var element = this; dispatch.elementClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill"), + event: d3.event, + element: element }); d3.event.stopPropagation(); }) .on('dblclick', function(d,i) { dispatch.elementDblClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }); @@ -196,7 +193,7 @@ nv.models.discreteBar = function() { }) .select('rect') .attr('height', function(d,i) { - return Math.max(Math.abs(y(getY(d,i)) - y((yDomain && yDomain[0]) || 0)) || 1) + return Math.max(Math.abs(y(getY(d,i)) - y(0)), 1) }); diff --git a/src/models/discreteBarChart.js b/src/models/discreteBarChart.js index ad8ace623..7b4a5d978 100644 --- a/src/models/discreteBarChart.js +++ b/src/models/discreteBarChart.js @@ -9,31 +9,30 @@ nv.models.discreteBarChart = function() { var discretebar = nv.models.discreteBar() , xAxis = nv.models.axis() , yAxis = nv.models.axis() + , legend = nv.models.legend() + , tooltip = nv.models.tooltip() ; var margin = {top: 15, right: 10, bottom: 50, left: 60} , width = null , height = null , color = nv.utils.getColor() + , showLegend = false , showXAxis = true , showYAxis = true , rightAlignYAxis = false , staggerLabels = false - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

    ' + x + '

    ' + - '

    ' + y + '

    ' - } + , wrapLabels = false + , rotateLabels = 0 , x , y - , noData = "No Data Available." - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'beforeUpdate','renderEnd') + , noData = null + , dispatch = d3.dispatch('beforeUpdate','renderEnd') , duration = 250 ; xAxis .orient('bottom') - .highlightZero(false) .showMaxMin(false) .tickFormat(function(d) { return d }) ; @@ -42,20 +41,20 @@ nv.models.discreteBarChart = function() { .tickFormat(d3.format(',.1f')) ; + tooltip + .duration(0) + .headerEnabled(false) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .keyFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(discretebar.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(discretebar.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var renderWatch = nv.utils.renderWatch(dispatch, duration); function chart(selection) { @@ -68,10 +67,8 @@ nv.models.discreteBarChart = function() { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { dispatch.beforeUpdate(); @@ -81,18 +78,7 @@ nv.models.discreteBarChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container); return chart; } else { container.selectAll('.nv-noData').remove(); @@ -114,8 +100,30 @@ nv.models.discreteBarChart = function() { .append('line'); gEnter.append('g').attr('class', 'nv-barsWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + if (showLegend) { + legend.width(availableWidth); + + g.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')') + } + + if (rightAlignYAxis) { + g.select(".nv-y.nv-axis") + .attr("transform", "translate(" + availableWidth + ",0)"); + } if (rightAlignYAxis) { g.select(".nv-y.nv-axis") @@ -128,7 +136,7 @@ nv.models.discreteBarChart = function() { .height(availableHeight); var barsWrap = g.select('.nv-barsWrap') - .datum(data.filter(function(d) { return !d.disabled })) + .datum(data.filter(function(d) { return !d.disabled })); barsWrap.transition().call(discretebar); @@ -146,7 +154,7 @@ nv.models.discreteBarChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight, 0); g.select('.nv-x.nv-axis') @@ -159,12 +167,24 @@ nv.models.discreteBarChart = function() { .selectAll('text') .attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' }) } + + if (rotateLabels) { + xTicks + .selectAll('.tick text') + .attr('transform', 'rotate(' + rotateLabels + ' 0,0)') + .style('text-anchor', rotateLabels > 0 ? 'start' : 'end'); + } + + if (wrapLabels) { + g.selectAll('.tick text') + .call(nv.utils.wrapTicks, chart.xAxis.rangeBand()) + } } if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis').call(yAxis); @@ -177,15 +197,6 @@ nv.models.discreteBarChart = function() { .attr("y1", y(0)) .attr("y2", y(0)) ; - - //============================================================ - // Event Handling/Dispatching (in chart's scope) - //------------------------------------------------------------ - - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - }); renderWatch.renderEnd('discreteBar chart immediate'); @@ -196,17 +207,21 @@ nv.models.discreteBarChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - discretebar.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + discretebar.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: chart.x()(evt.data), + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - discretebar.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + discretebar.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + discretebar.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -215,8 +230,10 @@ nv.models.discreteBarChart = function() { chart.dispatch = dispatch; chart.discretebar = discretebar; + chart.legend = legend; chart.xAxis = xAxis; chart.yAxis = yAxis; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -224,11 +241,12 @@ nv.models.discreteBarChart = function() { // simple options, just get/set the necessary values width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, + showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, + wrapLabels: {get: function(){return wrapLabels;}, set: function(_){wrapLabels=!!_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, // options that require extra logic in the setter @@ -248,6 +266,7 @@ nv.models.discreteBarChart = function() { color: {get: function(){return color;}, set: function(_){ color = nv.utils.getColor(_); discretebar.color(color); + legend.color(color); }}, rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ rightAlignYAxis = _; diff --git a/src/models/furiousLegend.js b/src/models/furiousLegend.js new file mode 100644 index 000000000..4a407b3c5 --- /dev/null +++ b/src/models/furiousLegend.js @@ -0,0 +1,347 @@ +nv.models.furiousLegend = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 5, right: 0, bottom: 5, left: 0} + , width = 400 + , height = 20 + , getKey = function(d) { return d.key } + , color = nv.utils.getColor() + , maxKeyLength = 20 //default value for key lengths + , align = true + , padding = 28 //define how much space between legend items. - recommend 32 for furious version + , rightAlign = true + , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch. + , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time) + , expanded = false + , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange') + , vers = 'classic' //Options are "classic" and "furious" + ; + + function chart(selection) { + selection.each(function(data) { + var availableWidth = width - margin.left - margin.right, + container = d3.select(this); + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-legend').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g'); + var g = wrap.select('g'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + var series = g.selectAll('.nv-series') + .data(function(d) { + if(vers != 'furious') return d; + + return d.filter(function(n) { + return expanded ? true : !n.disengaged; + }); + }); + var seriesEnter = series.enter().append('g').attr('class', 'nv-series') + + var seriesShape; + + if(vers == 'classic') { + seriesEnter.append('circle') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('r', 5); + + seriesShape = series.select('circle'); + } else if (vers == 'furious') { + seriesEnter.append('rect') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('rx', 3) + .attr('ry', 3); + + seriesShape = series.select('rect'); + + seriesEnter.append('g') + .attr('class', 'nv-check-box') + .property('innerHTML','') + .attr('transform', 'translate(-10,-8)scale(0.5)'); + + var seriesCheckbox = series.select('.nv-check-box'); + + seriesCheckbox.each(function(d,i) { + d3.select(this).selectAll('path') + .attr('stroke', setTextColor(d,i)); + }); + } + + seriesEnter.append('text') + .attr('text-anchor', 'start') + .attr('class','nv-legend-text') + .attr('dy', '.32em') + .attr('dx', '8'); + + var seriesText = series.select('text.nv-legend-text'); + + series + .on('mouseover', function(d,i) { + dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects + }) + .on('mouseout', function(d,i) { + dispatch.legendMouseout(d,i); + }) + .on('click', function(d,i) { + dispatch.legendClick(d,i); + // make sure we re-get data in case it was modified + var data = series.data(); + if (updateState) { + if(vers =='classic') { + if (radioButtonMode) { + //Radio button mode: set every series to disabled, + // and enable the clicked series. + data.forEach(function(series) { series.disabled = true}); + d.disabled = false; + } + else { + d.disabled = !d.disabled; + if (data.every(function(series) { return series.disabled})) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { series.disabled = false}); + } + } + } else if(vers == 'furious') { + if(expanded) { + d.disengaged = !d.disengaged; + d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled; + d.disabled = d.disengaged || d.userDisabled; + } else if (!expanded) { + d.disabled = !d.disabled; + d.userDisabled = d.disabled; + var engaged = data.filter(function(d) { return !d.disengaged; }); + if (engaged.every(function(series) { return series.userDisabled })) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { + series.disabled = series.userDisabled = false; + }); + } + } + } + dispatch.stateChange({ + disabled: data.map(function(d) { return !!d.disabled }), + disengaged: data.map(function(d) { return !!d.disengaged }) + }); + + } + }) + .on('dblclick', function(d,i) { + if(vers == 'furious' && expanded) return; + dispatch.legendDblclick(d,i); + if (updateState) { + // make sure we re-get data in case it was modified + var data = series.data(); + //the default behavior of NVD3 legends, when double clicking one, + // is to set all other series' to false, and make the double clicked series enabled. + data.forEach(function(series) { + series.disabled = true; + if(vers == 'furious') series.userDisabled = series.disabled; + }); + d.disabled = false; + if(vers == 'furious') d.userDisabled = d.disabled; + dispatch.stateChange({ + disabled: data.map(function(d) { return !!d.disabled }) + }); + } + }); + + series.classed('nv-disabled', function(d) { return d.userDisabled }); + series.exit().remove(); + + seriesText + .attr('fill', setTextColor) + .text(getKey); + + //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option) + // NEW ALIGNING CODE, TODO: clean up + + var versPadding; + switch(vers) { + case 'furious' : + versPadding = 23; + break; + case 'classic' : + versPadding = 20; + } + + if (align) { + + var seriesWidths = []; + series.each(function(d,i) { + var legendText; + if (getKey(d).length > maxKeyLength) { + var trimmedKey = getKey(d).substring(0, maxKeyLength); + legendText = d3.select(this).select('text').text(trimmedKey + "..."); + d3.select(this).append("svg:title").text(getKey(d)); + } else { + legendText = d3.select(this).select('text'); + } + var nodeTextLength; + try { + nodeTextLength = legendText.node().getComputedTextLength(); + // If the legendText is display:none'd (nodeTextLength == 0), simulate an error so we approximate, instead + if(nodeTextLength <= 0) throw Error(); + } + catch(e) { + nodeTextLength = nv.utils.calcApproxTextWidth(legendText); + } + + seriesWidths.push(nodeTextLength + padding); + }); + + var seriesPerRow = 0; + var legendWidth = 0; + var columnWidths = []; + + while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) { + columnWidths[seriesPerRow] = seriesWidths[seriesPerRow]; + legendWidth += seriesWidths[seriesPerRow++]; + } + if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row + + while ( legendWidth > availableWidth && seriesPerRow > 1 ) { + columnWidths = []; + seriesPerRow--; + + for (var k = 0; k < seriesWidths.length; k++) { + if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) ) + columnWidths[k % seriesPerRow] = seriesWidths[k]; + } + + legendWidth = columnWidths.reduce(function(prev, cur, index, array) { + return prev + cur; + }); + } + + var xPositions = []; + for (var i = 0, curX = 0; i < seriesPerRow; i++) { + xPositions[i] = curX; + curX += columnWidths[i]; + } + + series + .attr('transform', function(d, i) { + return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')'; + }); + + //position legend as far right as possible within the total width + if (rightAlign) { + g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')'); + } + else { + g.attr('transform', 'translate(0' + ',' + margin.top + ')'); + } + + height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding); + + } else { + + var ypos = 5, + newxpos = 5, + maxwidth = 0, + xpos; + series + .attr('transform', function(d, i) { + var length = d3.select(this).select('text').node().getComputedTextLength() + padding; + xpos = newxpos; + + if (width < margin.left + margin.right + xpos + length) { + newxpos = xpos = 5; + ypos += versPadding; + } + + newxpos += length; + if (newxpos > maxwidth) maxwidth = newxpos; + + return 'translate(' + xpos + ',' + ypos + ')'; + }); + + //position legend as far right as possible within the total width + g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')'); + + height = margin.top + margin.bottom + ypos + 15; + } + + if(vers == 'furious') { + // Size rectangles after text is placed + seriesShape + .attr('width', function(d,i) { + return seriesText[0][i].getComputedTextLength() + 27; + }) + .attr('height', 18) + .attr('y', -9) + .attr('x', -15) + } + + seriesShape + .style('fill', setBGColor) + .style('stroke', function(d,i) { return d.color || color(d, i) }); + }); + + function setTextColor(d,i) { + if(vers != 'furious') return '#000'; + if(expanded) { + return d.disengaged ? color(d,i) : '#fff'; + } else if (!expanded) { + return !!d.disabled ? color(d,i) : '#fff'; + } + } + + function setBGColor(d,i) { + if(expanded && vers == 'furious') { + return d.disengaged ? '#fff' : color(d,i); + } else { + return !!d.disabled ? '#fff' : color(d,i); + } + } + + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + key: {get: function(){return getKey;}, set: function(_){getKey=_;}}, + align: {get: function(){return align;}, set: function(_){align=_;}}, + rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}}, + maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}}, + padding: {get: function(){return padding;}, set: function(_){padding=_;}}, + updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}}, + radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}}, + expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}}, + vers: {get: function(){return vers;}, set: function(_){vers=_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + + return chart; +}; diff --git a/src/models/historicalBar.js b/src/models/historicalBar.js index 57e4dc612..9adec9b39 100644 --- a/src/models/historicalBar.js +++ b/src/models/historicalBar.js @@ -10,6 +10,7 @@ nv.models.historicalBar = function() { , width = null , height = null , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null , x = d3.scale.linear() , y = d3.scale.linear() , getX = function(d) { return d.x } @@ -23,7 +24,7 @@ nv.models.historicalBar = function() { , yDomain , xRange , yRange - , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') , interactive = true ; @@ -33,11 +34,9 @@ nv.models.historicalBar = function() { selection.each(function(data) { renderWatch.reset(); - var container = d3.select(this); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right; - var availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); nv.utils.initSVG(container); @@ -97,7 +96,7 @@ nv.models.historicalBar = function() { .data(function(d) { return d }, function(d,i) {return getX(d,i)}); bars.exit().remove(); - var barsEnter = bars.enter().append('rect') + bars.enter().append('rect') .attr('x', 0 ) .attr('y', function(d,i) { return nv.utils.NaNtoZero(y(Math.max(0, getY(d,i)))) }) .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.abs(y(getY(d,i)) - y(0))) }) @@ -106,12 +105,9 @@ nv.models.historicalBar = function() { if (!interactive) return; d3.select(this).classed('hover', true); dispatch.elementMouseover({ - point: d, - series: data[0], - pos: [x(getX(d,i)), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: 0, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); }) @@ -119,36 +115,34 @@ nv.models.historicalBar = function() { if (!interactive) return; d3.select(this).classed('hover', false); dispatch.elementMouseout({ - point: d, - series: data[0], - pointIndex: i, - seriesIndex: 0, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + if (!interactive) return; + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('click', function(d,i) { if (!interactive) return; dispatch.elementClick({ - //label: d[label], - value: getY(d,i), data: d, index: i, - pos: [x(getX(d,i)), y(getY(d,i))], - e: d3.event, - id: id + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }) .on('dblclick', function(d,i) { if (!interactive) return; dispatch.elementDblClick({ - //label: d[label], - value: getY(d,i), data: d, index: i, - pos: [x(getX(d,i)), y(getY(d,i))], - e: d3.event, - id: id + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }); @@ -180,14 +174,14 @@ nv.models.historicalBar = function() { //Create methods to allow outside functions to highlight a specific bar. chart.highlightPoint = function(pointIndex, isHoverOver) { - d3.select(".nv-historicalBar-" + id) + container .select(".nv-bars .nv-bar-0-" + pointIndex) .classed("hover", isHoverOver) ; }; chart.clearHighlights = function() { - d3.select(".nv-historicalBar-" + id) + container .select(".nv-bars .nv-bar.hover") .classed("hover", false) ; diff --git a/src/models/historicalBarChart.js b/src/models/historicalBarChart.js index 3a685da5d..e63176661 100644 --- a/src/models/historicalBarChart.js +++ b/src/models/historicalBarChart.js @@ -11,6 +11,7 @@ nv.models.historicalBarChart = function(bar_model) { , yAxis = nv.models.axis() , legend = nv.models.legend() , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() ; @@ -23,54 +24,32 @@ nv.models.historicalBarChart = function(bar_model) { , showYAxis = true , rightAlignYAxis = false , useInteractiveGuideline = false - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

    ' + key + '

    ' + - '

    ' + y + ' at ' + x + '

    ' - } , x , y , state = {} , defaultState = null - , noData = 'No Data Available.' - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , noData = null + , dispatch = d3.dispatch('tooltipHide', 'stateChange', 'changeState', 'renderEnd') , transitionDuration = 250 ; - xAxis - .orient('bottom') - .tickPadding(7) - ; - yAxis - .orient( (rightAlignYAxis) ? 'right' : 'left') - ; + xAxis.orient('bottom').tickPadding(7); + yAxis.orient( (rightAlignYAxis) ? 'right' : 'left'); + tooltip + .duration(0) + .headerEnabled(false) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - - // New addition to calculate position if SVG is scaled with viewBox, may move TODO: consider implementing everywhere else - if (offsetElement) { - var svg = d3.select(offsetElement).select('svg'); - var viewBox = (svg.node()) ? svg.attr('viewBox') : null; - if (viewBox) { - viewBox = viewBox.split(' '); - var ratio = parseInt(svg.style('width')) / viewBox[2]; - e.pos[0] = e.pos[0] * ratio; - e.pos[1] = e.pos[1] * ratio; - } - } - - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(bars.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(bars.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, null, null, offsetElement); - }; var renderWatch = nv.utils.renderWatch(dispatch, 0); function chart(selection) { @@ -83,11 +62,8 @@ nv.models.historicalBarChart = function(bar_model) { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; - + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { container.transition().duration(transitionDuration).call(chart) }; chart.container = this; @@ -108,18 +84,7 @@ nv.models.historicalBarChart = function(bar_model) { // Display noData message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -150,8 +115,7 @@ nv.models.historicalBarChart = function(bar_model) { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } wrap.select('.nv-legendWrap') @@ -189,6 +153,7 @@ nv.models.historicalBarChart = function(bar_model) { if (showXAxis) { xAxis .scale(x) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight, 0); g.select('.nv-x.nv-axis') @@ -201,7 +166,7 @@ nv.models.historicalBarChart = function(bar_model) { if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis') @@ -226,9 +191,9 @@ nv.models.historicalBarChart = function(bar_model) { pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); bars.highlightPoint(pointIndex,true); var point = series.values[pointIndex]; - if (typeof point === 'undefined') return; - if (typeof singlePoint === 'undefined') singlePoint = point; - if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + if (point === undefined) return; + if (singlePoint === undefined) singlePoint = point; + if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); allData.push({ key: series.key, value: chart.y()(point, pointIndex), @@ -239,18 +204,15 @@ nv.models.historicalBarChart = function(bar_model) { var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); interactiveLayer.tooltip - .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) .chartContainer(that.parentNode) - .enabled(tooltips) .valueFormatter(function(d,i) { return yAxis.tickFormat()(d); }) - .data( - { + .data({ value: xValue, + index: pointIndex, series: allData - } - )(); + })(); interactiveLayer.renderGuideLine(pointXLocation); @@ -290,12 +252,7 @@ nv.models.historicalBarChart = function(bar_model) { chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined') { data.forEach(function(series,i) { series.disabled = e.disabled[i]; @@ -316,17 +273,21 @@ nv.models.historicalBarChart = function(bar_model) { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - bars.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + bars.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: chart.x()(evt.data), + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - bars.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + bars.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + bars.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -340,6 +301,7 @@ nv.models.historicalBarChart = function(bar_model) { chart.xAxis = xAxis; chart.yAxis = yAxis; chart.interactiveLayer = interactiveLayer; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -350,8 +312,6 @@ nv.models.historicalBarChart = function(bar_model) { showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, @@ -392,7 +352,7 @@ nv.models.historicalBarChart = function(bar_model) { }; -// ohlcChart is just a historical chart with oclc bars and some tweaks +// ohlcChart is just a historical chart with ohlc bars and some tweaks nv.models.ohlcBarChart = function() { var chart = nv.models.historicalBarChart(nv.models.ohlcBar()); @@ -413,4 +373,27 @@ nv.models.ohlcBarChart = function() { ''; }); return chart; -}; \ No newline at end of file +}; + +// candlestickChart is just a historical chart with candlestick bars and some tweaks +nv.models.candlestickBarChart = function() { + var chart = nv.models.historicalBarChart(nv.models.candlestickBar()); + + // special default tooltip since we show multiple values per x + chart.useInteractiveGuideline(true); + chart.interactiveLayer.tooltip.contentGenerator(function(data) { + // we assume only one series exists for this chart + var d = data.series[0].data; + // match line colors as defined in nv.d3.css + var color = d.open < d.close ? "2ca02c" : "d62728"; + return '' + + '

    ' + data.value + '

    ' + + '' + + '' + + '' + + '' + + '' + + '
    open:' + chart.yAxis.tickFormat()(d.open) + '
    close:' + chart.yAxis.tickFormat()(d.close) + '
    high' + chart.yAxis.tickFormat()(d.high) + '
    low:' + chart.yAxis.tickFormat()(d.low) + '
    '; + }); + return chart; +}; diff --git a/src/models/legend.js b/src/models/legend.js index a64734b9e..777f6146f 100644 --- a/src/models/legend.js +++ b/src/models/legend.js @@ -9,12 +9,16 @@ nv.models.legend = function() { , width = 400 , height = 20 , getKey = function(d) { return d.key } - , color = nv.utils.defaultColor() + , color = nv.utils.getColor() + , maxKeyLength = 20 //default value for key lengths , align = true + , padding = 32 //define how much space between legend items. - recommend 32 for furious version , rightAlign = true , updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch. , radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time) + , expanded = false , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange') + , vers = 'classic' //Options are "classic" and "furious" ; function chart(selection) { @@ -31,8 +35,63 @@ nv.models.legend = function() { wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); var series = g.selectAll('.nv-series') - .data(function(d) { return d }); - var seriesEnter = series.enter().append('g').attr('class', 'nv-series') + .data(function(d) { + if(vers != 'furious') return d; + + return d.filter(function(n) { + return expanded ? true : !n.disengaged; + }); + }); + + var seriesEnter = series.enter().append('g').attr('class', 'nv-series'); + var seriesShape; + + var versPadding; + switch(vers) { + case 'furious' : + versPadding = 23; + break; + case 'classic' : + versPadding = 20; + } + + if(vers == 'classic') { + seriesEnter.append('circle') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('r', 5); + + seriesShape = series.select('circle'); + } else if (vers == 'furious') { + seriesEnter.append('rect') + .style('stroke-width', 2) + .attr('class','nv-legend-symbol') + .attr('rx', 3) + .attr('ry', 3); + seriesShape = series.select('.nv-legend-symbol'); + + seriesEnter.append('g') + .attr('class', 'nv-check-box') + .property('innerHTML','') + .attr('transform', 'translate(-10,-8)scale(0.5)'); + + var seriesCheckbox = series.select('.nv-check-box'); + + seriesCheckbox.each(function(d,i) { + d3.select(this).selectAll('path') + .attr('stroke', setTextColor(d,i)); + }); + } + + seriesEnter.append('text') + .attr('text-anchor', 'start') + .attr('class','nv-legend-text') + .attr('dy', '.32em') + .attr('dx', '8'); + + var seriesText = series.select('text.nv-legend-text'); + + series .on('mouseover', function(d,i) { dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects }) @@ -41,63 +100,91 @@ nv.models.legend = function() { }) .on('click', function(d,i) { dispatch.legendClick(d,i); + // make sure we re-get data in case it was modified + var data = series.data(); if (updateState) { - if (radioButtonMode) { - //Radio button mode: set every series to disabled, - // and enable the clicked series. - data.forEach(function(series) { series.disabled = true}); - d.disabled = false; - } - else { - d.disabled = !d.disabled; - if (data.every(function(series) { return series.disabled})) { - //the default behavior of NVD3 legends is, if every single series - // is disabled, turn all series' back on. - data.forEach(function(series) { series.disabled = false}); + if(vers =='classic') { + if (radioButtonMode) { + //Radio button mode: set every series to disabled, + // and enable the clicked series. + data.forEach(function(series) { series.disabled = true}); + d.disabled = false; + } + else { + d.disabled = !d.disabled; + if (data.every(function(series) { return series.disabled})) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { series.disabled = false}); + } + } + } else if(vers == 'furious') { + if(expanded) { + d.disengaged = !d.disengaged; + d.userDisabled = d.userDisabled == undefined ? !!d.disabled : d.userDisabled; + d.disabled = d.disengaged || d.userDisabled; + } else if (!expanded) { + d.disabled = !d.disabled; + d.userDisabled = d.disabled; + var engaged = data.filter(function(d) { return !d.disengaged; }); + if (engaged.every(function(series) { return series.userDisabled })) { + //the default behavior of NVD3 legends is, if every single series + // is disabled, turn all series' back on. + data.forEach(function(series) { + series.disabled = series.userDisabled = false; + }); + } } } dispatch.stateChange({ - disabled: data.map(function(d) { return !!d.disabled }) + disabled: data.map(function(d) { return !!d.disabled }), + disengaged: data.map(function(d) { return !!d.disengaged }) }); + } }) .on('dblclick', function(d,i) { + if(vers == 'furious' && expanded) return; dispatch.legendDblclick(d,i); if (updateState) { + // make sure we re-get data in case it was modified + var data = series.data(); //the default behavior of NVD3 legends, when double clicking one, // is to set all other series' to false, and make the double clicked series enabled. data.forEach(function(series) { series.disabled = true; + if(vers == 'furious') series.userDisabled = series.disabled; }); d.disabled = false; + if(vers == 'furious') d.userDisabled = d.disabled; dispatch.stateChange({ disabled: data.map(function(d) { return !!d.disabled }) }); } }); - seriesEnter.append('circle') - .style('stroke-width', 2) - .attr('class','nv-legend-symbol') - .attr('r', 5); - seriesEnter.append('text') - .attr('text-anchor', 'start') - .attr('class','nv-legend-text') - .attr('dy', '.32em') - .attr('dx', '8'); - series.classed('nv-disabled', function(d) { return d.disabled }); + + series.classed('nv-disabled', function(d) { return d.userDisabled }); series.exit().remove(); - series.select('circle') - .style('fill', function(d,i) { return d.color || color(d,i)}) - .style('stroke', function(d,i) { return d.color || color(d, i) }); - series.select('text').text(getKey); + + seriesText + .attr('fill', setTextColor) + .text(getKey); //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option) // NEW ALIGNING CODE, TODO: clean up + var legendWidth = 0; if (align) { var seriesWidths = []; series.each(function(d,i) { - var legendText = d3.select(this).select('text'); + var legendText; + if (getKey(d).length > maxKeyLength) { + var trimmedKey = getKey(d).substring(0, maxKeyLength); + legendText = d3.select(this).select('text').text(trimmedKey + "..."); + d3.select(this).append("svg:title").text(getKey(d)); + } else { + legendText = d3.select(this).select('text'); + } var nodeTextLength; try { nodeTextLength = legendText.node().getComputedTextLength(); @@ -108,12 +195,12 @@ nv.models.legend = function() { nodeTextLength = nv.utils.calcApproxTextWidth(legendText); } - seriesWidths.push(nodeTextLength + 28); // 28 is ~ the width of the circle plus some padding + seriesWidths.push(nodeTextLength + padding); }); var seriesPerRow = 0; - var legendWidth = 0; var columnWidths = []; + legendWidth = 0; while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) { columnWidths[seriesPerRow] = seriesWidths[seriesPerRow]; @@ -143,7 +230,7 @@ nv.models.legend = function() { series .attr('transform', function(d, i) { - return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * 20) + ')'; + return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * versPadding) + ')'; }); //position legend as far right as possible within the total width @@ -154,7 +241,7 @@ nv.models.legend = function() { g.attr('transform', 'translate(0' + ',' + margin.top + ')'); } - height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * 20); + height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * versPadding); } else { @@ -164,17 +251,20 @@ nv.models.legend = function() { xpos; series .attr('transform', function(d, i) { - var length = d3.select(this).select('text').node().getComputedTextLength() + 28; + var length = d3.select(this).select('text').node().getComputedTextLength() + padding; xpos = newxpos; if (width < margin.left + margin.right + xpos + length) { newxpos = xpos = 5; - ypos += 20; + ypos += versPadding; } newxpos += length; if (newxpos > maxwidth) maxwidth = newxpos; + if(legendWidth < xpos + maxwidth) { + legendWidth = xpos + maxwidth; + } return 'translate(' + xpos + ',' + ypos + ')'; }); @@ -183,8 +273,70 @@ nv.models.legend = function() { height = margin.top + margin.bottom + ypos + 15; } + + if(vers == 'furious') { + // Size rectangles after text is placed + seriesShape + .attr('width', function(d,i) { + return seriesText[0][i].getComputedTextLength() + 27; + }) + .attr('height', 18) + .attr('y', -9) + .attr('x', -15); + + // The background for the expanded legend (UI) + gEnter.insert('rect',':first-child') + .attr('class', 'nv-legend-bg') + .attr('fill', '#eee') + // .attr('stroke', '#444') + .attr('opacity',0); + + var seriesBG = g.select('.nv-legend-bg'); + + seriesBG + .transition().duration(300) + .attr('x', -versPadding ) + .attr('width', legendWidth + versPadding - 12) + .attr('height', height + 10) + .attr('y', -margin.top - 10) + .attr('opacity', expanded ? 1 : 0); + + + } + + seriesShape + .style('fill', setBGColor) + .style('fill-opacity', setBGOpacity) + .style('stroke', setBGColor); }); + function setTextColor(d,i) { + if(vers != 'furious') return '#000'; + if(expanded) { + return d.disengaged ? '#000' : '#fff'; + } else if (!expanded) { + if(!d.color) d.color = color(d,i); + return !!d.disabled ? d.color : '#fff'; + } + } + + function setBGColor(d,i) { + if(expanded && vers == 'furious') { + return d.disengaged ? '#eee' : d.color || color(d,i); + } else { + return d.color || color(d,i); + } + } + + + function setBGOpacity(d,i) { + if(expanded && vers == 'furious') { + return 1; + } else { + return !!d.disabled ? 0 : 1; + } + } + return chart; } @@ -199,11 +351,15 @@ nv.models.legend = function() { // simple options, just get/set the necessary values width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, - key: {get: function(){return getKey;}, set: function(_){getKey=_;}}, + key: {get: function(){return getKey;}, set: function(_){getKey=_;}}, align: {get: function(){return align;}, set: function(_){align=_;}}, + maxKeyLength: {get: function(){return maxKeyLength;}, set: function(_){maxKeyLength=_;}}, rightAlign: {get: function(){return rightAlign;}, set: function(_){rightAlign=_;}}, - updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}}, + padding: {get: function(){return padding;}, set: function(_){padding=_;}}, + updateState: {get: function(){return updateState;}, set: function(_){updateState=_;}}, radioButtonMode: {get: function(){return radioButtonMode;}, set: function(_){radioButtonMode=_;}}, + expanded: {get: function(){return expanded;}, set: function(_){expanded=_;}}, + vers: {get: function(){return vers;}, set: function(_){vers=_;}}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ diff --git a/src/models/line.js b/src/models/line.js index 736b41499..eacb635ce 100644 --- a/src/models/line.js +++ b/src/models/line.js @@ -11,6 +11,8 @@ nv.models.line = function() { var margin = {top: 0, right: 0, bottom: 0, left: 0} , width = 960 , height = 500 + , container = null + , strokeWidth = 1.5 , color = nv.utils.defaultColor() // a function that returns a color , getX = function(d) { return d.x } // accessor to get the x value from a data point , getY = function(d) { return d.y } // accessor to get the y value from a data point @@ -47,9 +49,9 @@ nv.models.line = function() { renderWatch.reset(); renderWatch.models(scatter); selection.each(function(data) { - var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); nv.utils.initSVG(container); // Setup Scales @@ -94,18 +96,21 @@ nv.models.line = function() { .data(function(d) { return d }, function(d) { return d.key }); groups.enter().append('g') .style('stroke-opacity', 1e-6) + .style('stroke-width', function(d) { return d.strokeWidth || strokeWidth }) .style('fill-opacity', 1e-6); groups.exit().remove(); groups - .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .attr('class', function(d,i) { + return (d.classed || '') + ' nv-group nv-series-' + i; + }) .classed('hover', function(d) { return d.hover }) .style('fill', function(d,i){ return color(d, i) }) .style('stroke', function(d,i){ return color(d, i)}); groups.watchTransition(renderWatch, 'line: groups') .style('stroke-opacity', 1) - .style('fill-opacity', .5); + .style('fill-opacity', function(d) { return d.fillOpacity || .5}); var areaPaths = groups.selectAll('path.nv-area') .data(function(d) { return isArea(d) ? [d] : [] }); // this is done differently than lines because I need to check if series is an area @@ -138,6 +143,7 @@ nv.models.line = function() { var linePaths = groups.selectAll('path.nv-line') .data(function(d) { return [d.values] }); + linePaths.enter().append('path') .attr('class', 'nv-line') .attr('d', @@ -173,9 +179,9 @@ nv.models.line = function() { chart.dispatch = dispatch; chart.scatter = scatter; // Pass through events - scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); }) - scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); }) - scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); }) + scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); }); + scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); }); + scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); }); chart.options = nv.utils.optionsFunc.bind(chart); diff --git a/src/models/lineChart.js b/src/models/lineChart.js index 68611a216..808d4861b 100644 --- a/src/models/lineChart.js +++ b/src/models/lineChart.js @@ -10,9 +10,15 @@ nv.models.lineChart = function() { , yAxis = nv.models.axis() , legend = nv.models.legend() , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() + , lines2 = nv.models.line() + , x2Axis = nv.models.axis() + , y2Axis = nv.models.axis() + , brush = d3.svg.brush() ; var margin = {top: 30, right: 20, bottom: 50, left: 60} + , margin2 = {top: 0, right: 20, bottom: 20, left: 60} , color = nv.utils.defaultColor() , width = null , height = null @@ -21,50 +27,59 @@ nv.models.lineChart = function() { , showYAxis = true , rightAlignYAxis = false , useInteractiveGuideline = false - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

    ' + key + '

    ' + - '

    ' + y + ' at ' + x + '

    ' - } , x , y + , x2 + , y2 + , focusEnable = false + , focusShowAxisY = false + , focusShowAxisX = true + , focusHeight = 50 + , brushExtent = null , state = nv.utils.state() , defaultState = null - , noData = 'No Data Available.' - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , noData = null + , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush', 'stateChange', 'changeState', 'renderEnd') , duration = 250 ; - xAxis - .orient('bottom') - .tickPadding(7) - ; - yAxis - .orient((rightAlignYAxis) ? 'right' : 'left') - ; + // set options on sub-objects for this chart + xAxis.orient('bottom').tickPadding(7); + yAxis.orient(rightAlignYAxis ? 'right' : 'left'); + + lines.clipEdge(true).duration(0); + lines2.interactive(false); + // We don't want any points emitted for the focus chart's scatter graph. + lines2.pointActive(function(d) { return false; }); + + x2Axis.orient('bottom').tickPadding(5); + y2Axis.orient(rightAlignYAxis ? 'right' : 'left'); + + tooltip.valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + + interactiveLayer.tooltip.valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, null, null, offsetElement); - }; - var renderWatch = nv.utils.renderWatch(dispatch, duration); var stateGetter = function(data) { return function(){ return { - active: data.map(function(d) { return !d.disabled }) + active: data.map(function(d) { return !d.disabled; }) }; - } + }; }; var stateSetter = function(data) { @@ -73,30 +88,31 @@ nv.models.lineChart = function() { data.forEach(function(series,i) { series.disabled = !state.active[i]; }); - } + }; }; function chart(selection) { renderWatch.reset(); renderWatch.models(lines); + renderWatch.models(lines2); if (showXAxis) renderWatch.models(xAxis); if (showYAxis) renderWatch.models(yAxis); + if (focusShowAxisX) renderWatch.models(x2Axis); + if (focusShowAxisY) renderWatch.models(y2Axis); selection.each(function(data) { - var container = d3.select(this), - that = this; + var container = d3.select(this); nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; - - - chart.update = function() { - if (duration === 0) - container.call(chart); - else - container.transition().duration(duration).call(chart) + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight1 = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focusHeight : 0), + availableHeight2 = focusHeight - margin2.top - margin2.bottom; + + chart.update = function() { + if( duration === 0 ) { + container.call( chart ); + } else { + container.transition().duration(duration).call(chart); + } }; chart.container = this; @@ -106,7 +122,7 @@ nv.models.lineChart = function() { .update(); // DEPRECATED set state.disableddisabled - state.disabled = data.map(function(d) { return !!d.disabled }); + state.disabled = data.map(function(d) { return !!d.disabled; }); if (!defaultState) { var key; @@ -120,19 +136,8 @@ nv.models.lineChart = function() { } // Display noData message if there's nothing to show. - if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + if (!data || !data.length || !data.filter(function(d) { return d.values.length; }).length) { + nv.utils.noData(chart, container); return chart; } else { container.selectAll('.nv-noData').remove(); @@ -142,22 +147,30 @@ nv.models.lineChart = function() { // Setup Scales x = lines.xScale(); y = lines.yScale(); + x2 = lines2.xScale(); + y2 = lines2.yScale(); // Setup containers and skeleton of chart var wrap = container.selectAll('g.nv-wrap.nv-lineChart').data([data]); var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineChart').append('g'); var g = wrap.select('g'); - gEnter.append("rect").style("opacity",0); - gEnter.append('g').attr('class', 'nv-x nv-axis'); - gEnter.append('g').attr('class', 'nv-y nv-axis'); - gEnter.append('g').attr('class', 'nv-linesWrap'); gEnter.append('g').attr('class', 'nv-legendWrap'); - gEnter.append('g').attr('class', 'nv-interactive'); - g.select("rect") - .attr("width",availableWidth) - .attr("height",(availableHeight > 0) ? availableHeight : 0); + var focusEnter = gEnter.append('g').attr('class', 'nv-focus'); + focusEnter.append('g').attr('class', 'nv-background').append('rect'); + focusEnter.append('g').attr('class', 'nv-x nv-axis'); + focusEnter.append('g').attr('class', 'nv-y nv-axis'); + focusEnter.append('g').attr('class', 'nv-linesWrap'); + focusEnter.append('g').attr('class', 'nv-interactive'); + + var contextEnter = gEnter.append('g').attr('class', 'nv-context'); + contextEnter.append('g').attr('class', 'nv-background').append('rect'); + contextEnter.append('g').attr('class', 'nv-x nv-axis'); + contextEnter.append('g').attr('class', 'nv-y nv-axis'); + contextEnter.append('g').attr('class', 'nv-linesWrap'); + contextEnter.append('g').attr('class', 'nv-brushBackground'); + contextEnter.append('g').attr('class', 'nv-x nv-brush'); // Legend if (showLegend) { @@ -169,12 +182,11 @@ nv.models.lineChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight1 = nv.utils.availableHeight(height, container, margin) - (focusEnable ? focusHeight : 0); } wrap.select('.nv-legendWrap') - .attr('transform', 'translate(0,' + (-margin.top) +')') + .attr('transform', 'translate(0,' + (-margin.top) +')'); } wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -188,47 +200,163 @@ nv.models.lineChart = function() { if (useInteractiveGuideline) { interactiveLayer .width(availableWidth) - .height(availableHeight) + .height(availableHeight1) .margin({left:margin.left, top:margin.top}) .svgContainer(container) .xScale(x); wrap.select(".nv-interactive").call(interactiveLayer); } + g.select('.nv-focus .nv-background rect') + .attr('width', availableWidth) + .attr('height', availableHeight1); + lines .width(availableWidth) - .height(availableHeight) + .height(availableHeight1) .color(data.map(function(d,i) { return d.color || color(d, i); - }).filter(function(d,i) { return !data[i].disabled })); + }).filter(function(d,i) { return !data[i].disabled; })); var linesWrap = g.select('.nv-linesWrap') - .datum(data.filter(function(d) { return !d.disabled })); + .datum(data.filter(function(d) { return !d.disabled; })); - linesWrap.call(lines); - // Setup Axes + // Setup Main (Focus) Axes if (showXAxis) { xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) - .tickSize(-availableHeight, 0); + ._ticks(nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight1, 0); - g.select('.nv-x.nv-axis') - .attr('transform', 'translate(0,' + y.range()[0] + ')'); - g.select('.nv-x.nv-axis') - .call(xAxis); } if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) .tickSize( -availableWidth, 0); + } + + //============================================================ + // Update Axes + //============================================================ + function updateXAxis() { + if(showXAxis) { + g.select('.nv-focus .nv-x.nv-axis') + .transition() + .duration(duration) + .call(xAxis) + ; + } + } - g.select('.nv-y.nv-axis') - .call(yAxis); + function updateYAxis() { + if(showYAxis) { + g.select('.nv-focus .nv-y.nv-axis') + .transition() + .duration(duration) + .call(yAxis) + ; + } + } + + g.select('.nv-focus .nv-x.nv-axis') + .attr('transform', 'translate(0,' + availableHeight1 + ')'); + + if( !focusEnable ) + { + linesWrap.call(lines); + updateXAxis(); + updateYAxis(); + } + else + { + lines2 + .defined(lines.defined()) + .width(availableWidth) + .height(availableHeight2) + .color(data.map(function(d,i) { + return d.color || color(d, i); + }).filter(function(d,i) { return !data[i].disabled; })); + + g.select('.nv-context') + .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')') + .style('display', focusEnable ? 'initial' : 'none') + ; + + var contextLinesWrap = g.select('.nv-context .nv-linesWrap') + .datum(data.filter(function(d) { return !d.disabled; })) + ; + + d3.transition(contextLinesWrap).call(lines2); + + + // Setup Brush + brush + .x(x2) + .on('brush', function() { + onBrush(); + }); + + if (brushExtent) brush.extent(brushExtent); + + var brushBG = g.select('.nv-brushBackground').selectAll('g') + .data([brushExtent || brush.extent()]); + + var brushBGenter = brushBG.enter() + .append('g'); + + brushBGenter.append('rect') + .attr('class', 'left') + .attr('x', 0) + .attr('y', 0) + .attr('height', availableHeight2); + + brushBGenter.append('rect') + .attr('class', 'right') + .attr('x', 0) + .attr('y', 0) + .attr('height', availableHeight2); + + var gBrush = g.select('.nv-x.nv-brush') + .call(brush); + gBrush.selectAll('rect') + .attr('height', availableHeight2); + gBrush.selectAll('.resize').append('path').attr('d', resizePath); + + onBrush(); + + g.select('.nv-context .nv-background rect') + .attr('width', availableWidth) + .attr('height', availableHeight2); + + // Setup Secondary (Context) Axes + if (focusShowAxisX) { + x2Axis + .scale(x2) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + .tickSize(-availableHeight2, 0); + + g.select('.nv-context .nv-x.nv-axis') + .attr('transform', 'translate(0,' + y2.range()[0] + ')'); + d3.transition(g.select('.nv-context .nv-x.nv-axis')) + .call(x2Axis); + } + + if (focusShowAxisY) { + y2Axis + .scale(y2) + ._ticks( nv.utils.calcTicksY(availableHeight2/36, data) ) + .tickSize( -availableWidth, 0); + + d3.transition(g.select('.nv-context .nv-y.nv-axis')) + .call(y2Axis); + } + + g.select('.nv-context .nv-x.nv-axis') + .attr('transform', 'translate(0,' + y2.range()[0] + ')'); } //============================================================ @@ -251,16 +379,25 @@ nv.models.lineChart = function() { return !series.disabled; }) .forEach(function(series,i) { - pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); - lines.highlightPoint(i, pointIndex, true); - var point = series.values[pointIndex]; - if (typeof point === 'undefined') return; - if (typeof singlePoint === 'undefined') singlePoint = point; - if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); + var extent = focusEnable ? (brush.empty() ? x2.domain() : brush.extent()) : x.domain(); + var currentValues = series.values.filter(function(d,i) { + return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; + }); + + pointIndex = nv.interactiveBisect(currentValues, e.pointXValue, lines.x()); + var point = currentValues[pointIndex]; + var pointYValue = chart.y()(point, pointIndex); + if (pointYValue !== null) { + lines.highlightPoint(i, pointIndex, true); + } + if (point === undefined) return; + if (singlePoint === undefined) singlePoint = point; + if (pointXLocation === undefined) pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); allData.push({ key: series.key, - value: chart.y()(point, pointIndex), - color: color(series,series.seriesIndex) + value: pointYValue, + color: color(series,series.seriesIndex), + data: point }); }); //Highlight the tooltip entry based on which point the mouse is closest to. @@ -268,25 +405,21 @@ nv.models.lineChart = function() { var yValue = chart.yScale().invert(e.mouseY); var domainExtent = Math.abs(chart.yScale().domain()[0] - chart.yScale().domain()[1]); var threshold = 0.03 * domainExtent; - var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value}),yValue,threshold); + var indexToHighlight = nv.nearestValueIndex(allData.map(function(d){return d.value;}),yValue,threshold); if (indexToHighlight !== null) allData[indexToHighlight].highlight = true; } - var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); interactiveLayer.tooltip - .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) - .chartContainer(that.parentNode) - .enabled(tooltips) + .chartContainer(chart.container.parentNode) .valueFormatter(function(d,i) { - return yAxis.tickFormat()(d); + return d === null ? "N/A" : yAxis.tickFormat()(d); }) - .data( - { - value: xValue, + .data({ + value: chart.x()( singlePoint,pointIndex ), + index: pointIndex, series: allData - } - )(); + })(); interactiveLayer.renderGuideLine(pointXLocation); @@ -317,16 +450,10 @@ nv.models.lineChart = function() { }); interactiveLayer.dispatch.on("elementMouseout",function(e) { - dispatch.tooltipHide(); lines.clearHighlights(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined' && data.length === e.disabled.length) { data.forEach(function(series,i) { series.disabled = e.disabled[i]; @@ -338,27 +465,100 @@ nv.models.lineChart = function() { chart.update(); }); + //============================================================ + // Functions + //------------------------------------------------------------ + + // Taken from crossfilter (http://square.github.com/crossfilter/) + function resizePath(d) { + var e = +(d == 'e'), + x = e ? 1 : -1, + y = availableHeight2 / 3; + return 'M' + (0.5 * x) + ',' + y + + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6) + + 'V' + (2 * y - 6) + + 'A6,6 0 0 ' + e + ' ' + (0.5 * x) + ',' + (2 * y) + + 'Z' + + 'M' + (2.5 * x) + ',' + (y + 8) + + 'V' + (2 * y - 8) + + 'M' + (4.5 * x) + ',' + (y + 8) + + 'V' + (2 * y - 8); + } + + + function updateBrushBG() { + if (!brush.empty()) brush.extent(brushExtent); + brushBG + .data([brush.empty() ? x2.domain() : brushExtent]) + .each(function(d,i) { + var leftWidth = x2(d[0]) - x.range()[0], + rightWidth = availableWidth - x2(d[1]); + d3.select(this).select('.left') + .attr('width', leftWidth < 0 ? 0 : leftWidth); + + d3.select(this).select('.right') + .attr('x', x2(d[1])) + .attr('width', rightWidth < 0 ? 0 : rightWidth); + }); + } + + + function onBrush() { + brushExtent = brush.empty() ? null : brush.extent(); + var extent = brush.empty() ? x2.domain() : brush.extent(); + + //The brush extent cannot be less than one. If it is, don't update the line chart. + if (Math.abs(extent[0] - extent[1]) <= 1) { + return; + } + + dispatch.brush({extent: extent, brush: brush}); + + + updateBrushBG(); + + // Update Main (Focus) + var focusLinesWrap = g.select('.nv-focus .nv-linesWrap') + .datum( + data + .filter(function(d) { return !d.disabled; }) + .map(function(d,i) { + return { + key: d.key, + area: d.area, + classed: d.classed, + values: d.values.filter(function(d,i) { + return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; + }) + }; + }) + ); + focusLinesWrap.transition().duration(duration).call(lines); + + + // Update Main (Focus) Axes + updateXAxis(); + updateYAxis(); + } + + }); renderWatch.renderEnd('lineChart immediate'); return chart; } + //============================================================ // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - lines.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - lines.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + lines.dispatch.on('elementMouseover.tooltip', function(evt) { + tooltip.data(evt).hidden(false); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + lines.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); //============================================================ @@ -368,10 +568,14 @@ nv.models.lineChart = function() { // expose chart's sub-components chart.dispatch = dispatch; chart.lines = lines; + chart.lines2 = lines2; chart.legend = legend; chart.xAxis = xAxis; + chart.x2Axis = x2Axis; chart.yAxis = yAxis; + chart.y2Axis = y2Axis; chart.interactiveLayer = interactiveLayer; + chart.tooltip = tooltip; chart.dispatch = dispatch; chart.options = nv.utils.optionsFunc.bind(chart); @@ -383,8 +587,11 @@ nv.models.lineChart = function() { showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, + focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}}, + focusHeight: {get: function(){return height2;}, set: function(_){focusHeight=_;}}, + focusShowAxisX: {get: function(){return focusShowAxisX;}, set: function(_){focusShowAxisX=_;}}, + focusShowAxisY: {get: function(){return focusShowAxisY;}, set: function(_){focusShowAxisY=_;}}, + brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, @@ -400,13 +607,41 @@ nv.models.lineChart = function() { renderWatch.reset(duration); lines.duration(duration); xAxis.duration(duration); + x2Axis.duration(duration); yAxis.duration(duration); + y2Axis.duration(duration); + }}, + focusMargin: {get: function(){return margin2;}, set: function(_){ + margin2.top = _.top !== undefined ? _.top : margin2.top; + margin2.right = _.right !== undefined ? _.right : margin2.right; + margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom; + margin2.left = _.left !== undefined ? _.left : margin2.left; }}, color: {get: function(){return color;}, set: function(_){ color = nv.utils.getColor(_); legend.color(color); lines.color(color); }}, + interpolate: {get: function(){return lines.interpolate();}, set: function(_){ + lines.interpolate(_); + lines2.interpolate(_); + }}, + xTickFormat: {get: function(){return xAxis.tickFormat();}, set: function(_){ + xAxis.tickFormat(_); + x2Axis.tickFormat(_); + }}, + yTickFormat: {get: function(){return yAxis.tickFormat();}, set: function(_){ + yAxis.tickFormat(_); + y2Axis.tickFormat(_); + }}, + x: {get: function(){return lines.x();}, set: function(_){ + lines.x(_); + lines2.x(_); + }}, + y: {get: function(){return lines.y();}, set: function(_){ + lines.y(_); + lines2.y(_); + }}, rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ rightAlignYAxis = _; yAxis.orient( rightAlignYAxis ? 'right' : 'left'); @@ -425,3 +660,9 @@ nv.models.lineChart = function() { return chart; }; + +nv.models.lineWithFocusChart = function() { + return nv.models.lineChart() + .margin({ bottom: 30 }) + .focusEnable( true ); +}; diff --git a/src/models/linePlusBarChart.js b/src/models/linePlusBarChart.js index 1c3d97d78..cbd5e193e 100644 --- a/src/models/linePlusBarChart.js +++ b/src/models/linePlusBarChart.js @@ -17,6 +17,7 @@ nv.models.linePlusBarChart = function() { , y4Axis = nv.models.axis() , legend = nv.models.legend() , brush = d3.svg.brush() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 30, bottom: 30, left: 60} @@ -33,19 +34,14 @@ nv.models.linePlusBarChart = function() { , focusHeight = 50 , extent , brushExtent = null - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

    ' + key + '

    ' + - '

    ' + y + ' at ' + x + '

    '; - } , x , x2 , y1 , y2 , y3 , y4 - , noData = "No Data Available." - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush', 'stateChange', 'changeState') + , noData = null + , dispatch = d3.dispatch('brush', 'stateChange', 'changeState') , transitionDuration = 0 , state = nv.utils.state() , defaultState = null @@ -53,50 +49,25 @@ nv.models.linePlusBarChart = function() { , legendRightAxisHint = ' (right axis)' ; - lines - .clipEdge(true) - ; - lines2 - .interactive(false) - ; - xAxis - .orient('bottom') - .tickPadding(5) - ; - y1Axis - .orient('left') - ; - y2Axis - .orient('right') - ; - x2Axis - .orient('bottom') - .tickPadding(5) - ; - y3Axis - .orient('left') - ; - y4Axis - .orient('right') - ; + lines.clipEdge(true); + lines2.interactive(false); + // We don't want any points emitted for the focus chart's scatter graph. + lines2.pointActive(function(d) { return false }); + xAxis.orient('bottom').tickPadding(5); + y1Axis.orient('left'); + y2Axis.orient('right'); + x2Axis.orient('bottom').tickPadding(5); + y3Axis.orient('left'); + y4Axis.orient('right'); + + tooltip.headerEnabled(true).headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - if (extent) { - e.pointIndex += Math.ceil(extent[0]); - } - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), - y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -114,15 +85,20 @@ nv.models.linePlusBarChart = function() { } }; + var allDisabled = function(data) { + return data.every(function(series) { + return series.disabled; + }); + } + function chart(selection) { selection.each(function(data) { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight1 = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom - (focusEnable ? focusHeight : 0) , + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight1 = nv.utils.availableHeight(height, container, margin) + - (focusEnable ? focusHeight : 0), availableHeight2 = focusHeight - margin2.top - margin2.bottom; chart.update = function() { container.transition().duration(transitionDuration).call(chart); }; @@ -149,18 +125,7 @@ nv.models.linePlusBarChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight1 / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -228,7 +193,10 @@ nv.models.linePlusBarChart = function() { //------------------------------------------------------------ if (showLegend) { - legend.width( availableWidth / 2 ); + var legendWidth = legend.align() ? availableWidth / 2 : availableWidth; + var legendXPosition = legend.align() ? legendWidth : 0; + + legend.width(legendWidth); g.select('.nv-legendWrap') .datum(data.map(function(series) { @@ -240,12 +208,12 @@ nv.models.linePlusBarChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight1 = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom - focusHeight; + // FIXME: shouldn't this be "- (focusEnabled ? focusHeight : 0)"? + availableHeight1 = nv.utils.availableHeight(height, container, margin) - focusHeight; } g.select('.nv-legendWrap') - .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')'); + .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')'); } wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -279,9 +247,11 @@ nv.models.linePlusBarChart = function() { {values: []} ]); var lines2Wrap = g.select('.nv-context .nv-linesWrap') - .datum(!dataLines[0].disabled ? dataLines : [ - {values: []} - ]); + .datum(allDisabled(dataLines) ? + [{values: []}] : + dataLines.filter(function(dataLine) { + return !dataLine.disabled; + })); g.select('.nv-context') .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')'); @@ -292,7 +262,7 @@ nv.models.linePlusBarChart = function() { // context (focus chart) axis controls if (focusShowAxisX) { x2Axis - .ticks(nv.utils.calcTicksX(availableWidth / 100, data)) + ._ticks( nv.utils.calcTicksX(availableWidth / 100, data)) .tickSize(-availableHeight2, 0); g.select('.nv-context .nv-x.nv-axis') .attr('transform', 'translate(0,' + y3.range()[0] + ')'); @@ -303,11 +273,11 @@ nv.models.linePlusBarChart = function() { if (focusShowAxisY) { y3Axis .scale(y3) - .ticks( availableHeight2 / 36 ) + ._ticks( availableHeight2 / 36 ) .tickSize( -availableWidth, 0); y4Axis .scale(y4) - .ticks( availableHeight2 / 36 ) + ._ticks( availableHeight2 / 36 ) .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none g.select('.nv-context .nv-y3.nv-axis') @@ -364,10 +334,6 @@ nv.models.linePlusBarChart = function() { chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { if (typeof e.disabled !== 'undefined') { @@ -451,10 +417,13 @@ nv.models.linePlusBarChart = function() { ); var focusLinesWrap = g.select('.nv-focus .nv-linesWrap') - .datum(dataLines[0].disabled ? [{values:[]}] : - dataLines - .map(function(d,i) { + .datum(allDisabled(dataLines) ? [{values:[]}] : + dataLines + .filter(function(dataLine) { return !dataLine.disabled; }) + .map(function(d,i) { return { + area: d.area, + fillOpacity: d.fillOpacity, key: d.key, values: d.values.filter(function(d,i) { return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; @@ -472,7 +441,7 @@ nv.models.linePlusBarChart = function() { xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight1, 0); xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]); @@ -490,17 +459,17 @@ nv.models.linePlusBarChart = function() { y1Axis .scale(y1) - .ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) .tickSize(-availableWidth, 0); y2Axis .scale(y2) - .ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none g.select('.nv-focus .nv-y1.nv-axis') .style('opacity', dataBars.length ? 1 : 0); g.select('.nv-focus .nv-y2.nv-axis') - .style('opacity', dataLines.length && !dataLines[0].disabled ? 1 : 0) + .style('opacity', dataLines.length && !allDisabled(dataLines) ? 1 : 0) .attr('transform', 'translate(' + x.range()[1] + ',0)'); g.select('.nv-focus .nv-y1.nv-axis').transition().duration(transitionDuration) @@ -520,26 +489,41 @@ nv.models.linePlusBarChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - lines.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + lines.dispatch.on('elementMouseover.tooltip', function(evt) { + tooltip + .duration(100) + .valueFormatter(function(d, i) { + return y2Axis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); }); - lines.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + lines.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) }); - bars.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + bars.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.value = chart.x()(evt.data); + evt['series'] = { + value: chart.y()(evt.data), + color: evt.color + }; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return y1Axis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); }); - bars.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + bars.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + bars.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -562,6 +546,7 @@ nv.models.linePlusBarChart = function() { chart.y2Axis = y2Axis; chart.y3Axis = y3Axis; chart.y4Axis = y4Axis; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -570,8 +555,6 @@ nv.models.linePlusBarChart = function() { width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, focusEnable: {get: function(){return focusEnable;}, set: function(_){focusEnable=_;}}, @@ -588,6 +571,12 @@ nv.models.linePlusBarChart = function() { margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; margin.left = _.left !== undefined ? _.left : margin.left; }}, + focusMargin: {get: function(){return margin2;}, set: function(_){ + margin2.top = _.top !== undefined ? _.top : margin2.top; + margin2.right = _.right !== undefined ? _.right : margin2.right; + margin2.bottom = _.bottom !== undefined ? _.bottom : margin2.bottom; + margin2.left = _.left !== undefined ? _.left : margin2.left; + }}, duration: {get: function(){return transitionDuration;}, set: function(_){ transitionDuration = _; }}, diff --git a/src/models/lineWithFocusChart.js b/src/models/lineWithFocusChart.js deleted file mode 100644 index ebb65299e..000000000 --- a/src/models/lineWithFocusChart.js +++ /dev/null @@ -1,496 +0,0 @@ -nv.models.lineWithFocusChart = function() { - "use strict"; - - //============================================================ - // Public Variables with Default Settings - //------------------------------------------------------------ - - var lines = nv.models.line() - , lines2 = nv.models.line() - , xAxis = nv.models.axis() - , yAxis = nv.models.axis() - , x2Axis = nv.models.axis() - , y2Axis = nv.models.axis() - , legend = nv.models.legend() - , brush = d3.svg.brush() - ; - - var margin = {top: 30, right: 30, bottom: 30, left: 60} - , margin2 = {top: 0, right: 30, bottom: 20, left: 60} - , color = nv.utils.defaultColor() - , width = null - , height = null - , height2 = 100 - , x - , y - , x2 - , y2 - , showLegend = true - , brushExtent = null - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

    ' + key + '

    ' + - '

    ' + y + ' at ' + x + '

    ' - } - , noData = "No Data Available." - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush', 'stateChange', 'changeState') - , transitionDuration = 250 - , state = nv.utils.state() - , defaultState = null - ; - - lines - .clipEdge(true) - ; - lines2 - .interactive(false) - ; - xAxis - .orient('bottom') - .tickPadding(5) - ; - yAxis - .orient('left') - ; - x2Axis - .orient('bottom') - .tickPadding(5) - ; - y2Axis - .orient('left') - ; - - //============================================================ - // Private Variables - //------------------------------------------------------------ - - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, null, null, offsetElement); - }; - - var stateGetter = function(data) { - return function(){ - return { - active: data.map(function(d) { return !d.disabled }) - }; - } - }; - - var stateSetter = function(data) { - return function(state) { - if (state.active !== undefined) - data.forEach(function(series,i) { - series.disabled = !state.active[i]; - }); - } - }; - - function chart(selection) { - selection.each(function(data) { - var container = d3.select(this), - that = this; - nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight1 = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom - height2, - availableHeight2 = height2 - margin2.top - margin2.bottom; - - chart.update = function() { container.transition().duration(transitionDuration).call(chart) }; - chart.container = this; - - state - .setter(stateSetter(data), chart.update) - .getter(stateGetter(data)) - .update(); - - // DEPRECATED set state.disableddisabled - state.disabled = data.map(function(d) { return !!d.disabled }); - - if (!defaultState) { - var key; - defaultState = {}; - for (key in state) { - if (state[key] instanceof Array) - defaultState[key] = state[key].slice(0); - else - defaultState[key] = state[key]; - } - } - - // Display No Data message if there's nothing to show. - if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight1 / 2) - .text(function(d) { return d }); - - return chart; - } else { - container.selectAll('.nv-noData').remove(); - } - - // Setup Scales - x = lines.xScale(); - y = lines.yScale(); - x2 = lines2.xScale(); - y2 = lines2.yScale(); - - // Setup containers and skeleton of chart - var wrap = container.selectAll('g.nv-wrap.nv-lineWithFocusChart').data([data]); - var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineWithFocusChart').append('g'); - var g = wrap.select('g'); - - gEnter.append('g').attr('class', 'nv-legendWrap'); - - var focusEnter = gEnter.append('g').attr('class', 'nv-focus'); - focusEnter.append('g').attr('class', 'nv-x nv-axis'); - focusEnter.append('g').attr('class', 'nv-y nv-axis'); - focusEnter.append('g').attr('class', 'nv-linesWrap'); - - var contextEnter = gEnter.append('g').attr('class', 'nv-context'); - contextEnter.append('g').attr('class', 'nv-x nv-axis'); - contextEnter.append('g').attr('class', 'nv-y nv-axis'); - contextEnter.append('g').attr('class', 'nv-linesWrap'); - contextEnter.append('g').attr('class', 'nv-brushBackground'); - contextEnter.append('g').attr('class', 'nv-x nv-brush'); - - // Legend - if (showLegend) { - legend.width(availableWidth); - - g.select('.nv-legendWrap') - .datum(data) - .call(legend); - - if ( margin.top != legend.height()) { - margin.top = legend.height(); - availableHeight1 = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom - height2; - } - - g.select('.nv-legendWrap') - .attr('transform', 'translate(0,' + (-margin.top) +')') - } - - wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - - // Main Chart Component(s) - lines - .width(availableWidth) - .height(availableHeight1) - .color( - data - .map(function(d,i) { - return d.color || color(d, i); - }) - .filter(function(d,i) { - return !data[i].disabled; - }) - ); - - lines2 - .defined(lines.defined()) - .width(availableWidth) - .height(availableHeight2) - .color( - data - .map(function(d,i) { - return d.color || color(d, i); - }) - .filter(function(d,i) { - return !data[i].disabled; - }) - ); - - g.select('.nv-context') - .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')') - - var contextLinesWrap = g.select('.nv-context .nv-linesWrap') - .datum(data.filter(function(d) { return !d.disabled })) - - d3.transition(contextLinesWrap).call(lines2); - - // Setup Main (Focus) Axes - xAxis - .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) - .tickSize(-availableHeight1, 0); - - yAxis - .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight1/36, data) ) - .tickSize( -availableWidth, 0); - - g.select('.nv-focus .nv-x.nv-axis') - .attr('transform', 'translate(0,' + availableHeight1 + ')'); - - // Setup Brush - brush - .x(x2) - .on('brush', function() { - //When brushing, turn off transitions because chart needs to change immediately. - var oldTransition = chart.duration(); - chart.duration(0); - onBrush(); - chart.duration(oldTransition); - }); - - if (brushExtent) brush.extent(brushExtent); - - var brushBG = g.select('.nv-brushBackground').selectAll('g') - .data([brushExtent || brush.extent()]) - - var brushBGenter = brushBG.enter() - .append('g'); - - brushBGenter.append('rect') - .attr('class', 'left') - .attr('x', 0) - .attr('y', 0) - .attr('height', availableHeight2); - - brushBGenter.append('rect') - .attr('class', 'right') - .attr('x', 0) - .attr('y', 0) - .attr('height', availableHeight2); - - var gBrush = g.select('.nv-x.nv-brush') - .call(brush); - gBrush.selectAll('rect') - //.attr('y', -5) - .attr('height', availableHeight2); - gBrush.selectAll('.resize').append('path').attr('d', resizePath); - - onBrush(); - - // Setup Secondary (Context) Axes - x2Axis - .scale(x2) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) - .tickSize(-availableHeight2, 0); - - g.select('.nv-context .nv-x.nv-axis') - .attr('transform', 'translate(0,' + y2.range()[0] + ')'); - d3.transition(g.select('.nv-context .nv-x.nv-axis')) - .call(x2Axis); - - y2Axis - .scale(y2) - .ticks( nv.utils.calcTicksY(availableHeight2/36, data) ) - .tickSize( -availableWidth, 0); - - d3.transition(g.select('.nv-context .nv-y.nv-axis')) - .call(y2Axis); - - g.select('.nv-context .nv-x.nv-axis') - .attr('transform', 'translate(0,' + y2.range()[0] + ')'); - - //============================================================ - // Event Handling/Dispatching (in chart's scope) - //------------------------------------------------------------ - - legend.dispatch.on('stateChange', function(newState) { - for (var key in newState) - state[key] = newState[key]; - dispatch.stateChange(state); - chart.update(); - }); - - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - - dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined') { - data.forEach(function(series,i) { - series.disabled = e.disabled[i]; - }); - } - chart.update(); - }); - - //============================================================ - // Functions - //------------------------------------------------------------ - - // Taken from crossfilter (http://square.github.com/crossfilter/) - function resizePath(d) { - var e = +(d == 'e'), - x = e ? 1 : -1, - y = availableHeight2 / 3; - return 'M' + (.5 * x) + ',' + y - + 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6) - + 'V' + (2 * y - 6) - + 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y) - + 'Z' - + 'M' + (2.5 * x) + ',' + (y + 8) - + 'V' + (2 * y - 8) - + 'M' + (4.5 * x) + ',' + (y + 8) - + 'V' + (2 * y - 8); - } - - - function updateBrushBG() { - if (!brush.empty()) brush.extent(brushExtent); - brushBG - .data([brush.empty() ? x2.domain() : brushExtent]) - .each(function(d,i) { - var leftWidth = x2(d[0]) - x.range()[0], - rightWidth = x.range()[1] - x2(d[1]); - d3.select(this).select('.left') - .attr('width', leftWidth < 0 ? 0 : leftWidth); - - d3.select(this).select('.right') - .attr('x', x2(d[1])) - .attr('width', rightWidth < 0 ? 0 : rightWidth); - }); - } - - - function onBrush() { - brushExtent = brush.empty() ? null : brush.extent(); - var extent = brush.empty() ? x2.domain() : brush.extent(); - - //The brush extent cannot be less than one. If it is, don't update the line chart. - if (Math.abs(extent[0] - extent[1]) <= 1) { - return; - } - - dispatch.brush({extent: extent, brush: brush}); - - - updateBrushBG(); - - // Update Main (Focus) - var focusLinesWrap = g.select('.nv-focus .nv-linesWrap') - .datum( - data - .filter(function(d) { return !d.disabled }) - .map(function(d,i) { - return { - key: d.key, - area: d.area, - values: d.values.filter(function(d,i) { - return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1]; - }) - } - }) - ); - focusLinesWrap.transition().duration(transitionDuration).call(lines); - - - // Update Main (Focus) Axes - g.select('.nv-focus .nv-x.nv-axis').transition().duration(transitionDuration) - .call(xAxis); - g.select('.nv-focus .nv-y.nv-axis').transition().duration(transitionDuration) - .call(yAxis); - } - }); - - return chart; - } - - //============================================================ - // Event Handling/Dispatching (out of chart's scope) - //------------------------------------------------------------ - - lines.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - lines.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); - }); - - //============================================================ - // Expose Public Variables - //------------------------------------------------------------ - - // expose chart's sub-components - chart.dispatch = dispatch; - chart.legend = legend; - chart.lines = lines; - chart.lines2 = lines2; - chart.xAxis = xAxis; - chart.yAxis = yAxis; - chart.x2Axis = x2Axis; - chart.y2Axis = y2Axis; - - chart.options = nv.utils.optionsFunc.bind(chart); - - chart._options = Object.create({}, { - // simple options, just get/set the necessary values - width: {get: function(){return width;}, set: function(_){width=_;}}, - height: {get: function(){return height;}, set: function(_){height=_;}}, - focusHeight: {get: function(){return height2;}, set: function(_){height2=_;}}, - showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, - brushExtent: {get: function(){return brushExtent;}, set: function(_){brushExtent=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, - defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, - noData: {get: function(){return noData;}, set: function(_){noData=_;}}, - - // options that require extra logic in the setter - margin: {get: function(){return margin;}, set: function(_){ - margin.top = _.top !== undefined ? _.top : margin.top; - margin.right = _.right !== undefined ? _.right : margin.right; - margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; - margin.left = _.left !== undefined ? _.left : margin.left; - }}, - color: {get: function(){return color;}, set: function(_){ - color = nv.utils.getColor(_); - legend.color(color); - // line color is handled above? - }}, - interpolate: {get: function(){return lines.interpolate();}, set: function(_){ - lines.interpolate(_); - lines2.interpolate(_); - }}, - xTickFormat: {get: function(){return xAxis.xTickFormat();}, set: function(_){ - xAxis.xTickFormat(_); - x2Axis.xTickFormat(_); - }}, - yTickFormat: {get: function(){return yAxis.yTickFormat();}, set: function(_){ - yAxis.yTickFormat(_); - y2Axis.yTickFormat(_); - }}, - duration: {get: function(){return transitionDuration;}, set: function(_){ - transitionDuration=_; - yAxis.duration(transitionDuration); - xAxis.duration(transitionDuration); - }}, - x: {get: function(){return lines.x();}, set: function(_){ - lines.x(_); - lines2.x(_); - }}, - y: {get: function(){return lines.y();}, set: function(_){ - lines.y(_); - lines2.y(_); - }} - }); - - nv.utils.inheritOptions(chart, lines); - nv.utils.initOptions(chart); - - return chart; -}; diff --git a/src/models/multiBar.js b/src/models/multiBar.js index d0c043d4e..938628b65 100644 --- a/src/models/multiBar.js +++ b/src/models/multiBar.js @@ -12,6 +12,7 @@ nv.models.multiBar = function() { , x = d3.scale.ordinal() , y = d3.scale.linear() , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null , getX = function(d) { return d.x } , getY = function(d) { return d.y } , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove @@ -28,7 +29,7 @@ nv.models.multiBar = function() { , xRange , yRange , groupSpacing = 0.1 - , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') ; //============================================================ @@ -45,10 +46,11 @@ nv.models.multiBar = function() { renderWatch.reset(); selection.each(function(data) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); - nv.utils.initSVG(container); + availableHeight = height - margin.top - margin.bottom; + container = d3.select(this); + nv.utils.initSVG(container); + var nonStackableCount = 0; // This function defines the requirements for render complete var endFn = function(d, i) { if (d.series === data.length - 1 && i === data[0].values.length - 1) @@ -66,53 +68,84 @@ nv.models.multiBar = function() { };} )}]; - if (stacked) - data = d3.layout.stack() + if (stacked) { + var parsed = d3.layout.stack() .offset(stackOffset) .values(function(d){ return d.values }) .y(getY) (!data.length && hideable ? hideable : data); - - //add series index to each data point for reference + parsed.forEach(function(series, i){ + // if series is non-stackable, use un-parsed data + if (series.nonStackable) { + data[i].nonStackableSeries = nonStackableCount++; + parsed[i] = data[i]; + } else { + // don't stack this seires on top of the nonStackable seriees + if (i > 0 && parsed[i - 1].nonStackable){ + parsed[i].values.map(function(d,j){ + d.y0 -= parsed[i - 1].values[j].y; + d.y1 = d.y0 + d.y; + }); + } + } + }); + data = parsed; + } + //add series index and key to each data point for reference data.forEach(function(series, i) { series.values.forEach(function(point) { point.series = i; + point.key = series.key; }); }); // HACK for negative value stacking - if (stacked) + if (stacked) { data[0].values.map(function(d,i) { var posBase = 0, negBase = 0; - data.map(function(d) { - var f = d.values[i] - f.size = Math.abs(f.y); - if (f.y<0) { - f.y1 = negBase; - negBase = negBase - f.size; - } else - { - f.y1 = f.size + posBase; - posBase = posBase + f.size; + data.map(function(d, idx) { + if (!data[idx].nonStackable) { + var f = d.values[i] + f.size = Math.abs(f.y); + if (f.y<0) { + f.y1 = negBase; + negBase = negBase - f.size; + } else + { + f.y1 = f.size + posBase; + posBase = posBase + f.size; + } } + }); }); - + } // Setup Scales // remap and flatten the data for use in calculating the scales' domains var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate - data.map(function(d) { + data.map(function(d, idx) { return d.values.map(function(d,i) { - return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 } + return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1, idx:idx } }) }); x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x })) .rangeBands(xRange || [0, availableWidth], groupSpacing); - y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 : d.y1 + d.y ) : d.y }).concat(forceY))) - .range(yRange || [availableHeight, 0]); + y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { + var domain = d.y; + // increase the domain range if this series is stackable + if (stacked && !data[d.idx].nonStackable) { + if (d.y > 0){ + domain = d.y1 + } else { + domain = d.y1 + d.y + } + } + return domain; + }).concat(forceY))) + .range(yRange || [availableHeight, 0]); // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point if (x.domain()[0] === x.domain()[1]) @@ -133,7 +166,7 @@ nv.models.multiBar = function() { var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibar'); var defsEnter = wrapEnter.append('defs'); var gEnter = wrapEnter.append('g'); - var g = wrap.select('g') + var g = wrap.select('g'); gEnter.append('g').attr('class', 'nv-groups'); wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -155,7 +188,15 @@ nv.models.multiBar = function() { var exitTransition = renderWatch .transition(groups.exit().selectAll('rect.nv-bar'), 'multibarExit', Math.min(100, duration)) - .attr('y', function(d) { return (stacked ? y0(d.y0) : y0(0)) || 0 }) + .attr('y', function(d, i, j) { + var yVal = y0(0) || 0; + if (stacked) { + if (data[d.series] && !data[d.series].nonStackable) { + yVal = y0(d.y0); + } + } + return yVal; + }) .attr('height', 0) .remove(); if (exitTransition.delay) @@ -179,11 +220,11 @@ nv.models.multiBar = function() { var barsEnter = bars.enter().append('rect') .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'}) .attr('x', function(d,i,j) { - return stacked ? 0 : (j * x.rangeBand() / data.length ) + return stacked && !data[j].nonStackable ? 0 : (j * x.rangeBand() / data.length ) }) - .attr('y', function(d) { return y0(stacked ? d.y0 : 0) || 0 }) + .attr('y', function(d,i,j) { return y0(stacked && !data[j].nonStackable ? d.y0 : 0) || 0 }) .attr('height', 0) - .attr('width', x.rangeBand() / (stacked ? 1 : data.length) ) + .attr('width', function(d,i,j) { return x.rangeBand() / (stacked && !data[j].nonStackable ? 1 : data.length) }) .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; }) ; bars @@ -192,47 +233,42 @@ nv.models.multiBar = function() { .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here d3.select(this).classed('hover', true); dispatch.elementMouseover({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('mouseout', function(d,i) { d3.select(this).classed('hover', false); dispatch.elementMouseout({ - value: getY(d,i), - point: d, - series: data[d.series], - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('click', function(d,i) { + var element = this; dispatch.elementClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill"), + event: d3.event, + element: element }); d3.event.stopPropagation(); }) .on('dblclick', function(d,i) { dispatch.elementDblClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }); @@ -252,22 +288,62 @@ nv.models.multiBar = function() { .delay(function(d,i) { return i * duration / data[0].values.length; }); - if (stacked) + if (stacked){ barSelection - .attr('y', function(d,i) { - return y((stacked ? d.y1 : 0)); + .attr('y', function(d,i,j) { + var yVal = 0; + // if stackable, stack it on top of the previous series + if (!data[j].nonStackable) { + yVal = y(d.y1); + } else { + if (getY(d,i) < 0){ + yVal = y(0); + } else { + if (y(0) - y(getY(d,i)) < -1){ + yVal = y(0) - 1; + } else { + yVal = y(getY(d, i)) || 0; + } + } + } + return yVal; }) - .attr('height', function(d,i) { - return Math.max(Math.abs(y(d.y + (stacked ? d.y0 : 0)) - y((stacked ? d.y0 : 0))),1); + .attr('height', function(d,i,j) { + if (!data[j].nonStackable) { + return Math.max(Math.abs(y(d.y+d.y0) - y(d.y0)), 0); + } else { + return Math.max(Math.abs(y(getY(d,i)) - y(0)), 0) || 0; + } }) - .attr('x', function(d,i) { - return stacked ? 0 : (d.series * x.rangeBand() / data.length ) + .attr('x', function(d,i,j) { + var width = 0; + if (data[j].nonStackable) { + width = d.series * x.rangeBand() / data.length; + if (data.length !== nonStackableCount){ + width = data[j].nonStackableSeries * x.rangeBand()/(nonStackableCount*2); + } + } + return width; }) - .attr('width', x.rangeBand() / (stacked ? 1 : data.length) ); - else + .attr('width', function(d,i,j){ + if (!data[j].nonStackable) { + return x.rangeBand(); + } else { + // if all series are nonStacable, take the full width + var width = (x.rangeBand() / nonStackableCount); + // otherwise, nonStackable graph will be only taking the half-width + // of the x rangeBand + if (data.length !== nonStackableCount) { + width = x.rangeBand()/(nonStackableCount*2); + } + return width; + } + }); + } + else { barSelection .attr('x', function(d,i) { - return d.series * x.rangeBand() / data.length + return d.series * x.rangeBand() / data.length; }) .attr('width', x.rangeBand() / data.length) .attr('y', function(d,i) { @@ -280,6 +356,7 @@ nv.models.multiBar = function() { .attr('height', function(d,i) { return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0; }); + } //store old scales for use in transitions on update x0 = x.copy(); @@ -341,11 +418,11 @@ nv.models.multiBar = function() { color = nv.utils.getColor(_); }}, barColor: {get: function(){return barColor;}, set: function(_){ - barColor = nv.utils.getColor(_); + barColor = _ ? nv.utils.getColor(_) : null; }} }); nv.utils.initOptions(chart); return chart; -}; +}; \ No newline at end of file diff --git a/src/models/multiBarChart.js b/src/models/multiBarChart.js index 240685b81..77012bef9 100644 --- a/src/models/multiBarChart.js +++ b/src/models/multiBarChart.js @@ -11,6 +11,7 @@ nv.models.multiBarChart = function() { , yAxis = nv.models.axis() , legend = nv.models.legend() , controls = nv.models.legend() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 20, bottom: 50, left: 60} @@ -25,31 +26,24 @@ nv.models.multiBarChart = function() { , rightAlignYAxis = false , reduceXTicks = true // if false a tick will show for every data point , staggerLabels = false + , wrapLabels = false , rotateLabels = 0 - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

    ' + key + '

    ' + - '

    ' + y + ' on ' + x + '

    ' - } , x //can be accessed via chart.xScale() , y //can be accessed via chart.yScale() , state = nv.utils.state() , defaultState = null - , noData = "No Data Available." - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') + , noData = null + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd') , controlWidth = function() { return showControls ? 180 : 0 } , duration = 250 ; state.stacked = false // DEPRECATED Maintained for backward compatibility - multibar - .stacked(false) - ; + multibar.stacked(false); xAxis .orient('bottom') .tickPadding(7) - .highlightZero(true) .showMaxMin(false) .tickFormat(function(d) { return d }) ; @@ -58,6 +52,15 @@ nv.models.multiBarChart = function() { .tickFormat(d3.format(',.1f')) ; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + controls.updateState(false); //============================================================ @@ -67,16 +70,6 @@ nv.models.multiBarChart = function() { var renderWatch = nv.utils.renderWatch(dispatch); var stacked = false; - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(multibar.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(multibar.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -107,10 +100,8 @@ nv.models.multiBarChart = function() { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { if (duration === 0) @@ -143,18 +134,7 @@ nv.models.multiBarChart = function() { // Display noData message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -179,19 +159,13 @@ nv.models.multiBarChart = function() { if (showLegend) { legend.width(availableWidth - controlWidth()); - if (multibar.barColor()) - data.forEach(function(series,i) { - series.color = d3.rgb('#ccc').darker(i * 1.5).toString(); - }); - g.select('.nv-legendWrap') .datum(data) .call(legend); if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.nv-legendWrap') @@ -237,7 +211,7 @@ nv.models.multiBarChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight, 0); g.select('.nv-x.nv-axis') @@ -271,6 +245,11 @@ nv.models.multiBarChart = function() { }); } + if (wrapLabels) { + g.selectAll('.tick text') + .call(nv.utils.wrapTicks, chart.xAxis.rangeBand()) + } + if (reduceXTicks) xTicks .filter(function(d,i) { @@ -292,7 +271,7 @@ nv.models.multiBarChart = function() { if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis') @@ -320,40 +299,33 @@ nv.models.multiBarChart = function() { switch (d.key) { case 'Grouped': + case controlLabels.grouped: multibar.stacked(false); break; case 'Stacked': + case controlLabels.stacked: multibar.stacked(true); break; } state.stacked = multibar.stacked(); dispatch.stateChange(state); - chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode) - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined') { data.forEach(function(series,i) { series.disabled = e.disabled[i]; }); - state.disabled = e.disabled; } - if (typeof e.stacked !== 'undefined') { multibar.stacked(e.stacked); state.stacked = e.stacked; stacked = e.stacked; } - chart.update(); }); }); @@ -366,16 +338,22 @@ nv.models.multiBarChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - multibar.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + multibar.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.value = chart.x()(evt.data); + evt['series'] = { + key: evt.data.key, + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - multibar.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + multibar.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + + multibar.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -386,9 +364,11 @@ nv.models.multiBarChart = function() { chart.dispatch = dispatch; chart.multibar = multibar; chart.legend = legend; + chart.controls = controls; chart.xAxis = xAxis; chart.yAxis = yAxis; chart.state = state; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -401,13 +381,12 @@ nv.models.multiBarChart = function() { controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, reduceXTicks: {get: function(){return reduceXTicks;}, set: function(_){reduceXTicks=_;}}, rotateLabels: {get: function(){return rotateLabels;}, set: function(_){rotateLabels=_;}}, staggerLabels: {get: function(){return staggerLabels;}, set: function(_){staggerLabels=_;}}, + wrapLabels: {get: function(){return wrapLabels;}, set: function(_){wrapLabels=!!_;}}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ @@ -430,6 +409,10 @@ nv.models.multiBarChart = function() { rightAlignYAxis: {get: function(){return rightAlignYAxis;}, set: function(_){ rightAlignYAxis = _; yAxis.orient( rightAlignYAxis ? 'right' : 'left'); + }}, + barColor: {get: function(){return multibar.barColor;}, set: function(_){ + multibar.barColor(_); + legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();}) }} }); diff --git a/src/models/multiBarHorizontal.js b/src/models/multiBarHorizontal.js index c5cf1593c..62e09b102 100644 --- a/src/models/multiBarHorizontal.js +++ b/src/models/multiBarHorizontal.js @@ -10,6 +10,7 @@ nv.models.multiBarHorizontal = function() { , width = 960 , height = 500 , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null , x = d3.scale.ordinal() , y = d3.scale.linear() , getX = function(d) { return d.x } @@ -23,6 +24,7 @@ nv.models.multiBarHorizontal = function() { , showValues = false , showBarLabels = false , valuePadding = 60 + , groupSpacing = 0.1 , valueFormat = d3.format(',.2f') , delay = 1200 , xDomain @@ -30,7 +32,7 @@ nv.models.multiBarHorizontal = function() { , xRange , yRange , duration = 250 - , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout','renderEnd') + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') ; //============================================================ @@ -44,8 +46,9 @@ nv.models.multiBarHorizontal = function() { renderWatch.reset(); selection.each(function(data) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); nv.utils.initSVG(container); if (stacked) @@ -55,10 +58,11 @@ nv.models.multiBarHorizontal = function() { .y(getY) (data); - //add series index to each data point for reference + //add series index and key to each data point for reference data.forEach(function(series, i) { series.values.forEach(function(point) { point.series = i; + point.key = series.key; }); }); @@ -90,7 +94,7 @@ nv.models.multiBarHorizontal = function() { }); x.domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x })) - .rangeBands(xRange || [0, availableHeight], .1); + .rangeBands(xRange || [0, availableHeight], groupSpacing); y.domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return stacked ? (d.y > 0 ? d.y1 + d.y : d.y1 ) : d.y }).concat(forceY))) @@ -147,47 +151,46 @@ nv.models.multiBarHorizontal = function() { .on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here d3.select(this).classed('hover', true); dispatch.elementMouseover({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [ y(getY(d,i) + (stacked ? d.y0 : 0)), x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length) ], - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('mouseout', function(d,i) { d3.select(this).classed('hover', false); dispatch.elementMouseout({ - value: getY(d,i), - point: d, - series: data[d.series], - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mouseout', function(d,i) { + dispatch.elementMouseout({ + data: d, + index: i, + color: d3.select(this).style("fill") + }); + }) + .on('mousemove', function(d,i) { + dispatch.elementMousemove({ + data: d, + index: i, + color: d3.select(this).style("fill") }); }) .on('click', function(d,i) { dispatch.elementClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }) .on('dblclick', function(d,i) { dispatch.elementDblClick({ - value: getY(d,i), - point: d, - series: data[d.series], - pos: [x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length), y(getY(d,i) + (stacked ? d.y0 : 0))], // TODO: Figure out why the value appears to be shifted - pointIndex: i, - seriesIndex: d.series, - e: d3.event + data: d, + index: i, + color: d3.select(this).style("fill") }); d3.event.stopPropagation(); }); @@ -218,13 +221,13 @@ nv.models.multiBarHorizontal = function() { .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' }) .attr('y', x.rangeBand() / (data.length * 2)) .attr('dy', '.32em') - .html(function(d,i) { + .text(function(d,i) { var t = valueFormat(getY(d,i)) , yerr = getYerr(d,i); if (yerr === undefined) return t; if (!yerr.length) - return t + '±' + valueFormat(Math.abs(yerr)); + return t + '±' + valueFormat(Math.abs(yerr)); return t + '+' + valueFormat(Math.abs(yerr[1])) + '-' + valueFormat(Math.abs(yerr[0])); }); bars.watchTransition(renderWatch, 'multibarhorizontal: bars') @@ -266,7 +269,7 @@ nv.models.multiBarHorizontal = function() { }) .select('rect') .attr('width', function(d,i) { - return Math.abs(y(getY(d,i) + d.y0) - y(d.y0)) + return Math.abs(y(getY(d,i) + d.y0) - y(d.y0)) || 0 }) .attr('height', x.rangeBand() ); else @@ -284,7 +287,7 @@ nv.models.multiBarHorizontal = function() { .select('rect') .attr('height', x.rangeBand() / data.length ) .attr('width', function(d,i) { - return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) + return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0 }); //store old scales for use in transitions on update @@ -327,6 +330,7 @@ nv.models.multiBarHorizontal = function() { id: {get: function(){return id;}, set: function(_){id=_;}}, valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}}, valuePadding: {get: function(){return valuePadding;}, set: function(_){valuePadding=_;}}, + groupSpacing:{get: function(){return groupSpacing;}, set: function(_){groupSpacing=_;}}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ @@ -342,12 +346,12 @@ nv.models.multiBarHorizontal = function() { color: {get: function(){return color;}, set: function(_){ color = nv.utils.getColor(_); }}, - barColor: {get: function(){return color;}, set: function(_){ - barColor = nv.utils.getColor(_); + barColor: {get: function(){return barColor;}, set: function(_){ + barColor = _ ? nv.utils.getColor(_) : null; }} }); nv.utils.initOptions(chart); return chart; -}; \ No newline at end of file +}; diff --git a/src/models/multiBarHorizontalChart.js b/src/models/multiBarHorizontalChart.js index 4fda48243..c56f4ac70 100644 --- a/src/models/multiBarHorizontalChart.js +++ b/src/models/multiBarHorizontalChart.js @@ -11,6 +11,7 @@ nv.models.multiBarHorizontalChart = function() { , yAxis = nv.models.axis() , legend = nv.models.legend().height(30) , controls = nv.models.legend().height(30) + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 20, bottom: 50, left: 60} @@ -23,30 +24,23 @@ nv.models.multiBarHorizontalChart = function() { , showXAxis = true , showYAxis = true , stacked = false - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

    ' + key + ' - ' + x + '

    ' + - '

    ' + y + '

    ' - } , x //can be accessed via chart.xScale() , y //can be accessed via chart.yScale() , state = nv.utils.state() , defaultState = null - , noData = 'No Data Available.' - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd') + , noData = null + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') , controlWidth = function() { return showControls ? 180 : 0 } , duration = 250 ; state.stacked = false; // DEPRECATED Maintained for backward compatibility - multibar - .stacked(stacked) - ; + multibar.stacked(stacked); + xAxis .orient('left') .tickPadding(5) - .highlightZero(false) .showMaxMin(false) .tickFormat(function(d) { return d }) ; @@ -55,22 +49,21 @@ nv.models.multiBarHorizontalChart = function() { .tickFormat(d3.format(',.1f')) ; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }) + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }); + controls.updateState(false); //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(multibar.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(multibar.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'e' : 'w', null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -103,10 +96,8 @@ nv.models.multiBarHorizontalChart = function() { var container = d3.select(this), that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { container.transition().duration(duration).call(chart) }; chart.container = this; @@ -134,18 +125,7 @@ nv.models.multiBarHorizontalChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -172,19 +152,13 @@ nv.models.multiBarHorizontalChart = function() { if (showLegend) { legend.width(availableWidth - controlWidth()); - if (multibar.barColor()) - data.forEach(function(series,i) { - series.color = d3.rgb('#ccc').darker(i * 1.5).toString(); - }); - g.select('.nv-legendWrap') .datum(data) .call(legend); if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.nv-legendWrap') @@ -225,7 +199,7 @@ nv.models.multiBarHorizontalChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( nv.utils.calcTicksY(availableHeight/24, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/24, data) ) .tickSize(-availableWidth, 0); g.select('.nv-x.nv-axis').call(xAxis); @@ -239,7 +213,7 @@ nv.models.multiBarHorizontalChart = function() { if (showYAxis) { yAxis .scale(y) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize( -availableHeight, 0); g.select('.nv-y.nv-axis') @@ -290,10 +264,6 @@ nv.models.multiBarHorizontalChart = function() { chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { @@ -322,16 +292,22 @@ nv.models.multiBarHorizontalChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - multibar.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + multibar.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.value = chart.x()(evt.data); + evt['series'] = { + key: evt.data.key, + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - multibar.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); + multibar.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + + multibar.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -342,9 +318,11 @@ nv.models.multiBarHorizontalChart = function() { chart.dispatch = dispatch; chart.multibar = multibar; chart.legend = legend; + chart.controls = controls; chart.xAxis = xAxis; chart.yAxis = yAxis; chart.state = state; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -357,8 +335,6 @@ nv.models.multiBarHorizontalChart = function() { controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, @@ -379,6 +355,10 @@ nv.models.multiBarHorizontalChart = function() { color: {get: function(){return color;}, set: function(_){ color = nv.utils.getColor(_); legend.color(color); + }}, + barColor: {get: function(){return multibar.barColor;}, set: function(_){ + multibar.barColor(_); + legend.color(function(d,i) {return d3.rgb('#ccc').darker(i * 1.5).toString();}) }} }); diff --git a/src/models/multiChart.js b/src/models/multiChart.js index cdf07e3c1..4f53aeee0 100644 --- a/src/models/multiChart.js +++ b/src/models/multiChart.js @@ -10,19 +10,13 @@ nv.models.multiChart = function() { width = null, height = null, showLegend = true, - tooltips = true, - tooltip = function(key, x, y, e, graph) { - return '

    ' + key + '

    ' + - '

    ' + y + ' at ' + x + '

    ' - }, - x, - y, - noData = 'No Data Available.', + noData = null, yDomain1, yDomain2, getX = function(d) { return d.x }, getY = function(d) { return d.y}, - interpolate = 'monotone' + interpolate = 'monotone', + useVoronoi = true ; //============================================================ @@ -36,6 +30,9 @@ nv.models.multiChart = function() { lines1 = nv.models.line().yScale(yScale1), lines2 = nv.models.line().yScale(yScale2), + scatters1 = nv.models.scatter().yScale(yScale1), + scatters2 = nv.models.scatter().yScale(yScale2), + bars1 = nv.models.multiBar().stacked(false).yScale(yScale1), bars2 = nv.models.multiBar().stacked(false).yScale(yScale2), @@ -47,17 +44,8 @@ nv.models.multiChart = function() { yAxis2 = nv.models.axis().scale(yScale2).orient('right'), legend = nv.models.legend().height(30), - dispatch = d3.dispatch('tooltipShow', 'tooltipHide'); - - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(lines1.x()(e.point, e.pointIndex)), - y = ((e.series.yAxis == 2) ? yAxis2 : yAxis1).tickFormat()(lines1.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, undefined, undefined, offsetElement.offsetParent); - }; + tooltip = nv.models.tooltip(), + dispatch = d3.dispatch(); function chart(selection) { selection.each(function(data) { @@ -68,13 +56,13 @@ nv.models.multiChart = function() { chart.update = function() { container.transition().call(chart); }; chart.container = this; - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); var dataLines1 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 1}); var dataLines2 = data.filter(function(d) {return d.type == 'line' && d.yAxis == 2}); + var dataScatters1 = data.filter(function(d) {return d.type == 'scatter' && d.yAxis == 1}); + var dataScatters2 = data.filter(function(d) {return d.type == 'scatter' && d.yAxis == 2}); var dataBars1 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 1}); var dataBars2 = data.filter(function(d) {return d.type == 'bar' && d.yAxis == 2}); var dataStack1 = data.filter(function(d) {return d.type == 'area' && d.yAxis == 1}); @@ -82,18 +70,7 @@ nv.models.multiChart = function() { // Display noData message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container); return chart; } else { container.selectAll('.nv-noData').remove(); @@ -102,28 +79,30 @@ nv.models.multiChart = function() { var series1 = data.filter(function(d) {return !d.disabled && d.yAxis == 1}) .map(function(d) { return d.values.map(function(d,i) { - return { x: d.x, y: d.y } + return { x: getX(d), y: getY(d) } }) }); var series2 = data.filter(function(d) {return !d.disabled && d.yAxis == 2}) .map(function(d) { return d.values.map(function(d,i) { - return { x: d.x, y: d.y } + return { x: getX(d), y: getY(d) } }) }); - x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } )) + x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return getX(d) })) .range([0, availableWidth]); var wrap = container.selectAll('g.wrap.multiChart').data([data]); var gEnter = wrap.enter().append('g').attr('class', 'wrap nvd3 multiChart').append('g'); - gEnter.append('g').attr('class', 'x axis'); - gEnter.append('g').attr('class', 'y1 axis'); - gEnter.append('g').attr('class', 'y2 axis'); + gEnter.append('g').attr('class', 'nv-x nv-axis'); + gEnter.append('g').attr('class', 'nv-y1 nv-axis'); + gEnter.append('g').attr('class', 'nv-y2 nv-axis'); gEnter.append('g').attr('class', 'lines1Wrap'); gEnter.append('g').attr('class', 'lines2Wrap'); + gEnter.append('g').attr('class', 'scatters1Wrap'); + gEnter.append('g').attr('class', 'scatters2Wrap'); gEnter.append('g').attr('class', 'bars1Wrap'); gEnter.append('g').attr('class', 'bars2Wrap'); gEnter.append('g').attr('class', 'stack1Wrap'); @@ -137,8 +116,11 @@ nv.models.multiChart = function() { }); if (showLegend) { + var legendWidth = legend.align() ? availableWidth / 2 : availableWidth; + var legendXPosition = legend.align() ? legendWidth : 0; + + legend.width(legendWidth); legend.color(color_array); - legend.width( availableWidth / 2 ); g.select('.legendWrap') .datum(data.map(function(series) { @@ -150,12 +132,11 @@ nv.models.multiChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.legendWrap') - .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')'); + .attr('transform', 'translate(' + legendXPosition + ',' + (-margin.top) +')'); } lines1 @@ -168,6 +149,14 @@ nv.models.multiChart = function() { .height(availableHeight) .interpolate(interpolate) .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'line'})); + scatters1 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'scatter'})); + scatters2 + .width(availableWidth) + .height(availableHeight) + .color(color_array.filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'scatter'})); bars1 .width(availableWidth) .height(availableHeight) @@ -188,51 +177,44 @@ nv.models.multiChart = function() { g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); var lines1Wrap = g.select('.lines1Wrap') - .datum( - dataLines1.filter(function(d){return !d.disabled}) - ); + .datum(dataLines1.filter(function(d){return !d.disabled})); + var scatters1Wrap = g.select('.scatters1Wrap') + .datum(dataScatters1.filter(function(d){return !d.disabled})); var bars1Wrap = g.select('.bars1Wrap') - .datum( - dataBars1.filter(function(d){return !d.disabled}) - ); + .datum(dataBars1.filter(function(d){return !d.disabled})); var stack1Wrap = g.select('.stack1Wrap') - .datum( - dataStack1.filter(function(d){return !d.disabled}) - ); - + .datum(dataStack1.filter(function(d){return !d.disabled})); var lines2Wrap = g.select('.lines2Wrap') - .datum( - dataLines2.filter(function(d){return !d.disabled}) - ); + .datum(dataLines2.filter(function(d){return !d.disabled})); + var scatters2Wrap = g.select('.scatters2Wrap') + .datum(dataScatters2.filter(function(d){return !d.disabled})); var bars2Wrap = g.select('.bars2Wrap') - .datum( - dataBars2.filter(function(d){return !d.disabled}) - ); + .datum(dataBars2.filter(function(d){return !d.disabled})); var stack2Wrap = g.select('.stack2Wrap') - .datum( - dataStack2.filter(function(d){return !d.disabled}) - ); + .datum(dataStack2.filter(function(d){return !d.disabled})); var extraValue1 = dataStack1.length ? dataStack1.map(function(a){return a.values}).reduce(function(a,b){ return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}}) - }).concat([{x:0, y:0}]) : [] + }).concat([{x:0, y:0}]) : []; var extraValue2 = dataStack2.length ? dataStack2.map(function(a){return a.values}).reduce(function(a,b){ return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}}) - }).concat([{x:0, y:0}]) : [] + }).concat([{x:0, y:0}]) : []; yScale1 .domain(yDomain1 || d3.extent(d3.merge(series1).concat(extraValue1), function(d) { return d.y } )) - .range([0, availableHeight]) + .range([0, availableHeight]); yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(extraValue2), function(d) { return d.y } )) - .range([0, availableHeight]) + .range([0, availableHeight]); - lines1.yDomain(yScale1.domain()) - bars1.yDomain(yScale1.domain()) - stack1.yDomain(yScale1.domain()) + lines1.yDomain(yScale1.domain()); + scatters1.yDomain(yScale1.domain()); + bars1.yDomain(yScale1.domain()); + stack1.yDomain(yScale1.domain()); - lines2.yDomain(yScale2.domain()) - bars2.yDomain(yScale2.domain()) - stack2.yDomain(yScale2.domain()) + lines2.yDomain(yScale2.domain()); + scatters2.yDomain(yScale2.domain()); + bars2.yDomain(yScale2.domain()); + stack2.yDomain(yScale2.domain()); if(dataStack1.length){d3.transition(stack1Wrap).call(stack1);} if(dataStack2.length){d3.transition(stack2Wrap).call(stack2);} @@ -243,35 +225,38 @@ nv.models.multiChart = function() { if(dataLines1.length){d3.transition(lines1Wrap).call(lines1);} if(dataLines2.length){d3.transition(lines2Wrap).call(lines2);} + if(dataScatters1.length){d3.transition(scatters1Wrap).call(scatters1);} + if(dataScatters2.length){d3.transition(scatters2Wrap).call(scatters2);} + xAxis - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize(-availableHeight, 0); - g.select('.x.axis') + g.select('.nv-x.nv-axis') .attr('transform', 'translate(0,' + availableHeight + ')'); - d3.transition(g.select('.x.axis')) + d3.transition(g.select('.nv-x.nv-axis')) .call(xAxis); yAxis1 - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); - d3.transition(g.select('.y1.axis')) + d3.transition(g.select('.nv-y1.nv-axis')) .call(yAxis1); yAxis2 - .ticks( nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); - d3.transition(g.select('.y2.axis')) + d3.transition(g.select('.nv-y2.nv-axis')) .call(yAxis2); - g.select('.y1.axis') + g.select('.nv-y1.nv-axis') .classed('nv-disabled', series1.length ? false : true) .attr('transform', 'translate(' + x.range()[0] + ',0)'); - g.select('.y2.axis') + g.select('.nv-y2.nv-axis') .classed('nv-disabled', series2.length ? false : true) .attr('transform', 'translate(' + x.range()[1] + ',0)'); @@ -279,116 +264,133 @@ nv.models.multiChart = function() { chart.update(); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - - }); - - return chart; - } - - //============================================================ - // Event Handling/Dispatching (out of chart's scope) - //------------------------------------------------------------ - - lines1.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - lines1.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - - lines2.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - lines2.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - - bars1.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - bars1.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - - bars2.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - bars2.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - - stack1.dispatch.on('tooltipShow', function(e) { - //disable tooltips when value ~= 0 - //// TODO: consider removing points from voronoi that have 0 value instead of this hack - if (!Math.round(stack1.y()(e.point) * 100)) { // 100 will not be good for very small numbers... will have to think about making this valu dynamic, based on data range - setTimeout(function() { d3.selectAll('.point.hover').classed('hover', false) }, 0); - return false; - } + //============================================================ + // Event Handling/Dispatching + //------------------------------------------------------------ + + function mouseover_line(evt) { + var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1; + evt.value = evt.point.x; + evt.series = { + value: evt.point.y, + color: evt.point.color, + key: evt.series.key + }; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top], - dispatch.tooltipShow(e); - }); + function mouseover_scatter(evt) { + var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1; + evt.value = evt.point.x; + evt.series = { + value: evt.point.y, + color: evt.point.color, + key: evt.series.key + }; + tooltip + .duration(100) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } - stack1.dispatch.on('tooltipHide', function(e) { - dispatch.tooltipHide(e); - }); + function mouseover_stack(evt) { + var yaxis = data[evt.seriesIndex].yAxis === 2 ? yAxis2 : yAxis1; + evt.point['x'] = stack1.x()(evt.point); + evt.point['y'] = stack1.y()(evt.point); + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } - stack2.dispatch.on('tooltipShow', function(e) { - //disable tooltips when value ~= 0 - //// TODO: consider removing points from voronoi that have 0 value instead of this hack - if (!Math.round(stack2.y()(e.point) * 100)) { // 100 will not be good for very small numbers... will have to think about making this valu dynamic, based on data range - setTimeout(function() { d3.selectAll('.point.hover').classed('hover', false) }, 0); - return false; - } + function mouseover_bar(evt) { + var yaxis = data[evt.data.series].yAxis === 2 ? yAxis2 : yAxis1; + + evt.value = bars1.x()(evt.data); + evt['series'] = { + value: bars1.y()(evt.data), + color: evt.color, + key: evt.data.key + }; + tooltip + .duration(0) + .valueFormatter(function(d, i) { + return yaxis.tickFormat()(d, i); + }) + .data(evt) + .hidden(false); + } - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top], - dispatch.tooltipShow(e); - }); + lines1.dispatch.on('elementMouseover.tooltip', mouseover_line); + lines2.dispatch.on('elementMouseover.tooltip', mouseover_line); + lines1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + lines2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); - stack2.dispatch.on('tooltipHide', function(e) { - dispatch.tooltipHide(e); - }); + scatters1.dispatch.on('elementMouseover.tooltip', mouseover_scatter); + scatters2.dispatch.on('elementMouseover.tooltip', mouseover_scatter); + scatters1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + scatters2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); - lines1.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); + stack1.dispatch.on('elementMouseover.tooltip', mouseover_stack); + stack2.dispatch.on('elementMouseover.tooltip', mouseover_stack); + stack1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + stack2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); - lines1.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); + bars1.dispatch.on('elementMouseover.tooltip', mouseover_bar); + bars2.dispatch.on('elementMouseover.tooltip', mouseover_bar); - lines2.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); + bars1.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + bars2.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + bars1.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + bars2.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); - lines2.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); + }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); - }); + return chart; + } //============================================================ // Global getters and setters //------------------------------------------------------------ chart.dispatch = dispatch; + chart.legend = legend; chart.lines1 = lines1; chart.lines2 = lines2; + chart.scatters1 = scatters1; + chart.scatters2 = scatters2; chart.bars1 = bars1; chart.bars2 = bars2; chart.stack1 = stack1; @@ -396,6 +398,7 @@ nv.models.multiChart = function() { chart.xAxis = xAxis; chart.yAxis1 = yAxis1; chart.yAxis2 = yAxis2; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); @@ -406,8 +409,6 @@ nv.models.multiChart = function() { showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, yDomain1: {get: function(){return yDomain1;}, set: function(_){yDomain1=_;}}, yDomain2: {get: function(){return yDomain2;}, set: function(_){yDomain2=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, interpolate: {get: function(){return interpolate;}, set: function(_){interpolate=_;}}, @@ -424,12 +425,31 @@ nv.models.multiChart = function() { x: {get: function(){return getX;}, set: function(_){ getX = _; lines1.x(_); + lines2.x(_); + scatters1.x(_); + scatters2.x(_); bars1.x(_); + bars2.x(_); + stack1.x(_); + stack2.x(_); }}, y: {get: function(){return getY;}, set: function(_){ getY = _; lines1.y(_); + lines2.y(_); + scatters1.y(_); + scatters2.y(_); + stack1.y(_); + stack2.y(_); bars1.y(_); + bars2.y(_); + }}, + useVoronoi: {get: function(){return useVoronoi;}, set: function(_){ + useVoronoi=_; + lines1.useVoronoi(_); + lines2.useVoronoi(_); + stack1.useVoronoi(_); + stack2.useVoronoi(_); }} }); @@ -437,4 +457,3 @@ nv.models.multiChart = function() { return chart; }; - diff --git a/src/models/ohlcBar.js b/src/models/ohlcBar.js index 3e7131e82..2636f61e4 100644 --- a/src/models/ohlcBar.js +++ b/src/models/ohlcBar.js @@ -10,6 +10,7 @@ nv.models.ohlcBar = function() { , width = null , height = null , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null , x = d3.scale.linear() , y = d3.scale.linear() , getX = function(d) { return d.x } @@ -28,7 +29,7 @@ nv.models.ohlcBar = function() { , yDomain , xRange , yRange - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout') + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd', 'chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove') ; //============================================================ @@ -37,21 +38,22 @@ nv.models.ohlcBar = function() { function chart(selection) { selection.each(function(data) { - var container = d3.select(this); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right; - var availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); nv.utils.initSVG(container); + // ohlc bar width. + var w = (availableWidth / data[0].values.length) * .9; + // Setup Scales x.domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) )); if (padData) x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]); else - x.range(xRange || [0, availableWidth]); + x.range(xRange || [5 + w/2, availableWidth - w/2 - 5]); y.domain(yDomain || [ d3.min(data[0].values.map(getLow).concat(forceY)), @@ -105,10 +107,9 @@ nv.models.ohlcBar = function() { .data(function(d) { return d }); ticks.exit().remove(); - var ticksEnter = ticks.enter().append('path') + ticks.enter().append('path') .attr('class', function(d,i,j) { return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i }) .attr('d', function(d,i) { - var w = (availableWidth / data[0].values.length) * .9; return 'm0,0l0,' + (y(getOpen(d,i)) - y(getHigh(d,i))) @@ -171,13 +172,13 @@ nv.models.ohlcBar = function() { //Create methods to allow outside functions to highlight a specific bar. chart.highlightPoint = function(pointIndex, isHoverOver) { chart.clearHighlights(); - d3.select(".nv-ohlcBar .nv-tick-0-" + pointIndex) + container.select(".nv-ohlcBar .nv-tick-0-" + pointIndex) .classed("hover", isHoverOver) ; }; chart.clearHighlights = function() { - d3.select(".nv-ohlcBar .nv-tick.hover") + container.select(".nv-ohlcBar .nv-tick.hover") .classed("hover", false) ; }; diff --git a/src/models/parallelCoordinates.js b/src/models/parallelCoordinates.js index acf38be73..6b71007e4 100644 --- a/src/models/parallelCoordinates.js +++ b/src/models/parallelCoordinates.js @@ -1,7 +1,5 @@ - // Code adapted from Jason Davies' "Parallel Coordinates" // http://bl.ocks.org/jasondavies/1341281 - nv.models.parallelCoordinates = function() { "use strict"; @@ -9,49 +7,119 @@ nv.models.parallelCoordinates = function() { // Public Variables with Default Settings //------------------------------------------------------------ - var margin = {top: 30, right: 10, bottom: 10, left: 10} + var margin = {top: 30, right: 0, bottom: 10, left: 0} , width = null , height = null , x = d3.scale.ordinal() , y = {} - , dimensions = [] + , dimensionData = [] + , enabledDimensions = [] + , dimensionNames = [] + , displayBrush = true , color = nv.utils.defaultColor() , filters = [] , active = [] - , dispatch = d3.dispatch('brush') + , dragging = [] + , axisWithUndefinedValues = [] + , lineTension = 1 + , foreground + , background + , dimensions + , line = d3.svg.line() + , axis = d3.svg.axis() + , dispatch = d3.dispatch('brush', 'brushEnd', 'dimensionsOrder', "stateChange", 'elementClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd', 'activeChanged') ; //============================================================ // Private Variables //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + function chart(selection) { + renderWatch.reset(); selection.each(function(data) { var container = d3.select(this); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right; - var availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); nv.utils.initSVG(container); - active = data; //set all active before first brush call - //This is a placeholder until this chart is made resizeable - chart.update = function() { }; + //Convert old data to new format (name, values) + if (data[0].values === undefined) { + var newData = []; + data.forEach(function (d) { + var val = {}; + var key = Object.keys(d); + key.forEach(function (k) { if (k !== "name") val[k] = d[k] }); + newData.push({ key: d.name, values: val }); + }); + data = newData; + } + + var dataValues = data.map(function (d) {return d.values}); + if (active.length === 0) { + active = data; + }; //set all active before first brush call + + dimensionNames = dimensionData.sort(function (a, b) { return a.currentPosition - b.currentPosition; }).map(function (d) { return d.key }); + enabledDimensions = dimensionData.filter(function (d) { return !d.disabled; }); + // Setup Scales - x.rangePoints([0, availableWidth], 1).domain(dimensions); + x.rangePoints([0, availableWidth], 1).domain(enabledDimensions.map(function (d) { return d.key; })); + //Set as true if all values on an axis are missing. // Extract the list of dimensions and create a scale for each. - dimensions.forEach(function(d) { + var oldDomainMaxValue = {}; + var displayMissingValuesline = false; + + dimensionNames.forEach(function(d) { + var extent = d3.extent(dataValues, function (p) { return +p[d]; }); + var min = extent[0]; + var max = extent[1]; + var onlyUndefinedValues = false; + //If there is no values to display on an axis, set the extent to 0 + if (isNaN(min) || isNaN(max)) { + onlyUndefinedValues = true; + min = 0; + max = 0; + } + //Scale axis if there is only one value + if (min === max) { + min = min - 1; + max = max + 1; + } + var f = filters.filter(function (k) { return k.dimension == d; }); + if (f.length !== 0) { + //If there is only NaN values, keep the existing domain. + if (onlyUndefinedValues) { + min = y[d].domain()[0]; + max = y[d].domain()[1]; + } + //If the brush extent is > max (< min), keep the extent value. + else if (!f[0].hasNaN && displayBrush) { + min = min > f[0].extent[0] ? f[0].extent[0] : min; + max = max < f[0].extent[1] ? f[0].extent[1] : max; + } + //If there is NaN values brushed be sure the brush extent is on the domain. + else if (f[0].hasNaN) { + max = max < f[0].extent[1] ? f[0].extent[1] : max; + oldDomainMaxValue[d] = y[d].domain()[1]; + displayMissingValuesline = true; + } + } + //Use 90% of (availableHeight - 12) for the axis range, 12 reprensenting the space necessary to display "undefined values" text. + //The remaining 10% are used to display the missingValue line. y[d] = d3.scale.linear() - .domain(d3.extent(data, function(p) { return +p[d]; })) - .range([availableHeight, 0]); + .domain([min, max]) + .range([(availableHeight - 12) * 0.9, 0]); - y[d].brush = d3.svg.brush().y(y[d]).on('brush', brush); + axisWithUndefinedValues = []; - return d != 'name'; + y[d].brush = d3.svg.brush().y(y[d]).on('brush', brush).on('brushend', brushend); }); // Setup containers and skeleton of chart @@ -60,79 +128,217 @@ nv.models.parallelCoordinates = function() { var gEnter = wrapEnter.append('g'); var g = wrap.select('g'); - gEnter.append('g').attr('class', 'nv-parallelCoordinatesWrap'); - wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + gEnter.append('g').attr('class', 'nv-parallelCoordinates background'); + gEnter.append('g').attr('class', 'nv-parallelCoordinates foreground'); + gEnter.append('g').attr('class', 'nv-parallelCoordinates missingValuesline'); - var line = d3.svg.line(), - axis = d3.svg.axis().orient('left'), - background, - foreground; + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + line.interpolate('cardinal').tension(lineTension); + axis.orient('left'); + var axisDrag = d3.behavior.drag() + .on('dragstart', dragStart) + .on('drag', dragMove) + .on('dragend', dragEnd); + + //Add missing value line at the bottom of the chart + var missingValuesline, missingValueslineText; + var step = x.range()[1] - x.range()[0]; + if (!isNaN(step)) { + var lineData = [0 + step / 2, availableHeight - 12, availableWidth - step / 2, availableHeight - 12]; + missingValuesline = wrap.select('.missingValuesline').selectAll('line').data([lineData]); + missingValuesline.enter().append('line'); + missingValuesline.exit().remove(); + missingValuesline.attr("x1", function(d) { return d[0]; }) + .attr("y1", function(d) { return d[1]; }) + .attr("x2", function(d) { return d[2]; }) + .attr("y2", function(d) { return d[3]; }); + + //Add the text "undefined values" under the missing value line + missingValueslineText = wrap.select('.missingValuesline').selectAll('text').data(["undefined values"]); + missingValueslineText.append('text').data(["undefined values"]); + missingValueslineText.enter().append('text'); + missingValueslineText.exit().remove(); + missingValueslineText.attr("y", availableHeight) + //To have the text right align with the missingValues line, substract 92 representing the text size. + .attr("x", availableWidth - 92 - step / 2) + .text(function(d) { return d; }); + } // Add grey background lines for context. - background = gEnter.append('g') - .attr('class', 'background') - .selectAll('path') - .data(data) - .enter().append('path') - .attr('d', path) - ; + background = wrap.select('.background').selectAll('path').data(data); + background.enter().append('path'); + background.exit().remove(); + background.attr('d', path); // Add blue foreground lines for focus. - foreground = gEnter.append('g') - .attr('class', 'foreground') - .selectAll('path') - .data(data) - .enter().append('path') - .attr('d', path) - .attr('stroke', color) - ; + foreground = wrap.select('.foreground').selectAll('path').data(data); + foreground.enter().append('path') + foreground.exit().remove(); + foreground.attr('d', path) + .style("stroke-width", function (d, i) { + if (isNaN(d.stroke)) { d.stroke = 1;} return d.stroke;}) + .attr('stroke', function (d, i) { return d.color || color(d, i); }); + foreground.on("mouseover", function (d, i) { + d3.select(this).classed('hover', true).style("stroke-width", d.stroke + 2 + "px").style("stroke-opacity", 1);; + dispatch.elementMouseover({ + label: d.name, + color: d.color || color(d, i) + }); + }); + foreground.on("mouseout", function (d, i) { + d3.select(this).classed('hover', false).style("stroke-width", d.stroke + "px").style("stroke-opacity", 0.7); + dispatch.elementMouseout({ + label: d.name, + index: i + }); + }); + foreground.on('mousemove', function (d, i) { + dispatch.elementMousemove(); + }); + foreground.on('click', function (d) { + dispatch.elementClick({ + id: d.id + }); + }); // Add a group element for each dimension. - var dimension = g.selectAll('.dimension') - .data(dimensions) - .enter().append('g') - .attr('class', 'dimension') - .attr('transform', function(d) { return 'translate(' + x(d) + ',0)'; }); + dimensions = g.selectAll('.dimension').data(enabledDimensions); + var dimensionsEnter = dimensions.enter().append('g').attr('class', 'nv-parallelCoordinates dimension'); + + dimensions.attr('transform', function(d) { return 'translate(' + x(d.key) + ',0)'; }); + dimensionsEnter.append('g').attr('class', 'nv-axis'); // Add an axis and title. - dimension.append('g') - .attr('class', 'axis') - .each(function(d) { d3.select(this).call(axis.scale(y[d])); }) - .append('text') + dimensionsEnter.append('text') + .attr('class', 'nv-label') + .style("cursor", "move") + .attr('dy', '-1em') .attr('text-anchor', 'middle') - .attr('y', -9) - .text(String); + .on("mouseover", function(d, i) { + dispatch.elementMouseover({ + label: d.tooltip || d.key + }); + }) + .on("mouseout", function(d, i) { + dispatch.elementMouseout({ + label: d.tooltip + }); + }) + .on('mousemove', function (d, i) { + dispatch.elementMousemove(); + }) + .call(axisDrag); + + dimensionsEnter.append('g').attr('class', 'nv-brushBackground'); + dimensions.exit().remove(); + dimensions.select('.nv-label').text(function (d) { return d.key }); + dimensions.select('.nv-axis') + .each(function (d, i) { + d3.select(this).call(axis.scale(y[d.key]).tickFormat(d3.format(d.format))); + }); // Add and store a brush for each axis. - dimension.append('g') - .attr('class', 'brush') - .each(function(d) { d3.select(this).call(y[d].brush); }) + filters.forEach(function (f) { + //If filter brushed NaN values, keep the brush on the bottom of the axis. + var brushDomain = y[f.dimension].brush.y().domain(); + if (f.hasOnlyNaN) { + f.extent[1] = (y[f.dimension].domain()[1] - brushDomain[0]) * (f.extent[1] - f.extent[0]) / (oldDomainMaxValue[f.dimension] - f.extent[0]) + brushDomain[0]; + } + if (f.hasNaN) { + f.extent[0] = brushDomain[0]; + } + if (displayBrush) + y[f.dimension].brush.extent(f.extent); + }); + + + var actives = dimensionNames.filter(function (p) { return !y[p].brush.empty(); }), + extents = actives.map(function (p) { return y[p].brush.extent(); }); + var formerActive = active.slice(0); + + //Restore active values + active = []; + foreground.style("display", function (d) { + var isActive = actives.every(function (p, i) { + if ((isNaN(d.values[p]) || isNaN(parseFloat(d.values[p]))) && extents[i][0] == y[p].brush.y().domain()[0]) { + return true; + } + return (extents[i][0] <= d.values[p] && d.values[p] <= extents[i][1]) && !isNaN(parseFloat(d.values[p])); + }); + if (isActive) + active.push(d); + return !isActive ? "none" : null; + + }); + + if (filters.length > 0 || !nv.utils.arrayEquals(active, formerActive)) { + dispatch.activeChanged(active); + } + + //Restore axis brush + dimensions.select('.nv-brushBackground') + .each(function (d) { + d3.select(this).call(y[d.key].brush); + }) .selectAll('rect') .attr('x', -8) .attr('width', 16); // Returns the path for a given data point. function path(d) { - return line(dimensions.map(function(p) { return [x(p), y[p](d[p])]; })); + return line(enabledDimensions.map(function (p) { + //If value if missing, put the value on the missing value line + if (isNaN(d.values[p.key]) || isNaN(parseFloat(d.values[p.key])) || displayMissingValuesline) { + var domain = y[p.key].domain(); + var range = y[p.key].range(); + var min = domain[0] - (domain[1] - domain[0]) / 9; + + //If it's not already the case, allow brush to select undefined values + if (axisWithUndefinedValues.indexOf(p.key) < 0) { + + var newscale = d3.scale.linear().domain([min, domain[1]]).range([availableHeight - 12, range[1]]); + y[p.key].brush.y(newscale); + axisWithUndefinedValues.push(p.key); + } + if (isNaN(d.values[p.key]) || isNaN(parseFloat(d.values[p.key]))) { + return [x(p.key), y[p.key](min)]; + } + } + + //If parallelCoordinate contain missing values show the missing values line otherwise, hide it. + if (missingValuesline !== undefined) { + if (axisWithUndefinedValues.length > 0 || displayMissingValuesline) { + missingValuesline.style("display", "inline"); + missingValueslineText.style("display", "inline"); + } else { + missingValuesline.style("display", "none"); + missingValueslineText.style("display", "none"); + } + } + return [x(p.key), y[p.key](d.values[p.key])]; + })); } // Handles a brush event, toggling the display of foreground lines. function brush() { - var actives = dimensions.filter(function(p) { return !y[p].brush.empty(); }), + actives = dimensionNames.filter(function (p) { return !y[p].brush.empty(); }), extents = actives.map(function(p) { return y[p].brush.extent(); }); filters = []; //erase current filters actives.forEach(function(d,i) { filters[i] = { dimension: d, - extent: extents[i] + extent: extents[i], + hasNaN: false, + hasOnlyNaN: false } }); active = []; //erase current active list foreground.style('display', function(d) { var isActive = actives.every(function(p, i) { - return extents[i][0] <= d[p] && d[p] <= extents[i][1]; + if ((isNaN(d.values[p]) || isNaN(parseFloat(d.values[p]))) && extents[i][0] == y[p].brush.y().domain()[0]) return true; + return (extents[i][0] <= d.values[p] && d.values[p] <= extents[i][1]) && !isNaN(parseFloat(d.values[p])); }); if (isActive) active.push(d); return isActive ? null : 'none'; @@ -143,6 +349,57 @@ nv.models.parallelCoordinates = function() { active: active }); } + function brushend() { + var hasActiveBrush = actives.length > 0 ? true : false; + filters.forEach(function (f) { + if (f.extent[0] === y[f.dimension].brush.y().domain()[0] && axisWithUndefinedValues.length > 0) + f.hasNaN = true; + if (f.extent[1] < y[f.dimension].domain()[0]) + f.hasOnlyNaN = true; + }); + dispatch.brushEnd(active, hasActiveBrush); + } + function dragStart(d) { + dragging[d.key] = this.parentNode.__origin__ = x(d.key); + background.attr("visibility", "hidden"); + + } + + function dragMove(d) { + dragging[d.key] = Math.min(availableWidth, Math.max(0, this.parentNode.__origin__ += d3.event.x)); + foreground.attr("d", path); + enabledDimensions.sort(function (a, b) { return dimensionPosition(a.key) - dimensionPosition(b.key); }); + enabledDimensions.forEach(function (d, i) { return d.currentPosition = i; }); + x.domain(enabledDimensions.map(function (d) { return d.key; })); + dimensions.attr("transform", function(d) { return "translate(" + dimensionPosition(d.key) + ")"; }); + } + + function dragEnd(d, i) { + delete this.parentNode.__origin__; + delete dragging[d.key]; + d3.select(this.parentNode).attr("transform", "translate(" + x(d.key) + ")"); + foreground + .attr("d", path); + background + .attr("d", path) + .attr("visibility", null); + + dispatch.dimensionsOrder(enabledDimensions); + } + function resetBrush() { + filters = []; + active = []; + dispatch.stateChange(); + } + function resetDrag() { + dimensionName.map(function (d, i) { return d.currentPosition = d.originalPosition; }); + dispatch.stateChange(); + } + + function dimensionPosition(d) { + var v = dragging[d]; + return v == null ? x(d) : v; + } }); return chart; @@ -157,16 +414,53 @@ nv.models.parallelCoordinates = function() { chart._options = Object.create({}, { // simple options, just get/set the necessary values - width: {get: function(){return width;}, set: function(_){width=_;}}, - height: {get: function(){return height;}, set: function(_){height=_;}}, - dimensions: {get: function(){return dimensions;}, set: function(_){dimensions=_;}}, + width: {get: function(){return width;}, set: function(_){width= _;}}, + height: {get: function(){return height;}, set: function(_){height= _;}}, + dimensionData: { get: function () { return dimensionData; }, set: function (_) { dimensionData = _; } }, + displayBrush: { get: function () { return displayBrush; }, set: function (_) { displayBrush = _; } }, + filters: { get: function () { return filters; }, set: function (_) { filters = _; } }, + active: { get: function () { return active; }, set: function (_) { active = _; } }, + lineTension: {get: function(){return lineTension;}, set: function(_){lineTension = _;}}, + + // deprecated options + dimensions: {get: function () { return dimensionData.map(function (d){return d.key}); }, set: function (_) { + // deprecated after 1.8.1 + nv.deprecated('dimensions', 'use dimensionData instead'); + if (dimensionData.length === 0) { + _.forEach(function (k) { dimensionData.push({ key: k }) }) + } else { + _.forEach(function (k, i) { dimensionData[i].key= k }) + } + } + }, + dimensionNames: {get: function () { return dimensionData.map(function (d){return d.key}); }, set: function (_) { + // deprecated after 1.8.1 + nv.deprecated('dimensionNames', 'use dimensionData instead'); + dimensionNames = []; + if (dimensionData.length === 0) { + _.forEach(function (k) { dimensionData.push({ key: k }) }) + } else { + _.forEach(function (k, i) { dimensionData[i].key = k }) + } + + }}, + dimensionFormats: {get: function () { return dimensionData.map(function (d) { return d.format }); }, set: function (_) { + // deprecated after 1.8.1 + nv.deprecated('dimensionFormats', 'use dimensionData instead'); + if (dimensionData.length === 0) { + _.forEach(function (f) { dimensionData.push({ format: f }) }) + } else { + _.forEach(function (f, i) { dimensionData[i].format = f }) + } + + }}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ - margin.top = typeof _.top != 'undefined' ? _.top : margin.top; - margin.right = typeof _.right != 'undefined' ? _.right : margin.right; - margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom; - margin.left = typeof _.left != 'undefined' ? _.left : margin.left; + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; }}, color: {get: function(){return color;}, set: function(_){ color = nv.utils.getColor(_); diff --git a/src/models/parallelCoordinatesChart.js b/src/models/parallelCoordinatesChart.js new file mode 100644 index 000000000..b5589b0bf --- /dev/null +++ b/src/models/parallelCoordinatesChart.js @@ -0,0 +1,282 @@ +nv.models.parallelCoordinatesChart = function () { + "use strict"; + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var parallelCoordinates = nv.models.parallelCoordinates() + var legend = nv.models.legend() + var tooltip = nv.models.tooltip(); + var dimensionTooltip = nv.models.tooltip(); + + var margin = { top: 0, right: 0, bottom: 0, left: 0 } + , width = null + , height = null + , showLegend = true + , color = nv.utils.defaultColor() + , state = nv.utils.state() + , dimensionData = [] + , dimensionNames = [] + , displayBrush = true + , defaultState = null + , noData = null + , dispatch = d3.dispatch('dimensionsOrder', 'brushEnd', 'stateChange', 'changeState', 'renderEnd') + , controlWidth = function () { return showControls ? 180 : 0 } + ; + + //============================================================ + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + + var stateGetter = function(data) { + return function() { + return { + active: data.map(function(d) { return !d.disabled }) + }; + } + }; + + var stateSetter = function(data) { + return function(state) { + if(state.active !== undefined) { + data.forEach(function(series, i) { + series.disabled = !state.active[i]; + }); + } + } + }; + + //============================================================ + // Chart function + //------------------------------------------------------------ + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(parallelCoordinates); + + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var that = this; + + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { container.call(chart); }; + chart.container = this; + + state.setter(stateSetter(dimensionData), chart.update) + .getter(stateGetter(dimensionData)) + .update(); + + //set state.disabled + state.disabled = dimensionData.map(function (d) { return !!d.disabled }); + + //Keep dimensions position in memory + dimensionData = dimensionData.map(function (d) {d.disabled = !!d.disabled; return d}); + dimensionData.forEach(function (d, i) { + d.originalPosition = isNaN(d.originalPosition) ? i : d.originalPosition; + d.currentPosition = isNaN(d.currentPosition) ? i : d.currentPosition; + }); + + var currentDimensions = dimensionNames.map(function (d) { return d.key; }); + var newDimensions = dimensionData.map(function (d) { return d.key; }); + dimensionData.forEach(function (k, i) { + var idx = currentDimensions.indexOf(k.key); + if (idx < 0) { + dimensionNames.splice(i, 0, k); + } else { + var gap = dimensionNames[idx].currentPosition - dimensionNames[idx].originalPosition; + dimensionNames[idx].originalPosition = k.originalPosition; + dimensionNames[idx].currentPosition = k.originalPosition + gap; + } + }); + //Remove old dimensions + dimensionNames = dimensionNames.filter(function (d) { return newDimensions.indexOf(d.key) >= 0; }); + + if (!defaultState) { + var key; + defaultState = {}; + for(key in state) { + if(state[key] instanceof Array) + defaultState[key] = state[key].slice(0); + else + defaultState[key] = state[key]; + } + } + + // Display No Data message if there's nothing to show. + if(!data || !data.length) { + nv.utils.noData(chart, container); + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + //------------------------------------------------------------ + // Setup containers and skeleton of chart + + var wrap = container.selectAll('g.nv-wrap.nv-parallelCoordinatesChart').data([data]); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-parallelCoordinatesChart').append('g'); + + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-parallelCoordinatesWrap'); + gEnter.append('g').attr('class', 'nv-legendWrap'); + + g.select("rect") + .attr("width", availableWidth) + .attr("height", (availableHeight > 0) ? availableHeight : 0); + + // Legend + if (showLegend) { + legend.width(availableWidth) + .color(function (d) { return "rgb(188,190,192)"; }); + + g.select('.nv-legendWrap') + .datum(dimensionNames.sort(function (a, b) { return a.originalPosition - b.originalPosition; })) + .call(legend); + + if (margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + wrap.select('.nv-legendWrap') + .attr('transform', 'translate( 0 ,' + (-margin.top) + ')'); + } + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + + + + // Main Chart Component(s) + parallelCoordinates + .width(availableWidth) + .height(availableHeight) + .dimensionData(dimensionNames) + .displayBrush(displayBrush); + + var parallelCoordinatesWrap = g.select('.nv-parallelCoordinatesWrap ') + .datum(data); + + parallelCoordinatesWrap.transition().call(parallelCoordinates); + + //============================================================ + // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + //Display reset brush button + parallelCoordinates.dispatch.on('brushEnd', function (active, hasActiveBrush) { + if (hasActiveBrush) { + displayBrush = true; + dispatch.brushEnd(active); + } else { + + displayBrush = false; + } + }); + + legend.dispatch.on('stateChange', function(newState) { + for(var key in newState) { + state[key] = newState[key]; + } + dispatch.stateChange(state); + chart.update(); + }); + + //Update dimensions order and display reset sorting button + parallelCoordinates.dispatch.on('dimensionsOrder', function (e) { + dimensionNames.sort(function (a, b) { return a.currentPosition - b.currentPosition; }); + var isSorted = false; + dimensionNames.forEach(function (d, i) { + d.currentPosition = i; + if (d.currentPosition !== d.originalPosition) + isSorted = true; + }); + dispatch.dimensionsOrder(dimensionNames, isSorted); + }); + + // Update chart from a state object passed to event handler + dispatch.on('changeState', function (e) { + + if (typeof e.disabled !== 'undefined') { + dimensionNames.forEach(function (series, i) { + series.disabled = e.disabled[i]; + }); + state.disabled = e.disabled; + } + chart.update(); + }); + }); + + renderWatch.renderEnd('parraleleCoordinateChart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + parallelCoordinates.dispatch.on('elementMouseover.tooltip', function (evt) { + evt['series'] = { + key: evt.label, + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + parallelCoordinates.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) + }); + + parallelCoordinates.dispatch.on('elementMousemove.tooltip', function () { + tooltip(); + }); + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.parallelCoordinates = parallelCoordinates; + chart.legend = legend; + chart.tooltip = tooltip; + + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: { get: function () { return width; }, set: function (_) { width = _; } }, + height: { get: function () { return height; }, set: function (_) { height = _; } }, + showLegend: { get: function () { return showLegend; }, set: function (_) { showLegend = _; } }, + defaultState: { get: function () { return defaultState; }, set: function (_) { defaultState = _; } }, + dimensionData: { get: function () { return dimensionData; }, set: function (_) { dimensionData = _; } }, + displayBrush: { get: function () { return displayBrush; }, set: function (_) { displayBrush = _; } }, + noData: { get: function () { return noData; }, set: function (_) { noData = _; } }, + + // options that require extra logic in the setter + margin: { + get: function () { return margin; }, + set: function (_) { + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + } + }, + color: {get: function(){return color;}, set: function(_){ + color = nv.utils.getColor(_); + legend.color(color); + parallelCoordinates.color(color); + }} + }); + + nv.utils.inheritOptions(chart, parallelCoordinates); + nv.utils.initOptions(chart); + + return chart; + }; \ No newline at end of file diff --git a/src/models/pie.js b/src/models/pie.js index 3b2d91770..9f8bb2fd0 100644 --- a/src/models/pie.js +++ b/src/models/pie.js @@ -11,12 +11,11 @@ nv.models.pie = function() { , getX = function(d) { return d.x } , getY = function(d) { return d.y } , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null , color = nv.utils.defaultColor() , valueFormat = d3.format(',.2f') - , labelFormat = d3.format('%') , showLabels = true - , pieLabelsOutside = true - , donutLabelsOutside = false + , labelsOutside = false , labelType = "key" , labelThreshold = .02 //if slice percentage is under this, don't show label , donut = false @@ -29,10 +28,12 @@ nv.models.pie = function() { , endAngle = false , cornerRadius = 0 , donutRatio = 0.5 - , duration = 250 - , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') + , arcsRadius = [] + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'elementMousemove', 'renderEnd') ; + var arcs = []; + var arcsOver = []; //============================================================ // chart function @@ -44,11 +45,25 @@ nv.models.pie = function() { renderWatch.reset(); selection.each(function(data) { var availableWidth = width - margin.left - margin.right - ,availableHeight = height - margin.top - margin.bottom - ,radius = Math.min(availableWidth, availableHeight) / 2 - ,arcRadius = radius-(radius / 5) - ,container = d3.select(this) + , availableHeight = height - margin.top - margin.bottom + , radius = Math.min(availableWidth, availableHeight) / 2 + , arcsRadiusOuter = [] + , arcsRadiusInner = [] ; + + container = d3.select(this) + if (arcsRadius.length === 0) { + var outer = radius - radius / 5; + var inner = donutRatio * radius; + for (var i = 0; i < data[0].length; i++) { + arcsRadiusOuter.push(outer); + arcsRadiusInner.push(inner); + } + } else { + arcsRadiusOuter = arcsRadius.map(function (d) { return (d.outer - d.outer / 5) * radius; }); + arcsRadiusInner = arcsRadius.map(function (d) { return (d.inner - d.inner / 5) * radius; }); + donutRatio = d3.min(arcsRadius.map(function (d) { return (d.inner - d.inner / 5); })); + } nv.utils.initSVG(container); // Setup containers and skeleton of chart @@ -73,21 +88,33 @@ nv.models.pie = function() { }); }); + arcs = []; + arcsOver = []; + for (var i = 0; i < data[0].length; i++) { - var arc = d3.svg.arc().outerRadius(arcRadius); - var arcOver = d3.svg.arc().outerRadius(arcRadius + 5); + var arc = d3.svg.arc().outerRadius(arcsRadiusOuter[i]); + var arcOver = d3.svg.arc().outerRadius(arcsRadiusOuter[i] + 5); - if (startAngle) { - arc.startAngle(startAngle); - arcOver.startAngle(startAngle); - } - if (endAngle) { - arc.endAngle(endAngle); - arcOver.endAngle(endAngle); - } - if (donut) { - arc.innerRadius(radius * donutRatio); - arcOver.innerRadius(radius * donutRatio); + if (startAngle !== false) { + arc.startAngle(startAngle); + arcOver.startAngle(startAngle); + } + if (endAngle !== false) { + arc.endAngle(endAngle); + arcOver.endAngle(endAngle); + } + if (donut) { + arc.innerRadius(arcsRadiusInner[i]); + arcOver.innerRadius(arcsRadiusInner[i]); + } + + if (arc.cornerRadius && cornerRadius) { + arc.cornerRadius(cornerRadius); + arcOver.cornerRadius(cornerRadius); + } + + arcs.push(arc); + arcsOver.push(arcOver); } // Setup the Pie chart and choose the data element @@ -100,21 +127,16 @@ nv.models.pie = function() { pie.padAngle(padAngle); } - if (arc.cornerRadius && cornerRadius) { - arc.cornerRadius(cornerRadius); - arcOver.cornerRadius(cornerRadius); - } - // if title is specified and donut, put it in the middle if (donut && title) { - var title_g = g_pie.append('g').attr('class', 'nv-pie'); + g_pie.append("text").attr('class', 'nv-pie-title'); - title_g.append("text") + wrap.select('.nv-pie-title') .style("text-anchor", "middle") - .attr('class', 'nv-pie-title') .text(function (d) { return title; }) + .style("font-size", (Math.min(availableWidth, availableHeight)) * donutRatio * 2 / (title.length + 2) + "px") .attr("dy", "0.35em") // trick to vertically center text .attr('transform', function(d, i) { return 'translate(0, '+ titleOffset + ')'; @@ -127,105 +149,98 @@ nv.models.pie = function() { slices.exit().remove(); pieLabels.exit().remove(); - var ae = slices.enter().append('g') - ae.attr('class', 'nv-slice') - ae.on('mouseover', function(d,i){ + var ae = slices.enter().append('g'); + ae.attr('class', 'nv-slice'); + ae.on('mouseover', function(d, i) { d3.select(this).classed('hover', true); if (growOnHover) { d3.select(this).select("path").transition() .duration(70) - .attr("d", arcOver); + .attr("d", arcsOver[i]); } dispatch.elementMouseover({ - label: getX(d.data), - value: getY(d.data), - point: d.data, - pointIndex: i, - pos: [d3.event.pageX, d3.event.pageY], - id: id, + data: d.data, + index: i, color: d3.select(this).style("fill") }); }); - ae.on('mouseout', function(d,i){ + ae.on('mouseout', function(d, i) { d3.select(this).classed('hover', false); if (growOnHover) { d3.select(this).select("path").transition() .duration(50) - .attr("d", arc); + .attr("d", arcs[i]); } - dispatch.elementMouseout({ - label: getX(d.data), - value: getY(d.data), - point: d.data, - index: i, - id: id - }); + dispatch.elementMouseout({data: d.data, index: i}); }); - - slices.attr('fill', function(d,i) { return color(d, i); }) - slices.attr('stroke', function(d,i) { return color(d, i); }); - - var paths = ae.append('path').each(function(d) { - this._current = d; + ae.on('mousemove', function(d, i) { + dispatch.elementMousemove({data: d.data, index: i}); }); - - paths.on('click', function(d,i) { + ae.on('click', function(d, i) { + var element = this; dispatch.elementClick({ - label: getX(d.data), - value: getY(d.data), - point: d.data, + data: d.data, index: i, - pos: d3.event, - id: id + color: d3.select(this).style("fill"), + event: d3.event, + element: element }); - d3.event.stopPropagation(); }); - paths.on('dblclick', function(d,i) { + ae.on('dblclick', function(d, i) { dispatch.elementDblClick({ - label: getX(d.data), - value: getY(d.data), - point: d.data, + data: d.data, index: i, - pos: d3.event, - id: id + color: d3.select(this).style("fill") }); - d3.event.stopPropagation(); }); + + slices.attr('fill', function(d,i) { return color(d.data, i); }); + slices.attr('stroke', function(d,i) { return color(d.data, i); }); + + var paths = ae.append('path').each(function(d) { + this._current = d; + }); + slices.select('path') .transition() - .attr('d', arc) + .attr('d', function (d, i) { return arcs[i](d); }) .attrTween('d', arcTween); if (showLabels) { // This does the normal label - var labelsArc = d3.svg.arc().innerRadius(0); - - if (pieLabelsOutside){ - var labelsArc = arc; - } - - if (donutLabelsOutside) { - labelsArc = d3.svg.arc().outerRadius(arc.outerRadius()); + var labelsArc = []; + for (var i = 0; i < data[0].length; i++) { + labelsArc.push(arcs[i]); + + if (labelsOutside) { + if (donut) { + labelsArc[i] = d3.svg.arc().outerRadius(arcs[i].outerRadius()); + if (startAngle !== false) labelsArc[i].startAngle(startAngle); + if (endAngle !== false) labelsArc[i].endAngle(endAngle); + } + } else if (!donut) { + labelsArc[i].innerRadius(0); + } } pieLabels.enter().append("g").classed("nv-label",true).each(function(d,i) { var group = d3.select(this); - group.attr('transform', function(d) { + group.attr('transform', function (d, i) { if (labelSunbeamLayout) { - d.outerRadius = arcRadius + 10; // Set Outer Coordinate - d.innerRadius = arcRadius + 15; // Set Inner Coordinate + d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate + d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI); - if ((d.startAngle+d.endAngle)/2 < Math.PI) { + if ((d.startAngle + d.endAngle) / 2 < Math.PI) { rotateAngle -= 90; } else { rotateAngle += 90; } - return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')'; + return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')'; } else { d.outerRadius = radius + 10; // Set Outer Coordinate d.innerRadius = radius + 15; // Set Inner Coordinate - return 'translate(' + labelsArc.centroid(d) + ')' + return 'translate(' + labelsArc[i].centroid(d) + ')' } }); @@ -238,7 +253,6 @@ nv.models.pie = function() { group.append('text') .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned .style('fill', '#000') - }); var labelLocationHash = {}; @@ -248,28 +262,28 @@ nv.models.pie = function() { return Math.floor(coordinates[0]/avgWidth) * avgWidth + ',' + Math.floor(coordinates[1]/avgHeight) * avgHeight; }; - pieLabels.watchTransition(renderWatch,'pie labels').attr('transform', function(d) { + pieLabels.watchTransition(renderWatch, 'pie labels').attr('transform', function (d, i) { if (labelSunbeamLayout) { - d.outerRadius = arcRadius + 10; // Set Outer Coordinate - d.innerRadius = arcRadius + 15; // Set Inner Coordinate + d.outerRadius = arcsRadiusOuter[i] + 10; // Set Outer Coordinate + d.innerRadius = arcsRadiusOuter[i] + 15; // Set Inner Coordinate var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI); - if ((d.startAngle+d.endAngle)/2 < Math.PI) { + if ((d.startAngle + d.endAngle) / 2 < Math.PI) { rotateAngle -= 90; } else { rotateAngle += 90; } - return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')'; + return 'translate(' + labelsArc[i].centroid(d) + ') rotate(' + rotateAngle + ')'; } else { d.outerRadius = radius + 10; // Set Outer Coordinate d.innerRadius = radius + 15; // Set Inner Coordinate /* - Overlapping pie labels are not good. What this attempts to do is, prevent overlapping. - Each label location is hashed, and if a hash collision occurs, we assume an overlap. - Adjust the label's y-position to remove the overlap. - */ - var center = labelsArc.centroid(d); - if(d.value){ + Overlapping pie labels are not good. What this attempts to do is, prevent overlapping. + Each label location is hashed, and if a hash collision occurs, we assume an overlap. + Adjust the label's y-position to remove the overlap. + */ + var center = labelsArc[i].centroid(d); + if (d.value) { var hashKey = createHashKey(center); if (labelLocationHash[hashKey]) { center[1] -= avgHeight; @@ -281,15 +295,35 @@ nv.models.pie = function() { }); pieLabels.select(".nv-label text") - .style('text-anchor', labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle') //center the text on it's origin or begin/end if orthogonal aligned + .style('text-anchor', function(d,i) { + //center the text on it's origin or begin/end if orthogonal aligned + return labelSunbeamLayout ? ((d.startAngle + d.endAngle) / 2 < Math.PI ? 'start' : 'end') : 'middle'; + }) .text(function(d, i) { var percent = (d.endAngle - d.startAngle) / (2 * Math.PI); - var labelTypes = { - "key" : getX(d.data), - "value": getY(d.data), - "percent": labelFormat(percent) - }; - return (d.value && percent > labelThreshold) ? labelTypes[labelType] : ''; + var label = ''; + if (!d.value || percent < labelThreshold) return ''; + + if(typeof labelType === 'function') { + label = labelType(d, i, { + 'key': getX(d.data), + 'value': getY(d.data), + 'percent': valueFormat(percent) + }); + } else { + switch (labelType) { + case 'key': + label = getX(d.data); + break; + case 'value': + label = valueFormat(getY(d.data)); + break; + case 'percent': + label = d3.format('%')(percent); + break; + } + } + return label; }) ; } @@ -301,14 +335,14 @@ nv.models.pie = function() { return a > 90 ? a - 180 : a; } - function arcTween(a) { + function arcTween(a, idx) { a.endAngle = isNaN(a.endAngle) ? 0 : a.endAngle; a.startAngle = isNaN(a.startAngle) ? 0 : a.startAngle; if (!donut) a.innerRadius = 0; var i = d3.interpolate(this._current, a); this._current = i(0); - return function(t) { - return arc(i(t)); + return function (t) { + return arcs[idx](i(t)); }; } }); @@ -326,13 +360,13 @@ nv.models.pie = function() { chart._options = Object.create({}, { // simple options, just get/set the necessary values + arcsRadius: { get: function () { return arcsRadius; }, set: function (_) { arcsRadius = _; } }, width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, showLabels: {get: function(){return showLabels;}, set: function(_){showLabels=_;}}, title: {get: function(){return title;}, set: function(_){title=_;}}, titleOffset: {get: function(){return titleOffset;}, set: function(_){titleOffset=_;}}, labelThreshold: {get: function(){return labelThreshold;}, set: function(_){labelThreshold=_;}}, - labelFormat: {get: function(){return labelFormat;}, set: function(_){labelFormat=_;}}, valueFormat: {get: function(){return valueFormat;}, set: function(_){valueFormat=_;}}, x: {get: function(){return getX;}, set: function(_){getX=_;}}, id: {get: function(){return id;}, set: function(_){id=_;}}, @@ -341,12 +375,27 @@ nv.models.pie = function() { padAngle: {get: function(){return padAngle;}, set: function(_){padAngle=_;}}, cornerRadius: {get: function(){return cornerRadius;}, set: function(_){cornerRadius=_;}}, donutRatio: {get: function(){return donutRatio;}, set: function(_){donutRatio=_;}}, - pieLabelsOutside: {get: function(){return pieLabelsOutside;}, set: function(_){pieLabelsOutside=_;}}, - donutLabelsOutside: {get: function(){return donutLabelsOutside;}, set: function(_){donutLabelsOutside=_;}}, + labelsOutside: {get: function(){return labelsOutside;}, set: function(_){labelsOutside=_;}}, labelSunbeamLayout: {get: function(){return labelSunbeamLayout;}, set: function(_){labelSunbeamLayout=_;}}, donut: {get: function(){return donut;}, set: function(_){donut=_;}}, growOnHover: {get: function(){return growOnHover;}, set: function(_){growOnHover=_;}}, + // depreciated after 1.7.1 + pieLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){ + labelsOutside=_; + nv.deprecated('pieLabelsOutside', 'use labelsOutside instead'); + }}, + // depreciated after 1.7.1 + donutLabelsOutside: {get: function(){return labelsOutside;}, set: function(_){ + labelsOutside=_; + nv.deprecated('donutLabelsOutside', 'use labelsOutside instead'); + }}, + // deprecated after 1.7.1 + labelFormat: {get: function(){ return valueFormat;}, set: function(_) { + valueFormat=_; + nv.deprecated('labelFormat','use valueFormat instead'); + }}, + // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ margin.top = typeof _.top != 'undefined' ? _.top : margin.top; diff --git a/src/models/pieChart.js b/src/models/pieChart.js index a8fc8291e..ede105a9e 100644 --- a/src/models/pieChart.js +++ b/src/models/pieChart.js @@ -7,39 +7,32 @@ nv.models.pieChart = function() { var pie = nv.models.pie(); var legend = nv.models.legend(); + var tooltip = nv.models.tooltip(); var margin = {top: 30, right: 20, bottom: 20, left: 20} , width = null , height = null , showLegend = true + , legendPosition = "top" , color = nv.utils.defaultColor() - , tooltips = true - , tooltip = function(key, y, e, graph) { - return '

    ' + key + '

    ' - + '

    ' + y + '

    '; - } , state = nv.utils.state() , defaultState = null - , noData = "No Data Available." + , noData = null , duration = 250 - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd') + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') ; + tooltip + .duration(0) + .headerEnabled(false) + .valueFormatter(function(d, i) { + return pie.valueFormat()(d, i); + }); + //============================================================ // Private Variables //------------------------------------------------------------ - var showTooltip = function(e, offsetElement) { - var tooltipLabel = pie.x()(e.point); - var left = e.pos[0] + ( (offsetElement && offsetElement.offsetLeft) || 0 ), - top = e.pos[1] + ( (offsetElement && offsetElement.offsetTop) || 0), - y = pie.valueFormat()(pie.y()(e.point)), - content = tooltip(tooltipLabel, y, e, chart) - ; - nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var renderWatch = nv.utils.renderWatch(dispatch); var stateGetter = function(data) { @@ -73,11 +66,8 @@ nv.models.pieChart = function() { nv.utils.initSVG(container); var that = this; - var availableWidth = (width || parseInt(container.style('width'), 10) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height'), 10) || 400) - - margin.top - margin.bottom - ; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { container.transition().call(chart); }; chart.container = this; @@ -102,18 +92,7 @@ nv.models.pieChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container); return chart; } else { container.selectAll('.nv-noData').remove(); @@ -129,20 +108,34 @@ nv.models.pieChart = function() { // Legend if (showLegend) { - legend.width( availableWidth ).key(pie.x()); - - wrap.select('.nv-legendWrap') - .datum(data) - .call(legend); - - if ( margin.top != legend.height()) { - margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + if (legendPosition === "top") { + legend.width( availableWidth ).key(pie.x()); + + wrap.select('.nv-legendWrap') + .datum(data) + .call(legend); + + if ( margin.top != legend.height()) { + margin.top = legend.height(); + availableHeight = nv.utils.availableHeight(height, container, margin); + } + + wrap.select('.nv-legendWrap') + .attr('transform', 'translate(0,' + (-margin.top) +')'); + } else if (legendPosition === "right") { + var legendWidth = nv.models.legend().width(); + if (availableWidth / 2 < legendWidth) { + legendWidth = (availableWidth / 2) + } + legend.height(availableHeight).key(pie.x()); + legend.width(legendWidth); + availableWidth -= legend.width(); + + wrap.select('.nv-legendWrap') + .datum(data) + .call(legend) + .attr('transform', 'translate(' + (availableWidth) +',0)'); } - - wrap.select('.nv-legendWrap') - .attr('transform', 'translate(0,' + (-margin.top) +')'); } wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -151,7 +144,10 @@ nv.models.pieChart = function() { var pieWrap = g.select('.nv-pieWrap').datum([data]); d3.transition(pieWrap).call(pie); + //============================================================ // Event Handling/Dispatching (in chart's scope) + //------------------------------------------------------------ + legend.dispatch.on('stateChange', function(newState) { for (var key in newState) { state[key] = newState[key]; @@ -160,10 +156,6 @@ nv.models.pieChart = function() { chart.update(); }); - pie.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { if (typeof e.disabled !== 'undefined') { @@ -174,7 +166,6 @@ nv.models.pieChart = function() { } chart.update(); }); - }); renderWatch.renderEnd('pieChart immediate'); @@ -185,17 +176,21 @@ nv.models.pieChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - pie.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + pie.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: chart.x()(evt.data), + value: chart.y()(evt.data), + color: evt.color + }; + tooltip.data(evt).hidden(false); }); - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e); + pie.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + pie.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); }); //============================================================ @@ -206,16 +201,17 @@ nv.models.pieChart = function() { chart.legend = legend; chart.dispatch = dispatch; chart.pie = pie; + chart.tooltip = tooltip; chart.options = nv.utils.optionsFunc.bind(chart); // use Object get/set functionality to map between vars and chart functions chart._options = Object.create({}, { // simple options, just get/set the necessary values noData: {get: function(){return noData;}, set: function(_){noData=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, + legendPosition: {get: function(){return legendPosition;}, set: function(_){legendPosition=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + // options that require extra logic in the setter color: {get: function(){return color;}, set: function(_){ color = _; @@ -225,6 +221,12 @@ nv.models.pieChart = function() { duration: {get: function(){return duration;}, set: function(_){ duration = _; renderWatch.reset(duration); + }}, + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; }} }); nv.utils.inheritOptions(chart, pie); diff --git a/src/models/scatter.js b/src/models/scatter.js index 03f2637a6..5df07af65 100644 --- a/src/models/scatter.js +++ b/src/models/scatter.js @@ -11,6 +11,7 @@ nv.models.scatter = function() { , height = null , color = nv.utils.defaultColor() // chooses color , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one + , container = null , x = d3.scale.linear() , y = d3.scale.linear() , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area @@ -27,6 +28,7 @@ nv.models.scatter = function() { , padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding , clipEdge = false // if true, masks points within x and y scale , clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance + , showVoronoi = false // display the voronoi areas , clipRadius = function() { return 25 } // function to get the radius for voronoi point clips , xDomain = null // Override x domain (skips the calculation from data) , yDomain = null // Override y domain @@ -38,6 +40,7 @@ nv.models.scatter = function() { , dispatch = d3.dispatch('elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout', 'renderEnd') , useVoronoi = true , duration = 250 + , interactiveUpdateDelay = 300 ; @@ -49,16 +52,15 @@ nv.models.scatter = function() { , timeoutID , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips , renderWatch = nv.utils.renderWatch(dispatch, duration) + , _sizeRange_def = [16, 256] ; function chart(selection) { renderWatch.reset(); selection.each(function(data) { - var container = d3.select(this); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right; - var availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); nv.utils.initSVG(container); @@ -92,10 +94,11 @@ nv.models.scatter = function() { .range(yRange || [availableHeight, 0]); z .domain(sizeDomain || d3.extent(seriesData.map(function(d) { return d.size }).concat(forceSize))) - .range(sizeRange || [16, 256]); + .range(sizeRange || _sizeRange_def); // If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point - if (x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]) singlePoint = true; + singlePoint = x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]; + if (x.domain()[0] === x.domain()[1]) x.domain()[0] ? x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01]) @@ -120,13 +123,15 @@ nv.models.scatter = function() { // Setup containers and skeleton of chart var wrap = container.selectAll('g.nv-wrap.nv-scatter').data([data]); - var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id + (singlePoint ? ' nv-single-point' : '')); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id); var defsEnter = wrapEnter.append('defs'); var gEnter = wrapEnter.append('g'); var g = wrap.select('g'); + wrap.classed('nv-single-point', singlePoint); gEnter.append('g').attr('class', 'nv-groups'); gEnter.append('g').attr('class', 'nv-point-paths'); + wrapEnter.append('g').attr('class', 'nv-point-clips'); wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); @@ -141,36 +146,37 @@ nv.models.scatter = function() { g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : ''); function updateInteractiveLayer() { + // Always clear needs-update flag regardless of whether or not + // we will actually do anything (avoids needless invocations). + needsUpdate = false; if (!interactive) return false; - var eventElements; - - var vertices = d3.merge(data.map(function(group, groupIndex) { - return group.values - .map(function(point, pointIndex) { - // *Adding noise to make duplicates very unlikely - // *Injecting series and point index for reference - /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi. - */ - var pX = getX(point,pointIndex); - var pY = getY(point,pointIndex); - - return [x(pX)+ Math.random() * 1e-7, - y(pY)+ Math.random() * 1e-7, - groupIndex, - pointIndex, point]; //temp hack to add noise untill I think of a better way so there are no duplicates - }) - .filter(function(pointArray, pointIndex) { - return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct! - }) - }) - ); - - //inject series and point index for reference into voronoi + // inject series and point index for reference into voronoi if (useVoronoi === true) { + var vertices = d3.merge(data.map(function(group, groupIndex) { + return group.values + .map(function(point, pointIndex) { + // *Adding noise to make duplicates very unlikely + // *Injecting series and point index for reference + /* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi. + */ + var pX = getX(point,pointIndex); + var pY = getY(point,pointIndex); + + return [x(pX)+ Math.random() * 1e-4, + y(pY)+ Math.random() * 1e-4, + groupIndex, + pointIndex, point]; //temp hack to add noise until I think of a better way so there are no duplicates + }) + .filter(function(pointArray, pointIndex) { + return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct! + }) + }) + ); - if(vertices.length < 3) { + if (vertices.length == 0) return false; // No active points, we're done + if (vertices.length < 3) { // Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]); vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]); @@ -198,7 +204,7 @@ nv.models.scatter = function() { // nuke all voronoi paths on reload and recreate them wrap.select('.nv-point-paths').selectAll('path').remove(); var pointPaths = wrap.select('.nv-point-paths').selectAll('path').data(voronoi); - pointPaths + var vPointPaths = pointPaths .enter().append("svg:path") .attr("d", function(d) { if (!d || !d.data || d.data.length === 0) @@ -208,38 +214,57 @@ nv.models.scatter = function() { }) .attr("id", function(d,i) { return "nv-path-"+i; }) - .attr("clip-path", function(d,i) { return "url(#nv-clip-"+i+")"; }) + .attr("clip-path", function(d,i) { return "url(#nv-clip-"+id+"-"+i+")"; }) ; - // chain these to above to see the voronoi elements (good for debugging) - //.style("fill", d3.rgb(230, 230, 230)) - //.style('fill-opacity', 0.4) - //.style('stroke-opacity', 1) - //.style("stroke", d3.rgb(200,200,200)); + + // good for debugging point hover issues + if (showVoronoi) { + vPointPaths.style("fill", d3.rgb(230, 230, 230)) + .style('fill-opacity', 0.4) + .style('stroke-opacity', 1) + .style("stroke", d3.rgb(200,200,200)); + } if (clipVoronoi) { // voronoi sections are already set to clip, // just create the circles with the IDs they expect - var clips = wrap.append("svg:g").attr("id", "nv-point-clips"); - clips.selectAll("clipPath") - .data(vertices) + wrap.select('.nv-point-clips').selectAll('*').remove(); // must do * since it has sub-dom + var pointClips = wrap.select('.nv-point-clips').selectAll('clipPath').data(vertices); + var vPointClips = pointClips .enter().append("svg:clipPath") - .attr("id", function(d, i) { return "nv-clip-"+i;}) + .attr("id", function(d, i) { return "nv-clip-"+id+"-"+i;}) .append("svg:circle") .attr('cx', function(d) { return d[0]; }) .attr('cy', function(d) { return d[1]; }) .attr('r', clipRadius); } - var mouseEventCallback = function(d,mDispatch) { + var mouseEventCallback = function(d, mDispatch) { if (needsUpdate) return 0; var series = data[d.series]; - if (typeof series === 'undefined') return; + if (series === undefined) return; var point = series.values[d.point]; + point['color'] = color(series, d.series); + + // standardize attributes for tooltip. + point['x'] = getX(point); + point['y'] = getY(point); + + // can't just get box of event node since it's actually a voronoi polygon + var box = container.node().getBoundingClientRect(); + var scrollTop = window.pageYOffset || document.documentElement.scrollTop; + var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft; + + var pos = { + left: x(getX(point, d.point)) + box.left + scrollLeft + margin.left + 10, + top: y(getY(point, d.point)) + box.top + scrollTop + margin.top + 10 + }; mDispatch({ point: point, series: series, - pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top], + pos: pos, + relativePos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top], seriesIndex: d.series, pointIndex: d.point }); @@ -260,17 +285,6 @@ nv.models.scatter = function() { }); } else { - /* - // bring data in form needed for click handlers - var dataWithPoints = vertices.map(function(d, i) { - return { - 'data': d, - 'series': vertices[i][2], - 'point': vertices[i][3] - } - }); - */ - // add event handlers to points instead voronoi paths wrap.select('.nv-groups').selectAll('.nv-group') .selectAll('.nv-point') @@ -285,7 +299,22 @@ nv.models.scatter = function() { dispatch.elementClick({ point: point, series: series, - pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], //TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + seriesIndex: d.series, + pointIndex: i + }); + }) + .on('dblclick', function(d,i) { + if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point + var series = data[d.series], + point = series.values[i]; + + dispatch.elementDblClick({ + point: point, + series: series, + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], seriesIndex: d.series, pointIndex: i }); @@ -298,9 +327,11 @@ nv.models.scatter = function() { dispatch.elementMouseover({ point: point, series: series, - pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], seriesIndex: d.series, - pointIndex: i + pointIndex: i, + color: color(d, i) }); }) .on('mouseout', function(d,i) { @@ -311,13 +342,14 @@ nv.models.scatter = function() { dispatch.elementMouseout({ point: point, series: series, + pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],//TODO: make this pos base on the page + relativePos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top], seriesIndex: d.series, - pointIndex: i + pointIndex: i, + color: color(d, i) }); }); } - - needsUpdate = false; } needsUpdate = true; @@ -329,7 +361,9 @@ nv.models.scatter = function() { groups.exit() .remove(); groups - .attr('class', function(d,i) { return 'nv-group nv-series-' + i }) + .attr('class', function(d,i) { + return (d.classed || '') + ' nv-group nv-series-' + i; + }) .classed('hover', function(d) { return d.hover }); groups.watchTransition(renderWatch, 'scatter: groups') .style('fill', function(d,i) { return color(d, i) }) @@ -337,50 +371,65 @@ nv.models.scatter = function() { .style('stroke-opacity', 1) .style('fill-opacity', .5); - // create the points + // create the points, maintaining their IDs from the original data set var points = groups.selectAll('path.nv-point') - .data(function(d) { return d.values }); + .data(function(d) { + return d.values.map( + function (point, pointIndex) { + return [point, pointIndex] + }).filter( + function(pointArray, pointIndex) { + return pointActive(pointArray[0], pointIndex) + }) + }); points.enter().append('path') - .style('fill', function (d,i) { return d.color }) - .style('stroke', function (d,i) { return d.color }) - .attr('transform', function(d,i) { - return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')' + .style('fill', function (d) { return d.color }) + .style('stroke', function (d) { return d.color }) + .attr('transform', function(d) { + return 'translate(' + x0(getX(d[0],d[1])) + ',' + y0(getY(d[0],d[1])) + ')' }) .attr('d', nv.utils.symbol() - .type(getShape) - .size(function(d,i) { return z(getSize(d,i)) }) + .type(function(d) { return getShape(d[0]); }) + .size(function(d) { return z(getSize(d[0],d[1])) }) ); points.exit().remove(); groups.exit().selectAll('path.nv-point') .watchTransition(renderWatch, 'scatter exit') - .attr('transform', function(d,i) { - return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')' + .attr('transform', function(d) { + return 'translate(' + x(getX(d[0],d[1])) + ',' + y(getY(d[0],d[1])) + ')' }) .remove(); - points.each(function(d,i) { + points.each(function(d) { d3.select(this) .classed('nv-point', true) - .classed('nv-point-' + i, true) + .classed('nv-point-' + d[1], true) + .classed('nv-noninteractive', !interactive) .classed('hover',false) ; }); points .watchTransition(renderWatch, 'scatter points') - .attr('transform', function(d,i) { - //nv.log(d,i,getX(d,i), x(getX(d,i))); - return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')' + .attr('transform', function(d) { + //nv.log(d, getX(d[0],d[1]), x(getX(d[0],d[1]))); + return 'translate(' + x(getX(d[0],d[1])) + ',' + y(getY(d[0],d[1])) + ')' }) .attr('d', nv.utils.symbol() - .type(getShape) - .size(function(d,i) { return z(getSize(d,i)) }) + .type(function(d) { return getShape(d[0]); }) + .size(function(d) { return z(getSize(d[0],d[1])) }) ); // Delay updating the invisible interactive layer for smoother animation - clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer - timeoutID = setTimeout(updateInteractiveLayer, 300); - //updateInteractiveLayer(); + if( interactiveUpdateDelay ) + { + clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer + timeoutID = setTimeout(updateInteractiveLayer, interactiveUpdateDelay ); + } + else + { + updateInteractiveLayer(); + } //store old scales for use in transitions on update x0 = x.copy(); @@ -402,12 +451,18 @@ nv.models.scatter = function() { // utility function calls provided by this chart chart._calls = new function() { this.clearHighlights = function () { - d3.selectAll(".nv-chart-" + id + " .nv-point.hover").classed("hover", false); + nv.dom.write(function() { + container.selectAll(".nv-point.hover").classed("hover", false); + }); return null; }; this.highlightPoint = function (seriesIndex, pointIndex, isHoverOver) { - d3.select(".nv-chart-" + id + " .nv-series-" + seriesIndex + " .nv-point-" + pointIndex) - .classed("hover", isHoverOver); + nv.dom.write(function() { + container.select('.nv-groups') + .selectAll(".nv-series-" + seriesIndex) + .selectAll(".nv-point-" + pointIndex) + .classed("hover", isHoverOver); + }); }; }; @@ -443,7 +498,9 @@ nv.models.scatter = function() { clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, clipVoronoi: {get: function(){return clipVoronoi;}, set: function(_){clipVoronoi=_;}}, clipRadius: {get: function(){return clipRadius;}, set: function(_){clipRadius=_;}}, + showVoronoi: {get: function(){return showVoronoi;}, set: function(_){showVoronoi=_;}}, id: {get: function(){return id;}, set: function(_){id=_;}}, + interactiveUpdateDelay: {get:function(){return interactiveUpdateDelay;}, set: function(_){interactiveUpdateDelay=_;}}, // simple functor options diff --git a/src/models/scatterChart.js b/src/models/scatterChart.js index 56c227736..1fe2f1b88 100644 --- a/src/models/scatterChart.js +++ b/src/models/scatterChart.js @@ -12,11 +12,13 @@ nv.models.scatterChart = function() { , legend = nv.models.legend() , distX = nv.models.distribution() , distY = nv.models.distribution() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 20, bottom: 50, left: 75} , width = null , height = null + , container = null , color = nv.utils.defaultColor() , x = scatter.xScale() , y = scatter.yScale() @@ -26,36 +28,28 @@ nv.models.scatterChart = function() { , showXAxis = true , showYAxis = true , rightAlignYAxis = false - , tooltips = true - , tooltipX = function(key, x, y) { return '' + x + '' } - , tooltipY = function(key, x, y) { return '' + y + '' } - , tooltip = function(key, x, y, date) { return '

    ' + key + '

    ' - + '

    ' + date + '

    ' } , state = nv.utils.state() , defaultState = null - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState', 'renderEnd') - , noData = "No Data Available." + , dispatch = d3.dispatch('stateChange', 'changeState', 'renderEnd') + , noData = null , duration = 250 ; - scatter - .xScale(x) - .yScale(y) - ; - xAxis - .orient('bottom') - .tickPadding(10) - ; + scatter.xScale(x).yScale(y); + xAxis.orient('bottom').tickPadding(10); yAxis .orient((rightAlignYAxis) ? 'right' : 'left') .tickPadding(10) ; - distX - .axis('x') - ; - distY - .axis('y') - ; + distX.axis('x'); + distY.axis('y'); + tooltip + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }); //============================================================ // Private Variables @@ -64,25 +58,6 @@ nv.models.scatterChart = function() { var x0, y0 , renderWatch = nv.utils.renderWatch(dispatch, duration); - var showTooltip = function(e, offsetElement) { - //TODO: make tooltip style an option between single or dual on axes (maybe on all charts with axes? - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - leftX = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - topX = y.range()[0] + margin.top + ( offsetElement.offsetTop || 0), - leftY = x.range()[0] + margin.left + ( offsetElement.offsetLeft || 0 ), - topY = e.pos[1] + ( offsetElement.offsetTop || 0), - xVal = xAxis.tickFormat()(scatter.x()(e.point, e.pointIndex)), - yVal = yAxis.tickFormat()(scatter.y()(e.point, e.pointIndex)); - - if( tooltipX != null ) - nv.tooltip.show([leftX, topX], tooltipX(e.series.key, xVal, yVal, e, chart), 'n', 1, offsetElement, 'x-nvtooltip'); - if( tooltipY != null ) - nv.tooltip.show([leftY, topY], tooltipY(e.series.key, xVal, yVal, e, chart), 'e', 1, offsetElement, 'y-nvtooltip'); - if( tooltip != null ) - nv.tooltip.show([left, top], tooltip(e.series.key, xVal, yVal, e.point.tooltip, e, chart), e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -109,14 +84,13 @@ nv.models.scatterChart = function() { if (showDistY) renderWatch.models(distY); selection.each(function(data) { - var container = d3.select(this), - that = this; + var that = this; + + container = d3.select(this); nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { if (duration === 0) @@ -147,20 +121,8 @@ nv.models.scatterChart = function() { // Display noData message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container); renderWatch.renderEnd('scatter immediate'); - return chart; } else { container.selectAll('.nv-noData').remove(); @@ -186,8 +148,6 @@ nv.models.scatterChart = function() { gEnter.append('g').attr('class', 'nv-distWrap'); gEnter.append('g').attr('class', 'nv-legendWrap'); - wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - if (rightAlignYAxis) { g.select(".nv-y.nv-axis") .attr("transform", "translate(" + availableWidth + ",0)"); @@ -195,7 +155,8 @@ nv.models.scatterChart = function() { // Legend if (showLegend) { - legend.width( availableWidth / 2 ); + var legendWidth = availableWidth; + legend.width(legendWidth); wrap.select('.nv-legendWrap') .datum(data) @@ -203,20 +164,22 @@ nv.models.scatterChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } wrap.select('.nv-legendWrap') - .attr('transform', 'translate(' + (availableWidth / 2) + ',' + (-margin.top) +')'); + .attr('transform', 'translate(0' + ',' + (-margin.top) +')'); } + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + // Main Chart Component(s) scatter .width(availableWidth) .height(availableHeight) .color(data.map(function(d,i) { - return d.color || color(d, i); + d.color = d.color || color(d, i); + return d.color; }).filter(function(d,i) { return !data[i].disabled })); wrap.select('.nv-scatterWrap') @@ -267,7 +230,7 @@ nv.models.scatterChart = function() { if (showXAxis) { xAxis .scale(x) - .ticks( xAxis.ticks() ? xAxis.ticks() : nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize( -availableHeight , 0); g.select('.nv-x.nv-axis') @@ -278,14 +241,14 @@ nv.models.scatterChart = function() { if (showYAxis) { yAxis .scale(y) - .ticks( yAxis.ticks() ? yAxis.ticks() : nv.utils.calcTicksY(availableHeight/36, data) ) + ._ticks( nv.utils.calcTicksY(availableHeight/36, data) ) .tickSize( -availableWidth, 0); g.select('.nv-y.nv-axis') .call(yAxis); } - + // Setup Distribution if (showDistX) { distX .getData(scatter.x()) @@ -329,35 +292,34 @@ nv.models.scatterChart = function() { chart.update(); }); - - scatter.dispatch.on('elementMouseover.tooltip', function(e) { - d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-distx-' + e.pointIndex) - .attr('y1', e.pos[1] - availableHeight); - d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-disty-' + e.pointIndex) - .attr('x2', e.pos[0] + distX.size()); - - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); - }); - - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { - if (typeof e.disabled !== 'undefined') { data.forEach(function(series,i) { series.disabled = e.disabled[i]; }); - state.disabled = e.disabled; } - chart.update(); }); + // mouseover needs availableHeight so we just keep scatter mouse events inside the chart block + scatter.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex) + .attr('y1', 0); + container.select('.nv-chart-' + scatter.id() + ' .nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex) + .attr('x2', distY.size()); + }); + + scatter.dispatch.on('elementMouseover.tooltip', function(evt) { + container.select('.nv-series-' + evt.seriesIndex + ' .nv-distx-' + evt.pointIndex) + .attr('y1', evt.relativePos[1] - availableHeight); + container.select('.nv-series-' + evt.seriesIndex + ' .nv-disty-' + evt.pointIndex) + .attr('x2', evt.relativePos[0] + distX.size()); + tooltip.data(evt).hidden(false); + }); + //store old scales for use in transitions on update x0 = x.copy(); y0 = y.copy(); @@ -368,22 +330,6 @@ nv.models.scatterChart = function() { return chart; } - //============================================================ - // Event Handling/Dispatching (out of chart's scope) - //------------------------------------------------------------ - - scatter.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - - d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-distx-' + e.pointIndex) - .attr('y1', 0); - d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-disty-' + e.pointIndex) - .attr('x2', distY.size()); - }); - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); - }); - //============================================================ // Expose Public Variables //------------------------------------------------------------ @@ -396,20 +342,19 @@ nv.models.scatterChart = function() { chart.yAxis = yAxis; chart.distX = distX; chart.distY = distY; + chart.tooltip = tooltip; + chart.options = nv.utils.optionsFunc.bind(chart); chart._options = Object.create({}, { // simple options, just get/set the necessary values width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, + container: {get: function(){return container;}, set: function(_){container=_;}}, showDistX: {get: function(){return showDistX;}, set: function(_){showDistX=_;}}, showDistY: {get: function(){return showDistY;}, set: function(_){showDistY=_;}}, showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, - tooltipXContent: {get: function(){return tooltipX;}, set: function(_){tooltipX=_;}}, - tooltipYContent: {get: function(){return tooltipY;}, set: function(_){tooltipY=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, duration: {get: function(){return duration;}, set: function(_){duration=_;}}, diff --git a/src/models/sparkline.js b/src/models/sparkline.js index 3c8d1f8b5..6dc5f0e02 100644 --- a/src/models/sparkline.js +++ b/src/models/sparkline.js @@ -9,6 +9,7 @@ nv.models.sparkline = function() { var margin = {top: 2, right: 0, bottom: 2, left: 0} , width = 400 , height = 32 + , container = null , animate = true , x = d3.scale.linear() , y = d3.scale.linear() @@ -19,13 +20,22 @@ nv.models.sparkline = function() { , yDomain , xRange , yRange + , dispatch = d3.dispatch('renderEnd') ; + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + function chart(selection) { + renderWatch.reset(); selection.each(function(data) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); nv.utils.initSVG(container); // Setup Scales @@ -83,7 +93,8 @@ nv.models.sparkline = function() { getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue' }); }); - + + renderWatch.renderEnd('sparkline immediate'); return chart; } @@ -121,6 +132,7 @@ nv.models.sparkline = function() { }} }); + chart.dispatch = dispatch; nv.utils.initOptions(chart); return chart; }; diff --git a/src/models/sparklinePlus.js b/src/models/sparklinePlus.js index bf877d1d1..d649248a1 100644 --- a/src/models/sparklinePlus.js +++ b/src/models/sparklinePlus.js @@ -17,39 +17,35 @@ nv.models.sparklinePlus = function() { , paused = false , xTickFormat = d3.format(',r') , yTickFormat = d3.format(',.2f') - , showValue = true + , showLastValue = true , alignValue = true , rightAlignValue = false - , noData = "No Data Available." + , noData = null + , dispatch = d3.dispatch('renderEnd') ; + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); function chart(selection) { + renderWatch.reset(); + renderWatch.models(sparkline); selection.each(function(data) { var container = d3.select(this); nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); - chart.update = function() { chart(selection) }; + chart.update = function() { container.call(chart); }; chart.container = this; // Display No Data message if there's nothing to show. if (!data || !data.length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -79,20 +75,24 @@ nv.models.sparklinePlus = function() { sparkline.width(availableWidth).height(availableHeight); sparklineWrap.call(sparkline); - var valueWrap = g.select('.nv-valueWrap'); - var value = valueWrap.selectAll('.nv-currentValue') - .data([currentValue]); + if (showLastValue) { + var valueWrap = g.select('.nv-valueWrap'); + var value = valueWrap.selectAll('.nv-currentValue') + .data([currentValue]); - value.enter().append('text').attr('class', 'nv-currentValue') - .attr('dx', rightAlignValue ? -8 : 8) - .attr('dy', '.9em') - .style('text-anchor', rightAlignValue ? 'end' : 'start'); - - value - .attr('x', availableWidth + (rightAlignValue ? margin.right : 0)) - .attr('y', alignValue ? function(d) { return y(d) } : 0) - .style('fill', sparkline.color()(data[data.length-1], data.length-1)) - .text(yTickFormat(currentValue)); + value.enter().append('text').attr('class', 'nv-currentValue') + .attr('dx', rightAlignValue ? -8 : 8) + .attr('dy', '.9em') + .style('text-anchor', rightAlignValue ? 'end' : 'start'); + + value + .attr('x', availableWidth + (rightAlignValue ? margin.right : 0)) + .attr('y', alignValue ? function (d) { + return y(d) + } : 0) + .style('fill', sparkline.color()(data[data.length - 1], data.length - 1)) + .text(yTickFormat(currentValue)); + } gEnter.select('.nv-hoverArea').append('rect') .on('mousemove', sparklineHover) @@ -108,7 +108,7 @@ nv.models.sparklinePlus = function() { function updateValueLine() { if (paused) return; - var hoverValue = g.selectAll('.nv-hoverValue').data(index) + var hoverValue = g.selectAll('.nv-hoverValue').data(index); var hoverEnter = hoverValue.enter() .append('g').attr('class', 'nv-hoverValue') @@ -139,7 +139,7 @@ nv.models.sparklinePlus = function() { .attr('x', -6) .attr('y', -margin.top) .attr('text-anchor', 'end') - .attr('dy', '.9em') + .attr('dy', '.9em'); g.select('.nv-hoverValue .nv-xValue') .text(xTickFormat(sparkline.x()(data[index[0]], index[0]))); @@ -148,7 +148,7 @@ nv.models.sparklinePlus = function() { .attr('x', 6) .attr('y', -margin.top) .attr('text-anchor', 'start') - .attr('dy', '.9em') + .attr('dy', '.9em'); g.select('.nv-hoverValue .nv-yValue') .text(yTickFormat(sparkline.y()(data[index[0]], index[0]))); @@ -176,7 +176,7 @@ nv.models.sparklinePlus = function() { } }); - + renderWatch.renderEnd('sparklinePlus immediate'); return chart; } @@ -185,6 +185,7 @@ nv.models.sparklinePlus = function() { //------------------------------------------------------------ // expose chart's sub-components + chart.dispatch = dispatch; chart.sparkline = sparkline; chart.options = nv.utils.optionsFunc.bind(chart); @@ -195,7 +196,7 @@ nv.models.sparklinePlus = function() { height: {get: function(){return height;}, set: function(_){height=_;}}, xTickFormat: {get: function(){return xTickFormat;}, set: function(_){xTickFormat=_;}}, yTickFormat: {get: function(){return yTickFormat;}, set: function(_){yTickFormat=_;}}, - showValue: {get: function(){return showValue;}, set: function(_){showValue=_;}}, + showLastValue: {get: function(){return showLastValue;}, set: function(_){showLastValue=_;}}, alignValue: {get: function(){return alignValue;}, set: function(_){alignValue=_;}}, rightAlignValue: {get: function(){return rightAlignValue;}, set: function(_){rightAlignValue=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, diff --git a/src/models/stackedArea.js b/src/models/stackedArea.js index abfb9484a..6192ce1f9 100644 --- a/src/models/stackedArea.js +++ b/src/models/stackedArea.js @@ -11,8 +11,10 @@ nv.models.stackedArea = function() { , height = 500 , color = nv.utils.defaultColor() // a function that computes the color , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one + , container = null , getX = function(d) { return d.x } // accessor to get the x value from a data point , getY = function(d) { return d.y } // accessor to get the y value from a data point + , defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined , style = 'stack' , offset = 'zero' , order = 'default' @@ -22,12 +24,9 @@ nv.models.stackedArea = function() { , y //can be accessed via chart.yScale() , scatter = nv.models.scatter() , duration = 250 - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'areaClick', 'areaMouseover', 'areaMouseout','renderEnd') + , dispatch = d3.dispatch('areaClick', 'areaMouseover', 'areaMouseout','renderEnd', 'elementClick', 'elementMouseover', 'elementMouseout') ; - // scatter is interactive by default, but this chart isn't so must disable - scatter.interactive(false); - scatter .pointSize(2.2) // default size .pointDomain([2.2, 2.2]) // all the same size by default @@ -52,8 +51,9 @@ nv.models.stackedArea = function() { renderWatch.models(scatter); selection.each(function(data) { var availableWidth = width - margin.left - margin.right, - availableHeight = height - margin.top - margin.bottom, - container = d3.select(this); + availableHeight = height - margin.top - margin.bottom; + + container = d3.select(this); nv.utils.initSVG(container); // Setup Scales @@ -82,9 +82,8 @@ nv.models.stackedArea = function() { .x(getX) .y(getY) .out(function(d, y0, y) { - var yHeight = (getY(d) === 0) ? 0 : y; d.display = { - y: yHeight, + y: y, y0: y0 }; }) @@ -101,12 +100,20 @@ nv.models.stackedArea = function() { gEnter.append('g').attr('class', 'nv-scatterWrap'); wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); - + + // If the user has not specified forceY, make sure 0 is included in the domain + // Otherwise, use user-specified values for forceY + if (scatter.forceY().length == 0) { + scatter.forceY().push(0); + } + scatter .width(availableWidth) .height(availableHeight) .x(getX) - .y(function(d) { return d.display.y + d.display.y0 }) + .y(function(d) { + if (d.display !== undefined) { return d.display.y + d.display.y0; } + }) .forceY([0]) .color(data.map(function(d,i) { return d.color || color(d, d.seriesIndex); @@ -128,6 +135,7 @@ nv.models.stackedArea = function() { g.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : ''); var area = d3.svg.area() + .defined(defined) .x(function(d,i) { return x(getX(d,i)) }) .y0(function(d) { return y(d.display.y0) @@ -138,6 +146,7 @@ nv.models.stackedArea = function() { .interpolate(interpolate); var zeroArea = d3.svg.area() + .defined(defined) .x(function(d,i) { return x(getX(d,i)) }) .y0(function(d) { return y(d.display.y0) }) .y1(function(d) { return y(d.display.y0) }); @@ -202,22 +211,21 @@ nv.models.stackedArea = function() { chart.d3_stackedOffset_stackPercent = function(stackData) { var n = stackData.length, //How many series m = stackData[0].length, //how many points per series - k = 1 / n, i, j, o, y0 = []; for (j = 0; j < m; ++j) { //Looping through all points - for (i = 0, o = 0; i < dataRaw.length; i++) { //looping through series' - o += getY(dataRaw[i].values[j]); //total value of all points at a certian point in time. + for (i = 0, o = 0; i < dataRaw.length; i++) { //looping through all series + o += getY(dataRaw[i].values[j]); //total y value of all series at a certian point in time. } - if (o) for (i = 0; i < n; i++) { + if (o) for (i = 0; i < n; i++) { //(total y value of all series at point in time i) != 0 stackData[i][j][1] /= o; - } else { + } else { //(total y value of all series at point in time i) == 0 for (i = 0; i < n; i++) { - stackData[i][j][1] = k; + stackData[i][j][1] = 0; } } } @@ -231,22 +239,6 @@ nv.models.stackedArea = function() { return chart; } - - //============================================================ - // Event Handling/Dispatching (out of chart's scope) - //------------------------------------------------------------ - - scatter.dispatch.on('elementClick.area', function(e) { - dispatch.areaClick(e); - }); - scatter.dispatch.on('elementMouseover.tooltip', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top], - dispatch.tooltipShow(e); - }); - scatter.dispatch.on('elementMouseout.tooltip', function(e) { - dispatch.tooltipHide(e); - }); - //============================================================ // Global getters and setters //------------------------------------------------------------ @@ -254,6 +246,10 @@ nv.models.stackedArea = function() { chart.dispatch = dispatch; chart.scatter = scatter; + scatter.dispatch.on('elementClick', function(){ dispatch.elementClick.apply(this, arguments); }); + scatter.dispatch.on('elementMouseover', function(){ dispatch.elementMouseover.apply(this, arguments); }); + scatter.dispatch.on('elementMouseout', function(){ dispatch.elementMouseout.apply(this, arguments); }); + chart.interpolate = function(_) { if (!arguments.length) return interpolate; interpolate = _; @@ -269,12 +265,14 @@ nv.models.stackedArea = function() { }; chart.dispatch = dispatch; + chart.scatter = scatter; chart.options = nv.utils.optionsFunc.bind(chart); chart._options = Object.create({}, { // simple options, just get/set the necessary values width: {get: function(){return width;}, set: function(_){width=_;}}, height: {get: function(){return height;}, set: function(_){height=_;}}, + defined: {get: function(){return defined;}, set: function(_){defined=_;}}, clipEdge: {get: function(){return clipEdge;}, set: function(_){clipEdge=_;}}, offset: {get: function(){return offset;}, set: function(_){offset=_;}}, order: {get: function(){return order;}, set: function(_){order=_;}}, diff --git a/src/models/stackedAreaChart.js b/src/models/stackedAreaChart.js index e77ef4c2a..567be8a97 100644 --- a/src/models/stackedAreaChart.js +++ b/src/models/stackedAreaChart.js @@ -12,6 +12,7 @@ nv.models.stackedAreaChart = function() { , legend = nv.models.legend() , controls = nv.models.legend() , interactiveLayer = nv.interactiveGuideline() + , tooltip = nv.models.tooltip() ; var margin = {top: 30, right: 25, bottom: 50, left: 60} @@ -24,20 +25,16 @@ nv.models.stackedAreaChart = function() { , showYAxis = true , rightAlignYAxis = false , useInteractiveGuideline = false - , tooltips = true - , tooltip = function(key, x, y, e, graph) { - return '

    ' + key + '

    ' + - '

    ' + y + ' on ' + x + '

    ' - } + , showTotalInTooltip = true + , totalLabel = 'TOTAL' , x //can be accessed via chart.xScale() , y //can be accessed via chart.yScale() - , yAxisTickFormat = d3.format(',.2f') , state = nv.utils.state() , defaultState = null - , noData = 'No Data Available.' - , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState','renderEnd') + , noData = null + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') , controlWidth = 250 - , cData = ['Stacked','Stream','Expanded'] + , controlOptions = ['Stacked','Stream','Expanded'] , controlLabels = {} , duration = 250 ; @@ -46,6 +43,25 @@ nv.models.stackedAreaChart = function() { xAxis.orient('bottom').tickPadding(7); yAxis.orient((rightAlignYAxis) ? 'right' : 'left'); + tooltip + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }); + + interactiveLayer.tooltip + .headerFormatter(function(d, i) { + return xAxis.tickFormat()(d, i); + }) + .valueFormatter(function(d, i) { + return yAxis.tickFormat()(d, i); + }); + + var oldYTickFormat = null, + oldValueFormatter = null; + controls.updateState(false); //============================================================ @@ -55,16 +71,6 @@ nv.models.stackedAreaChart = function() { var renderWatch = nv.utils.renderWatch(dispatch); var style = stacked.style(); - var showTooltip = function(e, offsetElement) { - var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ), - top = e.pos[1] + ( offsetElement.offsetTop || 0), - x = xAxis.tickFormat()(stacked.x()(e.point, e.pointIndex)), - y = yAxis.tickFormat()(stacked.y()(e.point, e.pointIndex)), - content = tooltip(e.series.key, x, y, e, chart); - - nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement); - }; - var stateGetter = function(data) { return function(){ return { @@ -85,6 +91,8 @@ nv.models.stackedAreaChart = function() { } }; + var percentFormatter = d3.format('%'); + function chart(selection) { renderWatch.reset(); renderWatch.models(stacked); @@ -96,10 +104,8 @@ nv.models.stackedAreaChart = function() { that = this; nv.utils.initSVG(container); - var availableWidth = (width || parseInt(container.style('width')) || 960) - - margin.left - margin.right, - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); chart.update = function() { container.transition().duration(duration).call(chart); }; chart.container = this; @@ -125,18 +131,7 @@ nv.models.stackedAreaChart = function() { // Display No Data message if there's nothing to show. if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) { - var noDataText = container.selectAll('.nv-noData').data([noData]); - - noDataText.enter().append('text') - .attr('class', 'nvd3 nv-noData') - .attr('dy', '-.7em') - .style('text-anchor', 'middle'); - - noDataText - .attr('x', margin.left + availableWidth / 2) - .attr('y', margin.top + availableHeight / 2) - .text(function(d) { return d }); - + nv.utils.noData(chart, container) return chart; } else { container.selectAll('.nv-noData').remove(); @@ -170,8 +165,7 @@ nv.models.stackedAreaChart = function() { if ( margin.top != legend.height()) { margin.top = legend.height(); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.nv-legendWrap') @@ -207,9 +201,9 @@ nv.models.stackedAreaChart = function() { } ]; - controlWidth = (cData.length/3) * 260; + controlWidth = (controlOptions.length/3) * 260; controlsData = controlsData.filter(function(d) { - return cData.indexOf(d.metaKey) !== -1; + return controlOptions.indexOf(d.metaKey) !== -1; }); controls @@ -222,8 +216,7 @@ nv.models.stackedAreaChart = function() { if ( margin.top != Math.max(controls.height(), legend.height()) ) { margin.top = Math.max(controls.height(), legend.height()); - availableHeight = (height || parseInt(container.style('height')) || 400) - - margin.top - margin.bottom; + availableHeight = nv.utils.availableHeight(height, container, margin); } g.select('.nv-controlsWrap') @@ -260,7 +253,7 @@ nv.models.stackedAreaChart = function() { // Setup Axes if (showXAxis) { xAxis.scale(x) - .ticks( nv.utils.calcTicksX(availableWidth/100, data) ) + ._ticks( nv.utils.calcTicksX(availableWidth/100, data) ) .tickSize( -availableHeight, 0); g.select('.nv-x.nv-axis') @@ -272,11 +265,32 @@ nv.models.stackedAreaChart = function() { } if (showYAxis) { + var ticks; + if (stacked.offset() === 'wiggle') { + ticks = 0; + } + else { + ticks = nv.utils.calcTicksY(availableHeight/36, data); + } yAxis.scale(y) - .ticks(stacked.offset() == 'wiggle' ? 0 : nv.utils.calcTicksY(availableHeight/36, data) ) - .tickSize(-availableWidth, 0) - .setTickFormat( (stacked.style() == 'expand' || stacked.style() == 'stack_percent') - ? d3.format('%') : yAxisTickFormat); + ._ticks(ticks) + .tickSize(-availableWidth, 0); + + if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') { + var currentFormat = yAxis.tickFormat(); + + if ( !oldYTickFormat || currentFormat !== percentFormatter ) + oldYTickFormat = currentFormat; + + //Forces the yAxis to use percentage in 'expand' mode. + yAxis.tickFormat(percentFormatter); + } + else { + if (oldYTickFormat) { + yAxis.tickFormat(oldYTickFormat); + oldYTickFormat = null; + } + } g.select('.nv-y.nv-axis') .transition().duration(0) @@ -330,7 +344,7 @@ nv.models.stackedAreaChart = function() { interactiveLayer.dispatch.on('elementMousemove', function(e) { stacked.clearHighlights(); - var singlePoint, pointIndex, pointXLocation, allData = []; + var singlePoint, pointIndex, pointXLocation, allData = [], valueSum = 0; data .filter(function(series, i) { series.seriesIndex = i; @@ -338,8 +352,11 @@ nv.models.stackedAreaChart = function() { }) .forEach(function(series,i) { pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x()); - stacked.highlightPoint(i, pointIndex, true); var point = series.values[pointIndex]; + var pointYValue = chart.y()(point, pointIndex); + if (pointYValue != null) { + stacked.highlightPoint(i, pointIndex, true); + } if (typeof point === 'undefined') return; if (typeof singlePoint === 'undefined') singlePoint = point; if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex)); @@ -352,6 +369,10 @@ nv.models.stackedAreaChart = function() { color: color(series,series.seriesIndex), stackedValue: point.display }); + + if (showTotalInTooltip && stacked.style() != 'expand') { + valueSum += tooltipValue; + }; }); allData.reverse(); @@ -377,16 +398,35 @@ nv.models.stackedAreaChart = function() { allData[indexToHighlight].highlight = true; } + //If we are not in 'expand' mode, add a 'Total' row to the tooltip. + if (showTotalInTooltip && stacked.style() != 'expand' && allData.length >= 2) { + allData.push({ + key: totalLabel, + value: valueSum, + total: true + }); + } + var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex)); - //If we are in 'expand' mode, force the format to be a percentage. - var valueFormatter = (stacked.style() == 'expand') ? - function(d,i) {return d3.format(".1%")(d);} : - function(d,i) {return yAxis.tickFormat()(d); }; + var valueFormatter = interactiveLayer.tooltip.valueFormatter(); + // Keeps track of the tooltip valueFormatter if the chart changes to expanded view + if (stacked.style() === 'expand' || stacked.style() === 'stack_percent') { + if ( !oldValueFormatter ) { + oldValueFormatter = valueFormatter; + } + //Forces the tooltip to use percentage in 'expand' mode. + valueFormatter = d3.format(".1%"); + } + else { + if (oldValueFormatter) { + valueFormatter = oldValueFormatter; + oldValueFormatter = null; + } + } + interactiveLayer.tooltip - .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top}) .chartContainer(that.parentNode) - .enabled(tooltips) .valueFormatter(valueFormatter) .data( { @@ -400,15 +440,9 @@ nv.models.stackedAreaChart = function() { }); interactiveLayer.dispatch.on("elementMouseout",function(e) { - dispatch.tooltipHide(); stacked.clearHighlights(); }); - - dispatch.on('tooltipShow', function(e) { - if (tooltips) showTooltip(e, that.parentNode); - }); - // Update chart from a state object passed to event handler dispatch.on('changeState', function(e) { @@ -438,17 +472,14 @@ nv.models.stackedAreaChart = function() { // Event Handling/Dispatching (out of chart's scope) //------------------------------------------------------------ - stacked.dispatch.on('tooltipShow', function(e) { - e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top]; - dispatch.tooltipShow(e); + stacked.dispatch.on('elementMouseover.tooltip', function(evt) { + evt.point['x'] = stacked.x()(evt.point); + evt.point['y'] = stacked.y()(evt.point); + tooltip.data(evt).hidden(false); }); - stacked.dispatch.on('tooltipHide', function(e) { - dispatch.tooltipHide(e); - }); - - dispatch.on('tooltipHide', function() { - if (tooltips) nv.tooltip.cleanup(); + stacked.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true) }); //============================================================ @@ -463,8 +494,7 @@ nv.models.stackedAreaChart = function() { chart.xAxis = xAxis; chart.yAxis = yAxis; chart.interactiveLayer = interactiveLayer; - - yAxis.setTickFormat = yAxis.tickFormat; + chart.tooltip = tooltip; chart.dispatch = dispatch; chart.options = nv.utils.optionsFunc.bind(chart); @@ -476,13 +506,13 @@ nv.models.stackedAreaChart = function() { showLegend: {get: function(){return showLegend;}, set: function(_){showLegend=_;}}, showXAxis: {get: function(){return showXAxis;}, set: function(_){showXAxis=_;}}, showYAxis: {get: function(){return showYAxis;}, set: function(_){showYAxis=_;}}, - tooltips: {get: function(){return tooltips;}, set: function(_){tooltips=_;}}, - tooltipContent: {get: function(){return tooltip;}, set: function(_){tooltip=_;}}, defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, noData: {get: function(){return noData;}, set: function(_){noData=_;}}, showControls: {get: function(){return showControls;}, set: function(_){showControls=_;}}, controlLabels: {get: function(){return controlLabels;}, set: function(_){controlLabels=_;}}, - yAxisTickFormat: {get: function(){return yAxisTickFormat;}, set: function(_){yAxisTickFormat=_;}}, + controlOptions: {get: function(){return controlOptions;}, set: function(_){controlOptions=_;}}, + showTotalInTooltip: {get: function(){return showTotalInTooltip;}, set: function(_){showTotalInTooltip=_;}}, + totalLabel: {get: function(){return totalLabel;}, set: function(_){totalLabel=_;}}, // options that require extra logic in the setter margin: {get: function(){return margin;}, set: function(_){ @@ -509,10 +539,9 @@ nv.models.stackedAreaChart = function() { }}, useInteractiveGuideline: {get: function(){return useInteractiveGuideline;}, set: function(_){ useInteractiveGuideline = !!_; - if (_) { - chart.interactive(false); - chart.useVoronoi(false); - } + chart.interactive(!_); + chart.useVoronoi(!_); + stacked.scatter.interactive(!_); }} }); diff --git a/src/models/sunburst.js b/src/models/sunburst.js new file mode 100644 index 000000000..afa89ebcd --- /dev/null +++ b/src/models/sunburst.js @@ -0,0 +1,225 @@ +// based on http://bl.ocks.org/kerryrodden/477c1bfb081b783f80ad +nv.models.sunburst = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var margin = {top: 0, right: 0, bottom: 0, left: 0} + , width = null + , height = null + , mode = "count" + , modes = {count: function(d) { return 1; }, size: function(d) { return d.size }} + , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one + , container = null + , color = nv.utils.defaultColor() + , groupColorByParent = true + , duration = 500 + , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMousemove', 'elementMouseover', 'elementMouseout', 'renderEnd') + ; + + var x = d3.scale.linear().range([0, 2 * Math.PI]); + var y = d3.scale.sqrt(); + + var partition = d3.layout.partition() + .sort(null) + .value(function(d) { return 1; }); + + var arc = d3.svg.arc() + .startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x))); }) + .endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x + d.dx))); }) + .innerRadius(function(d) { return Math.max(0, y(d.y)); }) + .outerRadius(function(d) { return Math.max(0, y(d.y + d.dy)); }); + + // Keep track of the current and previous node being displayed as the root. + var node, prevNode; + // Keep track of the root node + var rootNode; + + //============================================================ + // chart function + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + + function chart(selection) { + renderWatch.reset(); + selection.each(function(data) { + container = d3.select(this); + var availableWidth = nv.utils.availableWidth(width, container, margin); + var availableHeight = nv.utils.availableHeight(height, container, margin); + var radius = Math.min(availableWidth, availableHeight) / 2; + var path; + + nv.utils.initSVG(container); + + // Setup containers and skeleton of chart + var wrap = container.selectAll('.nv-wrap.nv-sunburst').data(data); + var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sunburst nv-chart-' + id); + + var g = wrapEnter.selectAll('nv-sunburst'); + + chart.update = function() { + if ( duration === 0 ) { + container.call(chart); + } else { + container.transition().duration(duration).call(chart); + } + }; + chart.container = this; + + + wrap.attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')'); + + container.on('click', function (d, i) { + dispatch.chartClick({ + data: d, + index: i, + pos: d3.event, + id: id + }); + }); + + y.range([0, radius]); + + node = node || data; + rootNode = data[0]; + partition.value(modes[mode] || modes["count"]); + path = g.data(partition.nodes).enter() + .append("path") + .attr("d", arc) + .style("fill", function (d) { + if (d.color) { + return d.color; + } + else if (groupColorByParent) { + return color((d.children ? d : d.parent).name); + } + else { + return color(d.name); + } + }) + .style("stroke", "#FFF") + .on("click", function(d) { + if (prevNode !== node && node !== d) prevNode = node; + node = d; + path.transition() + .duration(duration) + .attrTween("d", arcTweenZoom(d)); + }) + .each(stash) + .on("dblclick", function(d) { + if (prevNode.parent == d) { + path.transition() + .duration(duration) + .attrTween("d", arcTweenZoom(rootNode)); + } + }) + .each(stash) + .on('mouseover', function(d,i){ + d3.select(this).classed('hover', true).style('opacity', 0.8); + dispatch.elementMouseover({ + data: d, + color: d3.select(this).style("fill") + }); + }) + .on('mouseout', function(d,i){ + d3.select(this).classed('hover', false).style('opacity', 1); + dispatch.elementMouseout({ + data: d + }); + }) + .on('mousemove', function(d,i){ + dispatch.elementMousemove({ + data: d + }); + }); + + + + // Setup for switching data: stash the old values for transition. + function stash(d) { + d.x0 = d.x; + d.dx0 = d.dx; + } + + // When switching data: interpolate the arcs in data space. + function arcTweenData(a, i) { + var oi = d3.interpolate({x: a.x0, dx: a.dx0}, a); + + function tween(t) { + var b = oi(t); + a.x0 = b.x; + a.dx0 = b.dx; + return arc(b); + } + + if (i == 0) { + // If we are on the first arc, adjust the x domain to match the root node + // at the current zoom level. (We only need to do this once.) + var xd = d3.interpolate(x.domain(), [node.x, node.x + node.dx]); + return function (t) { + x.domain(xd(t)); + return tween(t); + }; + } else { + return tween; + } + } + + // When zooming: interpolate the scales. + function arcTweenZoom(d) { + var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]), + yd = d3.interpolate(y.domain(), [d.y, 1]), + yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]); + return function (d, i) { + return i + ? function (t) { + return arc(d); + } + : function (t) { + x.domain(xd(t)); + y.domain(yd(t)).range(yr(t)); + return arc(d); + }; + }; + } + + }); + + renderWatch.renderEnd('sunburst immediate'); + return chart; + } + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + chart.dispatch = dispatch; + chart.options = nv.utils.optionsFunc.bind(chart); + + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + width: {get: function(){return width;}, set: function(_){width=_;}}, + height: {get: function(){return height;}, set: function(_){height=_;}}, + mode: {get: function(){return mode;}, set: function(_){mode=_;}}, + id: {get: function(){return id;}, set: function(_){id=_;}}, + duration: {get: function(){return duration;}, set: function(_){duration=_;}}, + groupColorByParent: {get: function(){return groupColorByParent;}, set: function(_){groupColorByParent=!!_;}}, + + // options that require extra logic in the setter + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top != undefined ? _.top : margin.top; + margin.right = _.right != undefined ? _.right : margin.right; + margin.bottom = _.bottom != undefined ? _.bottom : margin.bottom; + margin.left = _.left != undefined ? _.left : margin.left; + }}, + color: {get: function(){return color;}, set: function(_){ + color=nv.utils.getColor(_); + }} + }); + + nv.utils.initOptions(chart); + return chart; +}; diff --git a/src/models/sunburstChart.js b/src/models/sunburstChart.js new file mode 100644 index 000000000..843f5c873 --- /dev/null +++ b/src/models/sunburstChart.js @@ -0,0 +1,145 @@ +nv.models.sunburstChart = function() { + "use strict"; + + //============================================================ + // Public Variables with Default Settings + //------------------------------------------------------------ + + var sunburst = nv.models.sunburst(); + var tooltip = nv.models.tooltip(); + + var margin = {top: 30, right: 20, bottom: 20, left: 20} + , width = null + , height = null + , color = nv.utils.defaultColor() + , id = Math.round(Math.random() * 100000) + , defaultState = null + , noData = null + , duration = 250 + , dispatch = d3.dispatch('stateChange', 'changeState','renderEnd') + ; + + tooltip.duration(0); + + //============================================================ + // Private Variables + //------------------------------------------------------------ + + var renderWatch = nv.utils.renderWatch(dispatch); + tooltip + .headerEnabled(false) + .valueFormatter(function(d, i) { + return d; + }); + + //============================================================ + // Chart function + //------------------------------------------------------------ + + function chart(selection) { + renderWatch.reset(); + renderWatch.models(sunburst); + + selection.each(function(data) { + var container = d3.select(this); + nv.utils.initSVG(container); + + var that = this; + var availableWidth = nv.utils.availableWidth(width, container, margin), + availableHeight = nv.utils.availableHeight(height, container, margin); + + chart.update = function() { + if (duration === 0) { + container.call(chart); + } else { + container.transition().duration(duration).call(chart); + } + }; + chart.container = this; + + // Display No Data message if there's nothing to show. + if (!data || !data.length) { + nv.utils.noData(chart, container); + return chart; + } else { + container.selectAll('.nv-noData').remove(); + } + + // Setup containers and skeleton of chart + var wrap = container.selectAll('g.nv-wrap.nv-sunburstChart').data(data); + var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sunburstChart').append('g'); + var g = wrap.select('g'); + + gEnter.append('g').attr('class', 'nv-sunburstWrap'); + + wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')'); + + // Main Chart Component(s) + sunburst.width(availableWidth).height(availableHeight); + var sunWrap = g.select('.nv-sunburstWrap').datum(data); + d3.transition(sunWrap).call(sunburst); + + }); + + renderWatch.renderEnd('sunburstChart immediate'); + return chart; + } + + //============================================================ + // Event Handling/Dispatching (out of chart's scope) + //------------------------------------------------------------ + + sunburst.dispatch.on('elementMouseover.tooltip', function(evt) { + evt['series'] = { + key: evt.data.name, + value: evt.data.size, + color: evt.color + }; + tooltip.data(evt).hidden(false); + }); + + sunburst.dispatch.on('elementMouseout.tooltip', function(evt) { + tooltip.hidden(true); + }); + + sunburst.dispatch.on('elementMousemove.tooltip', function(evt) { + tooltip(); + }); + + //============================================================ + // Expose Public Variables + //------------------------------------------------------------ + + // expose chart's sub-components + chart.dispatch = dispatch; + chart.sunburst = sunburst; + chart.tooltip = tooltip; + chart.options = nv.utils.optionsFunc.bind(chart); + + // use Object get/set functionality to map between vars and chart functions + chart._options = Object.create({}, { + // simple options, just get/set the necessary values + noData: {get: function(){return noData;}, set: function(_){noData=_;}}, + defaultState: {get: function(){return defaultState;}, set: function(_){defaultState=_;}}, + + // options that require extra logic in the setter + color: {get: function(){return color;}, set: function(_){ + color = _; + sunburst.color(color); + }}, + duration: {get: function(){return duration;}, set: function(_){ + duration = _; + renderWatch.reset(duration); + sunburst.duration(duration); + }}, + margin: {get: function(){return margin;}, set: function(_){ + margin.top = _.top !== undefined ? _.top : margin.top; + margin.right = _.right !== undefined ? _.right : margin.right; + margin.bottom = _.bottom !== undefined ? _.bottom : margin.bottom; + margin.left = _.left !== undefined ? _.left : margin.left; + }} + }); + nv.utils.inheritOptions(chart, sunburst); + nv.utils.initOptions(chart); + return chart; +}; diff --git a/src/nv.d3.css b/src/nv.d3.css deleted file mode 100644 index 26453e88f..000000000 --- a/src/nv.d3.css +++ /dev/null @@ -1,645 +0,0 @@ -/******************** - * SVG CSS - */ - - -svg { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - /* Trying to get SVG to act like a greedy block in all browsers */ - display: block; - width:100%; - height:100%; -} - -/******************** - Default CSS for an svg element nvd3 used -*/ -svg.nvd3-svg { - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -ms-user-select: none; - -moz-user-select: none; - user-select: none; - display: block; -} - -/******************** - Box shadow and border radius styling -*/ -.nvtooltip.with-3d-shadow, .with-3d-shadow .nvtooltip { - -moz-box-shadow: 0 5px 10px rgba(0,0,0,.2); - -webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2); - box-shadow: 0 5px 10px rgba(0,0,0,.2); - - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} - -/******************** - * TOOLTIP CSS - */ - -.nvtooltip { - position: absolute; - background-color: rgba(255,255,255,1.0); - padding: 1px; - border: 1px solid rgba(0,0,0,.2); - z-index: 10000; - - font-family: Arial; - font-size: 13px; - text-align: left; - pointer-events: none; - - white-space: nowrap; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -/*Give tooltips that old fade in transition by - putting a "with-transitions" class on the container div. -*/ -.nvtooltip.with-transitions, .with-transitions .nvtooltip { - transition: opacity 50ms linear; - -moz-transition: opacity 50ms linear; - -webkit-transition: opacity 50ms linear; - - transition-delay: 200ms; - -moz-transition-delay: 200ms; - -webkit-transition-delay: 200ms; -} - -.nvtooltip.x-nvtooltip, -.nvtooltip.y-nvtooltip { - padding: 8px; -} - -.nvtooltip h3 { - margin: 0; - padding: 4px 14px; - line-height: 18px; - font-weight: normal; - background-color: rgba(247,247,247,0.75); - text-align: center; - - border-bottom: 1px solid #ebebeb; - - -webkit-border-radius: 5px 5px 0 0; - -moz-border-radius: 5px 5px 0 0; - border-radius: 1px 5px 0 0; -} - -.nvtooltip p { - margin: 0; - padding: 5px 14px; - text-align: center; -} - -.nvtooltip span { - display: inline-block; - margin: 2px 0; -} - -.nvtooltip table { - margin: 6px; - border-spacing:0; -} - - -.nvtooltip table td { - padding: 2px 9px 2px 0; - vertical-align: middle; -} - -.nvtooltip table td.key { - font-weight:normal; -} -.nvtooltip table td.value { - text-align: right; - font-weight: bold; -} - -.nvtooltip table tr.highlight td { - padding: 1px 9px 1px 0; - border-bottom-style: solid; - border-bottom-width: 1px; - border-top-style: solid; - border-top-width: 1px; -} - -.nvtooltip table td.legend-color-guide div { - width: 8px; - height: 8px; - vertical-align: middle; -} - -.nvtooltip .footer { - padding: 3px; - text-align: center; -} - -.nvtooltip-pending-removal { - position: absolute; - pointer-events: none; -} - -.nvd3 text { - font: normal 12px Arial; -} - -.nvd3 .title { - font: bold 14px Arial; -} - -.nvd3 .nv-background { - fill: white; - fill-opacity: 0; -} - -.nvd3.nv-noData { - font-size: 18px; - font-weight: bold; -} - - -/********** -* Brush -*/ - -.nv-brush .extent { - fill-opacity: .125; - shape-rendering: crispEdges; -} - - -/********** -* Legend -*/ - -.nvd3 .nv-legend .nv-series { - cursor: pointer; -} - -.nvd3 .nv-legend .nv-disabled circle { - fill-opacity: 0; -} - - -/********** -* Axes -*/ - -.axis { - opacity: 1; -} - -.axis.nv-disabled { - opacity: 0; -} - -.nvd3 .nv-axis { - pointer-events:none; -} - -.nvd3 .nv-axis path { - fill: none; - stroke: #000; - stroke-opacity: .75; - shape-rendering: crispEdges; -} - -.nvd3 .nv-axis path.domain { - stroke-opacity: .75; -} - -.nvd3 .nv-axis.nv-x path.domain { - stroke-opacity: 0; -} - -.nvd3 .nv-axis line { - fill: none; - stroke: #e5e5e5; - shape-rendering: crispEdges; -} - -.nvd3 .nv-axis .zero line, -/*this selector may not be necessary*/ .nvd3 .nv-axis line.zero { - stroke-opacity: .75; -} - -.nvd3 .nv-axis .nv-axisMaxMin text { - font-weight: bold; -} - -.nvd3 .x .nv-axis .nv-axisMaxMin text, -.nvd3 .x2 .nv-axis .nv-axisMaxMin text, -.nvd3 .x3 .nv-axis .nv-axisMaxMin text { - text-anchor: middle -} - - -/********** -* Brush -*/ - -.nv-brush .resize path { - fill: #eee; - stroke: #666; -} - - -/********** -* Bars -*/ - -.nvd3 .nv-bars .negative rect { - zfill: brown; -} - -.nvd3 .nv-bars rect { - zfill: steelblue; - fill-opacity: .75; - - transition: fill-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear; -} - -.nvd3 .nv-bars rect.hover { - fill-opacity: 1; -} - -.nvd3 .nv-bars .hover rect { - fill: lightblue; -} - -.nvd3 .nv-bars text { - fill: rgba(0,0,0,0); -} - -.nvd3 .nv-bars .hover text { - fill: rgba(0,0,0,1); -} - - -/********** -* Bars -*/ - -.nvd3 .nv-multibar .nv-groups rect, -.nvd3 .nv-multibarHorizontal .nv-groups rect, -.nvd3 .nv-discretebar .nv-groups rect { - stroke-opacity: 0; - - transition: fill-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear; -} - -.nvd3 .nv-multibar .nv-groups rect:hover, -.nvd3 .nv-multibarHorizontal .nv-groups rect:hover, -.nvd3 .nv-discretebar .nv-groups rect:hover { - fill-opacity: 1; -} - -.nvd3 .nv-discretebar .nv-groups text, -.nvd3 .nv-multibarHorizontal .nv-groups text { - font-weight: bold; - fill: rgba(0,0,0,1); - stroke: rgba(0,0,0,0); -} - -/*********** -* Pie Chart -*/ - -.nvd3.nv-pie path { - stroke-opacity: 0; - transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear, stroke-width 250ms linear, stroke-opacity 250ms linear; - -} - -.nvd3.nv-pie .nv-pie-title { - font-size: 24px; - fill: rgba(19, 196, 249, 0.59); -} - -.nvd3.nv-pie .nv-slice text { - stroke: #000; - stroke-width: 0; -} - -.nvd3.nv-pie path { - stroke: #fff; - stroke-width: 1px; - stroke-opacity: 1; -} - -.nvd3.nv-pie .hover path { - fill-opacity: .7; -} -.nvd3.nv-pie .nv-label { - pointer-events: none; -} -.nvd3.nv-pie .nv-label rect { - fill-opacity: 0; - stroke-opacity: 0; -} - -/********** -* Lines -*/ - -.nvd3 .nv-groups path.nv-line { - fill: none; - stroke-width: 1.5px; -} - -.nvd3 .nv-groups path.nv-line.nv-thin-line { - stroke-width: 1px; -} - - -.nvd3 .nv-groups path.nv-area { - stroke: none; -} - -.nvd3 .nv-line.hover path { - stroke-width: 6px; -} - -.nvd3.nv-line .nvd3.nv-scatter .nv-groups .nv-point { - fill-opacity: 0; - stroke-opacity: 0; -} - -.nvd3.nv-scatter.nv-single-point .nv-groups .nv-point { - fill-opacity: .5 !important; - stroke-opacity: .5 !important; -} - - -.with-transitions .nvd3 .nv-groups .nv-point { - transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -moz-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: stroke-width 250ms linear, stroke-opacity 250ms linear; - -} - -.nvd3.nv-scatter .nv-groups .nv-point.hover, -.nvd3 .nv-groups .nv-point.hover { - stroke-width: 7px; - fill-opacity: .95 !important; - stroke-opacity: .95 !important; -} - - -.nvd3 .nv-point-paths path { - stroke: #aaa; - stroke-opacity: 0; - fill: #eee; - fill-opacity: 0; -} - - - -.nvd3 .nv-indexLine { - cursor: ew-resize; -} - - -/********** -* Distribution -*/ - -.nvd3 .nv-distribution { - pointer-events: none; -} - - -/********** -* Scatter -*/ - -.nvd3 .nv-groups .nv-point.hover { - stroke-width: 20px; - stroke-opacity: .5; -} - -.nvd3 .nv-scatter .nv-point.hover { - fill-opacity: 1; -} - - -/********** -* Stacked Area -*/ - -.nvd3.nv-stackedarea path.nv-area { - fill-opacity: .7; - stroke-opacity: 0; - transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; - -moz-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; - -webkit-transition: fill-opacity 250ms linear, stroke-opacity 250ms linear; -} - -.nvd3.nv-stackedarea path.nv-area.hover { - fill-opacity: .9; -} - - -.nvd3.nv-stackedarea .nv-groups .nv-point { - stroke-opacity: 0; - fill-opacity: 0; -} - - -/********** -* Line Plus Bar -*/ - -.nvd3.nv-linePlusBar .nv-bar rect { - fill-opacity: .75; -} - -.nvd3.nv-linePlusBar .nv-bar rect:hover { - fill-opacity: 1; -} - - -/********** -* Bullet -*/ - -.nvd3.nv-bullet { font: 10px sans-serif; } -.nvd3.nv-bullet .nv-measure { fill-opacity: .8; } -.nvd3.nv-bullet .nv-measure:hover { fill-opacity: 1; } -.nvd3.nv-bullet .nv-marker { stroke: #000; stroke-width: 2px; } -.nvd3.nv-bullet .nv-markerTriangle { stroke: #000; fill: #fff; stroke-width: 1.5px; } -.nvd3.nv-bullet .nv-tick line { stroke: #666; stroke-width: .5px; } -.nvd3.nv-bullet .nv-range.nv-s0 { fill: #eee; } -.nvd3.nv-bullet .nv-range.nv-s1 { fill: #ddd; } -.nvd3.nv-bullet .nv-range.nv-s2 { fill: #ccc; } -.nvd3.nv-bullet .nv-title { font-size: 14px; font-weight: bold; } -.nvd3.nv-bullet .nv-subtitle { fill: #999; } - - -.nvd3.nv-bullet .nv-range { - fill: #bababa; - fill-opacity: .4; -} -.nvd3.nv-bullet .nv-range:hover { - fill-opacity: .7; -} - - -/********** -* Sparkline -*/ - -.nvd3.nv-sparkline path { - fill: none; -} - -.nvd3.nv-sparklineplus g.nv-hoverValue { - pointer-events: none; -} - -.nvd3.nv-sparklineplus .nv-hoverValue line { - stroke: #333; - stroke-width: 1.5px; - } - -.nvd3.nv-sparklineplus, -.nvd3.nv-sparklineplus g { - pointer-events: all; -} - -.nvd3 .nv-hoverArea { - fill-opacity: 0; - stroke-opacity: 0; -} - -.nvd3.nv-sparklineplus .nv-xValue, -.nvd3.nv-sparklineplus .nv-yValue { - stroke-width: 0; - font-size: .9em; - font-weight: normal; -} - -.nvd3.nv-sparklineplus .nv-yValue { - stroke: #f66; -} - -.nvd3.nv-sparklineplus .nv-maxValue { - stroke: #2ca02c; - fill: #2ca02c; -} - -.nvd3.nv-sparklineplus .nv-minValue { - stroke: #d62728; - fill: #d62728; -} - -.nvd3.nv-sparklineplus .nv-currentValue { - font-weight: bold; - font-size: 1.1em; -} - -/********** -* historical stock -*/ - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick { - stroke-width: 1px; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.hover { - stroke-width: 2px; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.positive { - stroke: #2ca02c; -} - -.nvd3.nv-ohlcBar .nv-ticks .nv-tick.negative { - stroke: #d62728; -} - -.nvd3.nv-historicalStockChart .nv-axis .nv-axislabel { - font-weight: bold; -} - -.nvd3.nv-historicalStockChart .nv-dragTarget { - fill-opacity: 0; - stroke: none; - cursor: move; -} - -.nvd3 .nv-brush .extent { - fill-opacity: 0 !important; -} - -.nvd3 .nv-brushBackground rect { - stroke: #000; - stroke-width: .4; - fill: #fff; - fill-opacity: .7; -} - - -/********** -* Parallel Coordinates -*/ - -.nvd3 .background path { - fill: none; - stroke: #EEE; - stroke-opacity: .4; - shape-rendering: crispEdges; -} - -.nvd3 .foreground path { - fill: none; - stroke-opacity: .7; -} - -.nvd3 .brush .extent { - fill-opacity: .3; - stroke: #fff; - shape-rendering: crispEdges; -} - -.nvd3 .axis line, .axis path { - fill: none; - stroke: #000; - shape-rendering: crispEdges; -} - -.nvd3 .axis text { - text-shadow: 0 1px 0 #fff; -} - -/**** -Interactive Layer -*/ -.nvd3 .nv-interactiveGuideLine { - pointer-events:none; -} -.nvd3 line.nv-guideline { - stroke: #ccc; -} \ No newline at end of file diff --git a/src/tooltip.js b/src/tooltip.js index caea47efb..61ae896eb 100644 --- a/src/tooltip.js +++ b/src/tooltip.js @@ -1,492 +1,337 @@ -/* Tooltip rendering model for nvd3 charts. - window.nv.models.tooltip is the updated,new way to render tooltips. - window.nv.tooltip.show is the old tooltip code. - window.nv.tooltip.* also has various helper methods. +/* Model which can be instantiated to handle tooltip rendering. + Example usage: + var tip = nv.models.tooltip().gravity('w').distance(23) + .data(myDataObject); + + tip(); //just invoke the returned function to render tooltip. */ -(function() { +nv.models.tooltip = function() { "use strict"; - window.nv.tooltip = {}; - - /* Model which can be instantiated to handle tooltip rendering. - Example usage: - var tip = nv.models.tooltip().gravity('w').distance(23) - .data(myDataObject); - tip(); //just invoke the returned function to render tooltip. + /* + Tooltip data. If data is given in the proper format, a consistent tooltip is generated. + Example Format of data: + { + key: "Date", + value: "August 2009", + series: [ + {key: "Series 1", value: "Value 1", color: "#000"}, + {key: "Series 2", value: "Value 2", color: "#00f"} + ] + } + */ + var id = "nvtooltip-" + Math.floor(Math.random() * 100000) // Generates a unique id when you create a new tooltip() object. + , data = null + , gravity = 'w' // Can be 'n','s','e','w'. Determines how tooltip is positioned. + , distance = 25 // Distance to offset tooltip from the mouse location. + , snapDistance = 0 // Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect) + , classes = null // Attaches additional CSS classes to the tooltip DIV that is created. + , chartContainer = null // Parent dom element of the SVG that holds the chart. + , hidden = true // Start off hidden, toggle with hide/show functions below. + , hideDelay = 200 // Delay (in ms) before the tooltip hides after calling hide(). + , tooltip = null // d3 select of the tooltip div. + , lastPosition = { left: null, top: null } // Last position the tooltip was in. + , enabled = true // True -> tooltips are rendered. False -> don't render tooltips. + , duration = 100 // Tooltip movement duration, in ms. + , headerEnabled = true // If is to show the tooltip header. + , nvPointerEventsClass = "nv-pointer-events-none" // CSS class to specify whether element should not have mouse events. + ; + + /* + Function that returns the position (relative to the viewport) the tooltip should be placed in. + Should return: { + left: , + top: + } */ - window.nv.models.tooltip = function() { - //HTML contents of the tooltip. If null, the content is generated via the data variable. - var content = null; - - /* - Tooltip data. If data is given in the proper format, a consistent tooltip is generated. - Example Format of data: - { - key: "Date", - value: "August 2009", - series: [ - {key: "Series 1", value: "Value 1", color: "#000"}, - {key: "Series 2", value: "Value 2", color: "#00f"} - ] - } - */ - var data = null; - - var gravity = 'w' //Can be 'n','s','e','w'. Determines how tooltip is positioned. - ,distance = 50 //Distance to offset tooltip from the mouse location. - ,snapDistance = 25 //Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect) - , fixedTop = null //If not null, this fixes the top position of the tooltip. - , classes = null //Attaches additional CSS classes to the tooltip DIV that is created. - , chartContainer = null //Parent DIV, of the SVG Container that holds the chart. - , tooltipElem = null //actual DOM element representing the tooltip. - , position = {left: null, top: null} //Relative position of the tooltip inside chartContainer. - , enabled = true; //True -> tooltips are rendered. False -> don't render tooltips. - - //Generates a unique id when you create a new tooltip() object - var id = "nvtooltip-" + Math.floor(Math.random() * 100000); - - //CSS class to specify whether element should not have mouse events. - var nvPointerEventsClass = "nv-pointer-events-none"; - - //Format function for the tooltip values column - var valueFormatter = function(d,i) { - return d; + var position = function() { + return { + left: d3.event.clientX, + top: d3.event.clientY }; + }; - //Format function for the tooltip header value. - var headerFormatter = function(d) { - return d; - }; + // Format function for the tooltip values column. + var valueFormatter = function(d, i) { + return d; + }; - //By default, the tooltip model renders a beautiful table inside a DIV. - //You can override this function if a custom tooltip is desired. - var contentGenerator = function(d) { - if (content != null) { - return content; - } + // Format function for the tooltip header value. + var headerFormatter = function(d) { + return d; + }; - if (d == null) { - return ''; - } + var keyFormatter = function(d, i) { + return d; + }; - var table = d3.select(document.createElement("table")); + // By default, the tooltip model renders a beautiful table inside a DIV. + // You can override this function if a custom tooltip is desired. + var contentGenerator = function(d) { + if (d === null) { + return ''; + } + + var table = d3.select(document.createElement("table")); + if (headerEnabled) { var theadEnter = table.selectAll("thead") .data([d]) .enter().append("thead"); theadEnter.append("tr") .append("td") - .attr("colspan",3) + .attr("colspan", 3) .append("strong") - .classed("x-value",true) + .classed("x-value", true) .html(headerFormatter(d.value)); - - var tbodyEnter = table.selectAll("tbody") - .data([d]) - .enter().append("tbody"); - - var trowEnter = tbodyEnter.selectAll("tr") - .data(function(p) { return p.series}) - .enter() - .append("tr") - .classed("highlight", function(p) { return p.highlight}); - - trowEnter.append("td") - .classed("legend-color-guide",true) - .append("div") - .style("background-color", function(p) { return p.color}); - - trowEnter.append("td") - .classed("key",true) - .html(function(p) {return p.key}); - - trowEnter.append("td") - .classed("value",true) - .html(function(p,i) { return valueFormatter(p.value,i) }); - - - trowEnter.selectAll("td").each(function(p) { - if (p.highlight) { - var opacityScale = d3.scale.linear().domain([0,1]).range(["#fff",p.color]); - var opacity = 0.6; - d3.select(this) - .style("border-bottom-color", opacityScale(opacity)) - .style("border-top-color", opacityScale(opacity)) - ; - } - }); - - var html = table.node().outerHTML; - if (d.footer !== undefined) - html += ""; - return html; - - }; - - var dataSeriesExists = function(d) { - if (d && d.series && d.series.length > 0) { - return true; - } - return false; - }; - - //In situations where the chart is in a 'viewBox', re-position the tooltip based on how far chart is zoomed. - function convertViewBoxRatio() { - if (chartContainer) { - var svg = d3.select(chartContainer); - if (svg.node().tagName !== "svg") { - svg = svg.select("svg"); - } - var viewBox = (svg.node()) ? svg.attr('viewBox') : null; - if (viewBox) { - viewBox = viewBox.split(' '); - var ratio = parseInt(svg.style('width')) / viewBox[2]; - - position.left = position.left * ratio; - position.top = position.top * ratio; - } - } } - //Creates new tooltip container, or uses existing one on DOM. - function getTooltipContainer(newContent) { - var body; - if (chartContainer) { - body = d3.select(chartContainer); - } else { - body = d3.select("body"); - } - - var container = body.select(".nvtooltip"); - if (container.node() === null) { - //Create new tooltip div if it doesn't exist on DOM. - container = body.append("div") - .attr("class", "nvtooltip " + (classes? classes: "xy-tooltip")) - .attr("id",id) + var tbodyEnter = table.selectAll("tbody") + .data([d]) + .enter().append("tbody"); + + var trowEnter = tbodyEnter.selectAll("tr") + .data(function(p) { return p.series}) + .enter() + .append("tr") + .classed("highlight", function(p) { return p.highlight}); + + trowEnter.append("td") + .classed("legend-color-guide",true) + .append("div") + .style("background-color", function(p) { return p.color}); + + trowEnter.append("td") + .classed("key",true) + .classed("total",function(p) { return !!p.total}) + .html(function(p, i) { return keyFormatter(p.key, i)}); + + trowEnter.append("td") + .classed("value",true) + .html(function(p, i) { return valueFormatter(p.value, i) }); + + trowEnter.selectAll("td").each(function(p) { + if (p.highlight) { + var opacityScale = d3.scale.linear().domain([0,1]).range(["#fff",p.color]); + var opacity = 0.6; + d3.select(this) + .style("border-bottom-color", opacityScale(opacity)) + .style("border-top-color", opacityScale(opacity)) ; } + }); - container.node().innerHTML = newContent; - container.style("top",0).style("left",0).style("opacity",0); - container.selectAll("div, table, td, tr").classed(nvPointerEventsClass,true) - container.classed(nvPointerEventsClass,true); - return container.node(); - } - - //Draw the tooltip onto the DOM. - function nvtooltip() { - if (!enabled) return; - if (!dataSeriesExists(data)) return; - - convertViewBoxRatio(); - - var left = position.left; - var top = (fixedTop != null) ? fixedTop : position.top; - var container = getTooltipContainer(contentGenerator(data)); - tooltipElem = container; - if (chartContainer) { - var svgComp = chartContainer.getElementsByTagName("svg")[0]; - var boundRect = (svgComp) ? svgComp.getBoundingClientRect() : chartContainer.getBoundingClientRect(); - var svgOffset = {left:0,top:0}; - if (svgComp) { - var svgBound = svgComp.getBoundingClientRect(); - var chartBound = chartContainer.getBoundingClientRect(); - var svgBoundTop = svgBound.top; - - //Defensive code. Sometimes, svgBoundTop can be a really negative - // number, like -134254. That's a bug. - // If such a number is found, use zero instead. FireFox bug only - if (svgBoundTop < 0) { - var containerBound = chartContainer.getBoundingClientRect(); - svgBoundTop = (Math.abs(svgBoundTop) > containerBound.height) ? 0 : svgBoundTop; - } - svgOffset.top = Math.abs(svgBoundTop - chartBound.top); - svgOffset.left = Math.abs(svgBound.left - chartBound.left); - } - //If the parent container is an overflow
    with scrollbars, subtract the scroll offsets. - //You need to also add any offset between the element and its containing
    - //Finally, add any offset of the containing
    on the whole page. - left += chartContainer.offsetLeft + svgOffset.left - 2*chartContainer.scrollLeft; - top += chartContainer.offsetTop + svgOffset.top - 2*chartContainer.scrollTop; - } - - if (snapDistance && snapDistance > 0) { - top = Math.floor(top/snapDistance) * snapDistance; - } - - nv.tooltip.calcTooltipPosition([left,top], gravity, distance, container); - return nvtooltip; - } + var html = table.node().outerHTML; + if (d.footer !== undefined) + html += ""; + return html; - nvtooltip.nvPointerEventsClass = nvPointerEventsClass; - - nvtooltip.content = function(_) { - if (!arguments.length) return content; - content = _; - return nvtooltip; - }; - - //Returns tooltipElem...not able to set it. - nvtooltip.tooltipElem = function() { - return tooltipElem; - }; - - nvtooltip.contentGenerator = function(_) { - if (!arguments.length) return contentGenerator; - if (typeof _ === 'function') { - contentGenerator = _; - } - return nvtooltip; - }; - - nvtooltip.data = function(_) { - if (!arguments.length) return data; - data = _; - return nvtooltip; - }; - - nvtooltip.gravity = function(_) { - if (!arguments.length) return gravity; - gravity = _; - return nvtooltip; - }; - - nvtooltip.distance = function(_) { - if (!arguments.length) return distance; - distance = _; - return nvtooltip; - }; - - nvtooltip.snapDistance = function(_) { - if (!arguments.length) return snapDistance; - snapDistance = _; - return nvtooltip; - }; - - nvtooltip.classes = function(_) { - if (!arguments.length) return classes; - classes = _; - return nvtooltip; - }; - - nvtooltip.chartContainer = function(_) { - if (!arguments.length) return chartContainer; - chartContainer = _; - return nvtooltip; - }; - - nvtooltip.position = function(_) { - if (!arguments.length) return position; - position.left = (typeof _.left !== 'undefined') ? _.left : position.left; - position.top = (typeof _.top !== 'undefined') ? _.top : position.top; - return nvtooltip; - }; - - nvtooltip.fixedTop = function(_) { - if (!arguments.length) return fixedTop; - fixedTop = _; - return nvtooltip; - }; - - nvtooltip.enabled = function(_) { - if (!arguments.length) return enabled; - enabled = _; - return nvtooltip; - }; - - nvtooltip.valueFormatter = function(_) { - if (!arguments.length) return valueFormatter; - if (typeof _ === 'function') { - valueFormatter = _; - } - return nvtooltip; - }; - - nvtooltip.headerFormatter = function(_) { - if (!arguments.length) return headerFormatter; - if (typeof _ === 'function') { - headerFormatter = _; - } - return nvtooltip; - }; - - //id() is a read-only function. You can't use it to set the id. - nvtooltip.id = function() { - return id; - }; - - return nvtooltip; - }; - - //Original tooltip.show function. Kept for backward compatibility. - // pos = [left,top] - nv.tooltip.show = function(pos, content, gravity, dist, parentContainer, classes) { - - //Create new tooltip div if it doesn't exist on DOM. - var container = document.createElement('div'); - container.className = 'nvtooltip ' + (classes ? classes : 'xy-tooltip'); - - var body = parentContainer; - if ( !parentContainer || parentContainer.tagName.match(/g|svg/i)) { - //If the parent element is an SVG element, place tooltip in the element. - body = document.getElementsByTagName('body')[0]; - } - - container.style.left = 0; - container.style.top = 0; - container.style.opacity = 0; - // Content can also be dom element - if (typeof content !== 'string') - container.appendChild(content); - else - container.innerHTML = content; - body.appendChild(container); - - //If the parent container is an overflow
    with scrollbars, subtract the scroll offsets. - if (parentContainer) { - pos[0] = pos[0] - parentContainer.scrollLeft; - pos[1] = pos[1] - parentContainer.scrollTop; - } - nv.tooltip.calcTooltipPosition(pos, gravity, dist, container); }; - //Looks up the ancestry of a DOM element, and returns the first NON-svg node. - nv.tooltip.findFirstNonSVGParent = function(Elem) { - while(Elem.tagName.match(/^g|svg$/i) !== null) { - Elem = Elem.parentNode; - } - return Elem; - }; - - //Finds the total offsetTop of a given DOM element. - //Looks up the entire ancestry of an element, up to the first relatively positioned element. - nv.tooltip.findTotalOffsetTop = function ( Elem, initialTop ) { - var offsetTop = initialTop; - - do { - if( !isNaN( Elem.offsetTop ) ) { - offsetTop += (Elem.offsetTop); + var dataSeriesExists = function(d) { + if (d && d.series) { + if (d.series instanceof Array) { + return !!d.series.length; } - } while( Elem = Elem.offsetParent ); - return offsetTop; - }; - - //Finds the total offsetLeft of a given DOM element. - //Looks up the entire ancestry of an element, up to the first relatively positioned element. - nv.tooltip.findTotalOffsetLeft = function ( Elem, initialLeft) { - var offsetLeft = initialLeft; - - do { - if( !isNaN( Elem.offsetLeft ) ) { - offsetLeft += (Elem.offsetLeft); + // if object, it's okay just convert to array of the object + if (d.series instanceof Object) { + d.series = [d.series]; + return true; } - } while( Elem = Elem.offsetParent ); - return offsetLeft; + } + return false; }; - //Global utility function to render a tooltip on the DOM. - //pos = [left,top] coordinates of where to place the tooltip, relative to the SVG chart container. - //gravity = how to orient the tooltip - //dist = how far away from the mouse to place tooltip - //container = tooltip DIV - nv.tooltip.calcTooltipPosition = function(pos, gravity, dist, container) { - - var height = parseInt(container.offsetHeight), - width = parseInt(container.offsetWidth), - windowWidth = nv.utils.windowSize().width, - windowHeight = nv.utils.windowSize().height, - scrollTop = window.pageYOffset, - scrollLeft = window.pageXOffset, - left, top; - - windowHeight = window.innerWidth >= document.body.scrollWidth ? windowHeight : windowHeight - 16; - windowWidth = window.innerHeight >= document.body.scrollHeight ? windowWidth : windowWidth - 16; - - gravity = gravity || 's'; - dist = dist || 20; - - var tooltipTop = function ( Elem ) { - return nv.tooltip.findTotalOffsetTop(Elem, top); - }; - - var tooltipLeft = function ( Elem ) { - return nv.tooltip.findTotalOffsetLeft(Elem,left); - }; + // Calculates the gravity offset of the tooltip. Parameter is position of tooltip + // relative to the viewport. + var calcGravityOffset = function(pos) { + var height = tooltip.node().offsetHeight, + width = tooltip.node().offsetWidth, + clientWidth = document.documentElement.clientWidth, // Don't want scrollbars. + clientHeight = document.documentElement.clientHeight, // Don't want scrollbars. + left, top, tmp; + // calculate position based on gravity switch (gravity) { case 'e': - left = pos[0] - width - dist; - top = pos[1] - (height / 2); - var tLeft = tooltipLeft(container); - var tTop = tooltipTop(container); - if (tLeft < scrollLeft) left = pos[0] + dist > scrollLeft ? pos[0] + dist : scrollLeft - tLeft + left; - if (tTop < scrollTop) top = scrollTop - tTop + top; - if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height; + left = - width - distance; + top = - (height / 2); + if(pos.left + left < 0) left = distance; + if((tmp = pos.top + top) < 0) top -= tmp; + if((tmp = pos.top + top + height) > clientHeight) top -= tmp - clientHeight; break; case 'w': - left = pos[0] + dist; - top = pos[1] - (height / 2); - var tLeft = tooltipLeft(container); - var tTop = tooltipTop(container); - if (tLeft + width > windowWidth) left = pos[0] - width - dist; - if (tTop < scrollTop) top = scrollTop + 5; - if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height; + left = distance; + top = - (height / 2); + if (pos.left + left + width > clientWidth) left = - width - distance; + if ((tmp = pos.top + top) < 0) top -= tmp; + if ((tmp = pos.top + top + height) > clientHeight) top -= tmp - clientHeight; break; case 'n': - left = pos[0] - (width / 2) - 5; - top = pos[1] + dist; - var tLeft = tooltipLeft(container); - var tTop = tooltipTop(container); - if (tLeft < scrollLeft) left = scrollLeft + 5; - if (tLeft + width > windowWidth) left = left - width/2 + 5; - if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height; + left = - (width / 2) - 5; // - 5 is an approximation of the mouse's height. + top = distance; + if (pos.top + top + height > clientHeight) top = - height - distance; + if ((tmp = pos.left + left) < 0) left -= tmp; + if ((tmp = pos.left + left + width) > clientWidth) left -= tmp - clientWidth; break; case 's': - left = pos[0] - (width / 2); - top = pos[1] - height - dist; - var tLeft = tooltipLeft(container); - var tTop = tooltipTop(container); - if (tLeft < scrollLeft) left = scrollLeft + 5; - if (tLeft + width > windowWidth) left = left - width/2 + 5; - if (scrollTop > tTop) top = scrollTop; + left = - (width / 2); + top = - height - distance; + if (pos.top + top < 0) top = distance; + if ((tmp = pos.left + left) < 0) left -= tmp; + if ((tmp = pos.left + left + width) > clientWidth) left -= tmp - clientWidth; break; - case 'none': - left = pos[0]; - top = pos[1] - dist; - var tLeft = tooltipLeft(container); - var tTop = tooltipTop(container); + case 'center': + left = - (width / 2); + top = - (height / 2); + break; + default: + left = 0; + top = 0; break; } - container.style.left = left+'px'; - container.style.top = top+'px'; - container.style.opacity = 1; - container.style.position = 'absolute'; + return { 'left': left, 'top': top }; + }; + + /* + Positions the tooltip in the correct place, as given by the position() function. + */ + var positionTooltip = function() { + nv.dom.read(function() { + var pos = position(), + gravityOffset = calcGravityOffset(pos), + left = pos.left + gravityOffset.left, + top = pos.top + gravityOffset.top; + + // delay hiding a bit to avoid flickering + if (hidden) { + tooltip + .interrupt() + .transition() + .delay(hideDelay) + .duration(0) + .style('opacity', 0); + } else { + // using tooltip.style('transform') returns values un-usable for tween + var old_translate = 'translate(' + lastPosition.left + 'px, ' + lastPosition.top + 'px)'; + var new_translate = 'translate(' + left + 'px, ' + top + 'px)'; + var translateInterpolator = d3.interpolateString(old_translate, new_translate); + var is_hidden = tooltip.style('opacity') < 0.1; + + tooltip + .interrupt() // cancel running transitions + .transition() + .duration(is_hidden ? 0 : duration) + // using tween since some versions of d3 can't auto-tween a translate on a div + .styleTween('transform', function (d) { + return translateInterpolator; + }, 'important') + // Safari has its own `-webkit-transform` and does not support `transform` + .styleTween('-webkit-transform', function (d) { + return translateInterpolator; + }) + .style('-ms-transform', new_translate) + .style('opacity', 1); + } - return container; + lastPosition.left = left; + lastPosition.top = top; + }); }; - //Global utility function to remove tooltips from the DOM. - nv.tooltip.cleanup = function() { - - // Find the tooltips, mark them for removal by this class (so others cleanups won't find it) - var tooltips = document.getElementsByClassName('nvtooltip'); - var purging = []; - while(tooltips.length) { - purging.push(tooltips[0]); - tooltips[0].style.transitionDelay = '0 !important'; - tooltips[0].style.opacity = 0; - tooltips[0].className = 'nvtooltip-pending-removal'; + // Creates new tooltip container, or uses existing one on DOM. + function initTooltip() { + if (!tooltip) { + var container = chartContainer ? chartContainer : document.body; + + // Create new tooltip div if it doesn't exist on DOM. + tooltip = d3.select(container).append("div") + .attr("class", "nvtooltip " + (classes ? classes : "xy-tooltip")) + .attr("id", id); + tooltip.style("top", 0).style("left", 0); + tooltip.style('opacity', 0); + tooltip.style('position', 'fixed'); + tooltip.selectAll("div, table, td, tr").classed(nvPointerEventsClass, true); + tooltip.classed(nvPointerEventsClass, true); } + } + + // Draw the tooltip onto the DOM. + function nvtooltip() { + if (!enabled) return; + if (!dataSeriesExists(data)) return; + + nv.dom.write(function () { + initTooltip(); + // Generate data and set it into tooltip. + // Bonus - If you override contentGenerator and return falsey you can use something like + // React or Knockout to bind the data for your tooltip. + var newContent = contentGenerator(data); + if (newContent) { + tooltip.node().innerHTML = newContent; + } - setTimeout(function() { + positionTooltip(); + }); - while (purging.length) { - var removeMe = purging.pop(); - removeMe.parentNode.removeChild(removeMe); + return nvtooltip; + } + + nvtooltip.nvPointerEventsClass = nvPointerEventsClass; + nvtooltip.options = nv.utils.optionsFunc.bind(nvtooltip); + + nvtooltip._options = Object.create({}, { + // simple read/write options + duration: {get: function(){return duration;}, set: function(_){duration=_;}}, + gravity: {get: function(){return gravity;}, set: function(_){gravity=_;}}, + distance: {get: function(){return distance;}, set: function(_){distance=_;}}, + snapDistance: {get: function(){return snapDistance;}, set: function(_){snapDistance=_;}}, + classes: {get: function(){return classes;}, set: function(_){classes=_;}}, + chartContainer: {get: function(){return chartContainer;}, set: function(_){chartContainer=_;}}, + enabled: {get: function(){return enabled;}, set: function(_){enabled=_;}}, + hideDelay: {get: function(){return hideDelay;}, set: function(_){hideDelay=_;}}, + contentGenerator: {get: function(){return contentGenerator;}, set: function(_){contentGenerator=_;}}, + valueFormatter: {get: function(){return valueFormatter;}, set: function(_){valueFormatter=_;}}, + headerFormatter: {get: function(){return headerFormatter;}, set: function(_){headerFormatter=_;}}, + keyFormatter: {get: function(){return keyFormatter;}, set: function(_){keyFormatter=_;}}, + headerEnabled: {get: function(){return headerEnabled;}, set: function(_){headerEnabled=_;}}, + position: {get: function(){return position;}, set: function(_){position=_;}}, + + // Deprecated options + fixedTop: {get: function(){return null;}, set: function(_){ + // deprecated after 1.8.1 + nv.deprecated('fixedTop', 'feature removed after 1.8.1'); + }}, + offset: {get: function(){return {left: 0, top: 0};}, set: function(_){ + // deprecated after 1.8.1 + nv.deprecated('offset', 'use chart.tooltip.distance() instead'); + }}, + + // options with extra logic + hidden: {get: function(){return hidden;}, set: function(_){ + if (hidden != _) { + hidden = !!_; + nvtooltip(); } - }, 500); - }; + }}, + data: {get: function(){return data;}, set: function(_){ + // if showing a single data point, adjust data format with that + if (_.point) { + _.value = _.point.x; + _.series = _.series || {}; + _.series.value = _.point.y; + _.series.color = _.point.color || _.series.color; + } + data = _; + }}, + + // read only properties + node: {get: function(){return tooltip.node();}, set: function(_){}}, + id: {get: function(){return id;}, set: function(_){}} + }); -})(); + nv.utils.initOptions(nvtooltip); + return nvtooltip; +}; diff --git a/src/utils.js b/src/utils.js index f05d4c70a..d3aef1066 100644 --- a/src/utils.js +++ b/src/utils.js @@ -9,10 +9,11 @@ nv.utils.windowSize = function() { // Sane defaults var size = {width: 640, height: 480}; - // Earlier IE uses Doc.body - if (document.body && document.body.offsetWidth) { - size.width = document.body.offsetWidth; - size.height = document.body.offsetHeight; + // Most recent browsers use + if (window.innerWidth && window.innerHeight) { + size.width = window.innerWidth; + size.height = window.innerHeight; + return (size); } // IE can use depending on mode it is in @@ -22,17 +23,19 @@ nv.utils.windowSize = function() { size.width = document.documentElement.offsetWidth; size.height = document.documentElement.offsetHeight; + return (size); } - // Most recent browsers use - if (window.innerWidth && window.innerHeight) { - size.width = window.innerWidth; - size.height = window.innerHeight; + // Earlier IE uses Doc.body + if (document.body && document.body.offsetWidth) { + size.width = document.body.offsetWidth; + size.height = document.body.offsetHeight; + return (size); } + return (size); }; - /* Binds callback function to run when window is resized */ @@ -54,19 +57,25 @@ nv.utils.windowResize = function(handler) { /* Backwards compatible way to implement more d3-like coloring of graphs. -If passed an array, wrap it in a function which implements the old behavior -Else return what was passed in +Can take in nothing, an array, or a function/scale +To use a normal scale, get the range and pass that because we must be able +to take two arguments and use the index to keep backward compatibility */ nv.utils.getColor = function(color) { //if you pass in nothing, get default colors back - if (!arguments.length) { + if (color === undefined) { return nv.utils.defaultColor(); - //if passed an array, wrap it in a function - } else if(color instanceof Array) { - return function(d, i) { return d.color || color[i % color.length]; }; + //if passed an array, turn it into a color scale + // use isArray, instanceof fails if d3 range is created in an iframe + } else if(Array.isArray(color)) { + var color_scale = d3.scale.ordinal().range(color); + return function(d, i) { + var key = i === undefined ? d : i; + return d.color || color_scale(key); + }; - //if passed a function, return the function, or whatever it may be + //if passed a function or scale, return it, or whatever it may be //external libs, such as angularjs-nvd3-directives use this } else { //can't really help it if someone passes rubbish as color @@ -76,13 +85,12 @@ nv.utils.getColor = function(color) { /* -Default color chooser uses the index of an object as before. +Default color chooser uses a color scale of 20 colors from D3 + https://github.com/mbostock/d3/wiki/Ordinal-Scales#categorical-colors */ nv.utils.defaultColor = function() { - var colors = d3.scale.category20().range(); - return function(d, i) { - return d.color || colors[i % colors.length] - }; + // get range of the scale so we'll turn it into our own function. + return nv.utils.getColor(d3.scale.category20().range()); }; @@ -157,7 +165,7 @@ nv.utils.calcApproxTextWidth = function (svgTextElem) { if (typeof svgTextElem.style === 'function' && typeof svgTextElem.text === 'function') { - var fontSize = parseInt(svgTextElem.style("font-size").replace("px","")); + var fontSize = parseInt(svgTextElem.style("font-size").replace("px",""), 10); var textLength = svgTextElem.text().length; return textLength * fontSize * 0.5; } @@ -286,7 +294,7 @@ gives: {a: 2, b: 3, c: 4} nv.utils.deepExtend = function(dst){ var sources = arguments.length > 1 ? [].slice.call(arguments, 1) : []; sources.forEach(function(source) { - for (key in source) { + for (var key in source) { var isArray = dst[key] instanceof Array; var isObject = typeof dst[key] === 'object'; var srcObj = typeof source[key] === 'object'; @@ -386,7 +394,6 @@ To enable in the chart: chart.options = nv.utils.optionsFunc.bind(chart); */ nv.utils.optionsFunc = function(args) { - nv.deprecated('nv.utils.optionsFunc'); if (args) { d3.map(args).forEach((function(key,value) { if (typeof this[key] === "function") { @@ -450,9 +457,19 @@ nv.utils.initOption = function(chart, name) { } else { chart[name] = function (_) { if (!arguments.length) return chart._options[name]; + chart._overrides[name] = true; chart._options[name] = _; return chart; }; + // calling the option as _option will ignore if set by option already + // so nvd3 can set options internally but the stop if set manually + chart['_' + name] = function(_) { + if (!arguments.length) return chart._options[name]; + if (!chart._overrides[name]) { + chart._options[name] = _; + } + return chart; + } } }; @@ -461,6 +478,7 @@ nv.utils.initOption = function(chart, name) { Add all options in an options object to the chart */ nv.utils.initOptions = function(chart) { + chart._overrides = chart._overrides || {}; var ops = Object.getOwnPropertyNames(chart._options || {}); var calls = Object.getOwnPropertyNames(chart._calls || {}); ops = ops.concat(calls); @@ -557,4 +575,120 @@ Runs common initialize code on the svg before the chart builds */ nv.utils.initSVG = function(svg) { svg.classed({'nvd3-svg':true}); +}; + + +/* +Sanitize and provide default for the container height. +*/ +nv.utils.sanitizeHeight = function(height, container) { + return (height || parseInt(container.style('height'), 10) || 400); +}; + + +/* +Sanitize and provide default for the container width. +*/ +nv.utils.sanitizeWidth = function(width, container) { + return (width || parseInt(container.style('width'), 10) || 960); +}; + + +/* +Calculate the available height for a chart. +*/ +nv.utils.availableHeight = function(height, container, margin) { + return nv.utils.sanitizeHeight(height, container) - margin.top - margin.bottom; +}; + +/* +Calculate the available width for a chart. +*/ +nv.utils.availableWidth = function(width, container, margin) { + return nv.utils.sanitizeWidth(width, container) - margin.left - margin.right; +}; + +/* +Clear any rendered chart components and display a chart's 'noData' message +*/ +nv.utils.noData = function(chart, container) { + var opt = chart.options(), + margin = opt.margin(), + noData = opt.noData(), + data = (noData == null) ? ["No Data Available."] : [noData], + height = nv.utils.availableHeight(null, container, margin), + width = nv.utils.availableWidth(null, container, margin), + x = margin.left + width/2, + y = margin.top + height/2; + + //Remove any previously created chart components + container.selectAll('g').remove(); + + var noDataText = container.selectAll('.nv-noData').data(data); + + noDataText.enter().append('text') + .attr('class', 'nvd3 nv-noData') + .attr('dy', '-.7em') + .style('text-anchor', 'middle'); + + noDataText + .attr('x', x) + .attr('y', y) + .text(function(t){ return t; }); +}; + +/* + Wrap long labels. + */ +nv.utils.wrapTicks = function (text, width) { + text.each(function() { + var text = d3.select(this), + words = text.text().split(/\s+/).reverse(), + word, + line = [], + lineNumber = 0, + lineHeight = 1.1, + y = text.attr("y"), + dy = parseFloat(text.attr("dy")), + tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em"); + while (word = words.pop()) { + line.push(word); + tspan.text(line.join(" ")); + if (tspan.node().getComputedTextLength() > width) { + line.pop(); + tspan.text(line.join(" ")); + line = [word]; + tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", ++lineNumber * lineHeight + dy + "em").text(word); + } + } + }); +}; + +/* +Check equality of 2 array +*/ +nv.utils.arrayEquals = function (array1, array2) { + if (array1 === array2) + return true; + + if (!array1 || !array2) + return false; + + // compare lengths - can save a lot of time + if (array1.length != array2.length) + return false; + + for (var i = 0, + l = array1.length; i < l; i++) { + // Check if we have nested arrays + if (array1[i] instanceof Array && array2[i] instanceof Array) { + // recurse into the nested arrays + if (!nv.arrayEquals(array1[i], array2[i])) + return false; + } else if (array1[i] != array2[i]) { + // Warning - two different object instances will never be equal: {x:20} != {x:20} + return false; + } + } + return true; }; \ No newline at end of file diff --git a/test/ScatterChartTest.html b/test/ScatterChartTest.html index a96bfce7f..07406786a 100644 --- a/test/ScatterChartTest.html +++ b/test/ScatterChartTest.html @@ -111,6 +111,7 @@

    Scatter chart tests

    defaultChartTest("test6", randomData(1,1)); defaultChartTest("test7", randomData(1,2)); defaultChartTest("test8", randomData(3,1)); + defaultChartTest("test9", [ {key: "Group 0", values: []}, {key: "Group 1", values: [{x:1, y:1}]} @@ -150,8 +151,8 @@

    Scatter chart tests

    chart = nv.models.scatterChart() .showDistX(true).showDistY(true) ; - chart.xAxis.tickFormat(d3.format('.02f')); - chart.yAxis.tickFormat(d3.format('.02f')); + chart.xAxis.tickFormat(d3.format('.02f')).ticks(10); + chart.yAxis.tickFormat(d3.format('.02f')).ticks(10); if (margin) { chart.margin(margin); } diff --git a/test/boxPlotTest.html b/test/boxPlotTest.html new file mode 100644 index 000000000..8518eafc6 --- /dev/null +++ b/test/boxPlotTest.html @@ -0,0 +1,264 @@ + + + + + + + + +

    Box Plot test cases

    +
    + Normal data (maxBoxWidth and staggerLabel options) + +
    +
    + Normal data (forceY) + +
    +
    + Single box + +
    +
    + Twelve boxes (repeating) + +
    +
    + Bad whiskers + +
    +
    + Bad outliers + +
    + \ No newline at end of file diff --git a/test/lineChartTest.html b/test/lineChartTest.html index 86c426a49..5202e4292 100644 --- a/test/lineChartTest.html +++ b/test/lineChartTest.html @@ -126,6 +126,14 @@

    Line chart test cases - feel free to add more tests

    + +
    + Chart with missing data (discontinuous lines). Check that all highlighted points + have the same x, matching the guideline. Check that "N/A" appears in tooltip for + points with undefined y. + +
    +
    @@ -187,6 +195,7 @@

    Line chart test cases - feel free to add more tests

    defaultChartConfig("chart15", withNaNs()); defaultChartConfig("chart16", duplicateY(), false); defaultChartConfig("chart17", tinyPoints(), false); +defaultChartConfig("chart18", missingData(), true); function defaultChartConfig(containerid, data, guideline, useDates, auxOptions) { if (auxOptions === undefined) auxOptions = {}; @@ -442,6 +451,59 @@

    Line chart test cases - feel free to add more tests

    return [rval]; } +function missingData() { + var sin = [], + sin2 = [], + cos = [], + rand = [], + rand2 = [] + ; + + + for (var i = 0; i < 100; i++) { + + sin.push(i % 17 === 0 ? {x: i, y: null} : {x: i, y: Math.sin(i/10) }); + sin2.push(i % 19 === 0 ? {x: i, y: null} : {x: i, y: Math.sin(i/5) * 0.4 - 0.25}); + cos.push(i % 7 === 0 ? {x: i, y:null} : {x: i, y:.5 * Math.cos(i/10)}); + rand.push(i % 11 === 0 ? {x: i, y: null} : {x: i , y: Math.random() / 10}); + rand2.push( i % 13 === 0 ? {x: i, y: null} : {x: i, y: Math.cos(i/10) + Math.random() / 10 }); + } + + return [ + { + area: true, + values: sin, + key: "Sine Wave", + color: "#ff7f0e", + strokeWidth: 4, + classed: 'dashed' + }, + { + values: cos, + key: "Cosine Wave", + color: "#2ca02c" + }, + { + values: rand, + key: "Random Points", + color: "#2222ff" + }, + { + values: rand2, + key: "Random Cosine", + color: "#667711", + strokeWidth: 3.5 + }, + { + area: true, + values: sin2, + key: "Fill opacity", + color: "#EF9CFB", + fillOpacity: .1 + } + ]; +} + function dummyStocks(numPoints) { numPoints = numPoints || 200; function volatileChart(key,startPrice, volatility, isArea) { diff --git a/test/lineWithFocusChartMissingData.html b/test/lineWithFocusChartMissingData.html new file mode 100644 index 000000000..6250de2c8 --- /dev/null +++ b/test/lineWithFocusChartMissingData.html @@ -0,0 +1,79 @@ + + + + + + + + + + + + + +
    + +
    + + + + \ No newline at end of file diff --git a/test/mocha/axis.coffee b/test/mocha/axis.coffee index 174f91511..081bd5af8 100644 --- a/test/mocha/axis.coffee +++ b/test/mocha/axis.coffee @@ -24,7 +24,6 @@ describe 'NVD3', -> height: 60 axisLabel: 'Date' showMaxMin: true - highlightZero: true scale: d3.scale.linear() rotateYLabel: true rotateLabels: 0 @@ -115,7 +114,13 @@ describe 'NVD3', -> for tick in ticks transform = tick.getAttribute 'transform' - transform.should.equal 'rotate(30 0,0)' + transform.should.match /rotate\(30 0,\d+?.*?\)/ + + maxMin = builder.$ '.nv-x.nv-axis .nv-axisMaxMin text' + + for tick in maxMin + transform = tick.getAttribute 'transform' + transform.should.match /rotate\(30 0,\d+?.*?\)/ it 'axis stagger labels', -> axis = builder.model.xAxis @@ -141,3 +146,10 @@ describe 'NVD3', -> builder.model.update() done() + + it 'has CSS class "zero" to mark zero tick', -> + tick = builder.$ '.nv-x.nv-axis .tick.zero' + tick.length.should.equal 1, 'x axis zero' + + tick = builder.$ '.nv-y.nv-axis .tick.zero' + tick.length.should.equal 1, 'y axis zero' diff --git a/test/mocha/boxplot.coffee b/test/mocha/boxplot.coffee new file mode 100644 index 000000000..bb0299160 --- /dev/null +++ b/test/mocha/boxplot.coffee @@ -0,0 +1,115 @@ +describe 'NVD3', -> + describe 'Box Plot', -> + sampleData1 = [ + label: 'Sample A', + values: + Q1: 120, + Q2: 150, + Q3: 200, + whisker_low: 115, + whisker_high: 210, + outliers: [50, 100, 225] + ] + + sampleData2 = [ + label: 'Sample A', + values: + Q1: 120, + Q2: 150, + Q3: 200, + whisker_low: 115, + whisker_high: 210, + outliers: [] + ] + + sampleData3 = [ + { + label: 'Sample A', + values: { Q1: 120, Q2: 150, Q3: 200, whisker_low: 115, whisker_high: 210, outliers: [50, 100, 225] } + }, + { + label: 'Sample B', + values: { Q1: 300, Q2: 350, Q3: 400, whisker_low: 2255, whisker_high: 400, outliers: [175] } + } + ] + + options = + x: (d)-> d.label + y: (d)-> d.values.Q3 + margin: + top: 30 + right: 20 + bottom: 50 + left: 75 + color: nv.utils.defaultColor() + height: 400 + width: 800 + showXAxis: true + showYAxis: true + noData: 'No Data Available' + duration: 0 + maxBoxWidth: 75 + + builder = null + beforeEach -> + builder = new ChartBuilder nv.models.boxPlotChart() + builder.build options, sampleData1 + + afterEach -> + builder.teardown() + + it 'api check', -> + should.exist builder.model.options, 'options exposed' + for opt of options + should.exist builder.model[opt](), "#{opt} can be called" + + builder.model.update() + + it 'renders', -> + wrap = builder.$ 'g.nvd3.nv-boxPlotWithAxes' + should.exist wrap[0] + + it 'no data text', -> + builder = new ChartBuilder nv.models.boxPlotChart() + builder.build options, [] + + noData = builder.$ '.nv-noData' + noData[0].textContent.should.equal 'No Data Available' + + it 'has correct structure', -> + cssClasses = [ + '.nv-x.nv-axis' + '.nv-y.nv-axis' + '.nv-barsWrap' + '.nv-wrap' + '.nv-boxplot' + '.nv-boxplot-median' + '.nv-boxplot-tick.nv-boxplot-low' + '.nv-boxplot-whisker.nv-boxplot-low' + '.nv-boxplot-tick.nv-boxplot-high' + '.nv-boxplot-whisker.nv-boxplot-high' + ] + for cssClass in cssClasses + do (cssClass) -> + should.exist builder.$("g.nvd3.nv-boxPlotWithAxes #{cssClass}")[0] + + it 'Has boxplots', -> + builder = new ChartBuilder nv.models.boxPlotChart() + builder.buildover options, sampleData3, [] + + boxes = builder.$ '.nv-boxplot-box' + boxes.length.should.equal 2, 'boxplots exist' + + it 'Has outliers', -> + builder = new ChartBuilder nv.models.boxPlotChart() + builder.buildover options, sampleData1, [] + + outliers = builder.$ '.nv-boxplot .nv-boxplot-outlier' + outliers.length.should.equal 3, 'outliers exist' + + it 'Has no outliers', -> + builder = new ChartBuilder nv.models.boxPlotChart() + builder.buildover options, sampleData2, [] + + outliers = builder.$ '.nv-boxplot-outlier' + \ No newline at end of file diff --git a/test/mocha/bullet.coffee b/test/mocha/bullet.coffee index be04c142f..9bf174aba 100644 --- a/test/mocha/bullet.coffee +++ b/test/mocha/bullet.coffee @@ -1,24 +1,12 @@ describe 'NVD3', -> describe 'Bullet Chart', -> - removeAllTooltips = -> - elements = document.getElementsByClassName('nvtooltip') - while(elements[0]) - elements[0].parentNode.removeChild(elements[0]) - - eventTooltipData = - point: {series: 0, x: -1, y: 1} - pointIndex: 0 - pos: [210, 119] - series: {key: 'Series 1'} - seriesIndex: 0 - sampleData1 = title: 'Revenue' subtitle: 'US$ in thousands' ranges: [10,20,30] measures: [40] - markers: [50] + markers: [50, 100] options = orient: 'left' @@ -34,8 +22,6 @@ describe 'NVD3', -> width: 100 height: 110 tickFormat: (d)-> d.toFixed 2 - tooltips: true - tooltipContent: (key,x,y)-> "

    #{key}

    " noData: 'No Data Available' builder1 = null @@ -47,13 +33,18 @@ describe 'NVD3', -> builder1.teardown() it 'api check', -> - for opt of options - should.exist builder1.model[opt](), "#{opt} can be called" + should.exist builder1.model.options, 'options exposed' + for opt of options + should.exist builder1.model[opt](), "#{opt} can be called" it 'renders', -> wrap = builder1.$ 'g.nvd3.nv-bulletChart' should.exist wrap[0] + it 'displays multiple markers', -> + markers = document.querySelectorAll '.nv-markerTriangle' + markers.length.should.equal 2 + it 'has correct g.nvd3.nv-bulletChart position', -> chart = builder1.$ 'g.nvd3.nv-bulletChart' chart[0].getAttribute('transform').should.be.equal 'translate(90,60)' @@ -75,16 +66,6 @@ describe 'NVD3', -> do (cssClass) -> should.exist builder1.$("g.nvd3 #{cssClass}")[0] - it 'can show tooltip', -> - - removeAllTooltips() - - builder1.model.bullet.dispatch.elementMouseover eventTooltipData - - tooltip = document.querySelector '.nvtooltip' - should.exist tooltip - - describe "applies correctly option", -> builder = null @@ -139,6 +120,15 @@ describe 'NVD3', -> builder.build options, {} builder.svg.textContent.should.be.equal 'No Data Available' + + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.bulletChart() + builder.buildover options, sampleData, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' + + it 'margin', -> options = margin: @@ -177,29 +167,3 @@ describe 'NVD3', -> builder.build options, sampleData parseInt( builder.$(".nv-rangeMax")[0].getAttribute('height') ).should.be.equal 300 - it 'tooltips', -> - - removeAllTooltips() - - options = - tooltips: false - - builder.build options, sampleData - - builder.model.bullet.dispatch.elementMouseover eventTooltipData - - tooltip = document.querySelector '.nvtooltip' - should.not.exist tooltip - - it 'tooltipContent', -> - - removeAllTooltips() - - options = - tooltipContent: (key)-> "

    #{key}

    " - builder.build options, sampleData - - builder.model.bullet.dispatch.elementMouseover eventTooltipData - - tooltip = document.querySelectorAll '.nvtooltip' - expect(tooltip[0].innerHTML).to.contain "

    Revenue

    " diff --git a/test/mocha/core.coffee b/test/mocha/core.coffee index 45e5a95e6..fb4f6a18f 100644 --- a/test/mocha/core.coffee +++ b/test/mocha/core.coffee @@ -5,7 +5,6 @@ describe 'NVD3', -> objects = [ 'window.nv' 'd3_time_range' - 'nv.tooltip' 'nv.utils' 'nv.models' 'nv.charts' diff --git a/test/mocha/cumulative-line.coffee b/test/mocha/cumulative-line.coffee index ed2f8c389..003de642c 100644 --- a/test/mocha/cumulative-line.coffee +++ b/test/mocha/cumulative-line.coffee @@ -46,8 +46,6 @@ describe 'NVD3', -> showYAxis: true rightAlignYAxis: false useInteractiveGuideline: true - tooltips: true - tooltipContent: (key,x,y)-> "

    #{key}

    " noData: 'No Data Available' average: (d)-> d.average duration: 0 @@ -67,8 +65,9 @@ describe 'NVD3', -> builder1.teardown() it 'api check', -> - for opt of options - should.exist builder1.model[opt](), "#{opt} can be called" + should.exist builder1.model.options, 'options exposed' + for opt of options + should.exist builder1.model[opt](), "#{opt} can be called" it 'renders', -> wrap = builder1.$ 'g.nvd3.nv-cumulativeLine' @@ -78,6 +77,13 @@ describe 'NVD3', -> cumulativeLine = builder1.$ 'g.nvd3.nv-cumulativeLine' cumulativeLine[0].getAttribute('transform').should.be.equal "translate(40,30)" + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.cumulativeLineChart() + builder.buildover options, sampleData1, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' + it 'has correct structure', -> cssClasses = [ '.nv-interactive' @@ -150,6 +156,13 @@ describe 'NVD3', -> builder.build options, sampleData builder.$(".nv-cumulativeLine .nv-axis.nv-x *").length.should.be.equal 0 + it 'can override axis ticks', -> + builder.build options, sampleData + builder.model.xAxis.ticks(34) + builder.model.yAxis.ticks(56) + builder.model.update() + builder.model.xAxis.ticks().should.equal 34 + builder.model.yAxis.ticks().should.equal 56 describe 'showYAxis', -> it 'true', -> @@ -181,22 +194,6 @@ describe 'NVD3', -> builder.build options, sampleData builder.$(".nv-cumulativeLine .nv-interactiveLineLayer").should.have.length 0 - # todo: pass this - describe 'tooltips', -> - xit "true", -> - options.tooltips = true - builder.build options, sampleData - builder.model.interactiveLayer.dispatch.elementMousemove eventTooltipData - tooltip = document.querySelector '.nvtooltip' - should.exist tooltip - - xit "false", -> - options.tooltips = false - builder.build options, sampleData - builder.model.interactiveLayer.dispatch.elementMousemove eventTooltipData - tooltip = document.querySelector '.nvtooltip' - should.not.exist tooltip - # todo: pass this describe "noErrorCheck", -> xit "true", -> @@ -205,11 +202,6 @@ describe 'NVD3', -> xit "false", -> options.noErrorCheck = false builder.build options, sampleData - xit "tooltipContent", -> - options.tooltipContent = (key,x,y)-> "

    #{key}

    " - builder.build options, sampleData - # show a tooltip - expect(builder.$(".nv-cumulativeLine .nv-tooltip")).to.contain "

    #{sampleData1[0].key}

    " it "noData", -> options.noData = "error error" @@ -234,4 +226,4 @@ describe 'NVD3', -> it "duration", -> options.duration = 100 builder.build options, sampleData - builder.model.duration().should.be.equal 100 \ No newline at end of file + builder.model.duration().should.be.equal 100 diff --git a/test/mocha/discretebar.coffee b/test/mocha/discretebar.coffee index 3c51403c9..321ca7bc7 100644 --- a/test/mocha/discretebar.coffee +++ b/test/mocha/discretebar.coffee @@ -25,8 +25,6 @@ describe 'NVD3', -> staggerLabels: true showValues: true valueFormat: (d)-> d.toFixed 2 - tooltips: true - tooltipContent: (key,x,y)-> "

    #{key}

    " noData: 'No Data Available' duration: 0 @@ -39,6 +37,7 @@ describe 'NVD3', -> builder.teardown() it 'api check', -> + should.exist builder.model.options, 'options exposed' for opt of options should.exist builder.model[opt](), "#{opt} can be called" @@ -46,6 +45,13 @@ describe 'NVD3', -> wrap = builder.$ 'g.nvd3.nv-discreteBarWithAxes' should.exist wrap[0] + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.discreteBarChart() + builder.buildover options, sampleData1, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' + it 'has correct structure', -> cssClasses = [ '.nv-x.nv-axis' @@ -55,4 +61,12 @@ describe 'NVD3', -> ] for cssClass in cssClasses do (cssClass) -> - should.exist builder.$("g.nvd3.nv-discreteBarWithAxes #{cssClass}")[0] \ No newline at end of file + should.exist builder.$("g.nvd3.nv-discreteBarWithAxes #{cssClass}")[0] + + it 'can override axis ticks', -> + builder.model.xAxis.ticks(34) + builder.model.yAxis.ticks(56) + builder.model.update() + builder.model.xAxis.ticks().should.equal 34 + builder.model.yAxis.ticks().should.equal 56 + diff --git a/test/mocha/historical-bar.coffee b/test/mocha/historical-bar.coffee index 5106b4c11..f67a0e8a4 100644 --- a/test/mocha/historical-bar.coffee +++ b/test/mocha/historical-bar.coffee @@ -25,8 +25,6 @@ describe 'NVD3', -> showXAxis: true showYAxis: true rightAlignYAxis: false - tooltips: true - tooltipContent: (key,x,y)-> "

    #{key}

    " noData: 'No Data Available' builder = null @@ -38,6 +36,7 @@ describe 'NVD3', -> builder.teardown() it 'api check', -> + should.exist builder.model.options, 'options exposed' for opt of options should.exist builder.model[opt](), "#{opt} can be called" @@ -45,6 +44,13 @@ describe 'NVD3', -> wrap = builder.$ 'g.nvd3.nv-historicalBarChart' should.exist wrap[0] + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.historicalBarChart() + builder.buildover options, sampleData1, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' + it 'has correct structure', -> cssClasses = [ '.nv-x.nv-axis' @@ -55,4 +61,11 @@ describe 'NVD3', -> ] for cssClass in cssClasses do (cssClass) -> - should.exist builder.$("g.nvd3.nv-historicalBarChart #{cssClass}")[0] \ No newline at end of file + should.exist builder.$("g.nvd3.nv-historicalBarChart #{cssClass}")[0] + + it 'can override axis ticks', -> + builder.model.xAxis.ticks(34) + builder.model.yAxis.ticks(56) + builder.model.update() + builder.model.xAxis.ticks().should.equal 34 + builder.model.yAxis.ticks().should.equal 56 diff --git a/test/mocha/legend.coffee b/test/mocha/legend.coffee index 4d7c53e9c..fa40c7dd2 100644 --- a/test/mocha/legend.coffee +++ b/test/mocha/legend.coffee @@ -1,12 +1,21 @@ describe 'NVD3', -> describe 'Legend', -> - sampleData1 = [ {"values":[{"x":1,"y":2},{"x":3,"y":4},{"x":5,"y":6}],"key":"key 1"} {"values":[{"x":7,"y":8},{"x":9,"y":10},{"x":11,"y":12}],"key":"key 2"} {"values":[{"x":13,"y":14},{"x":15,"y":16},{"x":17,"y":18}],"key":"key 3"} ] + sampleData2 = [ + key: 'series 1' + , + key: 'series 2' + , + key: 'series 3' + , + key: 'series 4' + ] + legendOptions = margin: top: 0 @@ -59,4 +68,53 @@ describe 'NVD3', -> should.exist nvLegendSymbol should.exist nvLegendText - nvLegendText.textContent.should.be.equal key \ No newline at end of file + nvLegendText.textContent.should.be.equal key + + describe 'clicking and double clicking', -> + it 'clicking one legend turns it off', -> + legendItems = builder.$ '.nv-legend .nv-series' + legendItems.length.should.equal 3 + + clickFn = d3.select(legendItems[0]).on 'click' + clickFn(sampleData1[0]) + sampleData1[0].disabled.should.equal true + clickFn(sampleData1[1]) + sampleData1[1].disabled.should.equal true + + clickFn(sampleData1[2]) + sampleData1[0].disabled.should.equal false + sampleData1[1].disabled.should.equal false + sampleData1[2].disabled.should.equal false + + it 'double clicking legend keeps only one on', -> + legendItems = builder.$ '.nv-legend .nv-series' + + clickFn = d3.select(legendItems[0]).on 'dblclick' + clickFn(sampleData1[0]) + sampleData1[0].disabled.should.equal false + + sampleData1[1].disabled.should.equal true + sampleData1[2].disabled.should.equal true + + it 'updating legend data does not break double click (issue 784)', -> + builder.updateData sampleData2 + + legendItems = builder.$ '.nv-legend .nv-series' + + clickFn = d3.select(legendItems[0]).on 'dblclick' + clickFn(sampleData2[0]) + sampleData2[0].disabled.should.equal false + + sampleData2[1].disabled.should.equal true + sampleData2[2].disabled.should.equal true + sampleData2[3].disabled.should.equal true + + it 'legend padding', -> + builder = new ChartBuilder nv.models.legend() + builder.build {padding: 40}, sampleData1 + + legendItems = builder.$ '.nv-legend .nv-series' + xSpacing = [0, 80, 160] + for legend,i in legendItems + transform = legend.getAttribute 'transform' + transform.should.equal "translate(#{xSpacing[i]},5)" diff --git a/test/mocha/line.coffee b/test/mocha/line.coffee index 7121ac760..db09dd161 100644 --- a/test/mocha/line.coffee +++ b/test/mocha/line.coffee @@ -12,6 +12,7 @@ describe 'NVD3', -> sampleData2 = [ key: 'Series 1' + classed: 'dashed' values: [ [-1,-3] [0,6] @@ -52,8 +53,6 @@ describe 'NVD3', -> showYAxis: true rightAlignYAxis: true useInteractiveGuideline: true - tooltips: true - tooltipContent: (key,x,y)-> "

    #{key}

    " noData: 'No Data Available' duration: 0 clipEdge: false @@ -70,6 +69,7 @@ describe 'NVD3', -> builder.teardown() it 'api check', -> + should.exist builder.model.options, 'options exposed' for opt of options should.exist builder.model[opt](), "#{opt} can be called" @@ -86,27 +86,13 @@ describe 'NVD3', -> noData = builder.$ '.nv-noData' noData[0].textContent.should.equal 'No Data Available' - it 'interactive tooltip', -> + it 'clears chart objects for no data', -> builder = new ChartBuilder nv.models.lineChart() - builder.build options, sampleData2 + builder.buildover options, sampleData1, [] - evt = - mouseX: 243 - mouseY: 96 - pointXValue: 28.15 + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' - builder.model.interactiveLayer.dispatch.elementMousemove evt - - getGuideline = -> - line = builder.$ '.nv-interactiveGuideLine line' - line[0] - - should.exist getGuideline(), 'guideline exists' - - tooltip = document.querySelector '.nvtooltip' - should.exist tooltip, 'tooltip exists' - - builder.model.interactiveLayer.dispatch.elementMouseout() it 'has correct structure', -> cssClasses = [ @@ -120,4 +106,27 @@ describe 'NVD3', -> ] for cssClass in cssClasses do (cssClass) -> - should.exist builder.$("g.nvd3.nv-lineChart #{cssClass}")[0] \ No newline at end of file + should.exist builder.$("g.nvd3.nv-lineChart #{cssClass}")[0] + + it 'can override axis ticks', -> + builder.model.xAxis.ticks(34) + builder.model.yAxis.ticks(56) + builder.model.update() + builder.model.xAxis.ticks().should.equal 34 + builder.model.yAxis.ticks().should.equal 56 + + it 'can add custom CSS class to series', -> + builder.updateData sampleData2 + + classed = builder.$ '.nv-linesWrap .nv-groups .nv-group.dashed' + + # Since classing has been implemented at the data-level for + # scatter points, there will actually be 2 elements matching + # the above selector, one for the scatter g element, + # and one for the line. + + classed.length.should.equal 2, 'dashed class exists' + + scatter = builder.$ '.nv-scatterWrap .nv-groups .nv-group.dashed' + scatter.length.should.equal 1, 'one classed element is from scatter' + diff --git a/test/mocha/multibar-horizontal.coffee b/test/mocha/multibar-horizontal.coffee index a42306ff2..5b8121ad1 100644 --- a/test/mocha/multibar-horizontal.coffee +++ b/test/mocha/multibar-horizontal.coffee @@ -42,8 +42,6 @@ describe 'NVD3', -> showLegend: true showXAxis: true showYAxis: true - tooltips: true - tooltipContent: (key,x,y)-> "

    #{key}

    " noData: 'No Data Available' duration: 0 @@ -56,6 +54,7 @@ describe 'NVD3', -> builder.teardown() it 'api check', -> + should.exist builder.model.options, 'options exposed' for opt of options should.exist builder.model[opt](), "#{opt} can be called" @@ -63,19 +62,33 @@ describe 'NVD3', -> wrap = builder.$ 'g.nvd3.nv-multiBarHorizontalChart' should.exist wrap[0] + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.multiBarHorizontalChart() + builder.buildover options, sampleData1, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' + it 'has correct structure', -> - cssClasses = [ - '.nv-x.nv-axis' - '.nv-y.nv-axis' - '.nv-barsWrap' - '.nv-multibarHorizontal' - '.nv-legendWrap' - '.nv-controlsWrap' - ] - for cssClass in cssClasses - do (cssClass) -> - should.exist builder.$("g.nvd3.nv-multiBarHorizontalChart #{cssClass}")[0] + cssClasses = [ + '.nv-x.nv-axis' + '.nv-y.nv-axis' + '.nv-barsWrap' + '.nv-multibarHorizontal' + '.nv-legendWrap' + '.nv-controlsWrap' + ] + for cssClass in cssClasses + do (cssClass) -> + should.exist builder.$("g.nvd3.nv-multiBarHorizontalChart #{cssClass}")[0] it 'renders bars', -> - bars = builder.$('g.nvd3.nv-multiBarHorizontalChart .nv-multibarHorizontal .nv-bar') - bars.should.have.length 12 + bars = builder.$('g.nvd3.nv-multiBarHorizontalChart .nv-multibarHorizontal .nv-bar') + bars.should.have.length 12 + + it 'can override axis ticks', -> + builder.model.xAxis.ticks(34) + builder.model.yAxis.ticks(56) + builder.model.update() + builder.model.xAxis.ticks().should.equal 34 + builder.model.yAxis.ticks().should.equal 56 diff --git a/test/mocha/multibar.coffee b/test/mocha/multibar.coffee index 467299532..2c702ff5e 100644 --- a/test/mocha/multibar.coffee +++ b/test/mocha/multibar.coffee @@ -45,8 +45,6 @@ describe 'NVD3', -> reduceXTicks: true staggerLabels: true rotateLabels: 0 - tooltips: true - tooltipContent: (key,x,y)-> "

    #{key}

    " noData: 'No Data Available' duration: 0 @@ -59,6 +57,7 @@ describe 'NVD3', -> builder.teardown() it 'api check', -> + should.exist builder.model.options, 'options exposed' for opt of options should.exist builder.model[opt](), "#{opt} can be called" @@ -66,6 +65,13 @@ describe 'NVD3', -> wrap = builder.$ 'g.nvd3.nv-multiBarWithLegend' should.exist wrap[0] + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.multiBarChart() + builder.buildover options, sampleData1, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' + it 'has correct structure', -> cssClasses = [ '.nv-x.nv-axis' @@ -83,4 +89,12 @@ describe 'NVD3', -> it 'renders bars', -> bars = builder.$("g.nvd3.nv-multiBarWithLegend .nv-multibar .nv-bar") - bars.should.have.length 12 \ No newline at end of file + bars.should.have.length 12 + + it 'can override axis ticks', -> + builder.model.xAxis.ticks(34) + builder.model.yAxis.ticks(56) + builder.model.update() + builder.model.xAxis.ticks().should.equal 34 + builder.model.yAxis.ticks().should.equal 56 + diff --git a/test/mocha/pie.coffee b/test/mocha/pie.coffee index ddd51b65f..94913b57d 100644 --- a/test/mocha/pie.coffee +++ b/test/mocha/pie.coffee @@ -21,16 +21,18 @@ describe 'NVD3', -> showLegend: true valueFormat: (d)-> d.toFixed 2 showLabels: true - donutLabelsOutside: false - pieLabelsOutside: true + labelsOutside: true donut: false donutRatio: 0.5 labelThreshold: 0.02 labelType: 'key' - tooltips: true - tooltipContent: (key,x,y)-> "

    #{key}

    " noData: 'No Data Available' duration: 0 + startAngle: false + endAngle: false + padAngle: false + cornerRadius: 0 + labelSunbeamLayout: false builder = null beforeEach -> @@ -41,6 +43,7 @@ describe 'NVD3', -> builder.teardown() it 'api check', -> + should.exist builder.model.options, 'options exposed' for opt of options should.exist builder.model[opt](), "#{opt} can be called" @@ -56,6 +59,20 @@ describe 'NVD3', -> it '.nv-pieChart', -> should.exist wrap[0] + it 'can access margin', -> + builder.model.margin + top: 31 + right: 21 + bottom: 51 + left: 76 + + m = builder.model.margin() + m.should.deep.equal + top: 31 + right: 21 + bottom: 51 + left: 76 + describe 'labels correctly', -> it "[#{sampleData1.length}] labels", -> wrap[0].querySelectorAll('.nv-label').should.have.length sampleData1.length @@ -65,6 +82,13 @@ describe 'NVD3', -> it "label '#{item.label}'", -> item.label.should.be.equal labels[i].textContent + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.pieChart() + builder.buildover options, sampleData1, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' + it 'has correct structure', -> cssClasses = [ '.nv-pieWrap' @@ -74,4 +98,53 @@ describe 'NVD3', -> ] for cssClass in cssClasses do (cssClass) -> - should.exist builder.$("g.nvd3.nv-pieChart #{cssClass}")[0] \ No newline at end of file + should.exist builder.$("g.nvd3.nv-pieChart #{cssClass}")[0] + + it 'can handle donut mode and options', (done)-> + builder.teardown() + options.donut = true + options.labelSunbeamLayout = true + options.startAngle = (d)-> d.startAngle/2 - Math.PI/2 + options.endAngle = (d)-> d.endAngle/2 - Math.PI/2 + + builder.build options, sampleData1 + + done() + + it 'can handle cornerRadius and padAngle options', (done)-> + builder.teardown() + options.padAngle = 5 + options.cornerRadius = 5 + + builder.build options, sampleData1 + done() + + it 'can render pie labels in other formats', -> + opts = + x: (d)-> d.label + y: (d)-> d.value + labelType: 'value' + valueFormat: d3.format('.2f') + builder2 = new ChartBuilder nv.models.pie() + builder2.build opts, [sampleData1] + + labels = builder2.$ '.nv-pieLabels .nv-label text' + labels.length.should.equal 4 + + expected = ['100.00','200.00','50.00','70.00'] + for label,i in labels + label.textContent.should.equal expected[i] + + # Test labelType = 'percent' + builder2.teardown() + + opts.labelType = 'percent' + opts.valueFormat = d3.format('%') + builder2.build opts, [sampleData1] + + labels = builder2.$ '.nv-pieLabels .nv-label text' + labels.length.should.equal 4 + + expected = ['24%','48%','12%','17%'] + for label,i in labels + label.textContent.should.equal expected[i] diff --git a/test/mocha/scatter.coffee b/test/mocha/scatter.coffee index c0100fa6b..6518c73cd 100644 --- a/test/mocha/scatter.coffee +++ b/test/mocha/scatter.coffee @@ -47,10 +47,6 @@ describe 'NVD3', -> showXAxis: true showYAxis: true rightAlignYAxis: false - tooltips: true - tooltipContent: (d)-> "

    #{d}

    " - tooltipXContent: (d)-> 'x content' - tooltipYContent: (d)-> 'y content' noData: 'No Data Available' duration: 0 @@ -63,6 +59,7 @@ describe 'NVD3', -> builder.teardown() it 'api check', -> + should.exist builder.model.options, 'options exposed' for opt of options should.exist builder.model[opt], "#{opt} exists" should.exist builder.model[opt](), "#{opt} can be called" @@ -71,6 +68,13 @@ describe 'NVD3', -> wrap = builder.$ 'g.nvd3.nv-scatterChart' should.exist wrap[0] + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.scatterChart() + builder.buildover options, sampleData1, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' + it 'has correct structure', -> cssClasses = [ '.nv-background' @@ -93,26 +97,6 @@ describe 'NVD3', -> legend = builder.$ '.nv-legendWrap' should.exist legend, 'legend exists' - it 'can show a tooltip', -> - eventData = - point: - series: 0 - x: -1 - y: 1 - pointIndex: 0 - pos: [ - 210 - 119 - ] - series: - key: 'Series 1' - seriesIndex: 0 - - builder.model.scatter.dispatch.elementMouseover eventData - - tooltip = document.querySelector '.nvtooltip' - should.exist tooltip - it 'shows no data message', -> builder.teardown() builder.build options, [] @@ -152,3 +136,88 @@ describe 'NVD3', -> lines = builder.$ 'g.nvd3 .nv-regressionLinesWrap .nv-regLines' should.exist lines[0], 'regression lines exist' + + it 'sets legend.width same as availableWidth', -> + builder.model.legend.width() + .should.equal builder.model.scatter.width() + + it 'translates nv-wrap after legend height calculated', -> + builder.teardown() + sampleData4 = [] + for i in [0..40] + sampleData4.push + key: "Series #{i}" + values: [ + [Math.random(),Math.random()] + ] + + builder.build options, sampleData4 + + transform = builder.$('.nv-wrap')[0].getAttribute('transform') + transform.should.equal 'translate(75,830)' + + it 'can override axis ticks', -> + builder.model.xAxis.ticks(34) + builder.model.yAxis.ticks(56) + builder.model.update() + builder.model.xAxis.ticks().should.equal 34 + builder.model.yAxis.ticks().should.equal 56 + + it 'only appends one nv-point-clips group', (done)-> + builder2 = new ChartBuilder nv.models.scatterChart() + + builder2.build options, sampleData1 + + window.setTimeout -> + builder2.model.update() + window.setTimeout((-> + pointClips = builder2.svg.querySelector '.nv-point-clips' + should.exist pointClips, 'nv-point-clips exists' + + builder2.svg.querySelector('.nv-wrap.nv-scatter') + .childElementCount.should.equal 3 + + builder2.teardown() + done() + ), 500) + + , 500 + + it 'sets nv-single-point class if only one data point', -> + builder.teardown() + + singleData = [ + key: 'Series1' + values: [ + [1,1] + ] + ] + + builder.build options, singleData + + builder.svg.querySelector('.nv-wrap.nv-scatter') + .className.should.contain 'nv-single-point' + + builder.updateData sampleData1 + + builder.svg.querySelector('.nv-wrap.nv-scatter') + .className.should.not.contain 'nv-single-point' + + builder.updateData singleData + + builder.svg.querySelector('.nv-wrap.nv-scatter') + .className.should.contain 'nv-single-point' + + it 'should set color property if not specified', -> + builder.teardown() + + singleData = [ + key: 'Series1' + values: [ + [1,1] + ] + ] + + builder.build options, singleData + + should.exist singleData[0].color diff --git a/test/mocha/sparkline.coffee b/test/mocha/sparkline.coffee index 0704705b0..2f06aa061 100644 --- a/test/mocha/sparkline.coffee +++ b/test/mocha/sparkline.coffee @@ -20,7 +20,7 @@ describe 'NVD3', -> height: 50 xTickFormat: (d)-> d yTickFormat: (d)-> d.toFixed 2 - showValue: true + showLastValue: true alignValue: true rightAlignValue: false noData: 'No Data Available' @@ -34,13 +34,23 @@ describe 'NVD3', -> builder.teardown() it 'api check', -> + should.exist builder.model.options, 'options exposed' for opt of options should.exist builder.model[opt](), "#{opt} can be called" + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.sparklinePlus() + builder.buildover options, sampleData1, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' + it 'renders', -> wrap = builder.$ 'g.nvd3.nv-sparklineplus' should.exist wrap[0] + + it 'has correct structure', -> cssClasses = [ '.nv-sparklineWrap' diff --git a/test/mocha/stacked.coffee b/test/mocha/stacked.coffee index 2e9476774..d9f427ba0 100644 --- a/test/mocha/stacked.coffee +++ b/test/mocha/stacked.coffee @@ -43,8 +43,6 @@ describe 'NVD3', -> showYAxis: true rightAlignYAxis: false useInteractiveGuideline: true - tooltips: true - tooltipContent: (key,x,y)-> "

    #{key}

    " noData: 'No Data Available' duration: 0 controlLabels: @@ -61,6 +59,7 @@ describe 'NVD3', -> builder.teardown() it 'api check', -> + should.exist builder.model.options, 'options exposed' for opt of options should.exist builder.model[opt](), "#{opt} can be called" @@ -68,6 +67,13 @@ describe 'NVD3', -> wrap = builder.$ 'g.nvd3.nv-stackedAreaChart' should.exist wrap[0] + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.stackedAreaChart() + builder.buildover options, sampleData1, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' + it 'has correct structure', -> cssClasses = [ '.nv-x.nv-axis' @@ -81,3 +87,43 @@ describe 'NVD3', -> for cssClass in cssClasses do (cssClass) -> should.exist builder.$("g.nvd3.nv-stackedAreaChart #{cssClass}")[0] + + it 'formats y-Axis correctly depending on stacked style', -> + chart = nv.models.stackedAreaChart() + chart.yAxis.tickFormat (d)-> "<#{d}>" + + builder = new ChartBuilder chart + builder.build options, sampleData1 + + yTicks = builder.$ '.nv-y.nv-axis .tick text' + yTicks.should.have.length.greaterThan 2 + + for tick in yTicks + tick.textContent.should.match /<.*?>/ + + # Update chart to 'Expand' mode + chart.dispatch.changeState + style: 'expand' + + chart.stacked.style().should.equal 'expand' + newTickFormat = chart.yAxis.tickFormat() + newTickFormat(1).should.equal '100%' + + chart.dispatch.changeState + style: 'stacked' + + chart.stacked.style().should.equal 'stacked' + newTickFormat = chart.yAxis.tickFormat() + newTickFormat(1).should.equal '<1>' + + it 'can override axis ticks', -> + builder.model.xAxis.ticks(34) + builder.model.yAxis.ticks(56) + builder.model.update() + builder.model.xAxis.ticks().should.equal 34 + builder.model.yAxis.ticks().should.equal 56 + + it 'if stacked.offset is "wiggle", y ticks is zero', -> + builder.model.stacked.offset 'wiggle' + builder.model.update() + builder.model.yAxis.ticks().should.equal 0 diff --git a/test/mocha/sunburst.coffee b/test/mocha/sunburst.coffee new file mode 100644 index 000000000..05c036154 --- /dev/null +++ b/test/mocha/sunburst.coffee @@ -0,0 +1,191 @@ +describe 'NVD3', -> + describe 'Sunburst', -> + sampleData1 = [{ + "name": "flare", + "children": [ + { + "name": "analytics", + "children": [ + { + "name": "cluster", + "children": [ + {"name": "AgglomerativeCluster", "size": 3938}, + {"name": "CommunityStructure", "size": 3812}, + {"name": "HierarchicalCluster", "size": 6714}, + {"name": "MergeEdge", "size": 743} + ] + }, + { + "name": "graph", + "children": [ + {"name": "BetweennessCentrality", "size": 3534}, + {"name": "LinkDistance", "size": 5731}, + {"name": "MaxFlowMinCut", "size": 7840}, + {"name": "ShortestPaths", "size": 5914}, + {"name": "SpanningTree", "size": 3416} + ] + }, + { + "name": "optimization", + "children": [ + {"name": "AspectRatioBanker", "size": 7074} + ] + } + ] + }, + { + "name": "physics", + "children": [ + {"name": "DragForce", "size": 1082}, + {"name": "GravityForce", "size": 1336}, + {"name": "IForce", "size": 319}, + {"name": "NBodyForce", "size": 10498}, + {"name": "Particle", "size": 2822}, + {"name": "Simulation", "size": 9983}, + {"name": "Spring", "size": 2213}, + {"name": "SpringForce", "size": 1681} + ] + }, + { + "name": "vis", + "children": [ + { + "name": "data", + "children": [ + {"name": "Data", "size": 20544}, + {"name": "DataList", "size": 19788}, + {"name": "DataSprite", "size": 10349}, + {"name": "EdgeSprite", "size": 3301}, + {"name": "NodeSprite", "size": 19382}, + { + "name": "render", + "children": [ + {"name": "ArrowType", "size": 698}, + {"name": "EdgeRenderer", "size": 5569}, + {"name": "IRenderer", "size": 353}, + {"name": "ShapeRenderer", "size": 2247} + ] + }, + {"name": "ScaleBinding", "size": 11275}, + {"name": "Tree", "size": 7147}, + {"name": "TreeBuilder", "size": 9930} + ] + }, + { + "name": "operator", + "children": [ + { + "name": "distortion", + "children": [ + {"name": "BifocalDistortion", "size": 4461}, + {"name": "Distortion", "size": 6314}, + {"name": "FisheyeDistortion", "size": 3444} + ] + }, + { + "name": "encoder", + "children": [ + {"name": "ColorEncoder", "size": 3179}, + {"name": "Encoder", "size": 4060}, + {"name": "PropertyEncoder", "size": 4138}, + {"name": "ShapeEncoder", "size": 1690}, + {"name": "SizeEncoder", "size": 1830} + ] + }, + { + "name": "filter", + "children": [ + {"name": "FisheyeTreeFilter", "size": 5219}, + {"name": "GraphDistanceFilter", "size": 3165}, + {"name": "VisibilityFilter", "size": 3509} + ] + }, + {"name": "IOperator", "size": 1286}, + { + "name": "label", + "children": [ + {"name": "Labeler", "size": 9956}, + {"name": "RadialLabeler", "size": 3899}, + {"name": "StackedAreaLabeler", "size": 3202} + ] + }, + { + "name": "layout", + "children": [ + {"name": "AxisLayout", "size": 6725}, + {"name": "BundledEdgeRouter", "size": 3727}, + {"name": "CircleLayout", "size": 9317}, + {"name": "CirclePackingLayout", "size": 12003}, + {"name": "DendrogramLayout", "size": 4853}, + {"name": "ForceDirectedLayout", "size": 8411}, + {"name": "IcicleTreeLayout", "size": 4864}, + {"name": "IndentedTreeLayout", "size": 3174}, + {"name": "Layout", "size": 7881}, + {"name": "NodeLinkTreeLayout", "size": 12870}, + {"name": "PieLayout", "size": 2728}, + {"name": "RadialTreeLayout", "size": 12348}, + {"name": "RandomLayout", "size": 870}, + {"name": "StackedAreaLayout", "size": 9121}, + {"name": "TreeMapLayout", "size": 9191} + ] + }, + {"name": "Operator", "size": 2490}, + {"name": "OperatorList", "size": 5248}, + {"name": "OperatorSequence", "size": 4190}, + {"name": "OperatorSwitch", "size": 2581}, + {"name": "SortOperator", "size": 2023} + ] + }, + {"name": "Visualization", "size": 16540} + ] + } + ] + }] + + options = + margin: + top: 30 + right: 20 + bottom: 50 + left: 75 + width: 200 + height: 200 + color: d3.scale.category20c() + duration: 0 + + builder = null + beforeEach -> + builder = new ChartBuilder nv.models.sunburst() + builder.build options, sampleData1 + + afterEach -> + builder.teardown() + + it 'api check', -> + should.exist builder.model.options, 'options exposed' + for opt of options + should.exist builder.model[opt](), "#{opt} can be called" + + describe 'renders', -> + + wrap = null + + beforeEach -> + wrap = builder.$ 'g.nvd3.nv-sunburst' + + it '.nv-pieChart', -> + should.exist wrap[0] + + it 'can access margin', -> + builder.model.margin + top: 31 + right: 21 + bottom: 51 + left: 76 + + m = builder.model.margin() + m.should.deep.equal + top: 31 + right: 21 + bottom: 51 + left: 76 diff --git a/test/mocha/test-utils.coffee b/test/mocha/test-utils.coffee index 91b4359e8..b3bdae6a6 100644 --- a/test/mocha/test-utils.coffee +++ b/test/mocha/test-utils.coffee @@ -21,9 +21,42 @@ class ChartBuilder else @model[opt](val) - d3.select(@svg) - .datum(data) - .call(@model) + @updateData data + + ### + Update the data while preserving the chart model. + ### + updateData: (data)-> + d3.select(@svg).datum(data).call(@model) + + ### + options: an object hash of chart options. + data: sample data to pass in to initial chart render chart + data2: sample data to pass to second chart render + + This method builds a chart, puts it on the element, and then rebuilds using the second set of data + Useful for testing the results of transitioning and the 'noData' state after a chart has had data + ### + buildover: (options, data, data2)-> + @svg = document.createElement 'svg' + document.querySelector('body').appendChild @svg + + for opt, val of options + unless @model[opt]? + console.warn "#{opt} not property of model." + else + @model[opt](val) + + #Set initial data + chart = d3.select(@svg) + chart.datum(data) + .call(@model) + + #Reset the data + chart.datum(data2) + .call(@model) + + # Removes chart from element. teardown: -> diff --git a/test/mocha/utils.coffee b/test/mocha/utils.coffee index a07a19663..e59b1ebcc 100644 --- a/test/mocha/utils.coffee +++ b/test/mocha/utils.coffee @@ -13,6 +13,11 @@ describe 'NVD3', -> 'nv.utils.deepExtend' 'nv.utils.state' 'nv.utils.optionsFunc' + 'nv.utils.sanitizeHeight' + 'nv.utils.sanitizeWidth' + 'nv.utils.availableHeight' + 'nv.utils.availableWidth' + 'nv.utils.noData' ] describe 'has ', -> @@ -44,7 +49,43 @@ describe 'NVD3', -> returnedFunction({},2).should.be.equal '#aaa' returnedFunction({},3).should.be.equal '#000' + createCont = (wh = false)-> + obj = document.createElement('div') + obj.style.cssText = 'width:964px;height:404px' if wh + d3.select(obj) + + describe 'Sanitize Height and Width for a Container', -> + it 'provides default height and width', -> + cont = createCont() + expect(nv.utils.sanitizeHeight(null, cont)).to.equal 400 + expect(nv.utils.sanitizeWidth(null, cont)).to.equal 960 + expect(nv.utils.sanitizeHeight(undefined, cont)).to.equal 400 + expect(nv.utils.sanitizeWidth(undefined, cont)).to.equal 960 + expect(nv.utils.sanitizeHeight(0, cont)).to.equal 400 + expect(nv.utils.sanitizeWidth(0, cont)).to.equal 960 + it 'uses container width and height', -> + cont = createCont(true) + expect(nv.utils.sanitizeHeight(null, cont)).to.equal 404 + expect(nv.utils.sanitizeWidth(null, cont)).to.equal 964 + it 'uses given width and height', -> + cont = createCont(true) + expect(nv.utils.sanitizeHeight(408, cont)).to.equal 408 + expect(nv.utils.sanitizeWidth(968, cont)).to.equal 968 + + describe 'Available Container Height and Width', -> + it 'calculates height and width properly', -> + cont = createCont(true) + m = { left: 5, right: 6, top: 7, bottom: 8 } + expect(nv.utils.availableHeight(300, cont, m)).to.equal 285 + expect(nv.utils.availableWidth(300, cont, m)).to.equal 289 + expect(nv.utils.availableHeight(0, cont, m)).to.equal 389 + expect(nv.utils.availableWidth(0, cont, m)).to.equal 953 + describe 'Interactive Bisect', -> + it 'works with no accessor', -> + list = [{ x:0 },{ x:1 },{ x:1 },{ x:2 },{ x:3 },{ x:5 },{ x:8 },{ x:13 },{ x:21 },{ x:34 }] + expect(nv.interactiveBisect(list,7)).to.equal 6 + runTest = (list, searchVal, accessor = null)-> xAcc = unless accessor? (d)-> d @@ -56,6 +97,9 @@ describe 'NVD3', -> it 'exists', -> expect(nv.interactiveBisect).to.exist + it 'returns null when no array', -> + expect(nv.interactiveBisect('bad', 'a')).to.equal null + it 'basic test', -> expect(runTest([0,1,2,3,4,5], 3)).to.equal 3 @@ -89,21 +133,6 @@ describe 'NVD3', -> list = [0,1,1,2,3,5,8,13,21,34] expect(runTest(list,20)).to.equal 8 - it 'accessor in index mode - existing item', -> - x = (d,i)-> i - list = [0,1,1,2,3,5,8,13,21,34] - expect(runTest(list,7,x)).to.equal 7 - - it 'accessor in index mode - inbetween item 1', -> - x = (d,i)-> i - list = [0,1,1,2,3,5,8,13,21,34] - expect(runTest(list,7.3,x)).to.equal 7 - - it 'accessor in index mode - inbetween item 2', -> - x = (d,i)-> i - list = [0,1,1,2,3,5,8,13,21,34] - expect(runTest(list,7.50001,x)).to.equal 8 - it 'empty array', -> expect(runTest([],4)).to.equal 0 @@ -115,3 +144,51 @@ describe 'NVD3', -> it 'single element array - past the end', -> expect(runTest([0],1)).to.equal 0 + + describe 'NoData Chart Clearing', -> + sampleData1 = [ + key: 'Series 1' + values: [ + [-1,-1] + [0,0] + [1,1] + [2,2] + ] + ] + + options = + x: (d)-> d[0] + y: (d)-> d[1] + margin: + top: 30 + right: 20 + bottom: 50 + left: 75 + color: nv.utils.defaultColor() + height: 400 + width: 800 + showLegend: true + showXAxis: true + showYAxis: true + rightAlignYAxis: true + useInteractiveGuideline: true + noData: 'No Data Available' + duration: 0 + clipEdge: false + isArea: (d)-> d.area + defined: (d)-> true + interpolate: 'linear' + + it 'shows no data text', -> + builder = new ChartBuilder nv.models.lineChart() + builder.build options, [] + + noData = builder.$ '.nv-noData' + noData[0].textContent.should.equal 'No Data Available' + + it 'clears chart objects for no data', -> + builder = new ChartBuilder nv.models.lineChart() + builder.buildover options, sampleData1, [] + + groups = builder.$ 'g' + groups.length.should.equal 0, 'removes chart components' diff --git a/test/multiBarChartTest.html b/test/multiBarChartTest.html index 85fc5ff7c..26024cf1c 100644 --- a/test/multiBarChartTest.html +++ b/test/multiBarChartTest.html @@ -6,20 +6,32 @@

    Multibar chart test cases - feel free to add more tests

    -
    - Normal chart, with transition delay, and bar color set. +
    + Transition delay 1200ms, 0 non-stackable series and bar color set.
    -
    - Normal chart, no transitionDuration or delay, no bar color set. +
    + No transitionDuration or delay, 0 non-stackable series and no bar color set.
    -
    - Chart with single series, no group spacing. +
    + No transitionDuration or delay, 1 non-stackable series and no bar color set. + +
    +
    + TransitionDuration or delay 500ms, 1 non-stackable series(first) and color set. + +
    +
    + TransitionDuration or delay 500ms, 1 non-stackable series(mid) and color set. + +
    +
    + TransitionDuration or delay 500ms, 1 non-stackable series(last) and color set.
    -
    - Chart with 18 series, 7 data points per series. +
    + Chart with single series, no group spacing.
    @@ -30,7 +42,25 @@

    Multibar chart test cases - feel free to add more tests

    Chart with 2 data points
    -
    + +
    + Chart with 18 series, 7 data points per series and no non-stackable series. + +
    + +
    + Chart with no stackable series -> same as grouped graphs + +
    +
    + Chart with multi stackable series + +
    +
    + Chart with multi more non stackable series + +
    +
    Chart with 0 data points
    @@ -38,31 +68,93 @@

    Multibar chart test cases - feel free to add more tests

    + + +
    + +
    + + diff --git a/test/node/nodeTest.js b/test/node/nodeTest.js new file mode 100644 index 000000000..881cc16e7 --- /dev/null +++ b/test/node/nodeTest.js @@ -0,0 +1,26 @@ +window.d3 = require('d3'); +var nv = require('../../build/nv.d3'); +var invariant = require('invariant'); + +window.addEventListener("load", function load(event) { + window.removeEventListener("load", load, false); + invariant(typeof(nv) !== 'undefined', "Cannot resolve NVD3 via CommonJS"); + nv.addGraph(function() { + var chart = nv.models.bulletChart(); + d3.select('#chart svg') + .datum(exampleData()) + .transition().duration(1000) + .call(chart); + return chart; + }); +}, false); + +function exampleData() { + return { + "title":"Revenue", + "subtitle":"US$, in thousands", + "ranges":[150,225,300], + "measures":[220], + "markers":[250] + } +} diff --git a/test/node/package.json b/test/node/package.json new file mode 100644 index 000000000..8dcd00d2d --- /dev/null +++ b/test/node/package.json @@ -0,0 +1,13 @@ +{ + "name": "node-test", + "version": "0.0.0", + "private": true, + "dependencies": { + "d3": "<=3.4.4", + "invariant": "1.0.2" + }, + "devDependencies": { + "grunt-browserify": "3.3.0", + "grunt-contrib-copy": "~0.4.1" + } +} diff --git a/test/pieChartTest.html b/test/pieChartTest.html index c362b23e8..2e06e5989 100644 --- a/test/pieChartTest.html +++ b/test/pieChartTest.html @@ -60,6 +60,11 @@

    NaN, null, undefined values passed in

    +
    +

    Half donut pie chart with outside label

    + +
    + diff --git a/test/scrollTest.html b/test/scrollTest.html new file mode 100644 index 000000000..b8756e45f --- /dev/null +++ b/test/scrollTest.html @@ -0,0 +1,98 @@ + + + + + + + + + + +

    Charts:

    +
    +
    +

    Chart 1

    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + + + diff --git a/test/scrollTest2.html b/test/scrollTest2.html new file mode 100644 index 000000000..b337a53e3 --- /dev/null +++ b/test/scrollTest2.html @@ -0,0 +1,144 @@ + + + + + + + + + + + + + +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    +

    .

    + + diff --git a/test/stackedAreaChartMissingData.html b/test/stackedAreaChartMissingData.html new file mode 100644 index 000000000..4bcaf27b0 --- /dev/null +++ b/test/stackedAreaChartMissingData.html @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/tinytest/nv-is-defined-test.js b/test/tinytest/nv-is-defined-test.js new file mode 100644 index 000000000..48116913b --- /dev/null +++ b/test/tinytest/nv-is-defined-test.js @@ -0,0 +1,6 @@ +// nv-is-defined-test.js + +Tinytest.add('nv object is defined', function(test) { + test.isNotUndefined(nv, 'nv is undefined at global scope for Meteor'); +}); +