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) {
-
- //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;
- 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);
- }
- } 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);
- }
- } while( Elem = Elem.offsetParent );
- return offsetLeft;
- };
-
- //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);
- };
-
- 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;
- 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;
- 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;
- 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;
- break;
- case 'none':
- left = pos[0];
- top = pos[1] - dist;
- var tLeft = tooltipLeft(container);
- var tTop = tooltipTop(container);
- break;
- }
-
-
- container.style.left = left+'px';
- container.style.top = top+'px';
- container.style.opacity = 1;
- container.style.position = 'absolute';
-
- return container;
- };
-
- //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';
- }
-
- setTimeout(function() {
-
- while (purging.length) {
- var removeMe = purging.pop();
- removeMe.parentNode.removeChild(removeMe);
- }
- }, 500);
- };
-
-})();
-
-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;
- }
-
- // IE can use depending on mode it is in
- if (document.compatMode=='CSS1Compat' &&
- document.documentElement &&
- document.documentElement.offsetWidth ) {
- size.width = document.documentElement.offsetWidth;
- size.height = document.documentElement.offsetHeight;
- }
-
- // Most recent browsers use
- if (window.innerWidth && window.innerHeight) {
- size.width = window.innerWidth;
- size.height = window.innerHeight;
- }
- return (size);
-};
-
-
-
-// Easy way to bind multiple functions to window.onresize
-// TODO: give a way to remove a function after its bound, other than removing all of them
-nv.utils.windowResize = function(fun){
- if (fun === undefined) return;
- var oldresize = window.onresize;
-
- window.onresize = function(e) {
- if (typeof oldresize == 'function') oldresize(e);
- fun(e);
- }
-}
-
-// Backwards compatible way to implement more d3-like coloring of graphs.
-// If passed an array, wrap it in a function which implements the old default
-// behavior
-nv.utils.getColor = function(color) {
- if (!arguments.length) return nv.utils.defaultColor(); //if you pass in nothing, get default colors back
-
- if( Object.prototype.toString.call( color ) === '[object Array]' )
- return function(d, i) { return d.color || color[i % color.length]; };
- else
- return color;
- //can't really help it if someone passes rubbish as color
-}
-
-// Default color chooser uses the index of an object as before.
-nv.utils.defaultColor = function() {
- var colors = d3.scale.category20().range();
- return function(d, i) { return d.color || colors[i % colors.length] };
-}
-
-
-// Returns a color function that takes the result of 'getKey' for each series and
-// looks for a corresponding color from the dictionary,
-nv.utils.customTheme = function(dictionary, getKey, defaultColors) {
- getKey = getKey || function(series) { return series.key }; // use default series.key if getKey is undefined
- defaultColors = defaultColors || d3.scale.category20().range(); //default color function
-
- var defIndex = defaultColors.length; //current default color (going in reverse)
-
- return function(series, index) {
- var key = getKey(series);
-
- if (!defIndex) defIndex = defaultColors.length; //used all the default colors, start over
-
- if (typeof dictionary[key] !== "undefined")
- return (typeof dictionary[key] === "function") ? dictionary[key]() : dictionary[key];
- else
- return defaultColors[--defIndex]; // no match in dictionary, use default color
- }
-}
-
-
-
-// From the PJAX example on d3js.org, while this is not really directly needed
-// it's a very cool method for doing pjax, I may expand upon it a little bit,
-// open to suggestions on anything that may be useful
-nv.utils.pjax = function(links, content) {
- d3.selectAll(links).on("click", function() {
- history.pushState(this.href, this.textContent, this.href);
- load(this.href);
- d3.event.preventDefault();
- });
-
- function load(href) {
- d3.html(href, function(fragment) {
- var target = d3.select(content).node();
- target.parentNode.replaceChild(d3.select(fragment).select(content).node(), target);
- nv.utils.pjax(links, content);
- });
- }
-
- d3.select(window).on("popstate", function() {
- if (d3.event.state) load(d3.event.state);
- });
-}
-
-/* For situations where we want to approximate the width in pixels for an SVG:text element.
-Most common instance is when the element is in a display:none; container.
-Forumla is : text.length * font-size * constant_factor
-*/
-nv.utils.calcApproxTextWidth = function (svgTextElem) {
- if (typeof svgTextElem.style === 'function'
- && typeof svgTextElem.text === 'function') {
- var fontSize = parseInt(svgTextElem.style("font-size").replace("px",""));
- var textLength = svgTextElem.text().length;
-
- return textLength * fontSize * 0.5;
- }
- return 0;
-};
-
-/* Numbers that are undefined, null or NaN, convert them to zeros.
-*/
-nv.utils.NaNtoZero = function(n) {
- if (typeof n !== 'number'
- || isNaN(n)
- || n === null
- || n === Infinity) return 0;
-
- return n;
-};
-
-/*
-Snippet of code you can insert into each nv.models.* to give you the ability to
-do things like:
-chart.options({
- showXAxis: true,
- tooltips: true
-});
-
-To enable in the chart:
-chart.options = nv.utils.optionsFunc.bind(chart);
-*/
-nv.utils.optionsFunc = function(args) {
- if (args) {
- d3.map(args).forEach((function(key,value) {
- if (typeof this[key] === "function") {
- this[key](value);
- }
- }).bind(this));
- }
- return this;
-};nv.models.axis = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var axis = d3.svg.axis()
- ;
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 75 //only used for tickLabel currently
- , height = 60 //only used for tickLabel currently
- , scale = d3.scale.linear()
- , axisLabelText = null
- , showMaxMin = true //TODO: showMaxMin should be disabled on all ordinal scaled axes
- , highlightZero = true
- , rotateLabels = 0
- , rotateYLabel = true
- , staggerLabels = false
- , isOrdinal = false
- , ticks = null
- , axisLabelDistance = 12 //The larger this number is, the closer the axis label is to the axis.
- ;
-
- axis
- .scale(scale)
- .orient('bottom')
- .tickFormat(function(d) { return d })
- ;
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var scale0;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this);
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- 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')
-
- //------------------------------------------------------------
-
-
- if (ticks !== null)
- axis.ticks(ticks);
- else if (axis.orient() == 'top' || axis.orient() == 'bottom')
- axis.ticks(Math.abs(scale.range()[1] - scale.range()[0]) / 100);
-
-
- //TODO: consider calculating width/height based on whether or not label is added, for reference in charts using this component
-
-
- g.transition().call(axis);
-
- scale0 = scale0 || axis.scale();
-
- var fmt = axis.tickFormat();
- if (fmt == null) {
- fmt = scale0.tickFormat();
- }
-
- var axisLabel = g.selectAll('text.nv-axislabel')
- .data([axisLabelText || null]);
- axisLabel.exit().remove();
- switch (axis.orient()) {
- case 'top':
- axisLabel.enter().append('text').attr('class', 'nv-axislabel');
- var w = (scale.range().length==2) ? scale.range()[1] : (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')
- .data(scale.domain());
- axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text');
- axisMaxMin.exit().remove();
- axisMaxMin
- .attr('transform', function(d,i) {
- return 'translate(' + scale(d) + ',0)'
- })
- .select('text')
- .attr('dy', '-0.5em')
- .attr('y', -axis.tickPadding())
- .attr('text-anchor', 'middle')
- .text(function(d,i) {
- var v = fmt(d);
- return ('' + v).match('NaN') ? '' : v;
- });
- axisMaxMin.transition()
- .attr('transform', function(d,i) {
- return 'translate(' + scale.range()[i] + ',0)'
- });
- }
- break;
- case 'bottom':
- var xLabelMargin = 36;
- var maxTextWidth = 30;
- var xTicks = g.selectAll('g').select("text");
- if (rotateLabels%360) {
- //Calculate the longest xTick width
- xTicks.each(function(d,i){
- var width = this.getBBox().width;
- if(width > maxTextWidth) maxTextWidth = width;
- });
- //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;
- //Rotate all xTicks
- xTicks
- .attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' })
- .style('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end');
- }
- axisLabel.enter().append('text').attr('class', 'nv-axislabel');
- var w = (scale.range().length==2) ? scale.range()[1] : (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')
- //.data(scale.domain())
- .data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]);
- axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text');
- axisMaxMin.exit().remove();
- axisMaxMin
- .attr('transform', function(d,i) {
- return 'translate(' + (scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0)) + ',0)'
- })
- .select('text')
- .attr('dy', '.71em')
- .attr('y', axis.tickPadding())
- .attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' })
- .style('text-anchor', rotateLabels ? (rotateLabels%360 > 0 ? 'start' : 'end') : 'middle')
- .text(function(d,i) {
- var v = fmt(d);
- return ('' + v).match('NaN') ? '' : v;
- });
- axisMaxMin.transition()
- .attr('transform', function(d,i) {
- //return 'translate(' + scale.range()[i] + ',0)'
- //return 'translate(' + scale(d) + ',0)'
- return 'translate(' + (scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0)) + ',0)'
- });
- }
- if (staggerLabels)
- xTicks
- .attr('transform', function(d,i) { return 'translate(0,' + (i % 2 == 0 ? '0' : '12') + ')' });
-
- break;
- case 'right':
- axisLabel.enter().append('text').attr('class', 'nv-axislabel');
- 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());
- if (showMaxMin) {
- var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
- .data(scale.domain());
- axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text')
- .style('opacity', 0);
- axisMaxMin.exit().remove();
- axisMaxMin
- .attr('transform', function(d,i) {
- return 'translate(0,' + scale(d) + ')'
- })
- .select('text')
- .attr('dy', '.32em')
- .attr('y', 0)
- .attr('x', axis.tickPadding())
- .style('text-anchor', 'start')
- .text(function(d,i) {
- var v = fmt(d);
- return ('' + v).match('NaN') ? '' : v;
- });
- axisMaxMin.transition()
- .attr('transform', function(d,i) {
- return 'translate(0,' + scale.range()[i] + ')'
- })
- .select('text')
- .style('opacity', 1);
- }
- break;
- case 'left':
- /*
- //For dynamically placing the label. Can be used with dynamically-sized chart axis margins
- var yTicks = g.selectAll('g').select("text");
- yTicks.each(function(d,i){
- var labelPadding = this.getBBox().width + axis.tickPadding() + 16;
- if(labelPadding > width) width = labelPadding;
- });
- */
- axisLabel.enter().append('text').attr('class', 'nv-axislabel');
- axisLabel
- .style('text-anchor', rotateYLabel ? 'middle' : 'end')
- .attr('transform', rotateYLabel ? 'rotate(-90)' : '')
- .attr('y', rotateYLabel ? (-Math.max(margin.left,width) + axisLabelDistance) : -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());
- if (showMaxMin) {
- var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')
- .data(scale.domain());
- axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text')
- .style('opacity', 0);
- axisMaxMin.exit().remove();
- axisMaxMin
- .attr('transform', function(d,i) {
- return 'translate(0,' + scale0(d) + ')'
- })
- .select('text')
- .attr('dy', '.32em')
- .attr('y', 0)
- .attr('x', -axis.tickPadding())
- .attr('text-anchor', 'end')
- .text(function(d,i) {
- var v = fmt(d);
- return ('' + v).match('NaN') ? '' : v;
- });
- axisMaxMin.transition()
- .attr('transform', function(d,i) {
- return 'translate(0,' + scale.range()[i] + ')'
- })
- .select('text')
- .style('opacity', 1);
- }
- break;
- }
- axisLabel
- .text(function(d) { return d });
-
-
- if (showMaxMin && (axis.orient() === 'left' || axis.orient() === 'right')) {
- //check if max and min overlap other values, if so, hide the values that overlap
- g.selectAll('g') // the g's wrapping each tick
- .each(function(d,i) {
- d3.select(this).select('text').attr('opacity', 1);
- if (scale(d) < scale.range()[1] + 10 || scale(d) > scale.range()[0] - 10) { // 10 is assuming text height is 16... if d is 0, leave it!
- 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).attr('opacity', 0);
-
- d3.select(this).select('text').attr('opacity', 0); // Don't remove the ZERO line!!
- }
- });
-
- //if Max and Min = 0 only show min, Issue #281
- if (scale.domain()[0] == scale.domain()[1] && scale.domain()[0] == 0)
- wrap.selectAll('g.nv-axisMaxMin')
- .style('opacity', function(d,i) { return !i ? 1 : 0 });
-
- }
-
- if (showMaxMin && (axis.orient() === 'top' || axis.orient() === 'bottom')) {
- var maxMinRange = [];
- wrap.selectAll('g.nv-axisMaxMin')
- .each(function(d,i) {
- try {
- if (i) // i== 1, max position
- maxMinRange.push(scale(d) - this.getBBox().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.getBBox().width + 4)
- }catch (err) {
- if (i) // i== 1, max position
- maxMinRange.push(scale(d) - 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) + 4)
- }
- });
- g.selectAll('g') // the g's wrapping each tick
- .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();
- else
- d3.select(this).select('text').remove(); // Don't remove the ZERO line!!
- }
- });
- }
-
-
- //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(d.__data__*100000)/1000000) && (d.__data__ !== undefined) }) //this is because sometimes the 0 tick is a very small fraction, TODO: think of cleaner technique
- .classed('zero', true);
-
- //store old scales for use in transitions on update
- scale0 = scale.copy();
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.axis = axis;
-
- d3.rebind(chart, axis, 'orient', 'tickValues', 'tickSubdivide', 'tickSize', 'tickPadding', 'tickFormat');
- d3.rebind(chart, scale, 'domain', 'range', 'rangeBand', 'rangeBands'); //these are also accessible by chart.scale(), but added common ones directly for ease of use
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if(!arguments.length) return margin;
- 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;
- return chart;
- }
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.ticks = function(_) {
- if (!arguments.length) return ticks;
- ticks = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.axisLabel = function(_) {
- if (!arguments.length) return axisLabelText;
- axisLabelText = _;
- return chart;
- }
-
- chart.showMaxMin = function(_) {
- if (!arguments.length) return showMaxMin;
- showMaxMin = _;
- return chart;
- }
-
- chart.highlightZero = function(_) {
- if (!arguments.length) return highlightZero;
- highlightZero = _;
- return chart;
- }
-
- chart.scale = function(_) {
- if (!arguments.length) return scale;
- scale = _;
- axis.scale(scale);
- isOrdinal = typeof scale.rangeBands === 'function';
- d3.rebind(chart, scale, 'domain', 'range', 'rangeBand', 'rangeBands');
- return chart;
- }
-
- chart.rotateYLabel = function(_) {
- if(!arguments.length) return rotateYLabel;
- rotateYLabel = _;
- return chart;
- }
-
- chart.rotateLabels = function(_) {
- if(!arguments.length) return rotateLabels;
- rotateLabels = _;
- return chart;
- }
-
- chart.staggerLabels = function(_) {
- if (!arguments.length) return staggerLabels;
- staggerLabels = _;
- return chart;
- };
-
- chart.axisLabelDistance = function(_) {
- if (!arguments.length) return axisLabelDistance;
- axisLabelDistance = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-//TODO: consider deprecating and using multibar with single series for this
-nv.models.historicalBar = 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.linear()
- , y = d3.scale.linear()
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , forceX = []
- , forceY = [0]
- , padData = false
- , clipEdge = true
- , color = nv.utils.defaultColor()
- , xDomain
- , yDomain
- , xRange
- , yRange
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')
- , interactive = true
- ;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom,
- container = d3.select(this);
-
-
- //------------------------------------------------------------
- // 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]);
-
- y .domain(yDomain || d3.extent(data[0].values.map(getY).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 = container.selectAll('g.nv-wrap.nv-historicalBar-' + id).data([data[0].values]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBar-' + id);
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-bars');
-
- 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 bars = wrap.select('.nv-bars').selectAll('.nv-bar')
- .data(function(d) { return d }, function(d,i) {return getX(d,i)});
-
- bars.exit().remove();
-
-
- var barsEnter = bars.enter().append('rect')
- //.attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i })
- .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))) })
- .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; })
- .on('mouseover', function(d,i) {
- 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
- });
-
- })
- .on('mouseout', function(d,i) {
- if (!interactive) return;
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- point: d,
- series: data[0],
- pointIndex: i,
- seriesIndex: 0,
- e: d3.event
- });
- })
- .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
- });
- 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
- });
- d3.event.stopPropagation();
- });
-
- bars
- .attr('fill', function(d,i) { return color(d, i); })
- .attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i })
- .transition()
- .attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; })
- //TODO: better width calculations that don't assume always uniform data spacing;w
- .attr('width', (availableWidth / data[0].values.length) * .9 );
-
-
- bars.transition()
- .attr('y', function(d,i) {
- var rval = getY(d,i) < 0 ?
- y(0) :
- y(0) - y(getY(d,i)) < 1 ?
- y(0) - 1 :
- y(getY(d,i));
- return nv.utils.NaNtoZero(rval);
- })
- .attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.max(Math.abs(y(getY(d,i)) - y(0)),1)) });
-
- });
-
- return chart;
- }
-
- //Create methods to allow outside functions to highlight a specific bar.
- chart.highlightPoint = function(pointIndex, isHoverOver) {
- d3.select(".nv-historicalBar-" + id)
- .select(".nv-bars .nv-bar-0-" + pointIndex)
- .classed("hover", isHoverOver)
- ;
- };
-
- chart.clearHighlights = function() {
- d3.select(".nv-historicalBar-" + id)
- .select(".nv-bars .nv-bar.hover")
- .classed("hover", false)
- ;
- };
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = _;
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = _;
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.xScale = function(_) {
- if (!arguments.length) return x;
- x = _;
- return chart;
- };
-
- chart.yScale = function(_) {
- if (!arguments.length) return y;
- y = _;
- return chart;
- };
-
- chart.xDomain = function(_) {
- if (!arguments.length) return xDomain;
- xDomain = _;
- return chart;
- };
-
- chart.yDomain = function(_) {
- if (!arguments.length) return yDomain;
- yDomain = _;
- return chart;
- };
-
- chart.xRange = function(_) {
- if (!arguments.length) return xRange;
- xRange = _;
- return chart;
- };
-
- chart.yRange = function(_) {
- if (!arguments.length) return yRange;
- yRange = _;
- return chart;
- };
-
- chart.forceX = function(_) {
- if (!arguments.length) return forceX;
- forceX = _;
- return chart;
- };
-
- chart.forceY = function(_) {
- if (!arguments.length) return forceY;
- forceY = _;
- return chart;
- };
-
- chart.padData = function(_) {
- if (!arguments.length) return padData;
- padData = _;
- return chart;
- };
-
- chart.clipEdge = function(_) {
- if (!arguments.length) return clipEdge;
- clipEdge = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- chart.id = function(_) {
- if (!arguments.length) return id;
- id = _;
- return chart;
- };
-
- chart.interactive = function(_) {
- if(!arguments.length) return interactive;
- interactive = false;
- return 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 }
- , measures = function(d) { return d.measures }
- , rangeLabels = function(d) { return d.rangeLabels ? d.rangeLabels : [] }
- , markerLabels = function(d) { return d.markerLabels ? d.markerLabels : [] }
- , measureLabels = function(d) { return d.measureLabels ? d.measureLabels : [] }
- , forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
- , width = 380
- , height = 30
- , tickFormat = null
- , color = nv.utils.getColor(['#1f77b4'])
- , dispatch = d3.dispatch('elementMouseover', 'elementMouseout')
- ;
-
- //============================================================
-
-
- 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);
-
- var rangez = ranges.call(this, d, i).slice().sort(d3.descending),
- markerz = markers.call(this, d, i).slice().sort(d3.descending),
- measurez = measures.call(this, d, i).slice().sort(d3.descending),
- rangeLabelz = rangeLabels.call(this, d, i).slice(),
- markerLabelz = markerLabels.call(this, d, i).slice(),
- measureLabelz = measureLabels.call(this, d, i).slice();
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- // Compute the new x-scale.
- var x1 = d3.scale.linear()
- .domain( d3.extent(d3.merge([forceX, rangez])) )
- .range(reverse ? [availableWidth, 0] : [0, availableWidth]);
-
- // Retrieve the old x-scale, if this is an update.
- var x0 = this.__chart__ || d3.scale.linear()
- .domain([0, Infinity])
- .range(x1.range());
-
- // Stash the new scale.
- this.__chart__ = x1;
-
-
- var rangeMin = d3.min(rangez), //rangez[2]
- rangeMax = d3.max(rangez), //rangez[0]
- rangeAvg = rangez[1];
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-bullet').data([d]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bullet');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('rect').attr('class', 'nv-range nv-rangeMax');
- 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 + ')');
-
- //------------------------------------------------------------
-
-
-
- var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)
- w1 = function(d) { return Math.abs(x1(d) - x1(0)) };
- var xp0 = function(d) { return d < 0 ? x0(d) : x0(0) },
- xp1 = function(d) { return d < 0 ? x1(d) : x1(0) };
-
-
- g.select('rect.nv-rangeMax')
- .attr('height', availableHeight)
- .attr('width', w1(rangeMax > 0 ? rangeMax : rangeMin))
- .attr('x', xp1(rangeMax > 0 ? rangeMax : rangeMin))
- .datum(rangeMax > 0 ? rangeMax : rangeMin)
- /*
- .attr('x', rangeMin < 0 ?
- rangeMax > 0 ?
- x1(rangeMin)
- : x1(rangeMax)
- : x1(0))
- */
-
- g.select('rect.nv-rangeAvg')
- .attr('height', availableHeight)
- .attr('width', w1(rangeAvg))
- .attr('x', xp1(rangeAvg))
- .datum(rangeAvg)
- /*
- .attr('width', rangeMax <= 0 ?
- x1(rangeMax) - x1(rangeAvg)
- : x1(rangeAvg) - x1(rangeMin))
- .attr('x', rangeMax <= 0 ?
- x1(rangeAvg)
- : x1(rangeMin))
- */
-
- g.select('rect.nv-rangeMin')
- .attr('height', availableHeight)
- .attr('width', w1(rangeMax))
- .attr('x', xp1(rangeMax))
- .attr('width', w1(rangeMax > 0 ? rangeMin : rangeMax))
- .attr('x', xp1(rangeMax > 0 ? rangeMin : rangeMax))
- .datum(rangeMax > 0 ? rangeMin : rangeMax)
- /*
- .attr('width', rangeMax <= 0 ?
- x1(rangeAvg) - x1(rangeMin)
- : x1(rangeMax) - x1(rangeAvg))
- .attr('x', rangeMax <= 0 ?
- x1(rangeMin)
- : x1(rangeAvg))
- */
-
- g.select('rect.nv-measure')
- .style('fill', color)
- .attr('height', availableHeight / 3)
- .attr('y', availableHeight / 3)
- .attr('width', measurez < 0 ?
- x1(0) - x1(measurez[0])
- : x1(measurez[0]) - x1(0))
- .attr('x', xp1(measurez))
- .on('mouseover', function() {
- dispatch.elementMouseover({
- value: measurez[0],
- label: measureLabelz[0] || 'Current',
- pos: [x1(measurez[0]), availableHeight/2]
- })
- })
- .on('mouseout', function() {
- dispatch.elementMouseout({
- value: measurez[0],
- label: measureLabelz[0] || 'Current'
- })
- })
-
- 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();
- }
-
-
- 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]
- })
- })
- .on('mouseout', function(d,i) {
- var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum");
-
- dispatch.elementMouseout({
- value: d,
- label: label
- })
- })
-
-/* // THIS IS THE PREVIOUS BULLET IMPLEMENTATION, WILL REMOVE SHORTLY
- // Update the range rects.
- var range = g.selectAll('rect.nv-range')
- .data(rangez);
-
- range.enter().append('rect')
- .attr('class', function(d, i) { return 'nv-range nv-s' + i; })
- .attr('width', w0)
- .attr('height', availableHeight)
- .attr('x', reverse ? x0 : 0)
- .on('mouseover', function(d,i) {
- dispatch.elementMouseover({
- value: d,
- label: (i <= 0) ? 'Maximum' : (i > 1) ? 'Minimum' : 'Mean', //TODO: make these labels a variable
- pos: [x1(d), availableHeight/2]
- })
- })
- .on('mouseout', function(d,i) {
- dispatch.elementMouseout({
- value: d,
- label: (i <= 0) ? 'Minimum' : (i >=1) ? 'Maximum' : 'Mean' //TODO: make these labels a variable
- })
- })
-
- d3.transition(range)
- .attr('x', reverse ? x1 : 0)
- .attr('width', w1)
- .attr('height', availableHeight);
-
-
- // Update the measure rects.
- var measure = g.selectAll('rect.nv-measure')
- .data(measurez);
-
- measure.enter().append('rect')
- .attr('class', function(d, i) { return 'nv-measure nv-s' + i; })
- .style('fill', function(d,i) { return color(d,i ) })
- .attr('width', w0)
- .attr('height', availableHeight / 3)
- .attr('x', reverse ? x0 : 0)
- .attr('y', availableHeight / 3)
- .on('mouseover', function(d) {
- dispatch.elementMouseover({
- value: d,
- label: 'Current', //TODO: make these labels a variable
- pos: [x1(d), availableHeight/2]
- })
- })
- .on('mouseout', function(d) {
- dispatch.elementMouseout({
- value: d,
- label: 'Current' //TODO: make these labels a variable
- })
- })
-
- d3.transition(measure)
- .attr('width', w1)
- .attr('height', availableHeight / 3)
- .attr('x', reverse ? x1 : 0)
- .attr('y', availableHeight / 3);
-
-
-
- // Update the marker lines.
- var marker = g.selectAll('path.nv-markerTriangle')
- .data(markerz);
-
- var h3 = availableHeight / 6;
- marker.enter().append('path')
- .attr('class', 'nv-markerTriangle')
- .attr('transform', function(d) { return 'translate(' + x0(d) + ',' + (availableHeight / 2) + ')' })
- .attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z')
- .on('mouseover', function(d,i) {
- dispatch.elementMouseover({
- value: d,
- label: 'Previous',
- pos: [x1(d), availableHeight/2]
- })
- })
- .on('mouseout', function(d,i) {
- dispatch.elementMouseout({
- value: d,
- label: 'Previous'
- })
- });
-
- d3.transition(marker)
- .attr('transform', function(d) { return 'translate(' + (x1(d) - x1(0)) + ',' + (availableHeight / 2) + ')' });
-
- marker.exit().remove();
-*/
-
- });
-
- // d3.timer.flush(); // Not needed?
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- // left, right, top, bottom
- chart.orient = function(_) {
- if (!arguments.length) return orient;
- orient = _;
- reverse = orient == 'right' || orient == 'bottom';
- return chart;
- };
-
- // ranges (bad, satisfactory, good)
- chart.ranges = function(_) {
- if (!arguments.length) return ranges;
- ranges = _;
- return chart;
- };
-
- // markers (previous, goal)
- chart.markers = function(_) {
- if (!arguments.length) return markers;
- markers = _;
- return chart;
- };
-
- // measures (actual, forecast)
- chart.measures = function(_) {
- if (!arguments.length) return measures;
- measures = _;
- return chart;
- };
-
- chart.forceX = function(_) {
- if (!arguments.length) return forceX;
- forceX = _;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.tickFormat = function(_) {
- if (!arguments.length) return tickFormat;
- tickFormat = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return 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.bulletChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var bullet = nv.models.bullet()
- ;
-
- var orient = 'left' // TODO top & bottom
- , reverse = false
- , margin = {top: 5, right: 40, bottom: 20, left: 120}
- , ranges = function(d) { return d.ranges }
- , markers = function(d) { return d.markers }
- , measures = function(d) { return d.measures }
- , 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')
- ;
-
- //============================================================
-
-
- //============================================================
- // 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);
- };
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(d, i) {
- var container = d3.select(this);
-
- var availableWidth = (width || parseInt(container.style('width')) || 960)
- - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom,
- that = this;
-
-
- chart.update = function() { chart(selection) };
- chart.container = this;
-
- //------------------------------------------------------------
- // 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 });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
-
- var rangez = ranges.call(this, d, i).slice().sort(d3.descending),
- markerz = markers.call(this, d, i).slice().sort(d3.descending),
- measurez = measures.call(this, d, i).slice().sort(d3.descending);
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-bulletChart').data([d]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bulletChart');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-bulletWrap');
- gEnter.append('g').attr('class', 'nv-titles');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- //------------------------------------------------------------
-
-
- // Compute the new x-scale.
- var x1 = d3.scale.linear()
- .domain([0, Math.max(rangez[0], markerz[0], measurez[0])]) // TODO: need to allow forceX and forceY, and xDomain, yDomain
- .range(reverse ? [availableWidth, 0] : [0, availableWidth]);
-
- // Retrieve the old x-scale, if this is an update.
- var x0 = this.__chart__ || d3.scale.linear()
- .domain([0, Infinity])
- .range(x1.range());
-
- // Stash the new scale.
- this.__chart__ = x1;
-
- /*
- // Derive width-scales from the x-scales.
- var w0 = bulletWidth(x0),
- w1 = bulletWidth(x1);
-
- function bulletWidth(x) {
- var x0 = x(0);
- return function(d) {
- return Math.abs(x(d) - x(0));
- };
- }
-
- function bulletTranslate(x) {
- return function(d) {
- return 'translate(' + x(d) + ',0)';
- };
- }
- */
-
- var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)
- w1 = function(d) { return Math.abs(x1(d) - x1(0)) };
-
-
- var title = gEnter.select('.nv-titles').append('g')
- .attr('text-anchor', 'end')
- .attr('transform', 'translate(-6,' + (height - margin.top - margin.bottom) / 2 + ')');
- title.append('text')
- .attr('class', 'nv-title')
- .text(function(d) { return d.title; });
-
- title.append('text')
- .attr('class', 'nv-subtitle')
- .attr('dy', '1em')
- .text(function(d) { return d.subtitle; });
-
-
-
- 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( 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();
-
-
- //============================================================
- // 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();
-
- 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);
- });
-
- dispatch.on('tooltipHide', function() {
- if (tooltips) nv.tooltip.cleanup();
- });
-
- //============================================================
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.bullet = bullet;
-
- d3.rebind(chart, bullet, 'color');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- // left, right, top, bottom
- chart.orient = function(x) {
- if (!arguments.length) return orient;
- orient = x;
- reverse = orient == 'right' || orient == 'bottom';
- return chart;
- };
-
- // ranges (bad, satisfactory, good)
- chart.ranges = function(x) {
- if (!arguments.length) return ranges;
- ranges = x;
- return chart;
- };
-
- // markers (previous, goal)
- chart.markers = function(x) {
- if (!arguments.length) return markers;
- markers = x;
- return chart;
- };
-
- // measures (actual, forecast)
- chart.measures = function(x) {
- if (!arguments.length) return measures;
- measures = x;
- return chart;
- };
-
- chart.width = function(x) {
- if (!arguments.length) return width;
- width = x;
- return chart;
- };
-
- chart.height = function(x) {
- if (!arguments.length) return height;
- height = x;
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.tickFormat = function(x) {
- if (!arguments.length) return tickFormat;
- tickFormat = x;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-};
-
-
-
-nv.models.cumulativeLineChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var lines = nv.models.line()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , controls = nv.models.legend()
- , interactiveLayer = nv.interactiveGuideline()
- ;
-
- var margin = {top: 30, right: 30, bottom: 50, left: 60}
- , color = nv.utils.defaultColor()
- , width = null
- , height = null
- , showLegend = true
- , 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 = { index: 0, rescaleY: rescaleY }
- , defaultState = null
- , noData = 'No Data Available.'
- , average = function(d) { return d.average }
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
- , transitionDuration = 250
- ;
-
- xAxis
- .orient('bottom')
- .tickPadding(7)
- ;
- yAxis
- .orient((rightAlignYAxis) ? 'right' : 'left')
- ;
-
- //============================================================
- controls.updateState(false);
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var dx = d3.scale.linear()
- , index = {i: 0, x: 0}
- ;
-
- 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);
- };
-
- //============================================================
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this).classed('nv-chart-' + id, true),
- 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;
-
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
- chart.container = this;
-
- //set state.disabled
- 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];
- }
- }
-
- var indexDrag = d3.behavior.drag()
- .on('dragstart', dragStart)
- .on('drag', dragMove)
- .on('dragend', dragEnd);
-
-
- function dragStart(d,i) {
- d3.select(chart.container)
- .style('cursor', 'ew-resize');
- }
-
- function dragMove(d,i) {
- index.x = d3.event.x;
- index.i = Math.round(dx.invert(index.x));
- updateZero();
- }
-
- function dragEnd(d,i) {
- d3.select(chart.container)
- .style('cursor', 'auto');
-
- // update state and send stateChange with new index
- state.index = index.i;
- dispatch.stateChange(state);
- }
-
- //------------------------------------------------------------
- // 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 });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = lines.xScale();
- y = lines.yScale();
-
-
- if (!rescaleY) {
- var seriesDomains = data
- .filter(function(series) { return !series.disabled })
- .map(function(series,i) {
- var initialDomain = d3.extent(series.values, lines.y());
-
- //account for series being disabled when losing 95% or more
- if (initialDomain[0] < -.95) initialDomain[0] = -.95;
-
- return [
- (initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]),
- (initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0])
- ];
- });
-
- var completeDomain = [
- d3.min(seriesDomains, function(d) { return d[0] }),
- d3.max(seriesDomains, function(d) { return d[1] })
- ]
-
- lines.yDomain(completeDomain);
- } else {
- lines.yDomain(null);
- }
-
-
- dx .domain([0, data[0].values.length - 1]) //Assumes all series have same length
- .range([0, availableWidth])
- .clamp(true);
-
- //------------------------------------------------------------
-
-
- var data = indexify(index.i, data);
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
- var interactivePointerEvents = (useInteractiveGuideline) ? "none" : "all";
- var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-interactive');
- gEnter.append('g').attr('class', 'nv-x nv-axis').style("pointer-events","none");
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-background');
- gEnter.append('g').attr('class', 'nv-linesWrap').style("pointer-events",interactivePointerEvents);
- gEnter.append('g').attr('class', 'nv-avgLinesWrap').style("pointer-events","none");
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-controlsWrap');
-
-
- //------------------------------------------------------------
- // Legend
-
- if (showLegend) {
- legend.width(availableWidth);
-
- 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;
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Controls
-
- if (showControls) {
- var controlsData = [
- { key: 'Re-scale y-axis', disabled: !rescaleY }
- ];
-
- controls.width(140).color(['#444', '#444', '#444']);
- g.select('.nv-controlsWrap')
- .datum(controlsData)
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- .call(controls);
- }
-
- //------------------------------------------------------------
-
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- // Show error if series goes below 100%
- var tempDisabled = data.filter(function(d) { return d.tempDisabled });
-
- wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates
- if (tempDisabled.length) {
- wrap.append('text').attr('class', 'tempDisabled')
- .attr('x', availableWidth / 2)
- .attr('y', '-.71em')
- .style('text-anchor', 'end')
- .text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');
- }
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
- //------------------------------------------------------------
- //Set up interactive layer
- if (useInteractiveGuideline) {
- interactiveLayer
- .width(availableWidth)
- .height(availableHeight)
- .margin({left:margin.left,top:margin.top})
- .svgContainer(container)
- .xScale(x);
- wrap.select(".nv-interactive").call(interactiveLayer);
- }
-
- gEnter.select('.nv-background')
- .append('rect');
-
- g.select('.nv-background rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- lines
- //.x(function(d) { return d.x })
- .y(function(d) { return d.display.y })
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled; }));
-
-
-
- var linesWrap = g.select('.nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));
-
- //d3.transition(linesWrap).call(lines);
- linesWrap.call(lines);
-
- /*Handle average lines [AN-612] ----------------------------*/
-
- //Store a series index number in the data array.
- data.forEach(function(d,i) {
- d.seriesIndex = i;
- });
-
- var avgLineData = data.filter(function(d) {
- return !d.disabled && !!average(d);
- });
-
- var avgLines = g.select(".nv-avgLinesWrap").selectAll("line")
- .data(avgLineData, function(d) { return d.key; });
-
- var getAvgLineY = function(d) {
- //If average lines go off the svg element, clamp them to the svg bounds.
- var yVal = y(average(d));
- if (yVal < 0) return 0;
- if (yVal > availableHeight) return availableHeight;
- return yVal;
- };
-
- avgLines.enter()
- .append('line')
- .style('stroke-width',2)
- .style('stroke-dasharray','10,10')
- .style('stroke',function (d,i) {
- return lines.color()(d,d.seriesIndex);
- })
- .attr('x1',0)
- .attr('x2',availableWidth)
- .attr('y1', getAvgLineY)
- .attr('y2', getAvgLineY);
-
- avgLines
- .style('stroke-opacity',function(d){
- //If average lines go offscreen, make them transparent
- var yVal = y(average(d));
- if (yVal < 0 || yVal > availableHeight) return 0;
- return 1;
- })
- .attr('x1',0)
- .attr('x2',availableWidth)
- .attr('y1', getAvgLineY)
- .attr('y2', getAvgLineY);
-
- avgLines.exit().remove();
-
- //Create index line -----------------------------------------
-
- var indexLine = linesWrap.selectAll('.nv-indexLine')
- .data([index]);
- indexLine.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(indexDrag)
-
- indexLine
- .attr('transform', function(d) { return 'translate(' + dx(d.i) + ',0)' })
- .attr('height', availableHeight)
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Axes
-
- if (showXAxis) {
- xAxis
- .scale(x)
- //Suggest how many ticks based on the chart width and D3 should listen (70 is the optimal number for MM/DD/YY dates)
- .ticks( Math.min(data[0].values.length,availableWidth/70) )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')');
- d3.transition(g.select('.nv-x.nv-axis'))
- .call(xAxis);
- }
-
-
- if (showYAxis) {
- yAxis
- .scale(y)
- .ticks( availableHeight / 36 )
- .tickSize( -availableWidth, 0);
-
- d3.transition(g.select('.nv-y.nv-axis'))
- .call(yAxis);
- }
- //------------------------------------------------------------
-
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
-
- function updateZero() {
- indexLine
- .data([index]);
-
- //When dragging the index line, turn off line transitions.
- // Then turn them back on when done dragging.
- var oldDuration = chart.transitionDuration();
- chart.transitionDuration(0);
- chart.update();
- chart.transitionDuration(oldDuration);
- }
-
- g.select('.nv-background rect')
- .on('click', function() {
- index.x = d3.mouse(this)[0];
- index.i = Math.round(dx.invert(index.x));
-
- // update state and send stateChange with new index
- state.index = index.i;
- dispatch.stateChange(state);
-
- updateZero();
- });
-
- lines.dispatch.on('elementClick', function(e) {
- index.i = e.pointIndex;
- index.x = dx(index.i);
-
- // update state and send stateChange with new index
- state.index = index.i;
- dispatch.stateChange(state);
-
- updateZero();
- });
-
- controls.dispatch.on('legendClick', function(d,i) {
- d.disabled = !d.disabled;
- rescaleY = !d.disabled;
-
- state.rescaleY = rescaleY;
- dispatch.stateChange(state);
- chart.update();
- });
-
-
- legend.dispatch.on('stateChange', function(newState) {
- state.disabled = newState.disabled;
- dispatch.stateChange(state);
- chart.update();
- });
-
- 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) {
- 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));
- 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), 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(
- {
- value: xValue,
- series: allData
- }
- )();
-
- interactiveLayer.renderGuideLine(pointXLocation);
-
- });
-
- 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];
- });
-
- state.disabled = e.disabled;
- }
-
-
- if (typeof e.index !== 'undefined') {
- index.i = e.index;
- index.x = dx(index.i);
-
- state.index = e.index;
-
- indexLine
- .data([index]);
- }
-
-
- if (typeof e.rescaleY !== 'undefined') {
- rescaleY = e.rescaleY;
- }
-
- chart.update();
- });
-
- //============================================================
-
- });
-
- 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.lines = lines;
- chart.legend = legend;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.interactiveLayer = interactiveLayer;
-
- d3.rebind(chart, lines, 'defined', 'isArea', 'x', 'y', 'xScale','yScale', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi','useVoronoi', 'id');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- return chart;
- };
-
- chart.rescaleY = function(_) {
- if (!arguments.length) return rescaleY;
- rescaleY = _;
- return chart;
- };
-
- chart.showControls = function(_) {
- if (!arguments.length) return showControls;
- showControls = _;
- return chart;
- };
-
- chart.useInteractiveGuideline = function(_) {
- if(!arguments.length) return useInteractiveGuideline;
- useInteractiveGuideline = _;
- if (_ === true) {
- chart.interactive(false);
- chart.useVoronoi(false);
- }
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.showXAxis = function(_) {
- if (!arguments.length) return showXAxis;
- showXAxis = _;
- return chart;
- };
-
- chart.showYAxis = function(_) {
- if (!arguments.length) return showYAxis;
- showYAxis = _;
- return chart;
- };
-
- chart.rightAlignYAxis = function(_) {
- if(!arguments.length) return rightAlignYAxis;
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.state = function(_) {
- if (!arguments.length) return state;
- state = _;
- return chart;
- };
-
- chart.defaultState = function(_) {
- if (!arguments.length) return defaultState;
- defaultState = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.average = function(_) {
- if(!arguments.length) return average;
- average = _;
- return chart;
- };
-
- chart.transitionDuration = function(_) {
- if (!arguments.length) return transitionDuration;
- transitionDuration = _;
- return chart;
- };
-
- //============================================================
-
-
- //============================================================
- // Functions
- //------------------------------------------------------------
-
- /* Normalize the data according to an index point. */
- function indexify(idx, data) {
- return data.map(function(line, i) {
- if (!line.values) {
- return line;
- }
- var v = lines.y()(line.values[idx], idx);
-
- //TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue
- if (v < -.95) {
- //if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100)
- line.tempDisabled = true;
- return line;
- }
-
- line.tempDisabled = false;
-
- line.values = line.values.map(function(point, pointIndex) {
- point.display = {'y': (lines.y()(point, pointIndex) - v) / (1 + v) };
- return point;
- })
-
- return line;
- })
- }
-
- //============================================================
-
-
- return chart;
-}
-//TODO: consider deprecating by adding necessary features to multiBar model
-nv.models.discreteBar = 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 }
- , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove
- , color = nv.utils.defaultColor()
- , showValues = false
- , valueFormat = d3.format(',.2f')
- , xDomain
- , yDomain
- , xRange
- , yRange
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')
- , rectClass = 'discreteBar'
- ;
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom,
- container = d3.select(this);
-
-
- //add series index to each data point for reference
- data.forEach(function(series, i) {
- series.values.forEach(function(point) {
- point.series = i;
- });
- });
-
-
- //------------------------------------------------------------
- // 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) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), y0: d.y0 }
- })
- });
-
- x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))
- .rangeBands(xRange || [0, availableWidth], .1);
-
- y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y }).concat(forceY)));
-
-
- // If showValues, pad the Y axis range to account for label height
- if (showValues) y.range(yRange || [availableHeight - (y.domain()[0] < 0 ? 12 : 0), y.domain()[1] > 0 ? 12 : 0]);
- else 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.nv-discretebar').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discretebar');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-groups');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- //------------------------------------------------------------
-
-
-
- //TODO: by definition, the discrete bar should not have multiple groups, will modify/remove later
- var groups = wrap.select('.nv-groups').selectAll('.nv-group')
- .data(function(d) { return d }, function(d) { return d.key });
- groups.enter().append('g')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6);
- groups.exit()
- .transition()
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6)
- .remove();
- groups
- .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
- .classed('hover', function(d) { return d.hover });
- groups
- .transition()
- .style('stroke-opacity', 1)
- .style('fill-opacity', .75);
-
-
- var bars = groups.selectAll('g.nv-bar')
- .data(function(d) { return d.values });
-
- bars.exit().remove();
-
-
- var barsEnter = bars.enter().append('g')
- .attr('transform', function(d,i,j) {
- return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05 ) + ', ' + y(0) + ')'
- })
- .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
- });
- })
- .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
- });
- })
- .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
- });
- 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
- });
- d3.event.stopPropagation();
- });
-
- barsEnter.append('rect')
- .attr('height', 0)
- .attr('width', x.rangeBand() * .9 / data.length )
-
- if (showValues) {
- barsEnter.append('text')
- .attr('text-anchor', 'middle')
- ;
-
- bars.select('text')
- .text(function(d,i) { return valueFormat(getY(d,i)) })
- .transition()
- .attr('x', x.rangeBand() * .9 / 2)
- .attr('y', function(d,i) { return getY(d,i) < 0 ? y(getY(d,i)) - y(0) + 12 : -4 })
-
- ;
- } else {
- bars.selectAll('text').remove();
- }
-
- bars
- .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive' })
- .style('fill', function(d,i) { return d.color || color(d,i) })
- .style('stroke', function(d,i) { return d.color || color(d,i) })
- .select('rect')
- .attr('class', rectClass)
- .transition()
- .attr('width', x.rangeBand() * .9 / data.length);
- bars.transition()
- //.delay(function(d,i) { return i * 1200 / data[0].values.length })
- .attr('transform', function(d,i) {
- var left = x(getX(d,i)) + x.rangeBand() * .05,
- top = getY(d,i) < 0 ?
- y(0) :
- y(0) - y(getY(d,i)) < 1 ?
- y(0) - 1 : //make 1 px positive bars show up above y=0
- y(getY(d,i));
-
- return 'translate(' + left + ', ' + top + ')'
- })
- .select('rect')
- .attr('height', function(d,i) {
- return Math.max(Math.abs(y(getY(d,i)) - y((yDomain && yDomain[0]) || 0)) || 1)
- });
-
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = _;
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = _;
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.xScale = function(_) {
- if (!arguments.length) return x;
- x = _;
- return chart;
- };
-
- chart.yScale = function(_) {
- if (!arguments.length) return y;
- y = _;
- return chart;
- };
-
- chart.xDomain = function(_) {
- if (!arguments.length) return xDomain;
- xDomain = _;
- return chart;
- };
-
- chart.yDomain = function(_) {
- if (!arguments.length) return yDomain;
- yDomain = _;
- return chart;
- };
-
- chart.xRange = function(_) {
- if (!arguments.length) return xRange;
- xRange = _;
- return chart;
- };
-
- chart.yRange = function(_) {
- if (!arguments.length) return yRange;
- yRange = _;
- return chart;
- };
-
- chart.forceY = function(_) {
- if (!arguments.length) return forceY;
- forceY = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- chart.id = function(_) {
- if (!arguments.length) return id;
- id = _;
- return chart;
- };
-
- chart.showValues = function(_) {
- if (!arguments.length) return showValues;
- showValues = _;
- return chart;
- };
-
- chart.valueFormat= function(_) {
- if (!arguments.length) return valueFormat;
- valueFormat = _;
- return chart;
- };
-
- chart.rectClass= function(_) {
- if (!arguments.length) return rectClass;
- rectClass = _;
- return chart;
- };
- //============================================================
-
-
- return chart;
-}
-
-nv.models.discreteBarChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var discretebar = nv.models.discreteBar()
- , 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
- , tooltips = true
- , tooltip = function(key, x, y, e, graph) {
- return '
' + x + ' ' +
- '
' + y + '
'
- }
- , x
- , y
- , noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'beforeUpdate')
- , transitionDuration = 250
- ;
-
- xAxis
- .orient('bottom')
- .highlightZero(false)
- .showMaxMin(false)
- .tickFormat(function(d) { return d })
- ;
- yAxis
- .orient((rightAlignYAxis) ? 'right' : 'left')
- .tickFormat(d3.format(',.1f'))
- ;
-
- //============================================================
-
-
- //============================================================
- // 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);
- };
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- 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;
-
-
- chart.update = function() {
- dispatch.beforeUpdate();
- container.transition().duration(transitionDuration).call(chart);
- };
- chart.container = this;
-
-
- //------------------------------------------------------------
- // 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 });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = discretebar.xScale();
- y = discretebar.yScale().clamp(true);
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-discreteBarWithAxes').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discreteBarWithAxes').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)
-
- discretebar
- .width(availableWidth)
- .height(availableHeight);
-
-
- var barsWrap = g.select('.nv-barsWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
-
- barsWrap.transition().call(discretebar);
-
- //------------------------------------------------------------
-
-
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-x-label-clip-' + discretebar.id())
- .append('rect');
-
- g.select('#nv-x-label-clip-' + discretebar.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( availableWidth / 100 )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + (y.range()[0] + ((discretebar.showValues() && y.domain()[0] < 0) ? 16 : 0)) + ')');
- //d3.transition(g.select('.nv-x.nv-axis'))
- g.select('.nv-x.nv-axis').transition()
- .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( availableHeight / 36 )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis').transition()
- .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)
- //------------------------------------------------------------
-
- dispatch.on('tooltipShow', function(e) {
- if (tooltips) showTooltip(e, that.parentNode);
- });
-
- //============================================================
-
-
- });
-
- return chart;
- }
-
- //============================================================
- // 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('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.discretebar = discretebar;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
-
- d3.rebind(chart, discretebar, 'x', 'y', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'id', 'showValues', 'valueFormat');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- discretebar.color(color);
- return chart;
- };
-
- chart.showXAxis = function(_) {
- if (!arguments.length) return showXAxis;
- showXAxis = _;
- return chart;
- };
-
- chart.showYAxis = function(_) {
- if (!arguments.length) return showYAxis;
- showYAxis = _;
- return chart;
- };
-
- chart.rightAlignYAxis = function(_) {
- if(!arguments.length) return rightAlignYAxis;
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- return chart;
- };
-
- chart.staggerLabels = function(_) {
- if (!arguments.length) return staggerLabels;
- staggerLabels = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.transitionDuration = function(_) {
- if (!arguments.length) return transitionDuration;
- transitionDuration = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.distribution = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 400 //technically width or height depending on x or y....
- , size = 8
- , axis = 'x' // 'x' or 'y'... horizontal or vertical
- , getData = function(d) { return d[axis] } // defaults d.x or d.y
- , color = nv.utils.defaultColor()
- , scale = d3.scale.linear()
- , domain
- ;
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var scale0;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableLength = width - (axis === 'x' ? margin.left + margin.right : margin.top + margin.bottom),
- naxis = axis == 'x' ? 'y' : 'x',
- container = d3.select(this);
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- scale0 = scale0 || scale;
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-distribution').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-distribution');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
-
- //------------------------------------------------------------
-
-
- var distWrap = g.selectAll('g.nv-dist')
- .data(function(d) { return d }, function(d) { return d.key });
-
- distWrap.enter().append('g');
- distWrap
- .attr('class', function(d,i) { return 'nv-dist nv-series-' + i })
- .style('stroke', function(d,i) { return color(d, i) });
-
- var dist = distWrap.selectAll('line.nv-dist' + axis)
- .data(function(d) { return d.values })
- dist.enter().append('line')
- .attr(axis + '1', function(d,i) { return scale0(getData(d,i)) })
- .attr(axis + '2', function(d,i) { return scale0(getData(d,i)) })
- distWrap.exit().selectAll('line.nv-dist' + axis)
- .transition()
- .attr(axis + '1', function(d,i) { return scale(getData(d,i)) })
- .attr(axis + '2', function(d,i) { return scale(getData(d,i)) })
- .style('stroke-opacity', 0)
- .remove();
- dist
- .attr('class', function(d,i) { return 'nv-dist' + axis + ' nv-dist' + axis + '-' + i })
- .attr(naxis + '1', 0)
- .attr(naxis + '2', size);
- dist
- .transition()
- .attr(axis + '1', function(d,i) { return scale(getData(d,i)) })
- .attr(axis + '2', function(d,i) { return scale(getData(d,i)) })
-
-
- scale0 = scale.copy();
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.axis = function(_) {
- if (!arguments.length) return axis;
- axis = _;
- return chart;
- };
-
- chart.size = function(_) {
- if (!arguments.length) return size;
- size = _;
- return chart;
- };
-
- chart.getData = function(_) {
- if (!arguments.length) return getData;
- getData = d3.functor(_);
- return chart;
- };
-
- chart.scale = function(_) {
- if (!arguments.length) return scale;
- scale = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
- //============================================================
-
-
- return chart;
-}
-
-nv.models.historicalBarChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var bars = nv.models.historicalBar()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- ;
-
-
- var margin = {top: 30, right: 90, bottom: 50, left: 90}
- , color = nv.utils.defaultColor()
- , width = null
- , height = null
- , showLegend = false
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = 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')
- , transitionDuration = 250
- ;
-
- xAxis
- .orient('bottom')
- .tickPadding(7)
- ;
- yAxis
- .orient( (rightAlignYAxis) ? 'right' : 'left')
- ;
-
- //============================================================
-
-
- //============================================================
- // 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);
- };
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- 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;
-
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
- chart.container = this;
-
- //set state.disabled
- 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 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 });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = bars.xScale();
- y = bars.yScale();
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-historicalBarChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBarChart').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-barsWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Legend
-
- if (showLegend) {
- legend.width(availableWidth);
-
- 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;
- }
-
- wrap.select('.nv-legendWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- }
-
- //------------------------------------------------------------
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
- bars
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
-
-
- var barsWrap = g.select('.nv-barsWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
-
- barsWrap.transition().call(bars);
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Axes
-
- if (showXAxis) {
- xAxis
- .scale(x)
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')');
- g.select('.nv-x.nv-axis')
- .transition()
- .call(xAxis);
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- .ticks( availableHeight / 36 )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis')
- .transition()
- .call(yAxis);
- }
- //------------------------------------------------------------
-
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('legendClick', function(d,i) {
- d.disabled = !d.disabled;
-
- if (!data.filter(function(d) { return !d.disabled }).length) {
- data.map(function(d) {
- d.disabled = false;
- wrap.selectAll('.nv-series').classed('disabled', false);
- return d;
- });
- }
-
- state.disabled = data.map(function(d) { return !!d.disabled });
- dispatch.stateChange(state);
-
- selection.transition().call(chart);
- });
-
- legend.dispatch.on('legendDblclick', function(d) {
- //Double clicking should always enable current series, and disabled all others.
- data.forEach(function(d) {
- d.disabled = true;
- });
- d.disabled = false;
-
- state.disabled = data.map(function(d) { return !!d.disabled });
- 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];
- });
-
- state.disabled = e.disabled;
- }
-
- chart.update();
- });
-
- //============================================================
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // 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('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.bars = bars;
- chart.legend = legend;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
-
- d3.rebind(chart, bars, 'defined', 'isArea', 'x', 'y', 'size', 'xScale', 'yScale',
- 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id', 'interpolate','highlightPoint','clearHighlights', 'interactive');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.showXAxis = function(_) {
- if (!arguments.length) return showXAxis;
- showXAxis = _;
- return chart;
- };
-
- chart.showYAxis = function(_) {
- if (!arguments.length) return showYAxis;
- showYAxis = _;
- return chart;
- };
-
- chart.rightAlignYAxis = function(_) {
- if(!arguments.length) return rightAlignYAxis;
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.state = function(_) {
- if (!arguments.length) return state;
- state = _;
- return chart;
- };
-
- chart.defaultState = function(_) {
- if (!arguments.length) return defaultState;
- defaultState = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.transitionDuration = function(_) {
- if (!arguments.length) return transitionDuration;
- transitionDuration = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-nv.models.indentedTree = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0} //TODO: implement, maybe as margin on the containing div
- , width = 960
- , height = 500
- , color = nv.utils.defaultColor()
- , id = Math.floor(Math.random() * 10000)
- , header = true
- , filterZero = false
- , noData = "No Data Available."
- , childIndent = 20
- , columns = [{key:'key', label: 'Name', type:'text'}] //TODO: consider functions like chart.addColumn, chart.removeColumn, instead of a block like this
- , tableClass = null
- , iconOpen = 'images/grey-plus.png' //TODO: consider removing this and replacing with a '+' or '-' unless user defines images
- , iconClose = 'images/grey-minus.png'
- , dispatch = d3.dispatch('elementClick', 'elementDblclick', 'elementMouseover', 'elementMouseout')
- , getUrl = function(d) { return d.url }
- ;
-
- //============================================================
-
- var idx = 0;
-
- function chart(selection) {
- selection.each(function(data) {
- var depth = 1,
- container = d3.select(this);
-
- var tree = d3.layout.tree()
- .children(function(d) { return d.values })
- .size([height, childIndent]); //Not sure if this is needed now that the result is HTML
-
- chart.update = function() { container.transition().duration(600).call(chart) };
-
-
- //------------------------------------------------------------
- // Display No Data message if there's nothing to show.
- if (!data[0]) data[0] = {key: noData};
-
- //------------------------------------------------------------
-
-
- var nodes = tree.nodes(data[0]);
-
- // nodes.map(function(d) {
- // d.id = i++;
- // })
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = d3.select(this).selectAll('div').data([[nodes]]);
- var wrapEnter = wrap.enter().append('div').attr('class', 'nvd3 nv-wrap nv-indentedtree');
- var tableEnter = wrapEnter.append('table');
- var table = wrap.select('table').attr('width', '100%').attr('class', tableClass);
-
- //------------------------------------------------------------
-
-
- if (header) {
- var thead = tableEnter.append('thead');
-
- var theadRow1 = thead.append('tr');
-
- columns.forEach(function(column) {
- theadRow1
- .append('th')
- .attr('width', column.width ? column.width : '10%')
- .style('text-align', column.type == 'numeric' ? 'right' : 'left')
- .append('span')
- .text(column.label);
- });
- }
-
-
- var tbody = table.selectAll('tbody')
- .data(function(d) { return d });
- tbody.enter().append('tbody');
-
-
-
- //compute max generations
- depth = d3.max(nodes, function(node) { return node.depth });
- tree.size([height, depth * childIndent]); //TODO: see if this is necessary at all
-
-
- // Update the nodes…
- var node = tbody.selectAll('tr')
- // .data(function(d) { return d; }, function(d) { return d.id || (d.id == ++i)});
- .data(function(d) { return d.filter(function(d) { return (filterZero && !d.children) ? filterZero(d) : true; } )}, function(d,i) { return d.id || (d.id || ++idx)});
- //.style('display', 'table-row'); //TODO: see if this does anything
-
- node.exit().remove();
-
- node.select('img.nv-treeicon')
- .attr('src', icon)
- .classed('folded', folded);
-
- var nodeEnter = node.enter().append('tr');
-
-
- columns.forEach(function(column, index) {
-
- var nodeName = nodeEnter.append('td')
- .style('padding-left', function(d) { return (index ? 0 : d.depth * childIndent + 12 + (icon(d) ? 0 : 16)) + 'px' }, 'important') //TODO: check why I did the ternary here
- .style('text-align', column.type == 'numeric' ? 'right' : 'left');
-
-
- if (index == 0) {
- nodeName.append('img')
- .classed('nv-treeicon', true)
- .classed('nv-folded', folded)
- .attr('src', icon)
- .style('width', '14px')
- .style('height', '14px')
- .style('padding', '0 1px')
- .style('display', function(d) { return icon(d) ? 'inline-block' : 'none'; })
- .on('click', click);
- }
-
-
- nodeName.each(function(d) {
- if (!index && getUrl(d))
- d3.select(this)
- .append('a')
- .attr('href',getUrl)
- .attr('class', d3.functor(column.classes))
- .append('span')
- else
- d3.select(this)
- .append('span')
-
- d3.select(this).select('span')
- .attr('class', d3.functor(column.classes) )
- .text(function(d) { return column.format ? column.format(d) :
- (d[column.key] || '-') });
- });
-
- if (column.showCount) {
- nodeName.append('span')
- .attr('class', 'nv-childrenCount');
-
- node.selectAll('span.nv-childrenCount').text(function(d) {
- return ((d.values && d.values.length) || (d._values && d._values.length)) ? //If this is a parent
- '(' + ((d.values && (d.values.filter(function(d) { return filterZero ? filterZero(d) : true; }).length)) //If children are in values check its children and filter
- || (d._values && d._values.filter(function(d) { return filterZero ? filterZero(d) : true; }).length) //Otherwise, do the same, but with the other name, _values...
- || 0) + ')' //This is the catch-all in case there are no children after a filter
- : '' //If this is not a parent, just give an empty string
- });
- }
-
- // if (column.click)
- // nodeName.select('span').on('click', column.click);
-
- });
-
- node
- .order()
- .on('click', function(d) {
- dispatch.elementClick({
- row: this, //TODO: decide whether or not this should be consistent with scatter/line events or should be an html link (a href)
- data: d,
- pos: [d.x, d.y]
- });
- })
- .on('dblclick', function(d) {
- dispatch.elementDblclick({
- row: this,
- data: d,
- pos: [d.x, d.y]
- });
- })
- .on('mouseover', function(d) {
- dispatch.elementMouseover({
- row: this,
- data: d,
- pos: [d.x, d.y]
- });
- })
- .on('mouseout', function(d) {
- dispatch.elementMouseout({
- row: this,
- data: d,
- pos: [d.x, d.y]
- });
- });
-
-
-
-
- // Toggle children on click.
- function click(d, _, unshift) {
- d3.event.stopPropagation();
-
- if(d3.event.shiftKey && !unshift) {
- //If you shift-click, it'll toggle fold all the children, instead of itself
- d3.event.shiftKey = false;
- d.values && d.values.forEach(function(node){
- if (node.values || node._values) {
- click(node, 0, true);
- }
- });
- return true;
- }
- if(!hasChildren(d)) {
- //download file
- //window.location.href = d.url;
- return true;
- }
- if (d.values) {
- d._values = d.values;
- d.values = null;
- } else {
- d.values = d._values;
- d._values = null;
- }
- chart.update();
- }
-
-
- function icon(d) {
- return (d._values && d._values.length) ? iconOpen : (d.values && d.values.length) ? iconClose : '';
- }
-
- function folded(d) {
- return (d._values && d._values.length);
- }
-
- function hasChildren(d) {
- var values = d.values || d._values;
-
- return (values && values.length);
- }
-
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- scatter.color(color);
- return chart;
- };
-
- chart.id = function(_) {
- if (!arguments.length) return id;
- id = _;
- return chart;
- };
-
- chart.header = function(_) {
- if (!arguments.length) return header;
- header = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.filterZero = function(_) {
- if (!arguments.length) return filterZero;
- filterZero = _;
- return chart;
- };
-
- chart.columns = function(_) {
- if (!arguments.length) return columns;
- columns = _;
- return chart;
- };
-
- chart.tableClass = function(_) {
- if (!arguments.length) return tableClass;
- tableClass = _;
- return chart;
- };
-
- chart.iconOpen = function(_){
- if (!arguments.length) return iconOpen;
- iconOpen = _;
- return chart;
- }
-
- chart.iconClose = function(_){
- if (!arguments.length) return iconClose;
- iconClose = _;
- return chart;
- }
-
- chart.getUrl = function(_){
- if (!arguments.length) return getUrl;
- getUrl = _;
- return chart;
- }
-
- //============================================================
-
-
- return chart;
-};nv.models.legend = 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.defaultColor()
- , align = true
- , 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)
- , dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange')
- ;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- container = d3.select(this);
-
-
- //------------------------------------------------------------
- // 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) { return d });
- var seriesEnter = series.enter().append('g').attr('class', 'nv-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);
- 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});
- }
- }
- dispatch.stateChange({
- disabled: data.map(function(d) { return !!d.disabled })
- });
- }
- })
- .on('dblclick', function(d,i) {
- dispatch.legendDblclick(d,i);
- if (updateState) {
- //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;
- });
- d.disabled = false;
- 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('disabled', function(d) { return d.disabled });
- 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);
-
-
- //TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)
-
- // NEW ALIGNING CODE, TODO: clean up
- if (align) {
-
- var seriesWidths = [];
- series.each(function(d,i) {
- var legendText = d3.select(this).select('text');
- var nodeTextLength;
- try {
- nodeTextLength = legendText.node().getComputedTextLength();
- }
- catch(e) {
- nodeTextLength = nv.utils.calcApproxTextWidth(legendText);
- }
-
- seriesWidths.push(nodeTextLength + 28); // 28 is ~ the width of the circle plus some 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) * 20) + ')';
- });
-
- //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) * 20);
-
- } else {
-
- var ypos = 5,
- newxpos = 5,
- maxwidth = 0,
- xpos;
- series
- .attr('transform', function(d, i) {
- var length = d3.select(this).select('text').node().getComputedTextLength() + 28;
- xpos = newxpos;
-
- if (width < margin.left + margin.right + xpos + length) {
- newxpos = xpos = 5;
- ypos += 20;
- }
-
- 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;
-
- }
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.key = function(_) {
- if (!arguments.length) return getKey;
- getKey = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- chart.align = function(_) {
- if (!arguments.length) return align;
- align = _;
- return chart;
- };
-
- chart.rightAlign = function(_) {
- if (!arguments.length) return rightAlign;
- rightAlign = _;
- return chart;
- };
-
- chart.updateState = function(_) {
- if (!arguments.length) return updateState;
- updateState = _;
- return chart;
- };
-
- chart.radioButtonMode = function(_) {
- if (!arguments.length) return radioButtonMode;
- radioButtonMode = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.line = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var scatter = nv.models.scatter()
- ;
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , 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
- , 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
- , isArea = function(d) { return d.area } // decides if a line is an area or just a line
- , clipEdge = false // if true, masks lines within x and y scale
- , x //can be accessed via chart.xScale()
- , y //can be accessed via chart.yScale()
- , interpolate = "linear" // controls the line interpolation
- ;
-
- scatter
- .size(16) // default size
- .sizeDomain([16,256]) //set to speed up calculation, needs to be unset if there is a custom size accessor
- ;
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0 //used to store previous scales
- ;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom,
- container = d3.select(this);
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = scatter.xScale();
- y = scatter.yScale();
-
- x0 = x0 || x;
- y0 = y0 || y;
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-line').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-line');
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g')
-
- gEnter.append('g').attr('class', 'nv-groups');
- gEnter.append('g').attr('class', 'nv-scatterWrap');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- //------------------------------------------------------------
-
-
-
-
- scatter
- .width(availableWidth)
- .height(availableHeight)
-
- var scatterWrap = wrap.select('.nv-scatterWrap');
- //.datum(data); // Data automatically trickles down from the wrap
-
- scatterWrap.transition().call(scatter);
-
-
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-edge-clip-' + scatter.id())
- .append('rect');
-
- wrap.select('#nv-edge-clip-' + scatter.id() + ' rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
- scatterWrap
- .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');
-
-
-
-
- var groups = wrap.select('.nv-groups').selectAll('.nv-group')
- .data(function(d) { return d }, function(d) { return d.key });
- groups.enter().append('g')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6);
-
- groups.exit().remove();
-
- groups
- .attr('class', function(d,i) { return '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
- .transition()
- .style('stroke-opacity', 1)
- .style('fill-opacity', .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
- areaPaths.enter().append('path')
- .attr('class', 'nv-area')
- .attr('d', function(d) {
- return d3.svg.area()
- .interpolate(interpolate)
- .defined(defined)
- .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })
- .y0(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })
- .y1(function(d,i) { return y0( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })
- //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this
- .apply(this, [d.values])
- });
- groups.exit().selectAll('path.nv-area')
- .remove();
-
- areaPaths
- .transition()
- .attr('d', function(d) {
- return d3.svg.area()
- .interpolate(interpolate)
- .defined(defined)
- .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
- .y0(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
- .y1(function(d,i) { return y( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })
- //.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this
- .apply(this, [d.values])
- });
-
-
-
- var linePaths = groups.selectAll('path.nv-line')
- .data(function(d) { return [d.values] });
- linePaths.enter().append('path')
- .attr('class', 'nv-line')
- .attr('d',
- d3.svg.line()
- .interpolate(interpolate)
- .defined(defined)
- .x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })
- .y(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })
- );
-
- linePaths
- .transition()
- .attr('d',
- d3.svg.line()
- .interpolate(interpolate)
- .defined(defined)
- .x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
- .y(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
- );
-
-
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = scatter.dispatch;
- chart.scatter = scatter;
-
- d3.rebind(chart, scatter, 'id', 'interactive', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'xRange', 'yRange',
- 'sizeDomain', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'useVoronoi', 'clipRadius', 'padData','highlightPoint','clearHighlights');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = _;
- scatter.x(_);
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = _;
- scatter.y(_);
- return chart;
- };
-
- chart.clipEdge = function(_) {
- if (!arguments.length) return clipEdge;
- clipEdge = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- scatter.color(color);
- return chart;
- };
-
- chart.interpolate = function(_) {
- if (!arguments.length) return interpolate;
- interpolate = _;
- return chart;
- };
-
- chart.defined = function(_) {
- if (!arguments.length) return defined;
- defined = _;
- return chart;
- };
-
- chart.isArea = function(_) {
- if (!arguments.length) return isArea;
- isArea = d3.functor(_);
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.lineChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var lines = nv.models.line()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , interactiveLayer = nv.interactiveGuideline()
- ;
-
- var margin = {top: 30, right: 20, bottom: 50, left: 60}
- , color = nv.utils.defaultColor()
- , width = null
- , height = null
- , showLegend = true
- , showXAxis = true
- , 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')
- , transitionDuration = 250
- ;
-
- xAxis
- .orient('bottom')
- .tickPadding(7)
- ;
- yAxis
- .orient((rightAlignYAxis) ? 'right' : '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);
- };
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- 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;
-
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
- chart.container = this;
-
- //set state.disabled
- 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 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 });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = lines.xScale();
- y = lines.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);
- //------------------------------------------------------------
- // Legend
-
- if (showLegend) {
- legend.width(availableWidth);
-
- 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;
- }
-
- wrap.select('.nv-legendWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- }
-
- //------------------------------------------------------------
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
-
- //------------------------------------------------------------
- //Set up interactive layer
- if (useInteractiveGuideline) {
- interactiveLayer
- .width(availableWidth)
- .height(availableHeight)
- .margin({left:margin.left, top:margin.top})
- .svgContainer(container)
- .xScale(x);
- wrap.select(".nv-interactive").call(interactiveLayer);
- }
-
-
- lines
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
-
-
- var linesWrap = g.select('.nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
-
- linesWrap.transition().call(lines);
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Axes
-
- if (showXAxis) {
- xAxis
- .scale(x)
- .ticks( availableWidth / 100 )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')');
- g.select('.nv-x.nv-axis')
- .transition()
- .call(xAxis);
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- .ticks( availableHeight / 36 )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis')
- .transition()
- .call(yAxis);
- }
- //------------------------------------------------------------
-
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- state = newState;
- dispatch.stateChange(state);
- chart.update();
- });
-
- 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) {
- 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));
- 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
- .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})
- .chartContainer(that.parentNode)
- .enabled(tooltips)
- .valueFormatter(function(d,i) {
- return yAxis.tickFormat()(d);
- })
- .data(
- {
- value: xValue,
- series: allData
- }
- )();
-
- interactiveLayer.renderGuideLine(pointXLocation);
-
- });
-
- 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.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
-
- state.disabled = e.disabled;
- }
-
- chart.update();
- });
-
- //============================================================
-
- });
-
- 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.lines = lines;
- chart.legend = legend;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.interactiveLayer = interactiveLayer;
-
- d3.rebind(chart, lines, 'defined', 'isArea', 'x', 'y', 'size', 'xScale', 'yScale', 'xDomain', 'yDomain', 'xRange', 'yRange'
- , 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'useVoronoi','id', 'interpolate');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.showXAxis = function(_) {
- if (!arguments.length) return showXAxis;
- showXAxis = _;
- return chart;
- };
-
- chart.showYAxis = function(_) {
- if (!arguments.length) return showYAxis;
- showYAxis = _;
- return chart;
- };
-
- chart.rightAlignYAxis = function(_) {
- if(!arguments.length) return rightAlignYAxis;
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- return chart;
- };
-
- chart.useInteractiveGuideline = function(_) {
- if(!arguments.length) return useInteractiveGuideline;
- useInteractiveGuideline = _;
- if (_ === true) {
- chart.interactive(false);
- chart.useVoronoi(false);
- }
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.state = function(_) {
- if (!arguments.length) return state;
- state = _;
- return chart;
- };
-
- chart.defaultState = function(_) {
- if (!arguments.length) return defaultState;
- defaultState = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.transitionDuration = function(_) {
- if (!arguments.length) return transitionDuration;
- transitionDuration = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.linePlusBarChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var lines = nv.models.line()
- , bars = nv.models.historicalBar()
- , xAxis = nv.models.axis()
- , y1Axis = nv.models.axis()
- , y2Axis = nv.models.axis()
- , legend = nv.models.legend()
- ;
-
- var margin = {top: 30, right: 60, bottom: 50, left: 60}
- , width = null
- , height = null
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , color = nv.utils.defaultColor()
- , showLegend = true
- , tooltips = true
- , tooltip = function(key, x, y, e, graph) {
- return '
' + key + ' ' +
- '
' + y + ' at ' + x + '
';
- }
- , x
- , y1
- , y2
- , state = {}
- , defaultState = null
- , noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
- ;
-
- bars
- .padData(true)
- ;
- lines
- .clipEdge(false)
- .padData(true)
- ;
- xAxis
- .orient('bottom')
- .tickPadding(7)
- .highlightZero(false)
- ;
- y1Axis
- .orient('left')
- ;
- y2Axis
- .orient('right')
- ;
-
- //============================================================
-
-
- //============================================================
- // 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 = (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);
- }
- ;
-
- //------------------------------------------------------------
-
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- 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;
-
- chart.update = function() { container.transition().call(chart); };
- // chart.container = this;
-
- //set state.disabled
- 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 + availableHeight / 2)
- .text(function(d) { return d });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- var dataBars = data.filter(function(d) { return !d.disabled && d.bar });
- var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240
-
- //x = xAxis.scale();
- x = dataLines.filter(function(d) { return !d.disabled; }).length && dataLines.filter(function(d) { return !d.disabled; })[0].values.length ? lines.xScale() : bars.xScale();
- //x = dataLines.filter(function(d) { return !d.disabled; }).length ? lines.xScale() : bars.xScale(); //old code before change above
- y1 = bars.yScale();
- y2 = lines.yScale();
-
- //------------------------------------------------------------
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = d3.select(this).selectAll('g.nv-wrap.nv-linePlusBar').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');
- var g = wrap.select('g');
-
- 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', 'nv-barsWrap');
- gEnter.append('g').attr('class', 'nv-linesWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Legend
-
- if (showLegend) {
- legend.width( availableWidth / 2 );
-
- g.select('.nv-legendWrap')
- .datum(data.map(function(series) {
- series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;
- series.key = series.originalKey + (series.bar ? ' (left axis)' : ' (right axis)');
- return series;
- }))
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = (height || parseInt(container.style('height')) || 400)
- - margin.top - margin.bottom;
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')');
- }
-
- //------------------------------------------------------------
-
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
-
- lines
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled && !data[i].bar }))
-
- bars
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled && data[i].bar }))
-
-
-
- var barsWrap = g.select('.nv-barsWrap')
- .datum(dataBars.length ? dataBars : [{values:[]}])
-
- var linesWrap = g.select('.nv-linesWrap')
- .datum(dataLines[0] && !dataLines[0].disabled ? dataLines : [{values:[]}] );
- //.datum(!dataLines[0].disabled ? dataLines : [{values:dataLines[0].values.map(function(d) { return [d[0], null] }) }] );
-
- d3.transition(barsWrap).call(bars);
- d3.transition(linesWrap).call(lines);
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Axes
-
- xAxis
- .scale(x)
- .ticks( availableWidth / 100 )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y1.range()[0] + ')');
- d3.transition(g.select('.nv-x.nv-axis'))
- .call(xAxis);
-
-
- y1Axis
- .scale(y1)
- .ticks( availableHeight / 36 )
- .tickSize(-availableWidth, 0);
-
- d3.transition(g.select('.nv-y1.nv-axis'))
- .style('opacity', dataBars.length ? 1 : 0)
- .call(y1Axis);
-
-
- y2Axis
- .scale(y2)
- .ticks( availableHeight / 36 )
- .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
-
- g.select('.nv-y2.nv-axis')
- .style('opacity', dataLines.length ? 1 : 0)
- .attr('transform', 'translate(' + availableWidth + ',0)');
- //.attr('transform', 'translate(' + x.range()[1] + ',0)');
-
- d3.transition(g.select('.nv-y2.nv-axis'))
- .call(y2Axis);
-
- //------------------------------------------------------------
-
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- state = newState;
- 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;
- }
-
- chart.update();
- });
-
- //============================================================
-
-
- });
-
- 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);
- });
-
- 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('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.bars = bars;
- chart.xAxis = xAxis;
- chart.y1Axis = y1Axis;
- chart.y2Axis = y2Axis;
-
- d3.rebind(chart, lines, 'defined', 'size', 'clipVoronoi', 'interpolate');
- //TODO: consider rebinding x, y and some other stuff, and simply do soemthign lile bars.x(lines.x()), etc.
- //d3.rebind(chart, lines, 'x', 'y', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = _;
- lines.x(_);
- bars.x(_);
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = _;
- lines.y(_);
- bars.y(_);
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.state = function(_) {
- if (!arguments.length) return state;
- state = _;
- return chart;
- };
-
- chart.defaultState = function(_) {
- if (!arguments.length) return defaultState;
- defaultState = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-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')
- , transitionDuration = 250
- ;
-
- 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);
- };
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
-
- 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;
-
-
- //------------------------------------------------------------
- // 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);
-
- //------------------------------------------------------------
-
-
- /*
- var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
-
- d3.transition(focusLinesWrap).call(lines);
- */
-
-
- //------------------------------------------------------------
- // Setup Main (Focus) Axes
-
- xAxis
- .scale(x)
- .ticks( availableWidth / 100 )
- .tickSize(-availableHeight1, 0);
-
- yAxis
- .scale(y)
- .ticks( availableHeight1 / 36 )
- .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.transitionDuration();
- chart.transitionDuration(0);
- onBrush();
- chart.transitionDuration(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( availableWidth / 100 )
- .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( availableHeight2 / 36 )
- .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) {
- chart.update();
- });
-
- dispatch.on('tooltipShow', function(e) {
- if (tooltips) showTooltip(e, that.parentNode);
- });
-
- //============================================================
-
-
- //============================================================
- // 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,
- 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;
-
- d3.rebind(chart, lines, 'defined', 'isArea', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return lines.x;
- lines.x(_);
- lines2.x(_);
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return lines.y;
- lines.y(_);
- lines2.y(_);
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.margin2 = function(_) {
- if (!arguments.length) return margin2;
- margin2 = _;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.height2 = function(_) {
- if (!arguments.length) return height2;
- height2 = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color =nv.utils.getColor(_);
- legend.color(color);
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.interpolate = function(_) {
- if (!arguments.length) return lines.interpolate();
- lines.interpolate(_);
- lines2.interpolate(_);
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- // Chart has multiple similar Axes, to prevent code duplication, probably need to link all axis functions manually like below
- chart.xTickFormat = function(_) {
- if (!arguments.length) return xAxis.tickFormat();
- xAxis.tickFormat(_);
- x2Axis.tickFormat(_);
- return chart;
- };
-
- chart.yTickFormat = function(_) {
- if (!arguments.length) return yAxis.tickFormat();
- yAxis.tickFormat(_);
- y2Axis.tickFormat(_);
- return chart;
- };
-
- chart.brushExtent = function(_) {
- if (!arguments.length) return brushExtent;
- brushExtent = _;
- return chart;
- };
-
- chart.transitionDuration = function(_) {
- if (!arguments.length) return transitionDuration;
- transitionDuration = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.linePlusBarWithFocusChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var lines = nv.models.line()
- , lines2 = nv.models.line()
- , bars = nv.models.historicalBar()
- , bars2 = nv.models.historicalBar()
- , xAxis = nv.models.axis()
- , x2Axis = nv.models.axis()
- , y1Axis = nv.models.axis()
- , y2Axis = nv.models.axis()
- , y3Axis = nv.models.axis()
- , y4Axis = 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}
- , width = null
- , height = null
- , height2 = 100
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , color = nv.utils.defaultColor()
- , showLegend = true
- , 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')
- , transitionDuration = 0
- ;
-
- 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')
- ;
-
- //============================================================
-
-
- //============================================================
- // 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);
- };
-
- //------------------------------------------------------------
-
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
-
- 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;
-
-
- //------------------------------------------------------------
- // 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
-
- var dataBars = data.filter(function(d) { return !d.disabled && d.bar });
- var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #240
-
- x = bars.xScale();
- x2 = x2Axis.scale();
- y1 = bars.yScale();
- y2 = lines.yScale();
- y3 = bars2.yScale();
- y4 = lines2.yScale();
-
- var series1 = data
- .filter(function(d) { return !d.disabled && d.bar })
- .map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i) }
- })
- });
-
- var series2 = data
- .filter(function(d) { return !d.disabled && !d.bar })
- .map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i) }
- })
- });
-
- x .range([0, availableWidth]);
-
- x2 .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))
- .range([0, availableWidth]);
-
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-linePlusBar').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').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-y1 nv-axis');
- focusEnter.append('g').attr('class', 'nv-y2 nv-axis');
- focusEnter.append('g').attr('class', 'nv-barsWrap');
- 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-y1 nv-axis');
- contextEnter.append('g').attr('class', 'nv-y2 nv-axis');
- contextEnter.append('g').attr('class', 'nv-barsWrap');
- 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 / 2 );
-
- g.select('.nv-legendWrap')
- .datum(data.map(function(series) {
- series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;
- series.key = series.originalKey + (series.bar ? ' (left axis)' : ' (right axis)');
- return series;
- }))
- .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(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')');
- }
-
- //------------------------------------------------------------
-
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
-
- //------------------------------------------------------------
- // Context Components
-
- bars2
- .width(availableWidth)
- .height(availableHeight2)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled && data[i].bar }));
-
- lines2
- .width(availableWidth)
- .height(availableHeight2)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled && !data[i].bar }));
-
- var bars2Wrap = g.select('.nv-context .nv-barsWrap')
- .datum(dataBars.length ? dataBars : [{values:[]}]);
-
- var lines2Wrap = g.select('.nv-context .nv-linesWrap')
- .datum(!dataLines[0].disabled ? dataLines : [{values:[]}]);
-
- g.select('.nv-context')
- .attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')')
-
- bars2Wrap.transition().call(bars2);
- lines2Wrap.transition().call(lines2);
-
- //------------------------------------------------------------
-
-
-
- //------------------------------------------------------------
- // Setup Brush
-
- brush
- .x(x2)
- .on('brush', 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('y', -5)
- .attr('height', availableHeight2);
- gBrush.selectAll('.resize').append('path').attr('d', resizePath);
-
- //------------------------------------------------------------
-
- //------------------------------------------------------------
- // Setup Secondary (Context) Axes
-
- x2Axis
- .ticks( availableWidth / 100 )
- .tickSize(-availableHeight2, 0);
-
- g.select('.nv-context .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y3.range()[0] + ')');
- g.select('.nv-context .nv-x.nv-axis').transition()
- .call(x2Axis);
-
-
- y3Axis
- .scale(y3)
- .ticks( availableHeight2 / 36 )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-context .nv-y1.nv-axis')
- .style('opacity', dataBars.length ? 1 : 0)
- .attr('transform', 'translate(0,' + x2.range()[0] + ')');
-
- g.select('.nv-context .nv-y1.nv-axis').transition()
- .call(y3Axis);
-
-
- y4Axis
- .scale(y4)
- .ticks( availableHeight2 / 36 )
- .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
-
- g.select('.nv-context .nv-y2.nv-axis')
- .style('opacity', dataLines.length ? 1 : 0)
- .attr('transform', 'translate(' + x2.range()[1] + ',0)');
-
- g.select('.nv-context .nv-y2.nv-axis').transition()
- .call(y4Axis);
-
- //------------------------------------------------------------
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- chart.update();
- });
-
- dispatch.on('tooltipShow', function(e) {
- if (tooltips) showTooltip(e, that.parentNode);
- });
-
- //============================================================
-
-
- //============================================================
- // 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]) - x2.range()[0],
- rightWidth = x2.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();
- extent = brush.empty() ? x2.domain() : brush.extent();
-
-
- dispatch.brush({extent: extent, brush: brush});
-
- updateBrushBG();
-
-
- //------------------------------------------------------------
- // Prepare Main (Focus) Bars and Lines
-
- bars
- .width(availableWidth)
- .height(availableHeight1)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled && data[i].bar }));
-
-
- 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 && !data[i].bar }));
-
- var focusBarsWrap = g.select('.nv-focus .nv-barsWrap')
- .datum(!dataBars.length ? [{values:[]}] :
- dataBars
- .map(function(d,i) {
- return {
- key: d.key,
- values: d.values.filter(function(d,i) {
- return bars.x()(d,i) >= extent[0] && bars.x()(d,i) <= extent[1];
- })
- }
- })
- );
-
- var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')
- .datum(dataLines[0].disabled ? [{values:[]}] :
- dataLines
- .map(function(d,i) {
- return {
- key: d.key,
- values: d.values.filter(function(d,i) {
- return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];
- })
- }
- })
- );
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Update Main (Focus) X Axis
-
- if (dataBars.length) {
- x = bars.xScale();
- } else {
- x = lines.xScale();
- }
-
- xAxis
- .scale(x)
- .ticks( availableWidth / 100 )
- .tickSize(-availableHeight1, 0);
-
- xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]);
-
- g.select('.nv-x.nv-axis').transition().duration(transitionDuration)
- .call(xAxis);
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Update Main (Focus) Bars and Lines
-
- focusBarsWrap.transition().duration(transitionDuration).call(bars);
- focusLinesWrap.transition().duration(transitionDuration).call(lines);
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup and Update Main (Focus) Y Axes
-
- g.select('.nv-focus .nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y1.range()[0] + ')');
-
-
- y1Axis
- .scale(y1)
- .ticks( availableHeight1 / 36 )
- .tickSize(-availableWidth, 0);
-
- g.select('.nv-focus .nv-y1.nv-axis')
- .style('opacity', dataBars.length ? 1 : 0);
-
-
- y2Axis
- .scale(y2)
- .ticks( availableHeight1 / 36 )
- .tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none
-
- g.select('.nv-focus .nv-y2.nv-axis')
- .style('opacity', dataLines.length ? 1 : 0)
- .attr('transform', 'translate(' + x.range()[1] + ',0)');
-
- g.select('.nv-focus .nv-y1.nv-axis').transition().duration(transitionDuration)
- .call(y1Axis);
- g.select('.nv-focus .nv-y2.nv-axis').transition().duration(transitionDuration)
- .call(y2Axis);
- }
-
- //============================================================
-
- onBrush();
-
- });
-
- 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);
- });
-
- 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('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.bars = bars;
- chart.bars2 = bars2;
- chart.xAxis = xAxis;
- chart.x2Axis = x2Axis;
- chart.y1Axis = y1Axis;
- chart.y2Axis = y2Axis;
- chart.y3Axis = y3Axis;
- chart.y4Axis = y4Axis;
-
- d3.rebind(chart, lines, 'defined', 'size', 'clipVoronoi', 'interpolate');
- //TODO: consider rebinding x, y and some other stuff, and simply do soemthign lile bars.x(lines.x()), etc.
- //d3.rebind(chart, lines, 'x', 'y', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = _;
- lines.x(_);
- bars.x(_);
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = _;
- lines.y(_);
- bars.y(_);
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.brushExtent = function(_) {
- if (!arguments.length) return brushExtent;
- brushExtent = _;
- return chart;
- };
-
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.multiBar = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , 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
- , 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
- , clipEdge = true
- , stacked = false
- , stackOffset = 'zero' // options include 'silhouette', 'wiggle', 'expand', 'zero', or a custom function
- , color = nv.utils.defaultColor()
- , hideable = false
- , barColor = null // adding the ability to set the color for each rather than the whole group
- , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled
- , delay = 1200
- , xDomain
- , yDomain
- , xRange
- , yRange
- , groupSpacing = 0.1
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')
- ;
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0 //used to store previous scales
- ;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom,
- container = d3.select(this);
-
- if(hideable && data.length) hideable = [{
- values: data[0].values.map(function(d) {
- return {
- x: d.x,
- y: 0,
- series: d.series,
- size: 0.01
- };}
- )}];
-
- if (stacked)
- data = 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
- data.forEach(function(series, i) {
- series.values.forEach(function(point) {
- point.series = i;
- });
- });
-
-
- //------------------------------------------------------------
- // HACK for negative value stacking
- 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;
- }
- });
- });
-
- //------------------------------------------------------------
- // 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) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 }
- })
- });
-
- 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 d.y + (stacked ? d.y1 : 0) }).concat(forceY)))
- 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]);
-
- // 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]);
-
-
- x0 = x0 || x;
- y0 = y0 || y;
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-multibar').data([data]);
- 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')
-
- gEnter.append('g').attr('class', 'nv-groups');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- //------------------------------------------------------------
-
-
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-edge-clip-' + id)
- .append('rect');
- wrap.select('#nv-edge-clip-' + id + ' rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
-
-
-
- var groups = wrap.select('.nv-groups').selectAll('.nv-group')
- .data(function(d) { return d }, function(d,i) { return i });
- groups.enter().append('g')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6);
- groups.exit()
- .transition()
- .selectAll('rect.nv-bar')
- .delay(function(d,i) {
- return i * delay/ data[0].values.length;
- })
- .attr('y', function(d) { return stacked ? y0(d.y0) : y0(0) })
- .attr('height', 0)
- .remove();
- groups
- .attr('class', function(d,i) { return '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
- .transition()
- .style('stroke-opacity', 1)
- .style('fill-opacity', .75);
-
-
- var bars = groups.selectAll('rect.nv-bar')
- .data(function(d) { return (hideable && !data.length) ? hideable.values : d.values });
-
- bars.exit().remove();
-
-
- 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 )
- })
- .attr('y', function(d) { return y0(stacked ? d.y0 : 0) })
- .attr('height', 0)
- .attr('width', x.rangeBand() / (stacked ? 1 : data.length) )
- .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })
- ;
- bars
- .style('fill', function(d,i,j){ return color(d, j, i); })
- .style('stroke', function(d,i,j){ return color(d, j, i); })
- .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
- });
- })
- .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
- });
- })
- .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
- });
- 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
- });
- d3.event.stopPropagation();
- });
- bars
- .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
- .transition()
- .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })
-
- if (barColor) {
- if (!disabled) disabled = data.map(function() { return true });
- bars
- .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); })
- .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); });
- }
-
-
- if (stacked)
- bars.transition()
- .delay(function(d,i) {
-
- return i * delay / data[0].values.length;
- })
- .attr('y', function(d,i) {
-
- return y((stacked ? d.y1 : 0));
- })
- .attr('height', function(d,i) {
- return Math.max(Math.abs(y(d.y + (stacked ? d.y0 : 0)) - y((stacked ? d.y0 : 0))),1);
- })
- .attr('x', function(d,i) {
- return stacked ? 0 : (d.series * x.rangeBand() / data.length )
- })
- .attr('width', x.rangeBand() / (stacked ? 1 : data.length) );
- else
- bars.transition()
- .delay(function(d,i) {
- return i * delay/ data[0].values.length;
- })
- .attr('x', function(d,i) {
- return d.series * x.rangeBand() / data.length
- })
- .attr('width', x.rangeBand() / data.length)
- .attr('y', function(d,i) {
- return getY(d,i) < 0 ?
- y(0) :
- y(0) - y(getY(d,i)) < 1 ?
- y(0) - 1 :
- y(getY(d,i)) || 0;
- })
- .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();
- y0 = y.copy();
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = _;
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = _;
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.xScale = function(_) {
- if (!arguments.length) return x;
- x = _;
- return chart;
- };
-
- chart.yScale = function(_) {
- if (!arguments.length) return y;
- y = _;
- return chart;
- };
-
- chart.xDomain = function(_) {
- if (!arguments.length) return xDomain;
- xDomain = _;
- return chart;
- };
-
- chart.yDomain = function(_) {
- if (!arguments.length) return yDomain;
- yDomain = _;
- return chart;
- };
-
- chart.xRange = function(_) {
- if (!arguments.length) return xRange;
- xRange = _;
- return chart;
- };
-
- chart.yRange = function(_) {
- if (!arguments.length) return yRange;
- yRange = _;
- return chart;
- };
-
- chart.forceY = function(_) {
- if (!arguments.length) return forceY;
- forceY = _;
- return chart;
- };
-
- chart.stacked = function(_) {
- if (!arguments.length) return stacked;
- stacked = _;
- return chart;
- };
-
- chart.stackOffset = function(_) {
- if (!arguments.length) return stackOffset;
- stackOffset = _;
- return chart;
- };
-
- chart.clipEdge = function(_) {
- if (!arguments.length) return clipEdge;
- clipEdge = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- chart.barColor = function(_) {
- if (!arguments.length) return barColor;
- barColor = nv.utils.getColor(_);
- return chart;
- };
-
- chart.disabled = function(_) {
- if (!arguments.length) return disabled;
- disabled = _;
- return chart;
- };
-
- chart.id = function(_) {
- if (!arguments.length) return id;
- id = _;
- return chart;
- };
-
- chart.hideable = function(_) {
- if (!arguments.length) return hideable;
- hideable = _;
- return chart;
- };
-
- chart.delay = function(_) {
- if (!arguments.length) return delay;
- delay = _;
- return chart;
- };
-
- chart.groupSpacing = function(_) {
- if (!arguments.length) return groupSpacing;
- groupSpacing = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.multiBarChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var multibar = nv.models.multiBar()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , controls = nv.models.legend()
- ;
-
- var margin = {top: 30, right: 20, bottom: 50, left: 60}
- , width = null
- , height = null
- , color = nv.utils.defaultColor()
- , showControls = true
- , showLegend = true
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , reduceXTicks = true // if false a tick will show for every data point
- , staggerLabels = 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 = { stacked: false }
- , defaultState = null
- , noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
- , controlWidth = function() { return showControls ? 180 : 0 }
- , transitionDuration = 250
- ;
-
- multibar
- .stacked(false)
- ;
- xAxis
- .orient('bottom')
- .tickPadding(7)
- .highlightZero(true)
- .showMaxMin(false)
- .tickFormat(function(d) { return d })
- ;
- yAxis
- .orient((rightAlignYAxis) ? 'right' : 'left')
- .tickFormat(d3.format(',.1f'))
- ;
-
- 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 ? 'n' : 's', null, offsetElement);
- };
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- 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;
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
- chart.container = this;
-
- //set state.disabled
- 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 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 });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = multibar.xScale();
- y = multibar.yScale();
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-multiBarWithLegend').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarWithLegend').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-barsWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-controlsWrap');
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Legend
-
- 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;
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Controls
-
- if (showControls) {
- var controlsData = [
- { key: 'Grouped', disabled: multibar.stacked() },
- { key: 'Stacked', disabled: !multibar.stacked() }
- ];
-
- controls.width(controlWidth()).color(['#444', '#444', '#444']);
- g.select('.nv-controlsWrap')
- .datum(controlsData)
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- .call(controls);
- }
-
- //------------------------------------------------------------
-
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
- multibar
- .disabled(data.map(function(series) { return series.disabled }))
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }))
-
-
- var barsWrap = g.select('.nv-barsWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
-
- barsWrap.transition().call(multibar);
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Axes
-
- if (showXAxis) {
- xAxis
- .scale(x)
- .ticks( availableWidth / 100 )
- .tickSize(-availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')');
- g.select('.nv-x.nv-axis').transition()
- .call(xAxis);
-
- var xTicks = g.select('.nv-x.nv-axis > g').selectAll('g');
-
- xTicks
- .selectAll('line, text')
- .style('opacity', 1)
-
- if (staggerLabels) {
- var getTranslate = function(x,y) {
- return "translate(" + x + "," + y + ")";
- };
-
- var staggerUp = 5, staggerDown = 17; //pixels to stagger by
- // Issue #140
- xTicks
- .selectAll("text")
- .attr('transform', function(d,i,j) {
- return getTranslate(0, (j % 2 == 0 ? staggerUp : staggerDown));
- });
-
- var totalInBetweenTicks = d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;
- g.selectAll(".nv-x.nv-axis .nv-axisMaxMin text")
- .attr("transform", function(d,i) {
- return getTranslate(0, (i === 0 || totalInBetweenTicks % 2 !== 0) ? staggerDown : staggerUp);
- });
- }
-
- if (reduceXTicks)
- xTicks
- .filter(function(d,i) {
- return i % Math.ceil(data[0].values.length / (availableWidth / 100)) !== 0;
- })
- .selectAll('text, line')
- .style('opacity', 0);
-
- if(rotateLabels)
- xTicks
- .selectAll('.tick text')
- .attr('transform', 'rotate(' + rotateLabels + ' 0,0)')
- .style('text-anchor', rotateLabels > 0 ? 'start' : 'end');
-
- g.select('.nv-x.nv-axis').selectAll('g.nv-axisMaxMin text')
- .style('opacity', 1);
- }
-
-
- if (showYAxis) {
- yAxis
- .scale(y)
- .ticks( availableHeight / 36 )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis').transition()
- .call(yAxis);
- }
-
-
- //------------------------------------------------------------
-
-
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- state = newState;
- dispatch.stateChange(state);
- chart.update();
- });
-
- controls.dispatch.on('legendClick', function(d,i) {
- if (!d.disabled) return;
- controlsData = controlsData.map(function(s) {
- s.disabled = true;
- return s;
- });
- d.disabled = false;
-
- switch (d.key) {
- case 'Grouped':
- multibar.stacked(false);
- break;
- case '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;
- }
-
- chart.update();
- });
-
- //============================================================
-
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // 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('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.multibar = multibar;
- chart.legend = legend;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
-
- d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'clipEdge',
- 'id', 'stacked', 'stackOffset', 'delay', 'barColor','groupSpacing');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- return chart;
- };
-
- chart.showControls = function(_) {
- if (!arguments.length) return showControls;
- showControls = _;
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.showXAxis = function(_) {
- if (!arguments.length) return showXAxis;
- showXAxis = _;
- return chart;
- };
-
- chart.showYAxis = function(_) {
- if (!arguments.length) return showYAxis;
- showYAxis = _;
- return chart;
- };
-
- chart.rightAlignYAxis = function(_) {
- if(!arguments.length) return rightAlignYAxis;
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- return chart;
- };
-
- chart.reduceXTicks= function(_) {
- if (!arguments.length) return reduceXTicks;
- reduceXTicks = _;
- return chart;
- };
-
- chart.rotateLabels = function(_) {
- if (!arguments.length) return rotateLabels;
- rotateLabels = _;
- return chart;
- }
-
- chart.staggerLabels = function(_) {
- if (!arguments.length) return staggerLabels;
- staggerLabels = _;
- return chart;
- };
-
- chart.tooltip = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.state = function(_) {
- if (!arguments.length) return state;
- state = _;
- return chart;
- };
-
- chart.defaultState = function(_) {
- if (!arguments.length) return defaultState;
- defaultState = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.transitionDuration = function(_) {
- if (!arguments.length) return transitionDuration;
- transitionDuration = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.multiBarHorizontal = 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 }
- , forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove
- , color = nv.utils.defaultColor()
- , barColor = null // adding the ability to set the color for each rather than the whole group
- , disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled
- , stacked = false
- , showValues = false
- , showBarLabels = false
- , valuePadding = 60
- , valueFormat = d3.format(',.2f')
- , delay = 1200
- , xDomain
- , yDomain
- , xRange
- , yRange
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')
- ;
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0 //used to store previous scales
- ;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom,
- container = d3.select(this);
-
-
- if (stacked)
- data = d3.layout.stack()
- .offset('zero')
- .values(function(d){ return d.values })
- .y(getY)
- (data);
-
-
- //add series index to each data point for reference
- data.forEach(function(series, i) {
- series.values.forEach(function(point) {
- point.series = i;
- });
- });
-
-
-
- //------------------------------------------------------------
- // HACK for negative value stacking
- 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 - f.size;
- negBase = negBase - f.size;
- } else
- {
- f.y1 = 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) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 }
- })
- });
-
- x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))
- .rangeBands(xRange || [0, availableHeight], .1);
-
- //y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y0 : 0) }).concat(forceY)))
- 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)))
-
- if (showValues && !stacked)
- y.range(yRange || [(y.domain()[0] < 0 ? valuePadding : 0), availableWidth - (y.domain()[1] > 0 ? valuePadding : 0) ]);
- else
- y.range(yRange || [0, availableWidth]);
-
- x0 = x0 || x;
- y0 = y0 || d3.scale.linear().domain(y.domain()).range([y(0),y(0)]);
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = d3.select(this).selectAll('g.nv-wrap.nv-multibarHorizontal').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibarHorizontal');
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-groups');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- //------------------------------------------------------------
-
-
-
- var groups = wrap.select('.nv-groups').selectAll('.nv-group')
- .data(function(d) { return d }, function(d,i) { return i });
- groups.enter().append('g')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6);
- groups.exit().transition()
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6)
- .remove();
- groups
- .attr('class', function(d,i) { return '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.transition()
- .style('stroke-opacity', 1)
- .style('fill-opacity', .75);
-
-
- var bars = groups.selectAll('g.nv-bar')
- .data(function(d) { return d.values });
-
- bars.exit().remove();
-
-
- var barsEnter = bars.enter().append('g')
- .attr('transform', function(d,i,j) {
- return 'translate(' + y0(stacked ? d.y0 : 0) + ',' + (stacked ? 0 : (j * x.rangeBand() / data.length ) + x(getX(d,i))) + ')'
- });
-
- barsEnter.append('rect')
- .attr('width', 0)
- .attr('height', x.rangeBand() / (stacked ? 1 : data.length) )
-
- bars
- .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
- });
- })
- .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
- });
- })
- .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
- });
- 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
- });
- d3.event.stopPropagation();
- });
-
-
- barsEnter.append('text');
-
- if (showValues && !stacked) {
- bars.select('text')
- .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' })
- .attr('y', x.rangeBand() / (data.length * 2))
- .attr('dy', '.32em')
- .text(function(d,i) { return valueFormat(getY(d,i)) })
- bars.transition()
- .select('text')
- .attr('x', function(d,i) { return getY(d,i) < 0 ? -4 : y(getY(d,i)) - y(0) + 4 })
- } else {
- bars.selectAll('text').text('');
- }
-
- if (showBarLabels && !stacked) {
- barsEnter.append('text').classed('nv-bar-label',true);
- bars.select('text.nv-bar-label')
- .attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'start' : 'end' })
- .attr('y', x.rangeBand() / (data.length * 2))
- .attr('dy', '.32em')
- .text(function(d,i) { return getX(d,i) });
- bars.transition()
- .select('text.nv-bar-label')
- .attr('x', function(d,i) { return getY(d,i) < 0 ? y(0) - y(getY(d,i)) + 4 : -4 });
- }
- else {
- bars.selectAll('text.nv-bar-label').text('');
- }
-
- bars
- .attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})
-
- if (barColor) {
- if (!disabled) disabled = data.map(function() { return true });
- bars
- .style('fill', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); })
- .style('stroke', function(d,i,j) { return d3.rgb(barColor(d,i)).darker( disabled.map(function(d,i) { return i }).filter(function(d,i){ return !disabled[i] })[j] ).toString(); });
- }
-
- if (stacked)
- bars.transition()
- .attr('transform', function(d,i) {
- return 'translate(' + y(d.y1) + ',' + x(getX(d,i)) + ')'
- })
- .select('rect')
- .attr('width', function(d,i) {
- return Math.abs(y(getY(d,i) + d.y0) - y(d.y0))
- })
- .attr('height', x.rangeBand() );
- else
- bars.transition()
- .attr('transform', function(d,i) {
- //TODO: stacked must be all positive or all negative, not both?
- return 'translate(' +
- (getY(d,i) < 0 ? y(getY(d,i)) : y(0))
- + ',' +
- (d.series * x.rangeBand() / data.length
- +
- x(getX(d,i)) )
- + ')'
- })
- .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)
- });
-
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = _;
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = _;
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.xScale = function(_) {
- if (!arguments.length) return x;
- x = _;
- return chart;
- };
-
- chart.yScale = function(_) {
- if (!arguments.length) return y;
- y = _;
- return chart;
- };
-
- chart.xDomain = function(_) {
- if (!arguments.length) return xDomain;
- xDomain = _;
- return chart;
- };
-
- chart.yDomain = function(_) {
- if (!arguments.length) return yDomain;
- yDomain = _;
- return chart;
- };
-
- chart.xRange = function(_) {
- if (!arguments.length) return xRange;
- xRange = _;
- return chart;
- };
-
- chart.yRange = function(_) {
- if (!arguments.length) return yRange;
- yRange = _;
- return chart;
- };
-
- chart.forceY = function(_) {
- if (!arguments.length) return forceY;
- forceY = _;
- return chart;
- };
-
- chart.stacked = function(_) {
- if (!arguments.length) return stacked;
- stacked = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- chart.barColor = function(_) {
- if (!arguments.length) return barColor;
- barColor = nv.utils.getColor(_);
- return chart;
- };
-
- chart.disabled = function(_) {
- if (!arguments.length) return disabled;
- disabled = _;
- return chart;
- };
-
- chart.id = function(_) {
- if (!arguments.length) return id;
- id = _;
- return chart;
- };
-
- chart.delay = function(_) {
- if (!arguments.length) return delay;
- delay = _;
- return chart;
- };
-
- chart.showValues = function(_) {
- if (!arguments.length) return showValues;
- showValues = _;
- return chart;
- };
-
- chart.showBarLabels = function(_) {
- if (!arguments.length) return showBarLabels;
- showBarLabels = _;
- return chart;
- };
-
-
- chart.valueFormat= function(_) {
- if (!arguments.length) return valueFormat;
- valueFormat = _;
- return chart;
- };
-
- chart.valuePadding = function(_) {
- if (!arguments.length) return valuePadding;
- valuePadding = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.multiBarHorizontalChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var multibar = nv.models.multiBarHorizontal()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend().height(30)
- , controls = nv.models.legend().height(30)
- ;
-
- var margin = {top: 30, right: 20, bottom: 50, left: 60}
- , width = null
- , height = null
- , color = nv.utils.defaultColor()
- , showControls = true
- , showLegend = true
- , 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 = { stacked: stacked }
- , defaultState = null
- , noData = 'No Data Available.'
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
- , controlWidth = function() { return showControls ? 180 : 0 }
- , transitionDuration = 250
- ;
-
- multibar
- .stacked(stacked)
- ;
- xAxis
- .orient('left')
- .tickPadding(5)
- .highlightZero(false)
- .showMaxMin(false)
- .tickFormat(function(d) { return d })
- ;
- yAxis
- .orient('bottom')
- .tickFormat(d3.format(',.1f'))
- ;
-
- 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);
- };
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- 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;
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart) };
- chart.container = this;
-
- //set state.disabled
- 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 + availableHeight / 2)
- .text(function(d) { return d });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = multibar.xScale();
- y = multibar.yScale();
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-multiBarHorizontalChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarHorizontalChart').append('g');
- 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');
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-controlsWrap');
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Legend
-
- 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;
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Controls
-
- if (showControls) {
- var controlsData = [
- { key: 'Grouped', disabled: multibar.stacked() },
- { key: 'Stacked', disabled: !multibar.stacked() }
- ];
-
- controls.width(controlWidth()).color(['#444', '#444', '#444']);
- g.select('.nv-controlsWrap')
- .datum(controlsData)
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- .call(controls);
- }
-
- //------------------------------------------------------------
-
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
- multibar
- .disabled(data.map(function(series) { return series.disabled }))
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }))
-
-
- var barsWrap = g.select('.nv-barsWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
-
- barsWrap.transition().call(multibar);
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Axes
-
- if (showXAxis) {
- xAxis
- .scale(x)
- .ticks( availableHeight / 24 )
- .tickSize(-availableWidth, 0);
-
- g.select('.nv-x.nv-axis').transition()
- .call(xAxis);
-
- var xTicks = g.select('.nv-x.nv-axis').selectAll('g');
-
- xTicks
- .selectAll('line, text');
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- .ticks( availableWidth / 100 )
- .tickSize( -availableHeight, 0);
-
- g.select('.nv-y.nv-axis')
- .attr('transform', 'translate(0,' + availableHeight + ')');
- g.select('.nv-y.nv-axis').transition()
- .call(yAxis);
- }
-
- // Zero line
- g.select(".nv-zeroLine line")
- .attr("x1", y(0))
- .attr("x2", y(0))
- .attr("y1", 0)
- .attr("y2", -availableHeight)
- ;
-
- //------------------------------------------------------------
-
-
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- legend.dispatch.on('stateChange', function(newState) {
- state = newState;
- dispatch.stateChange(state);
- chart.update();
- });
-
- controls.dispatch.on('legendClick', function(d,i) {
- if (!d.disabled) return;
- controlsData = controlsData.map(function(s) {
- s.disabled = true;
- return s;
- });
- d.disabled = false;
-
- switch (d.key) {
- case 'Grouped':
- multibar.stacked(false);
- break;
- case '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;
- }
-
- chart.update();
- });
- //============================================================
-
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // 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('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.multibar = multibar;
- chart.legend = legend;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
-
- d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY',
- 'clipEdge', 'id', 'delay', 'showValues','showBarLabels', 'valueFormat', 'stacked', 'barColor');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- return chart;
- };
-
- chart.showControls = function(_) {
- if (!arguments.length) return showControls;
- showControls = _;
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.showXAxis = function(_) {
- if (!arguments.length) return showXAxis;
- showXAxis = _;
- return chart;
- };
-
- chart.showYAxis = function(_) {
- if (!arguments.length) return showYAxis;
- showYAxis = _;
- return chart;
- };
-
- chart.tooltip = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.state = function(_) {
- if (!arguments.length) return state;
- state = _;
- return chart;
- };
-
- chart.defaultState = function(_) {
- if (!arguments.length) return defaultState;
- defaultState = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.transitionDuration = function(_) {
- if (!arguments.length) return transitionDuration;
- transitionDuration = _;
- return chart;
- };
- //============================================================
-
-
- return chart;
-}
-nv.models.multiChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 30, right: 20, bottom: 50, left: 60},
- color = d3.scale.category20().range(),
- width = null,
- height = null,
- showLegend = true,
- tooltips = true,
- tooltip = function(key, x, y, e, graph) {
- return '
' + key + ' ' +
- '
' + y + ' at ' + x + '
'
- },
- x,
- y,
- yDomain1,
- yDomain2
- ; //can be accessed via chart.lines.[x/y]Scale()
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x = d3.scale.linear(),
- yScale1 = d3.scale.linear(),
- yScale2 = d3.scale.linear(),
-
- lines1 = nv.models.line().yScale(yScale1),
- lines2 = nv.models.line().yScale(yScale2),
-
- bars1 = nv.models.multiBar().stacked(false).yScale(yScale1),
- bars2 = nv.models.multiBar().stacked(false).yScale(yScale2),
-
- stack1 = nv.models.stackedArea().yScale(yScale1),
- stack2 = nv.models.stackedArea().yScale(yScale2),
-
- xAxis = nv.models.axis().scale(x).orient('bottom').tickPadding(5),
- yAxis1 = nv.models.axis().scale(yScale1).orient('left'),
- 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);
- };
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- that = this;
-
- 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 dataLines1 = data.filter(function(d) {return !d.disabled && d.type == 'line' && d.yAxis == 1})
- var dataLines2 = data.filter(function(d) {return !d.disabled && d.type == 'line' && d.yAxis == 2})
- var dataBars1 = data.filter(function(d) {return !d.disabled && d.type == 'bar' && d.yAxis == 1})
- var dataBars2 = data.filter(function(d) {return !d.disabled && d.type == 'bar' && d.yAxis == 2})
- var dataStack1 = data.filter(function(d) {return !d.disabled && d.type == 'area' && d.yAxis == 1})
- var dataStack2 = data.filter(function(d) {return !d.disabled && d.type == 'area' && d.yAxis == 2})
-
- 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 }
- })
- })
-
- 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 }
- })
- })
-
- x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))
- .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', 'lines1Wrap');
- gEnter.append('g').attr('class', 'lines2Wrap');
- gEnter.append('g').attr('class', 'bars1Wrap');
- gEnter.append('g').attr('class', 'bars2Wrap');
- gEnter.append('g').attr('class', 'stack1Wrap');
- gEnter.append('g').attr('class', 'stack2Wrap');
- gEnter.append('g').attr('class', 'legendWrap');
-
- var g = wrap.select('g');
-
- if (showLegend) {
- legend.width( availableWidth / 2 );
-
- g.select('.legendWrap')
- .datum(data.map(function(series) {
- series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;
- series.key = series.originalKey + (series.yAxis == 1 ? '' : ' (right axis)');
- return series;
- }))
- .call(legend);
-
- if ( margin.top != legend.height()) {
- margin.top = legend.height();
- availableHeight = (height || parseInt(container.style('height')) || 400)
- - margin.top - margin.bottom;
- }
-
- g.select('.legendWrap')
- .attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')');
- }
-
-
- lines1
- .width(availableWidth)
- .height(availableHeight)
- .interpolate("monotone")
- .color(data.map(function(d,i) {
- return d.color || color[i % color.length];
- }).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'line'}));
-
- lines2
- .width(availableWidth)
- .height(availableHeight)
- .interpolate("monotone")
- .color(data.map(function(d,i) {
- return d.color || color[i % color.length];
- }).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'line'}));
-
- bars1
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color[i % color.length];
- }).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'bar'}));
-
- bars2
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color[i % color.length];
- }).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'bar'}));
-
- stack1
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color[i % color.length];
- }).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'area'}));
-
- stack2
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color[i % color.length];
- }).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'area'}));
-
- g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
-
- var lines1Wrap = g.select('.lines1Wrap')
- .datum(dataLines1)
- var bars1Wrap = g.select('.bars1Wrap')
- .datum(dataBars1)
- var stack1Wrap = g.select('.stack1Wrap')
- .datum(dataStack1)
-
- var lines2Wrap = g.select('.lines2Wrap')
- .datum(dataLines2)
- var bars2Wrap = g.select('.bars2Wrap')
- .datum(dataBars2)
- var stack2Wrap = g.select('.stack2Wrap')
- .datum(dataStack2)
-
- 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}]) : []
- 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}]) : []
-
- yScale1 .domain(yDomain1 || d3.extent(d3.merge(series1).concat(extraValue1), function(d) { return d.y } ))
- .range([0, availableHeight])
-
- yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(extraValue2), function(d) { return d.y } ))
- .range([0, availableHeight])
-
- lines1.yDomain(yScale1.domain())
- bars1.yDomain(yScale1.domain())
- stack1.yDomain(yScale1.domain())
-
- lines2.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);}
-
- if(dataBars1.length){d3.transition(bars1Wrap).call(bars1);}
- if(dataBars2.length){d3.transition(bars2Wrap).call(bars2);}
-
- if(dataLines1.length){d3.transition(lines1Wrap).call(lines1);}
- if(dataLines2.length){d3.transition(lines2Wrap).call(lines2);}
-
-
-
- xAxis
- .ticks( availableWidth / 100 )
- .tickSize(-availableHeight, 0);
-
- g.select('.x.axis')
- .attr('transform', 'translate(0,' + availableHeight + ')');
- d3.transition(g.select('.x.axis'))
- .call(xAxis);
-
- yAxis1
- .ticks( availableHeight / 36 )
- .tickSize( -availableWidth, 0);
-
-
- d3.transition(g.select('.y1.axis'))
- .call(yAxis1);
-
- yAxis2
- .ticks( availableHeight / 36 )
- .tickSize( -availableWidth, 0);
-
- d3.transition(g.select('.y2.axis'))
- .call(yAxis2);
-
- g.select('.y2.axis')
- .style('opacity', series2.length ? 1 : 0)
- .attr('transform', 'translate(' + x.range()[1] + ',0)');
-
- legend.dispatch.on('stateChange', function(newState) {
- 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;
- }
-
- e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top],
- dispatch.tooltipShow(e);
- });
-
- stack1.dispatch.on('tooltipHide', function(e) {
- dispatch.tooltipHide(e);
- });
-
- 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;
- }
-
- e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top],
- dispatch.tooltipShow(e);
- });
-
- stack2.dispatch.on('tooltipHide', function(e) {
- dispatch.tooltipHide(e);
- });
-
- 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);
- });
-
- dispatch.on('tooltipHide', function() {
- if (tooltips) nv.tooltip.cleanup();
- });
-
-
-
- //============================================================
- // Global getters and setters
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.lines1 = lines1;
- chart.lines2 = lines2;
- chart.bars1 = bars1;
- chart.bars2 = bars2;
- chart.stack1 = stack1;
- chart.stack2 = stack2;
- chart.xAxis = xAxis;
- chart.yAxis1 = yAxis1;
- chart.yAxis2 = yAxis2;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = _;
- lines1.x(_);
- bars1.x(_);
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = _;
- lines1.y(_);
- bars1.y(_);
- return chart;
- };
-
- chart.yDomain1 = function(_) {
- if (!arguments.length) return yDomain1;
- yDomain1 = _;
- return chart;
- };
-
- chart.yDomain2 = function(_) {
- if (!arguments.length) return yDomain2;
- yDomain2 = _;
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- margin = _;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = _;
- legend.color(_);
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- return chart;
-}
-
-
-nv.models.ohlcBar = 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.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()
- , xDomain
- , yDomain
- , xRange
- , yRange
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')
- ;
-
- //============================================================
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- //TODO: store old scales for transitions
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom,
- container = d3.select(this);
-
-
- //------------------------------------------------------------
- // 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]);
-
- 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-ohlcBar').data([data[0].values]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-ohlcBar');
- 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 ticksEnter = 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)))
- + 'l'
- + (-w/2)
- + ',0l'
- + (w/2)
- + ',0l0,'
- + (y(getLow(d,i)) - y(getOpen(d,i)))
- + 'l0,'
- + (y(getClose(d,i))
- - y(getLow(d,i)))
- + 'l'
- + (w/2)
- + ',0l'
- + (-w/2)
- + ',0z';
- })
- .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; })
- //.attr('fill', function(d,i) { return color[0]; })
- //.attr('stroke', function(d,i) { return color[0]; })
- //.attr('x', 0 )
- //.attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })
- //.attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) })
- .on('mouseover', function(d,i) {
- 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
- });
-
- })
- .on('mouseout', function(d,i) {
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- point: d,
- series: data[0],
- pointIndex: i,
- seriesIndex: 0,
- e: d3.event
- });
- })
- .on('click', function(d,i) {
- 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
- });
- d3.event.stopPropagation();
- })
- .on('dblclick', function(d,i) {
- 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
- });
- d3.event.stopPropagation();
- });
-
- ticks
- .attr('class', function(d,i,j) { return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i })
- d3.transition(ticks)
- .attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,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)))
- + 'l'
- + (-w/2)
- + ',0l'
- + (w/2)
- + ',0l0,'
- + (y(getLow(d,i))
- - y(getOpen(d,i)))
- + 'l0,'
- + (y(getClose(d,i))
- - y(getLow(d,i)))
- + 'l'
- + (w/2)
- + ',0l'
- + (-w/2)
- + ',0z';
- })
- //.attr('width', (availableWidth / data[0].values.length) * .9 )
-
-
- //d3.transition(ticks)
- //.attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })
- //.attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) });
- //.order(); // not sure if this makes any sense for this model
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = _;
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = _;
- return chart;
- };
-
- chart.open = function(_) {
- if (!arguments.length) return getOpen;
- getOpen = _;
- return chart;
- };
-
- chart.close = function(_) {
- if (!arguments.length) return getClose;
- getClose = _;
- return chart;
- };
-
- chart.high = function(_) {
- if (!arguments.length) return getHigh;
- getHigh = _;
- return chart;
- };
-
- chart.low = function(_) {
- if (!arguments.length) return getLow;
- getLow = _;
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.xScale = function(_) {
- if (!arguments.length) return x;
- x = _;
- return chart;
- };
-
- chart.yScale = function(_) {
- if (!arguments.length) return y;
- y = _;
- return chart;
- };
-
- chart.xDomain = function(_) {
- if (!arguments.length) return xDomain;
- xDomain = _;
- return chart;
- };
-
- chart.yDomain = function(_) {
- if (!arguments.length) return yDomain;
- yDomain = _;
- return chart;
- };
-
- chart.xRange = function(_) {
- if (!arguments.length) return xRange;
- xRange = _;
- return chart;
- };
-
- chart.yRange = function(_) {
- if (!arguments.length) return yRange;
- yRange = _;
- return chart;
- };
-
- chart.forceX = function(_) {
- if (!arguments.length) return forceX;
- forceX = _;
- return chart;
- };
-
- chart.forceY = function(_) {
- if (!arguments.length) return forceY;
- forceY = _;
- return chart;
- };
-
- chart.padData = function(_) {
- if (!arguments.length) return padData;
- padData = _;
- return chart;
- };
-
- chart.clipEdge = function(_) {
- if (!arguments.length) return clipEdge;
- clipEdge = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- chart.id = function(_) {
- if (!arguments.length) return id;
- id = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-nv.models.pie = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 500
- , height = 500
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , getDescription = function(d) { return d.description }
- , id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one
- , color = nv.utils.defaultColor()
- , valueFormat = d3.format(',.2f')
- , showLabels = true
- , pieLabelsOutside = true
- , donutLabelsOutside = false
- , labelType = "key"
- , labelThreshold = .02 //if slice percentage is under this, don't show label
- , donut = false
- , labelSunbeamLayout = false
- , startAngle = false
- , endAngle = false
- , donutRatio = 0.5
- , dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')
- ;
-
- //============================================================
-
-
- function chart(selection) {
- 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);
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- //var wrap = container.selectAll('.nv-wrap.nv-pie').data([data]);
- var wrap = container.selectAll('.nv-wrap.nv-pie').data(data);
- var wrapEnter = wrap.enter().append('g').attr('class','nvd3 nv-wrap nv-pie nv-chart-' + id);
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-pie');
- gEnter.append('g').attr('class', 'nv-pieLabels');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
- g.select('.nv-pie').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');
- g.select('.nv-pieLabels').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');
-
- //------------------------------------------------------------
-
-
- container
- .on('click', function(d,i) {
- dispatch.chartClick({
- data: d,
- index: i,
- pos: d3.event,
- id: id
- });
- });
-
-
- var arc = d3.svg.arc()
- .outerRadius(arcRadius);
-
- if (startAngle) arc.startAngle(startAngle)
- if (endAngle) arc.endAngle(endAngle);
- if (donut) arc.innerRadius(radius * donutRatio);
-
- // Setup the Pie chart and choose the data element
- var pie = d3.layout.pie()
- .sort(null)
- .value(function(d) { return d.disabled ? 0 : getY(d) });
-
- var slices = wrap.select('.nv-pie').selectAll('.nv-slice')
- .data(pie);
-
- var pieLabels = wrap.select('.nv-pieLabels').selectAll('.nv-label')
- .data(pie);
-
- slices.exit().remove();
- pieLabels.exit().remove();
-
- var ae = slices.enter().append('g')
- .attr('class', 'nv-slice')
- .on('mouseover', function(d,i){
- d3.select(this).classed('hover', true);
- dispatch.elementMouseover({
- label: getX(d.data),
- value: getY(d.data),
- point: d.data,
- pointIndex: i,
- pos: [d3.event.pageX, d3.event.pageY],
- id: id
- });
- })
- .on('mouseout', function(d,i){
- d3.select(this).classed('hover', false);
- dispatch.elementMouseout({
- label: getX(d.data),
- value: getY(d.data),
- point: d.data,
- index: i,
- id: id
- });
- })
- .on('click', function(d,i) {
- dispatch.elementClick({
- label: getX(d.data),
- value: getY(d.data),
- point: d.data,
- index: i,
- pos: d3.event,
- id: id
- });
- d3.event.stopPropagation();
- })
- .on('dblclick', function(d,i) {
- dispatch.elementDblClick({
- label: getX(d.data),
- value: getY(d.data),
- point: d.data,
- index: i,
- pos: d3.event,
- id: id
- });
- d3.event.stopPropagation();
- });
-
- slices
- .attr('fill', function(d,i) { return color(d, i); })
- .attr('stroke', function(d,i) { return color(d, i); });
-
- var paths = ae.append('path')
- .each(function(d) { this._current = d; });
- //.attr('d', arc);
-
- slices.select('path')
- .transition()
- .attr('d', arc)
- .attrTween('d', arcTween);
-
- if (showLabels) {
- // This does the normal label
- var labelsArc = d3.svg.arc().innerRadius(0);
-
- if (pieLabelsOutside){ labelsArc = arc; }
-
- if (donutLabelsOutside) { labelsArc = d3.svg.arc().outerRadius(arc.outerRadius()); }
-
- pieLabels.enter().append("g").classed("nv-label",true)
- .each(function(d,i) {
- var group = d3.select(this);
-
- group
- .attr('transform', function(d) {
- if (labelSunbeamLayout) {
- d.outerRadius = arcRadius + 10; // Set Outer Coordinate
- d.innerRadius = arcRadius + 15; // Set Inner Coordinate
- var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);
- if ((d.startAngle+d.endAngle)/2 < Math.PI) {
- rotateAngle -= 90;
- } else {
- rotateAngle += 90;
- }
- return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')';
- } else {
- d.outerRadius = radius + 10; // Set Outer Coordinate
- d.innerRadius = radius + 15; // Set Inner Coordinate
- return 'translate(' + labelsArc.centroid(d) + ')'
- }
- });
-
- group.append('rect')
- .style('stroke', '#fff')
- .style('fill', '#fff')
- .attr("rx", 3)
- .attr("ry", 3);
-
- 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 = {};
- var avgHeight = 14;
- var avgWidth = 140;
- var createHashKey = function(coordinates) {
-
- return Math.floor(coordinates[0]/avgWidth) * avgWidth + ',' + Math.floor(coordinates[1]/avgHeight) * avgHeight;
- };
- pieLabels.transition()
- .attr('transform', function(d) {
- if (labelSunbeamLayout) {
- d.outerRadius = arcRadius + 10; // Set Outer Coordinate
- d.innerRadius = arcRadius + 15; // Set Inner Coordinate
- var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);
- if ((d.startAngle+d.endAngle)/2 < Math.PI) {
- rotateAngle -= 90;
- } else {
- rotateAngle += 90;
- }
- return 'translate(' + labelsArc.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);
- var hashKey = createHashKey(center);
- if (labelLocationHash[hashKey]) {
- center[1] -= avgHeight;
- }
- labelLocationHash[createHashKey(center)] = true;
- return 'translate(' + center + ')'
- }
- });
- 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
- .text(function(d, i) {
- var percent = (d.endAngle - d.startAngle) / (2 * Math.PI);
- var labelTypes = {
- "key" : getX(d.data),
- "value": getY(d.data),
- "percent": d3.format('%')(percent)
- };
- return (d.value && percent > labelThreshold) ? labelTypes[labelType] : '';
- });
- }
-
-
- // Computes the angle of an arc, converting from radians to degrees.
- function angle(d) {
- var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
- return a > 90 ? a - 180 : a;
- }
-
- function arcTween(a) {
- 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));
- };
- }
-
- function tweenPie(b) {
- b.innerRadius = 0;
- var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
- return function(t) {
- return arc(i(t));
- };
- }
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.values = function(_) {
- nv.log("pie.values() is no longer supported.");
- return chart;
- };
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = _;
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = d3.functor(_);
- return chart;
- };
-
- chart.description = function(_) {
- if (!arguments.length) return getDescription;
- getDescription = _;
- return chart;
- };
-
- chart.showLabels = function(_) {
- if (!arguments.length) return showLabels;
- showLabels = _;
- return chart;
- };
-
- chart.labelSunbeamLayout = function(_) {
- if (!arguments.length) return labelSunbeamLayout;
- labelSunbeamLayout = _;
- return chart;
- };
-
- chart.donutLabelsOutside = function(_) {
- if (!arguments.length) return donutLabelsOutside;
- donutLabelsOutside = _;
- return chart;
- };
-
- chart.pieLabelsOutside = function(_) {
- if (!arguments.length) return pieLabelsOutside;
- pieLabelsOutside = _;
- return chart;
- };
-
- chart.labelType = function(_) {
- if (!arguments.length) return labelType;
- labelType = _;
- labelType = labelType || "key";
- return chart;
- };
-
- chart.donut = function(_) {
- if (!arguments.length) return donut;
- donut = _;
- return chart;
- };
-
- chart.donutRatio = function(_) {
- if (!arguments.length) return donutRatio;
- donutRatio = _;
- return chart;
- };
-
- chart.startAngle = function(_) {
- if (!arguments.length) return startAngle;
- startAngle = _;
- return chart;
- };
-
- chart.endAngle = function(_) {
- if (!arguments.length) return endAngle;
- endAngle = _;
- return chart;
- };
-
- chart.id = function(_) {
- if (!arguments.length) return id;
- id = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- chart.valueFormat = function(_) {
- if (!arguments.length) return valueFormat;
- valueFormat = _;
- return chart;
- };
-
- chart.labelThreshold = function(_) {
- if (!arguments.length) return labelThreshold;
- labelThreshold = _;
- return chart;
- };
- //============================================================
-
-
- return chart;
-}
-nv.models.pieChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var pie = nv.models.pie()
- , legend = nv.models.legend()
- ;
-
- var margin = {top: 30, right: 20, bottom: 20, left: 20}
- , width = null
- , height = null
- , showLegend = true
- , color = nv.utils.defaultColor()
- , tooltips = true
- , tooltip = function(key, y, e, graph) {
- return '
' + key + ' ' +
- '
' + y + '
'
- }
- , state = {}
- , defaultState = null
- , noData = "No Data Available."
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
- ;
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var showTooltip = function(e, offsetElement) {
- var tooltipLabel = pie.description()(e.point) || 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);
- };
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- 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;
-
- chart.update = function() { container.transition().call(chart); };
- chart.container = this;
-
- //set state.disabled
- 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) {
- 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 containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-pieChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-pieChart').append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-pieWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // 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;
- }
-
- wrap.select('.nv-legendWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')');
- }
-
- //------------------------------------------------------------
-
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
- pie
- .width(availableWidth)
- .height(availableHeight);
-
-
- 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) {
- state = newState;
- dispatch.stateChange(state);
- 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') {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
-
- state.disabled = e.disabled;
- }
-
- chart.update();
- });
-
- //============================================================
-
-
- });
-
- return chart;
- }
-
- //============================================================
- // 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);
- });
-
- dispatch.on('tooltipShow', function(e) {
- if (tooltips) showTooltip(e);
- });
-
- dispatch.on('tooltipHide', function() {
- if (tooltips) nv.tooltip.cleanup();
- });
-
- //============================================================
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.legend = legend;
- chart.dispatch = dispatch;
- chart.pie = pie;
-
- d3.rebind(chart, pie, 'valueFormat', 'values', 'x', 'y', 'description', 'id', 'showLabels', 'donutLabelsOutside', 'pieLabelsOutside', 'labelType', 'donut', 'donutRatio', 'labelThreshold');
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- pie.color(color);
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.state = function(_) {
- if (!arguments.length) return state;
- state = _;
- return chart;
- };
-
- chart.defaultState = function(_) {
- if (!arguments.length) return defaultState;
- defaultState = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.scatter = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , height = 500
- , color = nv.utils.defaultColor() // chooses color
- , id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one
- , x = d3.scale.linear()
- , y = d3.scale.linear()
- , z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area
- , getX = function(d) { return d.x } // accessor to get the x value
- , getY = function(d) { return d.y } // accessor to get the y value
- , getSize = function(d) { return d.size || 1} // accessor to get the point size
- , getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape
- , onlyCircles = true // Set to false to use shapes
- , forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)
- , forceY = [] // List of numbers to Force into the Y scale
- , forceSize = [] // List of numbers to Force into the Size scale
- , interactive = true // If true, plots a voronoi overlay for advanced point intersection
- , pointKey = null
- , pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out
- , padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart
- , 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
- , 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
- , xRange = null // Override x range
- , yRange = null // Override y range
- , sizeDomain = null // Override point size domain
- , sizeRange = null
- , singlePoint = false
- , dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout')
- , useVoronoi = true
- ;
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0, z0 // used to store previous scales
- , timeoutID
- , needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips
- ;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom,
- container = d3.select(this);
-
- //add series index to each data point for reference
- data.forEach(function(series, i) {
- series.values.forEach(function(point) {
- point.series = i;
- });
- });
-
- //------------------------------------------------------------
- // Setup Scales
-
- // remap and flatten the data for use in calculating the scales' domains
- var seriesData = (xDomain && yDomain && sizeDomain) ? [] : // if we know xDomain and yDomain and sizeDomain, no need to calculate.... if Size is constant remember to set sizeDomain to speed up performance
- d3.merge(
- data.map(function(d) {
- return d.values.map(function(d,i) {
- return { x: getX(d,i), y: getY(d,i), size: getSize(d,i) }
- })
- })
- );
-
- x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x; }).concat(forceX)))
-
- if (padData && data[0])
- x.range(xRange || [(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]);
- //x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);
- else
- x.range(xRange || [0, availableWidth]);
-
- y .domain(yDomain || d3.extent(seriesData.map(function(d) { return d.y }).concat(forceY)))
- .range(yRange || [availableHeight, 0]);
-
- z .domain(sizeDomain || d3.extent(seriesData.map(function(d) { return d.size }).concat(forceSize)))
- .range(sizeRange || [16, 256]);
-
- // 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;
- 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]);
-
- if ( isNaN(x.domain()[0])) {
- x.domain([-1,1]);
- }
-
- if ( isNaN(y.domain()[0])) {
- y.domain([-1,1]);
- }
-
-
- x0 = x0 || x;
- y0 = y0 || y;
- z0 = z0 || z;
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // 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 defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-groups');
- gEnter.append('g').attr('class', 'nv-point-paths');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- //------------------------------------------------------------
-
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-edge-clip-' + id)
- .append('rect');
-
- wrap.select('#nv-edge-clip-' + id + ' rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
-
-
- function updateInteractiveLayer() {
-
- 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
- if (useVoronoi === true) {
-
- if (clipVoronoi) {
- var pointClipsEnter = wrap.select('defs').selectAll('.nv-point-clips')
- .data([id])
- .enter();
-
- pointClipsEnter.append('clipPath')
- .attr('class', 'nv-point-clips')
- .attr('id', 'nv-points-clip-' + id);
-
- var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')
- .data(vertices);
- pointClips.enter().append('circle')
- .attr('r', clipRadius);
- pointClips.exit().remove();
- pointClips
- .attr('cx', function(d) { return d[0] })
- .attr('cy', function(d) { return d[1] });
-
- wrap.select('.nv-point-paths')
- .attr('clip-path', 'url(#nv-points-clip-' + id + ')');
- }
-
-
- if(vertices.length) {
- // 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]);
- vertices.push([x.range()[0] - 20, y.range()[0] + 20, null, null]);
- vertices.push([x.range()[1] + 20, y.range()[1] - 20, null, null]);
- }
-
- var bounds = d3.geom.polygon([
- [-10,-10],
- [-10,height + 10],
- [width + 10,height + 10],
- [width + 10,-10]
- ]);
-
- var voronoi = d3.geom.voronoi(vertices).map(function(d, i) {
- return {
- 'data': bounds.clip(d),
- 'series': vertices[i][2],
- 'point': vertices[i][3]
- }
- });
-
-
- var pointPaths = wrap.select('.nv-point-paths').selectAll('path')
- .data(voronoi);
- pointPaths.enter().append('path')
- .attr('class', function(d,i) { return 'nv-path-'+i; });
- pointPaths.exit().remove();
- pointPaths
- .attr('d', function(d) {
- if (d.data.length === 0)
- return 'M 0 0'
- else
- return 'M' + d.data.join('L') + 'Z';
- });
-
- var mouseEventCallback = function(d,mDispatch) {
- if (needsUpdate) return 0;
- var series = data[d.series];
- if (typeof series === 'undefined') return;
-
- var point = series.values[d.point];
-
- mDispatch({
- point: point,
- series: series,
- pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],
- seriesIndex: d.series,
- pointIndex: d.point
- });
- };
-
- pointPaths
- .on('click', function(d) {
- mouseEventCallback(d, dispatch.elementClick);
- })
- .on('mouseover', function(d) {
- mouseEventCallback(d, dispatch.elementMouseover);
- })
- .on('mouseout', function(d, i) {
- mouseEventCallback(d, dispatch.elementMouseout);
- });
-
-
- } 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')
- //.data(dataWithPoints)
- //.style('pointer-events', 'auto') // recativate events, disabled by css
- .on('click', function(d,i) {
- //nv.log('test', 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.elementClick({
- point: point,
- series: series,
- pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
- seriesIndex: d.series,
- pointIndex: i
- });
- })
- .on('mouseover', 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.elementMouseover({
- point: point,
- series: series,
- pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],
- seriesIndex: d.series,
- pointIndex: i
- });
- })
- .on('mouseout', 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.elementMouseout({
- point: point,
- series: series,
- seriesIndex: d.series,
- pointIndex: i
- });
- });
- }
-
- needsUpdate = false;
- }
-
- needsUpdate = true;
-
- var groups = wrap.select('.nv-groups').selectAll('.nv-group')
- .data(function(d) { return d }, function(d) { return d.key });
- groups.enter().append('g')
- .style('stroke-opacity', 1e-6)
- .style('fill-opacity', 1e-6);
- groups.exit()
- .remove();
- groups
- .attr('class', function(d,i) { return 'nv-group nv-series-' + i })
- .classed('hover', function(d) { return d.hover });
- groups
- .transition()
- .style('fill', function(d,i) { return color(d, i) })
- .style('stroke', function(d,i) { return color(d, i) })
- .style('stroke-opacity', 1)
- .style('fill-opacity', .5);
-
-
- if (onlyCircles) {
-
- var points = groups.selectAll('circle.nv-point')
- .data(function(d) { return d.values }, pointKey);
- points.enter().append('circle')
- .style('fill', function (d,i) { return d.color })
- .style('stroke', function (d,i) { return d.color })
- .attr('cx', function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })
- .attr('cy', function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })
- .attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
- points.exit().remove();
- groups.exit().selectAll('path.nv-point').transition()
- .attr('cx', function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
- .attr('cy', function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
- .remove();
- points.each(function(d,i) {
- d3.select(this)
- .classed('nv-point', true)
- .classed('nv-point-' + i, true)
- .classed('hover',false)
- ;
- });
- points.transition()
- .attr('cx', function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })
- .attr('cy', function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })
- .attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });
-
- } else {
-
- var points = groups.selectAll('path.nv-point')
- .data(function(d) { return d.values });
- 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)) + ')'
- })
- .attr('d',
- d3.svg.symbol()
- .type(getShape)
- .size(function(d,i) { return z(getSize(d,i)) })
- );
- points.exit().remove();
- groups.exit().selectAll('path.nv-point')
- .transition()
- .attr('transform', function(d,i) {
- return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'
- })
- .remove();
- points.each(function(d,i) {
- d3.select(this)
- .classed('nv-point', true)
- .classed('nv-point-' + i, true)
- .classed('hover',false)
- ;
- });
- points.transition()
- .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('d',
- d3.svg.symbol()
- .type(getShape)
- .size(function(d,i) { return z(getSize(d,i)) })
- );
- }
-
-
- // Delay updating the invisible interactive layer for smoother animation
- clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer
- timeoutID = setTimeout(updateInteractiveLayer, 300);
- //updateInteractiveLayer();
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
- z0 = z.copy();
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
- chart.clearHighlights = function() {
- //Remove the 'hover' class from all highlighted points.
- d3.selectAll(".nv-chart-" + id + " .nv-point.hover").classed("hover",false);
- };
-
- chart.highlightPoint = function(seriesIndex,pointIndex,isHoverOver) {
- d3.select(".nv-chart-" + id + " .nv-series-" + seriesIndex + " .nv-point-" + pointIndex)
- .classed("hover",isHoverOver);
- };
-
-
- dispatch.on('elementMouseover.point', function(d) {
- if (interactive) chart.highlightPoint(d.seriesIndex,d.pointIndex,true);
- });
-
- dispatch.on('elementMouseout.point', function(d) {
- if (interactive) chart.highlightPoint(d.seriesIndex,d.pointIndex,false);
- });
-
- //============================================================
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = d3.functor(_);
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = d3.functor(_);
- return chart;
- };
-
- chart.size = function(_) {
- if (!arguments.length) return getSize;
- getSize = d3.functor(_);
- return chart;
- };
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.xScale = function(_) {
- if (!arguments.length) return x;
- x = _;
- return chart;
- };
-
- chart.yScale = function(_) {
- if (!arguments.length) return y;
- y = _;
- return chart;
- };
-
- chart.zScale = function(_) {
- if (!arguments.length) return z;
- z = _;
- return chart;
- };
-
- chart.xDomain = function(_) {
- if (!arguments.length) return xDomain;
- xDomain = _;
- return chart;
- };
-
- chart.yDomain = function(_) {
- if (!arguments.length) return yDomain;
- yDomain = _;
- return chart;
- };
-
- chart.sizeDomain = function(_) {
- if (!arguments.length) return sizeDomain;
- sizeDomain = _;
- return chart;
- };
-
- chart.xRange = function(_) {
- if (!arguments.length) return xRange;
- xRange = _;
- return chart;
- };
-
- chart.yRange = function(_) {
- if (!arguments.length) return yRange;
- yRange = _;
- return chart;
- };
-
- chart.sizeRange = function(_) {
- if (!arguments.length) return sizeRange;
- sizeRange = _;
- return chart;
- };
-
- chart.forceX = function(_) {
- if (!arguments.length) return forceX;
- forceX = _;
- return chart;
- };
-
- chart.forceY = function(_) {
- if (!arguments.length) return forceY;
- forceY = _;
- return chart;
- };
-
- chart.forceSize = function(_) {
- if (!arguments.length) return forceSize;
- forceSize = _;
- return chart;
- };
-
- chart.interactive = function(_) {
- if (!arguments.length) return interactive;
- interactive = _;
- return chart;
- };
-
- chart.pointKey = function(_) {
- if (!arguments.length) return pointKey;
- pointKey = _;
- return chart;
- };
-
- chart.pointActive = function(_) {
- if (!arguments.length) return pointActive;
- pointActive = _;
- return chart;
- };
-
- chart.padData = function(_) {
- if (!arguments.length) return padData;
- padData = _;
- return chart;
- };
-
- chart.padDataOuter = function(_) {
- if (!arguments.length) return padDataOuter;
- padDataOuter = _;
- return chart;
- };
-
- chart.clipEdge = function(_) {
- if (!arguments.length) return clipEdge;
- clipEdge = _;
- return chart;
- };
-
- chart.clipVoronoi= function(_) {
- if (!arguments.length) return clipVoronoi;
- clipVoronoi = _;
- return chart;
- };
-
- chart.useVoronoi= function(_) {
- if (!arguments.length) return useVoronoi;
- useVoronoi = _;
- if (useVoronoi === false) {
- clipVoronoi = false;
- }
- return chart;
- };
-
- chart.clipRadius = function(_) {
- if (!arguments.length) return clipRadius;
- clipRadius = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- chart.shape = function(_) {
- if (!arguments.length) return getShape;
- getShape = _;
- return chart;
- };
-
- chart.onlyCircles = function(_) {
- if (!arguments.length) return onlyCircles;
- onlyCircles = _;
- return chart;
- };
-
- chart.id = function(_) {
- if (!arguments.length) return id;
- id = _;
- return chart;
- };
-
- chart.singlePoint = function(_) {
- if (!arguments.length) return singlePoint;
- singlePoint = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-nv.models.scatterChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var scatter = nv.models.scatter()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , controls = nv.models.legend()
- , distX = nv.models.distribution()
- , distY = nv.models.distribution()
- ;
-
- var margin = {top: 30, right: 20, bottom: 50, left: 75}
- , width = null
- , height = null
- , color = nv.utils.defaultColor()
- , x = d3.fisheye ? d3.fisheye.scale(d3.scale.linear).distortion(0) : scatter.xScale()
- , y = d3.fisheye ? d3.fisheye.scale(d3.scale.linear).distortion(0) : scatter.yScale()
- , xPadding = 0
- , yPadding = 0
- , showDistX = false
- , showDistY = false
- , showLegend = true
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , showControls = !!d3.fisheye
- , fisheye = 0
- , pauseFisheye = false
- , tooltips = true
- , tooltipX = function(key, x, y) { return '
' + x + ' ' }
- , tooltipY = function(key, x, y) { return '
' + y + ' ' }
- , tooltip = null
- , state = {}
- , defaultState = null
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
- , noData = "No Data Available."
- , transitionDuration = 250
- ;
-
- scatter
- .xScale(x)
- .yScale(y)
- ;
- xAxis
- .orient('bottom')
- .tickPadding(10)
- ;
- yAxis
- .orient((rightAlignYAxis) ? 'right' : 'left')
- .tickPadding(10)
- ;
- distX
- .axis('x')
- ;
- distY
- .axis('y')
- ;
-
- controls.updateState(false);
-
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0;
-
- 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, chart), e.value < 0 ? 'n' : 's', null, offsetElement);
- };
-
- var controlsData = [
- { key: 'Magnify', disabled: true }
- ];
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- 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;
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart); };
- chart.container = this;
-
- //set state.disabled
- 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 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 });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x0 = x0 || x;
- y0 = y0 || y;
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id());
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- // background for pointer events
- gEnter.append('rect').attr('class', 'nvd3 nv-background');
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-scatterWrap');
- gEnter.append('g').attr('class', 'nv-distWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-controlsWrap');
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Legend
-
- if (showLegend) {
- var legendWidth = (showControls) ? availableWidth / 2 : availableWidth;
- legend.width(legendWidth);
-
- 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;
- }
-
- wrap.select('.nv-legendWrap')
- .attr('transform', 'translate(' + (availableWidth - legendWidth) + ',' + (-margin.top) +')');
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Controls
-
- if (showControls) {
- controls.width(180).color(['#444']);
- g.select('.nv-controlsWrap')
- .datum(controlsData)
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- .call(controls);
- }
-
- //------------------------------------------------------------
-
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
- scatter
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
-
- if (xPadding !== 0)
- scatter.xDomain(null);
-
- if (yPadding !== 0)
- scatter.yDomain(null);
-
- wrap.select('.nv-scatterWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(scatter);
-
- //Adjust for x and y padding
- if (xPadding !== 0) {
- var xRange = x.domain()[1] - x.domain()[0];
- scatter.xDomain([x.domain()[0] - (xPadding * xRange), x.domain()[1] + (xPadding * xRange)]);
- }
-
- if (yPadding !== 0) {
- var yRange = y.domain()[1] - y.domain()[0];
- scatter.yDomain([y.domain()[0] - (yPadding * yRange), y.domain()[1] + (yPadding * yRange)]);
- }
-
- //Only need to update the scatter again if x/yPadding changed the domain.
- if (yPadding !== 0 || xPadding !== 0) {
- wrap.select('.nv-scatterWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(scatter);
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Axes
- if (showXAxis) {
- xAxis
- .scale(x)
- .ticks( xAxis.ticks() && xAxis.ticks().length ? xAxis.ticks() : availableWidth / 100 )
- .tickSize( -availableHeight , 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')')
- .call(xAxis);
-
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- .ticks( yAxis.ticks() && yAxis.ticks().length ? yAxis.ticks() : availableHeight / 36 )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis')
- .call(yAxis);
- }
-
-
- if (showDistX) {
- distX
- .getData(scatter.x())
- .scale(x)
- .width(availableWidth)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
- gEnter.select('.nv-distWrap').append('g')
- .attr('class', 'nv-distributionX');
- g.select('.nv-distributionX')
- .attr('transform', 'translate(0,' + y.range()[0] + ')')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(distX);
- }
-
- if (showDistY) {
- distY
- .getData(scatter.y())
- .scale(y)
- .width(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
- gEnter.select('.nv-distWrap').append('g')
- .attr('class', 'nv-distributionY');
- g.select('.nv-distributionY')
- .attr('transform',
- 'translate(' + (rightAlignYAxis ? availableWidth : -distY.size() ) + ',0)')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(distY);
- }
-
- //------------------------------------------------------------
-
-
-
-
- if (d3.fisheye) {
- g.select('.nv-background')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- g.select('.nv-background').on('mousemove', updateFisheye);
- g.select('.nv-background').on('click', function() { pauseFisheye = !pauseFisheye;});
- scatter.dispatch.on('elementClick.freezeFisheye', function() {
- pauseFisheye = !pauseFisheye;
- });
- }
-
-
- function updateFisheye() {
- if (pauseFisheye) {
- g.select('.nv-point-paths').style('pointer-events', 'all');
- return false;
- }
-
- g.select('.nv-point-paths').style('pointer-events', 'none' );
-
- var mouse = d3.mouse(this);
- x.distortion(fisheye).focus(mouse[0]);
- y.distortion(fisheye).focus(mouse[1]);
-
- g.select('.nv-scatterWrap')
- .call(scatter);
-
- if (showXAxis)
- g.select('.nv-x.nv-axis').call(xAxis);
-
- if (showYAxis)
- g.select('.nv-y.nv-axis').call(yAxis);
-
- g.select('.nv-distributionX')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(distX);
- g.select('.nv-distributionY')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(distY);
- }
-
-
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- controls.dispatch.on('legendClick', function(d,i) {
- d.disabled = !d.disabled;
-
- fisheye = d.disabled ? 0 : 2.5;
- g.select('.nv-background') .style('pointer-events', d.disabled ? 'none' : 'all');
- g.select('.nv-point-paths').style('pointer-events', d.disabled ? 'all' : 'none' );
-
- if (d.disabled) {
- x.distortion(fisheye).focus(0);
- y.distortion(fisheye).focus(0);
-
- g.select('.nv-scatterWrap').call(scatter);
- g.select('.nv-x.nv-axis').call(xAxis);
- g.select('.nv-y.nv-axis').call(yAxis);
- } else {
- pauseFisheye = false;
- }
-
- chart.update();
- });
-
- legend.dispatch.on('stateChange', function(newState) {
- state.disabled = newState.disabled;
- dispatch.stateChange(state);
- 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', function(d,i) { return 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();
- });
-
- //============================================================
-
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
-
-
- });
-
- 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
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.scatter = scatter;
- chart.legend = legend;
- chart.controls = controls;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.distX = distX;
- chart.distY = distY;
-
- d3.rebind(chart, scatter, 'id', 'interactive', 'pointActive', 'x', 'y', 'shape', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'xRange', 'yRange', 'sizeDomain', 'sizeRange', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'clipRadius', 'useVoronoi');
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- distX.color(color);
- distY.color(color);
- return chart;
- };
-
- chart.showDistX = function(_) {
- if (!arguments.length) return showDistX;
- showDistX = _;
- return chart;
- };
-
- chart.showDistY = function(_) {
- if (!arguments.length) return showDistY;
- showDistY = _;
- return chart;
- };
-
- chart.showControls = function(_) {
- if (!arguments.length) return showControls;
- showControls = _;
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.showXAxis = function(_) {
- if (!arguments.length) return showXAxis;
- showXAxis = _;
- return chart;
- };
-
- chart.showYAxis = function(_) {
- if (!arguments.length) return showYAxis;
- showYAxis = _;
- return chart;
- };
-
- chart.rightAlignYAxis = function(_) {
- if(!arguments.length) return rightAlignYAxis;
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- return chart;
- };
-
-
- chart.fisheye = function(_) {
- if (!arguments.length) return fisheye;
- fisheye = _;
- return chart;
- };
-
- chart.xPadding = function(_) {
- if (!arguments.length) return xPadding;
- xPadding = _;
- return chart;
- };
-
- chart.yPadding = function(_) {
- if (!arguments.length) return yPadding;
- yPadding = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.tooltipXContent = function(_) {
- if (!arguments.length) return tooltipX;
- tooltipX = _;
- return chart;
- };
-
- chart.tooltipYContent = function(_) {
- if (!arguments.length) return tooltipY;
- tooltipY = _;
- return chart;
- };
-
- chart.state = function(_) {
- if (!arguments.length) return state;
- state = _;
- return chart;
- };
-
- chart.defaultState = function(_) {
- if (!arguments.length) return defaultState;
- defaultState = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.transitionDuration = function(_) {
- if (!arguments.length) return transitionDuration;
- transitionDuration = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.scatterPlusLineChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var scatter = nv.models.scatter()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , controls = nv.models.legend()
- , distX = nv.models.distribution()
- , distY = nv.models.distribution()
- ;
-
- var margin = {top: 30, right: 20, bottom: 50, left: 75}
- , width = null
- , height = null
- , color = nv.utils.defaultColor()
- , x = d3.fisheye ? d3.fisheye.scale(d3.scale.linear).distortion(0) : scatter.xScale()
- , y = d3.fisheye ? d3.fisheye.scale(d3.scale.linear).distortion(0) : scatter.yScale()
- , showDistX = false
- , showDistY = false
- , showLegend = true
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , showControls = !!d3.fisheye
- , fisheye = 0
- , pauseFisheye = 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 = {}
- , defaultState = null
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
- , noData = "No Data Available."
- , transitionDuration = 250
- ;
-
- scatter
- .xScale(x)
- .yScale(y)
- ;
- xAxis
- .orient('bottom')
- .tickPadding(10)
- ;
- yAxis
- .orient((rightAlignYAxis) ? 'right' : 'left')
- .tickPadding(10)
- ;
- distX
- .axis('x')
- ;
- distY
- .axis('y')
- ;
-
- controls.updateState(false);
- //============================================================
-
-
- //============================================================
- // Private Variables
- //------------------------------------------------------------
-
- var x0, y0;
-
- 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 controlsData = [
- { key: 'Magnify', disabled: true }
- ];
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- 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;
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart); };
- chart.container = this;
-
- //set state.disabled
- 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 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 });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = scatter.xScale();
- y = scatter.yScale();
-
- x0 = x0 || x;
- y0 = y0 || y;
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id());
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g')
-
- // background for pointer events
- gEnter.append('rect').attr('class', 'nvd3 nv-background').style("pointer-events","none");
-
- gEnter.append('g').attr('class', 'nv-x nv-axis');
- gEnter.append('g').attr('class', 'nv-y nv-axis');
- gEnter.append('g').attr('class', 'nv-scatterWrap');
- gEnter.append('g').attr('class', 'nv-regressionLinesWrap');
- gEnter.append('g').attr('class', 'nv-distWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-controlsWrap');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Legend
-
- if (showLegend) {
- legend.width( availableWidth / 2 );
-
- 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;
- }
-
- wrap.select('.nv-legendWrap')
- .attr('transform', 'translate(' + (availableWidth / 2) + ',' + (-margin.top) +')');
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Controls
-
- if (showControls) {
- controls.width(180).color(['#444']);
- g.select('.nv-controlsWrap')
- .datum(controlsData)
- .attr('transform', 'translate(0,' + (-margin.top) +')')
- .call(controls);
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
- scatter
- .width(availableWidth)
- .height(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }))
-
- wrap.select('.nv-scatterWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(scatter);
-
- wrap.select('.nv-regressionLinesWrap')
- .attr('clip-path', 'url(#nv-edge-clip-' + scatter.id() + ')');
-
- var regWrap = wrap.select('.nv-regressionLinesWrap').selectAll('.nv-regLines')
- .data(function(d) {return d });
-
- regWrap.enter().append('g').attr('class', 'nv-regLines');
-
- var regLine = regWrap.selectAll('.nv-regLine').data(function(d){return [d]});
- var regLineEnter = regLine.enter()
- .append('line').attr('class', 'nv-regLine')
- .style('stroke-opacity', 0);
-
- regLine
- .transition()
- .attr('x1', x.range()[0])
- .attr('x2', x.range()[1])
- .attr('y1', function(d,i) {return y(x.domain()[0] * d.slope + d.intercept) })
- .attr('y2', function(d,i) { return y(x.domain()[1] * d.slope + d.intercept) })
- .style('stroke', function(d,i,j) { return color(d,j) })
- .style('stroke-opacity', function(d,i) {
- return (d.disabled || typeof d.slope === 'undefined' || typeof d.intercept === 'undefined') ? 0 : 1
- });
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Axes
-
- if (showXAxis) {
- xAxis
- .scale(x)
- .ticks( xAxis.ticks() ? xAxis.ticks() : availableWidth / 100 )
- .tickSize( -availableHeight , 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + y.range()[0] + ')')
- .call(xAxis);
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- .ticks( yAxis.ticks() ? yAxis.ticks() : availableHeight / 36 )
- .tickSize( -availableWidth, 0);
-
- g.select('.nv-y.nv-axis')
- .call(yAxis);
- }
-
-
- if (showDistX) {
- distX
- .getData(scatter.x())
- .scale(x)
- .width(availableWidth)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
- gEnter.select('.nv-distWrap').append('g')
- .attr('class', 'nv-distributionX');
- g.select('.nv-distributionX')
- .attr('transform', 'translate(0,' + y.range()[0] + ')')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(distX);
- }
-
- if (showDistY) {
- distY
- .getData(scatter.y())
- .scale(y)
- .width(availableHeight)
- .color(data.map(function(d,i) {
- return d.color || color(d, i);
- }).filter(function(d,i) { return !data[i].disabled }));
- gEnter.select('.nv-distWrap').append('g')
- .attr('class', 'nv-distributionY');
- g.select('.nv-distributionY')
- .attr('transform', 'translate(' + (rightAlignYAxis ? availableWidth : -distY.size() ) + ',0)')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(distY);
- }
-
- //------------------------------------------------------------
-
-
-
-
- if (d3.fisheye) {
- g.select('.nv-background')
- .attr('width', availableWidth)
- .attr('height', availableHeight)
- ;
-
- g.select('.nv-background').on('mousemove', updateFisheye);
- g.select('.nv-background').on('click', function() { pauseFisheye = !pauseFisheye;});
- scatter.dispatch.on('elementClick.freezeFisheye', function() {
- pauseFisheye = !pauseFisheye;
- });
- }
-
-
- function updateFisheye() {
- if (pauseFisheye) {
- g.select('.nv-point-paths').style('pointer-events', 'all');
- return false;
- }
-
- g.select('.nv-point-paths').style('pointer-events', 'none' );
-
- var mouse = d3.mouse(this);
- x.distortion(fisheye).focus(mouse[0]);
- y.distortion(fisheye).focus(mouse[1]);
-
- g.select('.nv-scatterWrap')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(scatter);
-
- if (showXAxis)
- g.select('.nv-x.nv-axis').call(xAxis);
-
- if (showYAxis)
- g.select('.nv-y.nv-axis').call(yAxis);
-
- g.select('.nv-distributionX')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(distX);
- g.select('.nv-distributionY')
- .datum(data.filter(function(d) { return !d.disabled }))
- .call(distY);
- }
-
-
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- controls.dispatch.on('legendClick', function(d,i) {
- d.disabled = !d.disabled;
-
- fisheye = d.disabled ? 0 : 2.5;
- g.select('.nv-background') .style('pointer-events', d.disabled ? 'none' : 'all');
- g.select('.nv-point-paths').style('pointer-events', d.disabled ? 'all' : 'none' );
-
- if (d.disabled) {
- x.distortion(fisheye).focus(0);
- y.distortion(fisheye).focus(0);
-
- g.select('.nv-scatterWrap').call(scatter);
- g.select('.nv-x.nv-axis').call(xAxis);
- g.select('.nv-y.nv-axis').call(yAxis);
- } else {
- pauseFisheye = false;
- }
-
- chart.update();
- });
-
- legend.dispatch.on('stateChange', function(newState) {
- state = newState;
- dispatch.stateChange(state);
- 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();
- });
-
- //============================================================
-
-
- //store old scales for use in transitions on update
- x0 = x.copy();
- y0 = y.copy();
-
-
- });
-
- 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
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.dispatch = dispatch;
- chart.scatter = scatter;
- chart.legend = legend;
- chart.controls = controls;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.distX = distX;
- chart.distY = distY;
-
- d3.rebind(chart, scatter, 'id', 'interactive', 'pointActive', 'x', 'y', 'shape', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'xRange', 'yRange', 'sizeDomain', 'sizeRange', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'clipRadius', 'useVoronoi');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- distX.color(color);
- distY.color(color);
- return chart;
- };
-
- chart.showDistX = function(_) {
- if (!arguments.length) return showDistX;
- showDistX = _;
- return chart;
- };
-
- chart.showDistY = function(_) {
- if (!arguments.length) return showDistY;
- showDistY = _;
- return chart;
- };
-
- chart.showControls = function(_) {
- if (!arguments.length) return showControls;
- showControls = _;
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.showXAxis = function(_) {
- if (!arguments.length) return showXAxis;
- showXAxis = _;
- return chart;
- };
-
- chart.showYAxis = function(_) {
- if (!arguments.length) return showYAxis;
- showYAxis = _;
- return chart;
- };
-
- chart.rightAlignYAxis = function(_) {
- if(!arguments.length) return rightAlignYAxis;
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- return chart;
- };
-
- chart.fisheye = function(_) {
- if (!arguments.length) return fisheye;
- fisheye = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.tooltipXContent = function(_) {
- if (!arguments.length) return tooltipX;
- tooltipX = _;
- return chart;
- };
-
- chart.tooltipYContent = function(_) {
- if (!arguments.length) return tooltipY;
- tooltipY = _;
- return chart;
- };
-
- chart.state = function(_) {
- if (!arguments.length) return state;
- state = _;
- return chart;
- };
-
- chart.defaultState = function(_) {
- if (!arguments.length) return defaultState;
- defaultState = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.transitionDuration = function(_) {
- if (!arguments.length) return transitionDuration;
- transitionDuration = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.sparkline = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 2, right: 0, bottom: 2, left: 0}
- , width = 400
- , height = 32
- , animate = true
- , x = d3.scale.linear()
- , y = d3.scale.linear()
- , getX = function(d) { return d.x }
- , getY = function(d) { return d.y }
- , color = nv.utils.getColor(['#000'])
- , xDomain
- , yDomain
- , xRange
- , yRange
- ;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom,
- container = d3.select(this);
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x .domain(xDomain || d3.extent(data, getX ))
- .range(xRange || [0, availableWidth]);
-
- y .domain(yDomain || d3.extent(data, getY ))
- .range(yRange || [availableHeight, 0]);
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-sparkline').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparkline');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
-
- //------------------------------------------------------------
-
-
- var paths = wrap.selectAll('path')
- .data(function(d) { return [d] });
- paths.enter().append('path');
- paths.exit().remove();
- paths
- .style('stroke', function(d,i) { return d.color || color(d, i) })
- .attr('d', d3.svg.line()
- .x(function(d,i) { return x(getX(d,i)) })
- .y(function(d,i) { return y(getY(d,i)) })
- );
-
-
- // TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent)
- var points = wrap.selectAll('circle.nv-point')
- .data(function(data) {
- var yValues = data.map(function(d, i) { return getY(d,i); });
- function pointIndex(index) {
- if (index != -1) {
- var result = data[index];
- result.pointIndex = index;
- return result;
- } else {
- return null;
- }
- }
- var maxPoint = pointIndex(yValues.lastIndexOf(y.domain()[1])),
- minPoint = pointIndex(yValues.indexOf(y.domain()[0])),
- currentPoint = pointIndex(yValues.length - 1);
- return [minPoint, maxPoint, currentPoint].filter(function (d) {return d != null;});
- });
- points.enter().append('circle');
- points.exit().remove();
- points
- .attr('cx', function(d,i) { return x(getX(d,d.pointIndex)) })
- .attr('cy', function(d,i) { return y(getY(d,d.pointIndex)) })
- .attr('r', 2)
- .attr('class', function(d,i) {
- return getX(d, d.pointIndex) == x.domain()[1] ? 'nv-point nv-currentValue' :
- getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue'
- });
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = d3.functor(_);
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = d3.functor(_);
- return chart;
- };
-
- chart.xScale = function(_) {
- if (!arguments.length) return x;
- x = _;
- return chart;
- };
-
- chart.yScale = function(_) {
- if (!arguments.length) return y;
- y = _;
- return chart;
- };
-
- chart.xDomain = function(_) {
- if (!arguments.length) return xDomain;
- xDomain = _;
- return chart;
- };
-
- chart.yDomain = function(_) {
- if (!arguments.length) return yDomain;
- yDomain = _;
- return chart;
- };
-
- chart.xRange = function(_) {
- if (!arguments.length) return xRange;
- xRange = _;
- return chart;
- };
-
- chart.yRange = function(_) {
- if (!arguments.length) return yRange;
- yRange = _;
- return chart;
- };
-
- chart.animate = function(_) {
- if (!arguments.length) return animate;
- animate = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.sparklinePlus = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var sparkline = nv.models.sparkline();
-
- var margin = {top: 15, right: 100, bottom: 10, left: 50}
- , width = null
- , height = null
- , x
- , y
- , index = []
- , paused = false
- , xTickFormat = d3.format(',r')
- , yTickFormat = d3.format(',.2f')
- , showValue = true
- , alignValue = true
- , rightAlignValue = false
- , noData = "No Data Available."
- ;
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this);
-
- 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() { chart(selection) };
- 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 });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- var currentValue = sparkline.y()(data[data.length-1], data.length-1);
-
- //------------------------------------------------------------
-
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = sparkline.xScale();
- y = sparkline.yScale();
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-sparklineplus').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparklineplus');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-sparklineWrap');
- gEnter.append('g').attr('class', 'nv-valueWrap');
- gEnter.append('g').attr('class', 'nv-hoverArea');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
- var sparklineWrap = g.select('.nv-sparklineWrap');
-
- sparkline
- .width(availableWidth)
- .height(availableHeight);
-
- sparklineWrap
- .call(sparkline);
-
- //------------------------------------------------------------
-
-
- 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));
-
-
-
- gEnter.select('.nv-hoverArea').append('rect')
- .on('mousemove', sparklineHover)
- .on('click', function() { paused = !paused })
- .on('mouseout', function() { index = []; updateValueLine(); });
- //.on('mouseout', function() { index = null; updateValueLine(); });
-
- g.select('.nv-hoverArea rect')
- .attr('transform', function(d) { return 'translate(' + -margin.left + ',' + -margin.top + ')' })
- .attr('width', availableWidth + margin.left + margin.right)
- .attr('height', availableHeight + margin.top);
-
-
-
- function updateValueLine() { //index is currently global (within the chart), may or may not keep it that way
- if (paused) return;
-
- var hoverValue = g.selectAll('.nv-hoverValue').data(index)
-
- var hoverEnter = hoverValue.enter()
- .append('g').attr('class', 'nv-hoverValue')
- .style('stroke-opacity', 0)
- .style('fill-opacity', 0);
-
- hoverValue.exit()
- .transition().duration(250)
- .style('stroke-opacity', 0)
- .style('fill-opacity', 0)
- .remove();
-
- hoverValue
- .attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' })
- .transition().duration(250)
- .style('stroke-opacity', 1)
- .style('fill-opacity', 1);
-
- if (!index.length) return;
-
- hoverEnter.append('line')
- .attr('x1', 0)
- .attr('y1', -margin.top)
- .attr('x2', 0)
- .attr('y2', availableHeight);
-
-
- hoverEnter.append('text').attr('class', 'nv-xValue')
- .attr('x', -6)
- .attr('y', -margin.top)
- .attr('text-anchor', 'end')
- .attr('dy', '.9em')
-
-
- g.select('.nv-hoverValue .nv-xValue')
- .text(xTickFormat(sparkline.x()(data[index[0]], index[0])));
-
- hoverEnter.append('text').attr('class', 'nv-yValue')
- .attr('x', 6)
- .attr('y', -margin.top)
- .attr('text-anchor', 'start')
- .attr('dy', '.9em')
-
- g.select('.nv-hoverValue .nv-yValue')
- .text(yTickFormat(sparkline.y()(data[index[0]], index[0])));
-
- }
-
-
- function sparklineHover() {
- if (paused) return;
-
- var pos = d3.mouse(this)[0] - margin.left;
-
- function getClosestIndex(data, x) {
- var distance = Math.abs(sparkline.x()(data[0], 0) - x);
- var closestIndex = 0;
- for (var i = 0; i < data.length; i++){
- if (Math.abs(sparkline.x()(data[i], i) - x) < distance) {
- distance = Math.abs(sparkline.x()(data[i], i) - x);
- closestIndex = i;
- }
- }
- return closestIndex;
- }
-
- index = [getClosestIndex(data, Math.round(x.invert(pos)))];
-
- updateValueLine();
- }
-
- });
-
- return chart;
- }
-
-
- //============================================================
- // Expose Public Variables
- //------------------------------------------------------------
-
- // expose chart's sub-components
- chart.sparkline = sparkline;
-
- d3.rebind(chart, sparkline, 'x', 'y', 'xScale', 'yScale', 'color');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.xTickFormat = function(_) {
- if (!arguments.length) return xTickFormat;
- xTickFormat = _;
- return chart;
- };
-
- chart.yTickFormat = function(_) {
- if (!arguments.length) return yTickFormat;
- yTickFormat = _;
- return chart;
- };
-
- chart.showValue = function(_) {
- if (!arguments.length) return showValue;
- showValue = _;
- return chart;
- };
-
- chart.alignValue = function(_) {
- if (!arguments.length) return alignValue;
- alignValue = _;
- return chart;
- };
-
- chart.rightAlignValue = function(_) {
- if (!arguments.length) return rightAlignValue;
- rightAlignValue = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- //============================================================
-
-
- return chart;
-}
-
-nv.models.stackedArea = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var margin = {top: 0, right: 0, bottom: 0, left: 0}
- , width = 960
- , 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
- , 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'
- , offset = 'zero'
- , order = 'default'
- , interpolate = 'linear' // controls the line interpolation
- , clipEdge = false // if true, masks lines within x and y scale
- , x //can be accessed via chart.xScale()
- , y //can be accessed via chart.yScale()
- , scatter = nv.models.scatter()
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'areaClick', 'areaMouseover', 'areaMouseout')
- ;
-
- scatter
- .size(2.2) // default size
- .sizeDomain([2.2,2.2]) // all the same size by default
- ;
-
- /************************************
- * offset:
- * 'wiggle' (stream)
- * 'zero' (stacked)
- * 'expand' (normalize to 100%)
- * 'silhouette' (simple centered)
- *
- * order:
- * 'inside-out' (stream)
- * 'default' (input order)
- ************************************/
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var availableWidth = width - margin.left - margin.right,
- availableHeight = height - margin.top - margin.bottom,
- container = d3.select(this);
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = scatter.xScale();
- y = scatter.yScale();
-
- //------------------------------------------------------------
-
- var dataRaw = data;
- // Injecting point index into each point because d3.layout.stack().out does not give index
- data.forEach(function(aseries, i) {
- aseries.seriesIndex = i;
- aseries.values = aseries.values.map(function(d, j) {
- d.index = j;
- d.seriesIndex = i;
- return d;
- });
- });
-
- var dataFiltered = data.filter(function(series) {
- return !series.disabled;
- });
-
- data = d3.layout.stack()
- .order(order)
- .offset(offset)
- .values(function(d) { return d.values }) //TODO: make values customizeable in EVERY model in this fashion
- .x(getX)
- .y(getY)
- .out(function(d, y0, y) {
- var yHeight = (getY(d) === 0) ? 0 : y;
- d.display = {
- y: yHeight,
- y0: y0
- };
- })
- (dataFiltered);
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-stackedarea').data([data]);
- var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedarea');
- var defsEnter = wrapEnter.append('defs');
- var gEnter = wrapEnter.append('g');
- var g = wrap.select('g');
-
- gEnter.append('g').attr('class', 'nv-areaWrap');
- gEnter.append('g').attr('class', 'nv-scatterWrap');
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- //------------------------------------------------------------
-
-
- scatter
- .width(availableWidth)
- .height(availableHeight)
- .x(getX)
- .y(function(d) { return d.display.y + d.display.y0 })
- .forceY([0])
- .color(data.map(function(d,i) {
- return d.color || color(d, d.seriesIndex);
- }));
-
-
- var scatterWrap = g.select('.nv-scatterWrap')
- .datum(data);
-
- scatterWrap.call(scatter);
-
- defsEnter.append('clipPath')
- .attr('id', 'nv-edge-clip-' + id)
- .append('rect');
-
- wrap.select('#nv-edge-clip-' + id + ' rect')
- .attr('width', availableWidth)
- .attr('height', availableHeight);
-
- g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');
-
- var area = d3.svg.area()
- .x(function(d,i) { return x(getX(d,i)) })
- .y0(function(d) {
- return y(d.display.y0)
- })
- .y1(function(d) {
- return y(d.display.y + d.display.y0)
- })
- .interpolate(interpolate);
-
- var zeroArea = d3.svg.area()
- .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) });
-
-
- var path = g.select('.nv-areaWrap').selectAll('path.nv-area')
- .data(function(d) { return d });
-
- path.enter().append('path').attr('class', function(d,i) { return 'nv-area nv-area-' + i })
- .attr('d', function(d,i){
- return zeroArea(d.values, d.seriesIndex);
- })
- .on('mouseover', function(d,i) {
- d3.select(this).classed('hover', true);
- dispatch.areaMouseover({
- point: d,
- series: d.key,
- pos: [d3.event.pageX, d3.event.pageY],
- seriesIndex: d.seriesIndex
- });
- })
- .on('mouseout', function(d,i) {
- d3.select(this).classed('hover', false);
- dispatch.areaMouseout({
- point: d,
- series: d.key,
- pos: [d3.event.pageX, d3.event.pageY],
- seriesIndex: d.seriesIndex
- });
- })
- .on('click', function(d,i) {
- d3.select(this).classed('hover', false);
- dispatch.areaClick({
- point: d,
- series: d.key,
- pos: [d3.event.pageX, d3.event.pageY],
- seriesIndex: d.seriesIndex
- });
- })
-
- path.exit().remove();
-
- path
- .style('fill', function(d,i){
- return d.color || color(d, d.seriesIndex)
- })
- .style('stroke', function(d,i){ return d.color || color(d, d.seriesIndex) });
- path.transition()
- .attr('d', function(d,i) {
- return area(d.values,i)
- });
-
-
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- scatter.dispatch.on('elementMouseover.area', function(e) {
- g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', true);
- });
- scatter.dispatch.on('elementMouseout.area', function(e) {
- g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', false);
- });
-
- //============================================================
- //Special offset functions
- 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.
-
- if (o) for (i = 0; i < n; i++)
- stackData[i][j][1] /= o;
- else
- for (i = 0; i < n; i++)
- stackData[i][j][1] = k;
- }
- for (j = 0; j < m; ++j) y0[j] = 0;
- return y0;
- };
-
- });
-
-
- 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
- //------------------------------------------------------------
-
- chart.dispatch = dispatch;
- chart.scatter = scatter;
-
- d3.rebind(chart, scatter, 'interactive', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'xRange', 'yRange',
- 'sizeDomain', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'useVoronoi','clipRadius','highlightPoint','clearHighlights');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.x = function(_) {
- if (!arguments.length) return getX;
- getX = d3.functor(_);
- return chart;
- };
-
- chart.y = function(_) {
- if (!arguments.length) return getY;
- getY = d3.functor(_);
- return chart;
- }
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.clipEdge = function(_) {
- if (!arguments.length) return clipEdge;
- clipEdge = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- return chart;
- };
-
- chart.offset = function(_) {
- if (!arguments.length) return offset;
- offset = _;
- return chart;
- };
-
- chart.order = function(_) {
- if (!arguments.length) return order;
- order = _;
- return chart;
- };
-
- //shortcut for offset + order
- chart.style = function(_) {
- if (!arguments.length) return style;
- style = _;
-
- switch (style) {
- case 'stack':
- chart.offset('zero');
- chart.order('default');
- break;
- case 'stream':
- chart.offset('wiggle');
- chart.order('inside-out');
- break;
- case 'stream-center':
- chart.offset('silhouette');
- chart.order('inside-out');
- break;
- case 'expand':
- chart.offset('expand');
- chart.order('default');
- break;
- case 'stack_percent':
- chart.offset(chart.d3_stackedOffset_stackPercent);
- chart.order('default');
- break;
- }
-
- return chart;
- };
-
- chart.interpolate = function(_) {
- if (!arguments.length) return interpolate;
- interpolate = _;
- return chart;
- };
- //============================================================
-
-
- return chart;
-}
-
-nv.models.stackedAreaChart = function() {
- "use strict";
- //============================================================
- // Public Variables with Default Settings
- //------------------------------------------------------------
-
- var stacked = nv.models.stackedArea()
- , xAxis = nv.models.axis()
- , yAxis = nv.models.axis()
- , legend = nv.models.legend()
- , controls = nv.models.legend()
- , interactiveLayer = nv.interactiveGuideline()
- ;
-
- var margin = {top: 30, right: 25, bottom: 50, left: 60}
- , width = null
- , height = null
- , color = nv.utils.defaultColor() // a function that takes in d, i and returns color
- , showControls = true
- , showLegend = true
- , showXAxis = true
- , showYAxis = true
- , rightAlignYAxis = false
- , useInteractiveGuideline = false
- , 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()
- , yAxisTickFormat = d3.format(',.2f')
- , state = { style: stacked.style() }
- , defaultState = null
- , noData = 'No Data Available.'
- , dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')
- , controlWidth = 250
- , cData = ['Stacked','Stream','Expanded']
- , controlLabels = {}
- , transitionDuration = 250
- ;
-
- xAxis
- .orient('bottom')
- .tickPadding(7)
- ;
- yAxis
- .orient((rightAlignYAxis) ? 'right' : 'left')
- ;
-
- 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()(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);
- };
-
- //============================================================
-
-
- function chart(selection) {
- selection.each(function(data) {
- var container = d3.select(this),
- 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;
-
- chart.update = function() { container.transition().duration(transitionDuration).call(chart); };
- chart.container = this;
-
- //set state.disabled
- 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 + availableHeight / 2)
- .text(function(d) { return d });
-
- return chart;
- } else {
- container.selectAll('.nv-noData').remove();
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Scales
-
- x = stacked.xScale();
- y = stacked.yScale();
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup containers and skeleton of chart
-
- var wrap = container.selectAll('g.nv-wrap.nv-stackedAreaChart').data([data]);
- var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedAreaChart').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-stackedWrap');
- gEnter.append('g').attr('class', 'nv-legendWrap');
- gEnter.append('g').attr('class', 'nv-controlsWrap');
- gEnter.append('g').attr('class', 'nv-interactive');
-
- g.select("rect").attr("width",availableWidth).attr("height",availableHeight);
- //------------------------------------------------------------
- // Legend
-
- if (showLegend) {
- var legendWidth = (showControls) ? availableWidth - controlWidth : availableWidth;
- legend
- .width(legendWidth);
-
- 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;
- }
-
- g.select('.nv-legendWrap')
- .attr('transform', 'translate(' + (availableWidth-legendWidth) + ',' + (-margin.top) +')');
- }
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Controls
-
- if (showControls) {
- var controlsData = [
- {
- key: controlLabels.stacked || 'Stacked',
- metaKey: 'Stacked',
- disabled: stacked.style() != 'stack',
- style: 'stack'
- },
- {
- key: controlLabels.stream || 'Stream',
- metaKey: 'Stream',
- disabled: stacked.style() != 'stream',
- style: 'stream'
- },
- {
- key: controlLabels.expanded || 'Expanded',
- metaKey: 'Expanded',
- disabled: stacked.style() != 'expand',
- style: 'expand'
- },
- {
- key: controlLabels.stack_percent || 'Stack %',
- metaKey: 'Stack_Percent',
- disabled: stacked.style() != 'stack_percent',
- style: 'stack_percent'
- }
- ];
-
- controlWidth = (cData.length/3) * 260;
-
- controlsData = controlsData.filter(function(d) {
- return cData.indexOf(d.metaKey) !== -1;
- })
-
- controls
- .width( controlWidth )
- .color(['#444', '#444', '#444']);
-
- g.select('.nv-controlsWrap')
- .datum(controlsData)
- .call(controls);
-
-
- 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;
- }
-
-
- g.select('.nv-controlsWrap')
- .attr('transform', 'translate(0,' + (-margin.top) +')');
- }
-
- //------------------------------------------------------------
-
-
- wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
-
- if (rightAlignYAxis) {
- g.select(".nv-y.nv-axis")
- .attr("transform", "translate(" + availableWidth + ",0)");
- }
-
- //------------------------------------------------------------
- // Main Chart Component(s)
-
- //------------------------------------------------------------
- //Set up interactive layer
- if (useInteractiveGuideline) {
- interactiveLayer
- .width(availableWidth)
- .height(availableHeight)
- .margin({left: margin.left, top: margin.top})
- .svgContainer(container)
- .xScale(x);
- wrap.select(".nv-interactive").call(interactiveLayer);
- }
-
- stacked
- .width(availableWidth)
- .height(availableHeight)
-
- var stackedWrap = g.select('.nv-stackedWrap')
- .datum(data);
-
- stackedWrap.transition().call(stacked);
-
- //------------------------------------------------------------
-
-
- //------------------------------------------------------------
- // Setup Axes
-
- if (showXAxis) {
- xAxis
- .scale(x)
- .ticks( availableWidth / 100 )
- .tickSize( -availableHeight, 0);
-
- g.select('.nv-x.nv-axis')
- .attr('transform', 'translate(0,' + availableHeight + ')');
-
- g.select('.nv-x.nv-axis')
- .transition().duration(0)
- .call(xAxis);
- }
-
- if (showYAxis) {
- yAxis
- .scale(y)
- .ticks(stacked.offset() == 'wiggle' ? 0 : availableHeight / 36)
- .tickSize(-availableWidth, 0)
- .setTickFormat( (stacked.style() == 'expand' || stacked.style() == 'stack_percent')
- ? d3.format('%') : yAxisTickFormat);
-
- g.select('.nv-y.nv-axis')
- .transition().duration(0)
- .call(yAxis);
- }
-
- //------------------------------------------------------------
-
-
- //============================================================
- // Event Handling/Dispatching (in chart's scope)
- //------------------------------------------------------------
-
- stacked.dispatch.on('areaClick.toggle', function(e) {
- if (data.filter(function(d) { return !d.disabled }).length === 1)
- data.forEach(function(d) {
- d.disabled = false;
- });
- else
- data.forEach(function(d,i) {
- d.disabled = (i != e.seriesIndex);
- });
-
- state.disabled = data.map(function(d) { return !!d.disabled });
- dispatch.stateChange(state);
-
- chart.update();
- });
-
- legend.dispatch.on('stateChange', function(newState) {
- state.disabled = newState.disabled;
- dispatch.stateChange(state);
- chart.update();
- });
-
- controls.dispatch.on('legendClick', function(d,i) {
- if (!d.disabled) return;
-
- controlsData = controlsData.map(function(s) {
- s.disabled = true;
- return s;
- });
- d.disabled = false;
-
- stacked.style(d.style);
-
-
- state.style = stacked.style();
- dispatch.stateChange(state);
-
- chart.update();
- });
-
-
- interactiveLayer.dispatch.on('elementMousemove', function(e) {
- stacked.clearHighlights();
- var singlePoint, pointIndex, pointXLocation, allData = [];
- data
- .filter(function(series, i) {
- series.seriesIndex = i;
- return !series.disabled;
- })
- .forEach(function(series,i) {
- pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());
- stacked.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));
-
- //If we are in 'expand' mode, use the stacked percent value instead of raw value.
- var tooltipValue = (stacked.style() == 'expand') ? point.display.y : chart.y()(point,pointIndex);
- allData.push({
- key: series.key,
- value: tooltipValue,
- color: color(series,series.seriesIndex),
- stackedValue: point.display
- });
- });
-
- allData.reverse();
-
- //Highlight the tooltip entry based on which stack the mouse is closest to.
- if (allData.length > 2) {
- var yValue = chart.yScale().invert(e.mouseY);
- var yDistMax = Infinity, indexToHighlight = null;
- allData.forEach(function(series,i) {
-
- //To handle situation where the stacked area chart is negative, we need to use absolute values
- //when checking if the mouse Y value is within the stack area.
- yValue = Math.abs(yValue);
- var stackedY0 = Math.abs(series.stackedValue.y0);
- var stackedY = Math.abs(series.stackedValue.y);
- if ( yValue >= stackedY0 && yValue <= (stackedY + stackedY0))
- {
- indexToHighlight = i;
- return;
- }
- });
- if (indexToHighlight != null)
- allData[indexToHighlight].highlight = 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); };
- interactiveLayer.tooltip
- .position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})
- .chartContainer(that.parentNode)
- .enabled(tooltips)
- .valueFormatter(valueFormatter)
- .data(
- {
- value: xValue,
- series: allData
- }
- )();
-
- interactiveLayer.renderGuideLine(pointXLocation);
-
- });
-
- 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) {
-
- if (typeof e.disabled !== 'undefined') {
- data.forEach(function(series,i) {
- series.disabled = e.disabled[i];
- });
-
- state.disabled = e.disabled;
- }
-
- if (typeof e.style !== 'undefined') {
- stacked.style(e.style);
- }
-
- chart.update();
- });
-
- });
-
-
- return chart;
- }
-
-
- //============================================================
- // Event Handling/Dispatching (out of chart's scope)
- //------------------------------------------------------------
-
- stacked.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(stacked.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;
- }
- */
-
- e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top],
- dispatch.tooltipShow(e);
- });
-
- stacked.dispatch.on('tooltipHide', 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.stacked = stacked;
- chart.legend = legend;
- chart.controls = controls;
- chart.xAxis = xAxis;
- chart.yAxis = yAxis;
- chart.interactiveLayer = interactiveLayer;
-
- d3.rebind(chart, stacked, 'x', 'y', 'size', 'xScale', 'yScale', 'xDomain', 'yDomain', 'xRange', 'yRange', 'sizeDomain', 'interactive', 'useVoronoi', 'offset', 'order', 'style', 'clipEdge', 'forceX', 'forceY', 'forceSize', 'interpolate');
-
- chart.options = nv.utils.optionsFunc.bind(chart);
-
- chart.margin = function(_) {
- if (!arguments.length) return margin;
- 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;
- return chart;
- };
-
- chart.width = function(_) {
- if (!arguments.length) return width;
- width = _;
- return chart;
- };
-
- chart.height = function(_) {
- if (!arguments.length) return height;
- height = _;
- return chart;
- };
-
- chart.color = function(_) {
- if (!arguments.length) return color;
- color = nv.utils.getColor(_);
- legend.color(color);
- stacked.color(color);
- return chart;
- };
-
- chart.showControls = function(_) {
- if (!arguments.length) return showControls;
- showControls = _;
- return chart;
- };
-
- chart.showLegend = function(_) {
- if (!arguments.length) return showLegend;
- showLegend = _;
- return chart;
- };
-
- chart.showXAxis = function(_) {
- if (!arguments.length) return showXAxis;
- showXAxis = _;
- return chart;
- };
-
- chart.showYAxis = function(_) {
- if (!arguments.length) return showYAxis;
- showYAxis = _;
- return chart;
- };
-
- chart.rightAlignYAxis = function(_) {
- if(!arguments.length) return rightAlignYAxis;
- rightAlignYAxis = _;
- yAxis.orient( (_) ? 'right' : 'left');
- return chart;
- };
-
- chart.useInteractiveGuideline = function(_) {
- if(!arguments.length) return useInteractiveGuideline;
- useInteractiveGuideline = _;
- if (_ === true) {
- chart.interactive(false);
- chart.useVoronoi(false);
- }
- return chart;
- };
-
- chart.tooltip = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.tooltips = function(_) {
- if (!arguments.length) return tooltips;
- tooltips = _;
- return chart;
- };
-
- chart.tooltipContent = function(_) {
- if (!arguments.length) return tooltip;
- tooltip = _;
- return chart;
- };
-
- chart.state = function(_) {
- if (!arguments.length) return state;
- state = _;
- return chart;
- };
-
- chart.defaultState = function(_) {
- if (!arguments.length) return defaultState;
- defaultState = _;
- return chart;
- };
-
- chart.noData = function(_) {
- if (!arguments.length) return noData;
- noData = _;
- return chart;
- };
-
- chart.transitionDuration = function(_) {
- if (!arguments.length) return transitionDuration;
- transitionDuration = _;
- return chart;
- };
-
- chart.controlsData = function(_) {
- if (!arguments.length) return cData;
- cData = _;
- return chart;
- };
-
- chart.controlLabels = function(_) {
- if (!arguments.length) return controlLabels;
- if (typeof _ !== 'object') return controlLabels;
- controlLabels = _;
- return chart;
- };
-
- yAxis.setTickFormat = yAxis.tickFormat;
-
- yAxis.tickFormat = function(_) {
- if (!arguments.length) return yAxisTickFormat;
- yAxisTickFormat = _;
- return yAxis;
- };
-
-
- //============================================================
-
- return chart;
-}
-})();
\ No newline at end of file
diff --git a/modoboa/extensions/stats/static/stats/js/nv.d3.min.js b/modoboa/extensions/stats/static/stats/js/nv.d3.min.js
deleted file mode 100644
index e7650d99d..000000000
--- a/modoboa/extensions/stats/static/stats/js/nv.d3.min.js
+++ /dev/null
@@ -1,6 +0,0 @@
-/*! nvd3 - v0.0.1 - 2013-12-18 */!function(){function a(a,b){return new Date(b,a+1,0).getDate()}function b(a,b,c){return function(d,e,f){var g=a(d),h=[];if(d>g&&b(g),f>1)for(;e>g;){var i=new Date(+g);0===c(i)%f&&h.push(i),b(g)}else for(;e>g;)h.push(new Date(+g)),b(g);return h}}var c=window.nv||{};c.version="1.1.15b",c.dev=!0,window.nv=c,c.tooltip=c.tooltip||{},c.utils=c.utils||{},c.models=c.models||{},c.charts={},c.graphs=[],c.logs={},c.dispatch=d3.dispatch("render_start","render_end"),c.dev&&(c.dispatch.on("render_start",function(){c.logs.startTime=+new Date}),c.dispatch.on("render_end",function(){c.logs.endTime=+new Date,c.logs.totalTime=c.logs.endTime-c.logs.startTime,c.log("total",c.logs.totalTime)})),c.log=function(){if(c.dev&&console.log&&console.log.apply)console.log.apply(console,arguments);else if(c.dev&&"function"==typeof console.log&&Function.prototype.bind){var a=Function.prototype.bind.call(console.log,console);a.apply(console,arguments)}return arguments[arguments.length-1]},c.render=function(a){a=a||1,c.render.active=!0,c.dispatch.render_start(),setTimeout(function(){for(var b,d,e=0;a>e&&(d=c.render.queue[e]);e++)b=d.generate(),typeof d.callback==typeof Function&&d.callback(b),c.graphs.push(b);c.render.queue.splice(0,e),c.render.queue.length?setTimeout(arguments.callee,0):(c.dispatch.render_end(),c.render.active=!1)},0)},c.render.active=!1,c.render.queue=[],c.addGraph=function(a){typeof arguments[0]==typeof Function&&(a={generate:arguments[0],callback:arguments[1]}),c.render.queue.push(a),c.render.active||c.render()},c.identity=function(a){return a},c.strip=function(a){return a.replace(/(\s|&)/g,"")},d3.time.monthEnd=function(a){return new Date(a.getFullYear(),a.getMonth(),0)},d3.time.monthEnds=b(d3.time.monthEnd,function(b){b.setUTCDate(b.getUTCDate()+1),b.setDate(a(b.getMonth()+1,b.getFullYear()))},function(a){return a.getMonth()}),c.interactiveGuideline=function(){"use strict";function a(l){l.each(function(l){function m(){var c=d3.mouse(this),d=c[0],e=c[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(b.nvPointerEventsClass))return;return h.elementMouseout({mouseX:d,mouseY:e}),a.renderGuideLine(null),void 0}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})}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),a.renderGuideLine=function(a){if(i){var b=q.select(".nv-interactiveGuideLine").selectAll("line").data(null!=a?[c.utils.NaNtoZero(a)]:[],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 b=c.models.tooltip(),d=null,e=null,f={left:0,top:0},g=d3.scale.linear(),h=(d3.scale.linear(),d3.dispatch("elementMousemove","elementMouseout","elementDblclick")),i=!0,j=null,k=-1!==navigator.userAgent.indexOf("MSIE");return a.dispatch=h,a.tooltip=b,a.margin=function(b){return arguments.length?(f.top="undefined"!=typeof b.top?b.top:f.top,f.left="undefined"!=typeof b.left?b.left:f.left,a):f},a.width=function(b){return arguments.length?(d=b,a):d},a.height=function(b){return arguments.length?(e=b,a):e},a.xScale=function(b){return arguments.length?(g=b,a):g},a.showGuideLine=function(b){return arguments.length?(i=b,a):i},a.svgContainer=function(b){return arguments.length?(j=b,a):j},a},c.interactiveBisect=function(a,b,c){"use strict";if(!a instanceof Array)return null;"function"!=typeof c&&(c=function(a){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},c.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 a(){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 b(a){var b;b=l?d3.select(l):d3.select("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)){a();var e=n.left,k=null!=j?j:n.top,p=b(t(f));if(m=p,l){var q=l.getElementsByTagName("svg")[0];q?q.getBoundingClientRect():l.getBoundingClientRect();var r={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),c.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){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});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))}});var g=b.node().outerHTML;return void 0!==a.footer&&(g+=""),g},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},c.tooltip.show=function(a,b,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,h.innerHTML=b,i.appendChild(h),f&&(a[0]=a[0]-f.scrollLeft,a[1]=a[1]-f.scrollTop),c.tooltip.calcTooltipPosition(a,d,e,h)},c.tooltip.findFirstNonSVGParent=function(a){for(;null!==a.tagName.match(/^g|svg$/i);)a=a.parentNode;return a},c.tooltip.findTotalOffsetTop=function(a,b){var c=b;do isNaN(a.offsetTop)||(c+=a.offsetTop);while(a=a.offsetParent);return c},c.tooltip.findTotalOffsetLeft=function(a,b){var c=b;do isNaN(a.offsetLeft)||(c+=a.offsetLeft);while(a=a.offsetParent);return c},c.tooltip.calcTooltipPosition=function(a,b,d,e){var f,g,h=parseInt(e.offsetHeight),i=parseInt(e.offsetWidth),j=c.utils.windowSize().width,k=c.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,b=b||"s",d=d||20;var n=function(a){return c.tooltip.findTotalOffsetTop(a,g)},o=function(a){return c.tooltip.findTotalOffsetLeft(a,f)};switch(b){case"e":f=a[0]-i-d,g=a[1]-h/2;var p=o(e),q=n(e);m>p&&(f=a[0]+d>m?a[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=a[0]+d,g=a[1]-h/2;var p=o(e),q=n(e);p+i>j&&(f=a[0]-i-d),l>q&&(g=l+5),q+h>l+k&&(g=l+k-q+g-h);break;case"n":f=a[0]-i/2-5,g=a[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=a[0]-i/2,g=a[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=a[0],g=a[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},c.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)}}(),c.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},c.utils.windowResize=function(a){if(void 0!==a){var b=window.onresize;window.onresize=function(c){"function"==typeof b&&b(c),a(c)}}},c.utils.getColor=function(a){return arguments.length?"[object Array]"===Object.prototype.toString.call(a)?function(b,c){return b.color||a[c%a.length]}:a:c.utils.defaultColor()},c.utils.defaultColor=function(){var a=d3.scale.category20().range();return function(b,c){return b.color||a[c%a.length]}},c.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){var f=b(e);return d||(d=c.length),"undefined"!=typeof a[f]?"function"==typeof a[f]?a[f]():a[f]:c[--d]}},c.utils.pjax=function(a,b){function d(d){d3.html(d,function(d){var e=d3.select(b).node();e.parentNode.replaceChild(d3.select(d).select(b).node(),e),c.utils.pjax(a,b)})}d3.selectAll(a).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)})},c.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.5*c*b}return 0},c.utils.NaNtoZero=function(a){return"number"!=typeof a||isNaN(a)||null===a||1/0===a?0:a},c.utils.optionsFunc=function(a){return a&&d3.map(a).forEach(function(a,b){"function"==typeof this[a]&&this[a](b)}.bind(this)),this},c.models.axis=function(){"use strict";function a(c){return c.each(function(a){var c=d3.select(this),f=c.selectAll("g.nv-wrap.nv-axis").data([a]),r=f.enter().append("g").attr("class","nvd3 nv-wrap nv-axis");r.append("g");var s=f.select("g");null!==o?b.ticks(o):("top"==b.orient()||"bottom"==b.orient())&&b.ticks(Math.abs(g.range()[1]-g.range()[0])/100),s.transition().call(b),q=q||b.scale();var t=b.tickFormat();null==t&&(t=q.tickFormat());var u=s.selectAll("text.nv-axislabel").data([h||null]);switch(u.exit().remove(),b.orient()){case"top":u.enter().append("text").attr("class","nv-axislabel");var v=2==g.range().length?g.range()[1]:g.range()[g.range().length-1]+(g.range()[1]-g.range()[0]);if(u.attr("text-anchor","middle").attr("y",0).attr("x",v/2),i){var w=f.selectAll("g.nv-axisMaxMin").data(g.domain());w.enter().append("g").attr("class","nv-axisMaxMin").append("text"),w.exit().remove(),w.attr("transform",function(a){return"translate("+g(a)+",0)"}).select("text").attr("dy","-0.5em").attr("y",-b.tickPadding()).attr("text-anchor","middle").text(function(a){var b=t(a);return(""+b).match("NaN")?"":b}),w.transition().attr("transform",function(a,b){return"translate("+g.range()[b]+",0)"})}break;case"bottom":var x=36,y=30,z=s.selectAll("g").select("text");if(k%360){z.each(function(){var a=this.getBBox().width;a>y&&(y=a)});var A=Math.abs(Math.sin(k*Math.PI/180)),x=(A?A*y:y)+30;z.attr("transform",function(){return"rotate("+k+" 0,0)"}).style("text-anchor",k%360>0?"start":"end")}u.enter().append("text").attr("class","nv-axislabel");var v=2==g.range().length?g.range()[1]:g.range()[g.range().length-1]+(g.range()[1]-g.range()[0]);if(u.attr("text-anchor","middle").attr("y",x).attr("x",v/2),i){var w=f.selectAll("g.nv-axisMaxMin").data([g.domain()[0],g.domain()[g.domain().length-1]]);w.enter().append("g").attr("class","nv-axisMaxMin").append("text"),w.exit().remove(),w.attr("transform",function(a){return"translate("+(g(a)+(n?g.rangeBand()/2:0))+",0)"}).select("text").attr("dy",".71em").attr("y",b.tickPadding()).attr("transform",function(){return"rotate("+k+" 0,0)"}).style("text-anchor",k?k%360>0?"start":"end":"middle").text(function(a){var b=t(a);return(""+b).match("NaN")?"":b}),w.transition().attr("transform",function(a){return"translate("+(g(a)+(n?g.rangeBand()/2:0))+",0)"})}m&&z.attr("transform",function(a,b){return"translate(0,"+(0==b%2?"0":"12")+")"});break;case"right":if(u.enter().append("text").attr("class","nv-axislabel"),u.style("text-anchor",l?"middle":"begin").attr("transform",l?"rotate(90)":"").attr("y",l?-Math.max(d.right,e)+12:-10).attr("x",l?g.range()[0]/2:b.tickPadding()),i){var w=f.selectAll("g.nv-axisMaxMin").data(g.domain());w.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),w.exit().remove(),w.attr("transform",function(a){return"translate(0,"+g(a)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",b.tickPadding()).style("text-anchor","start").text(function(a){var b=t(a);return(""+b).match("NaN")?"":b}),w.transition().attr("transform",function(a,b){return"translate(0,"+g.range()[b]+")"}).select("text").style("opacity",1)}break;case"left":if(u.enter().append("text").attr("class","nv-axislabel"),u.style("text-anchor",l?"middle":"end").attr("transform",l?"rotate(-90)":"").attr("y",l?-Math.max(d.left,e)+p:-10).attr("x",l?-g.range()[0]/2:-b.tickPadding()),i){var w=f.selectAll("g.nv-axisMaxMin").data(g.domain());w.enter().append("g").attr("class","nv-axisMaxMin").append("text").style("opacity",0),w.exit().remove(),w.attr("transform",function(a){return"translate(0,"+q(a)+")"}).select("text").attr("dy",".32em").attr("y",0).attr("x",-b.tickPadding()).attr("text-anchor","end").text(function(a){var b=t(a);return(""+b).match("NaN")?"":b}),w.transition().attr("transform",function(a,b){return"translate(0,"+g.range()[b]+")"}).select("text").style("opacity",1)}}if(u.text(function(a){return a}),!i||"left"!==b.orient()&&"right"!==b.orient()||(s.selectAll("g").each(function(a){d3.select(this).select("text").attr("opacity",1),(g(a)
g.range()[0]-10)&&((a>1e-10||-1e-10>a)&&d3.select(this).attr("opacity",0),d3.select(this).select("text").attr("opacity",0))}),g.domain()[0]==g.domain()[1]&&0==g.domain()[0]&&f.selectAll("g.nv-axisMaxMin").style("opacity",function(a,b){return b?0:1})),i&&("top"===b.orient()||"bottom"===b.orient())){var B=[];f.selectAll("g.nv-axisMaxMin").each(function(a,b){try{b?B.push(g(a)-this.getBBox().width-4):B.push(g(a)+this.getBBox().width+4)}catch(c){b?B.push(g(a)-4):B.push(g(a)+4)}}),s.selectAll("g").each(function(a){(g(a)B[1])&&(a>1e-10||-1e-10>a?d3.select(this).remove():d3.select(this).select("text").remove())})}j&&s.selectAll(".tick").filter(function(a){return!parseFloat(Math.round(1e5*a.__data__)/1e6)&&void 0!==a.__data__}).classed("zero",!0),q=g.copy()}),a}var b=d3.svg.axis(),d={top:0,right:0,bottom:0,left:0},e=75,f=60,g=d3.scale.linear(),h=null,i=!0,j=!0,k=0,l=!0,m=!1,n=!1,o=null,p=12;b.scale(g).orient("bottom").tickFormat(function(a){return a});var q;return a.axis=b,d3.rebind(a,b,"orient","tickValues","tickSubdivide","tickSize","tickPadding","tickFormat"),d3.rebind(a,g,"domain","range","rangeBand","rangeBands"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(d.top="undefined"!=typeof b.top?b.top:d.top,d.right="undefined"!=typeof b.right?b.right:d.right,d.bottom="undefined"!=typeof b.bottom?b.bottom:d.bottom,d.left="undefined"!=typeof b.left?b.left:d.left,a):d},a.width=function(b){return arguments.length?(e=b,a):e},a.ticks=function(b){return arguments.length?(o=b,a):o},a.height=function(b){return arguments.length?(f=b,a):f},a.axisLabel=function(b){return arguments.length?(h=b,a):h},a.showMaxMin=function(b){return arguments.length?(i=b,a):i},a.highlightZero=function(b){return arguments.length?(j=b,a):j},a.scale=function(c){return arguments.length?(g=c,b.scale(g),n="function"==typeof g.rangeBands,d3.rebind(a,g,"domain","range","rangeBand","rangeBands"),a):g},a.rotateYLabel=function(b){return arguments.length?(l=b,a):l},a.rotateLabels=function(b){return arguments.length?(k=b,a):k},a.staggerLabels=function(b){return arguments.length?(m=b,a):m},a.axisLabelDistance=function(b){return arguments.length?(p=b,a):p},a},c.models.historicalBar=function(){"use strict";function a(v){return v.each(function(a){var v=h-g.left-g.right,w=i-g.top-g.bottom,x=d3.select(this);k.domain(b||d3.extent(a[0].values.map(m).concat(o))),q?k.range(e||[.5*v/a[0].values.length,v*(a[0].values.length-.5)/a[0].values.length]):k.range(e||[0,v]),l.domain(d||d3.extent(a[0].values.map(n).concat(p))).range(f||[w,0]),k.domain()[0]===k.domain()[1]&&(k.domain()[0]?k.domain([k.domain()[0]-.01*k.domain()[0],k.domain()[1]+.01*k.domain()[1]]):k.domain([-1,1])),l.domain()[0]===l.domain()[1]&&(l.domain()[0]?l.domain([l.domain()[0]+.01*l.domain()[0],l.domain()[1]-.01*l.domain()[1]]):l.domain([-1,1]));var y=x.selectAll("g.nv-wrap.nv-historicalBar-"+j).data([a[0].values]),z=y.enter().append("g").attr("class","nvd3 nv-wrap nv-historicalBar-"+j),A=z.append("defs"),B=z.append("g"),C=y.select("g");B.append("g").attr("class","nv-bars"),y.attr("transform","translate("+g.left+","+g.top+")"),x.on("click",function(a,b){t.chartClick({data:a,index:b,pos:d3.event,id:j})}),A.append("clipPath").attr("id","nv-chart-clip-path-"+j).append("rect"),y.select("#nv-chart-clip-path-"+j+" rect").attr("width",v).attr("height",w),C.attr("clip-path",r?"url(#nv-chart-clip-path-"+j+")":"");var D=y.select(".nv-bars").selectAll(".nv-bar").data(function(a){return a},function(a,b){return m(a,b)});D.exit().remove(),D.enter().append("rect").attr("x",0).attr("y",function(a,b){return c.utils.NaNtoZero(l(Math.max(0,n(a,b))))}).attr("height",function(a,b){return c.utils.NaNtoZero(Math.abs(l(n(a,b))-l(0)))}).attr("transform",function(b,c){return"translate("+(k(m(b,c))-.45*(v/a[0].values.length))+",0)"}).on("mouseover",function(b,c){u&&(d3.select(this).classed("hover",!0),t.elementMouseover({point:b,series:a[0],pos:[k(m(b,c)),l(n(b,c))],pointIndex:c,seriesIndex:0,e:d3.event}))}).on("mouseout",function(b,c){u&&(d3.select(this).classed("hover",!1),t.elementMouseout({point:b,series:a[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())}),D.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}).transition().attr("transform",function(b,c){return"translate("+(k(m(b,c))-.45*(v/a[0].values.length))+",0)"}).attr("width",.9*(v/a[0].values.length)),D.transition().attr("y",function(a,b){var d=n(a,b)<0?l(0):l(0)-l(n(a,b))<1?l(0)-1:l(n(a,b));return c.utils.NaNtoZero(d)}).attr("height",function(a,b){return c.utils.NaNtoZero(Math.max(Math.abs(l(n(a,b))-l(0)),1))})}),a}var b,d,e,f,g={top:0,right:0,bottom:0,left:0},h=960,i=500,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=c.utils.defaultColor(),t=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),u=!0;return a.highlightPoint=function(a,b){d3.select(".nv-historicalBar-"+j).select(".nv-bars .nv-bar-0-"+a).classed("hover",b)},a.clearHighlights=function(){d3.select(".nv-historicalBar-"+j).select(".nv-bars .nv-bar.hover").classed("hover",!1)},a.dispatch=t,a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(m=b,a):m},a.y=function(b){return arguments.length?(n=b,a):n},a.margin=function(b){return arguments.length?(g.top="undefined"!=typeof b.top?b.top:g.top,g.right="undefined"!=typeof b.right?b.right:g.right,g.bottom="undefined"!=typeof b.bottom?b.bottom:g.bottom,g.left="undefined"!=typeof b.left?b.left:g.left,a):g},a.width=function(b){return arguments.length?(h=b,a):h},a.height=function(b){return arguments.length?(i=b,a):i},a.xScale=function(b){return arguments.length?(k=b,a):k},a.yScale=function(b){return arguments.length?(l=b,a):l},a.xDomain=function(c){return arguments.length?(b=c,a):b},a.yDomain=function(b){return arguments.length?(d=b,a):d},a.xRange=function(b){return arguments.length?(e=b,a):e},a.yRange=function(b){return arguments.length?(f=b,a):f},a.forceX=function(b){return arguments.length?(o=b,a):o},a.forceY=function(b){return arguments.length?(p=b,a):p},a.padData=function(b){return arguments.length?(q=b,a):q},a.clipEdge=function(b){return arguments.length?(r=b,a):r},a.color=function(b){return arguments.length?(s=c.utils.getColor(b),a):s},a.id=function(b){return arguments.length?(j=b,a):j},a.interactive=function(){return arguments.length?(u=!1,a):u},a},c.models.bullet=function(){"use strict";function a(c){return c.each(function(a,c){var d=m-b.left-b.right,o=n-b.top-b.bottom,r=d3.select(this),s=f.call(this,a,c).slice().sort(d3.descending),t=g.call(this,a,c).slice().sort(d3.descending),u=h.call(this,a,c).slice().sort(d3.descending),v=i.call(this,a,c).slice(),w=j.call(this,a,c).slice(),x=k.call(this,a,c).slice(),y=d3.scale.linear().domain(d3.extent(d3.merge([l,s]))).range(e?[d,0]:[0,d]);this.__chart__||d3.scale.linear().domain([0,1/0]).range(y.range()),this.__chart__=y;var z=d3.min(s),A=d3.max(s),B=s[1],C=r.selectAll("g.nv-wrap.nv-bullet").data([a]),D=C.enter().append("g").attr("class","nvd3 nv-wrap nv-bullet"),E=D.append("g"),F=C.select("g");E.append("rect").attr("class","nv-range nv-rangeMax"),E.append("rect").attr("class","nv-range nv-rangeAvg"),E.append("rect").attr("class","nv-range nv-rangeMin"),E.append("rect").attr("class","nv-measure"),E.append("path").attr("class","nv-markerTriangle"),C.attr("transform","translate("+b.left+","+b.top+")");var G=function(a){return Math.abs(y(a)-y(0))},H=function(a){return 0>a?y(a):y(0)};F.select("rect.nv-rangeMax").attr("height",o).attr("width",G(A>0?A:z)).attr("x",H(A>0?A:z)).datum(A>0?A:z),F.select("rect.nv-rangeAvg").attr("height",o).attr("width",G(B)).attr("x",H(B)).datum(B),F.select("rect.nv-rangeMin").attr("height",o).attr("width",G(A)).attr("x",H(A)).attr("width",G(A>0?z:A)).attr("x",H(A>0?z:A)).datum(A>0?z:A),F.select("rect.nv-measure").style("fill",p).attr("height",o/3).attr("y",o/3).attr("width",0>u?y(0)-y(u[0]):y(u[0])-y(0)).attr("x",H(u)).on("mouseover",function(){q.elementMouseover({value:u[0],label:x[0]||"Current",pos:[y(u[0]),o/2]})}).on("mouseout",function(){q.elementMouseout({value:u[0],label:x[0]||"Current"})});var I=o/6;t[0]?F.selectAll("path.nv-markerTriangle").attr("transform",function(){return"translate("+y(t[0])+","+o/2+")"}).attr("d","M0,"+I+"L"+I+","+-I+" "+-I+","+-I+"Z").on("mouseover",function(){q.elementMouseover({value:t[0],label:w[0]||"Previous",pos:[y(t[0]),o/2]})}).on("mouseout",function(){q.elementMouseout({value:t[0],label:w[0]||"Previous"})}):F.selectAll("path.nv-markerTriangle").remove(),C.selectAll(".nv-range").on("mouseover",function(a,b){var c=v[b]||(b?1==b?"Mean":"Minimum":"Maximum");q.elementMouseover({value:a,label:c,pos:[y(a),o/2]})}).on("mouseout",function(a,b){var c=v[b]||(b?1==b?"Mean":"Minimum":"Maximum");q.elementMouseout({value:a,label:c})})}),a}var b={top:0,right:0,bottom:0,left:0},d="left",e=!1,f=function(a){return a.ranges},g=function(a){return a.markers},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=c.utils.getColor(["#1f77b4"]),q=d3.dispatch("elementMouseover","elementMouseout");return a.dispatch=q,a.options=c.utils.optionsFunc.bind(a),a.orient=function(b){return arguments.length?(d=b,e="right"==d||"bottom"==d,a):d},a.ranges=function(b){return arguments.length?(f=b,a):f},a.markers=function(b){return arguments.length?(g=b,a):g},a.measures=function(b){return arguments.length?(h=b,a):h},a.forceX=function(b){return arguments.length?(l=b,a):l},a.width=function(b){return arguments.length?(m=b,a):m},a.height=function(b){return arguments.length?(n=b,a):n},a.margin=function(c){return arguments.length?(b.top="undefined"!=typeof c.top?c.top:b.top,b.right="undefined"!=typeof c.right?c.right:b.right,b.bottom="undefined"!=typeof c.bottom?c.bottom:b.bottom,b.left="undefined"!=typeof c.left?c.left:b.left,a):b},a.tickFormat=function(b){return arguments.length?(o=b,a):o},a.color=function(b){return arguments.length?(p=c.utils.getColor(b),a):p},a},c.models.bulletChart=function(){"use strict";function a(c){return c.each(function(d,n){var r=d3.select(this),s=(j||parseInt(r.style("width"))||960)-f.left-f.right,t=k-f.top-f.bottom,u=this;if(a.update=function(){a(c)},a.container=this,!d||!g.call(this,d,n)){var v=r.selectAll(".nv-noData").data([o]);return v.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),v.attr("x",f.left+s/2).attr("y",18+f.top+t/2).text(function(a){return a}),a}r.selectAll(".nv-noData").remove();var w=g.call(this,d,n).slice().sort(d3.descending),x=h.call(this,d,n).slice().sort(d3.descending),y=i.call(this,d,n).slice().sort(d3.descending),z=r.selectAll("g.nv-wrap.nv-bulletChart").data([d]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-bulletChart"),B=A.append("g"),C=z.select("g");B.append("g").attr("class","nv-bulletWrap"),B.append("g").attr("class","nv-titles"),z.attr("transform","translate("+f.left+","+f.top+")");var D=d3.scale.linear().domain([0,Math.max(w[0],x[0],y[0])]).range(e?[s,0]:[0,s]),E=this.__chart__||d3.scale.linear().domain([0,1/0]).range(D.range());this.__chart__=D;var F=B.select(".nv-titles").append("g").attr("text-anchor","end").attr("transform","translate(-6,"+(k-f.top-f.bottom)/2+")");F.append("text").attr("class","nv-title").text(function(a){return a.title}),F.append("text").attr("class","nv-subtitle").attr("dy","1em").text(function(a){return a.subtitle}),b.width(s).height(t);var G=C.select(".nv-bulletWrap");d3.transition(G).call(b);var H=l||D.tickFormat(s/100),I=C.selectAll("g.nv-tick").data(D.ticks(s/50),function(a){return this.textContent||H(a)}),J=I.enter().append("g").attr("class","nv-tick").attr("transform",function(a){return"translate("+E(a)+",0)"}).style("opacity",1e-6);J.append("line").attr("y1",t).attr("y2",7*t/6),J.append("text").attr("text-anchor","middle").attr("dy","1em").attr("y",7*t/6).text(H);var K=d3.transition(I).attr("transform",function(a){return"translate("+D(a)+",0)"}).style("opacity",1);K.select("line").attr("y1",t).attr("y2",7*t/6),K.select("text").attr("y",7*t/6),d3.transition(I.exit()).attr("transform",function(a){return"translate("+D(a)+",0)"}).style("opacity",1e-6).remove(),p.on("tooltipShow",function(a){a.key=d.title,m&&q(a,u.parentNode)})}),d3.timer.flush(),a}var b=c.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},i=function(a){return a.measures},j=null,k=55,l=null,m=!0,n=function(a,b,c){return""+b+" "+" "+c+"
"},o="No Data Available.",p=d3.dispatch("tooltipShow","tooltipHide"),q=function(b,d){var e=b.pos[0]+(d.offsetLeft||0)+f.left,g=b.pos[1]+(d.offsetTop||0)+f.top,h=n(b.key,b.label,b.value,b,a);c.tooltip.show([e,g],h,b.value<0?"e":"w",null,d)};return b.dispatch.on("elementMouseover.tooltip",function(a){p.tooltipShow(a)}),b.dispatch.on("elementMouseout.tooltip",function(a){p.tooltipHide(a)}),p.on("tooltipHide",function(){m&&c.tooltip.cleanup()}),a.dispatch=p,a.bullet=b,d3.rebind(a,b,"color"),a.options=c.utils.optionsFunc.bind(a),a.orient=function(b){return arguments.length?(d=b,e="right"==d||"bottom"==d,a):d},a.ranges=function(b){return arguments.length?(g=b,a):g},a.markers=function(b){return arguments.length?(h=b,a):h},a.measures=function(b){return arguments.length?(i=b,a):i},a.width=function(b){return arguments.length?(j=b,a):j},a.height=function(b){return arguments.length?(k=b,a):k},a.margin=function(b){return arguments.length?(f.top="undefined"!=typeof b.top?b.top:f.top,f.right="undefined"!=typeof b.right?b.right:f.right,f.bottom="undefined"!=typeof b.bottom?b.bottom:f.bottom,f.left="undefined"!=typeof b.left?b.left:f.left,a):f},a.tickFormat=function(b){return arguments.length?(l=b,a):l},a.tooltips=function(b){return arguments.length?(m=b,a):m},a.tooltipContent=function(b){return arguments.length?(n=b,a):n},a.noData=function(b){return arguments.length?(o=b,a):o},a},c.models.cumulativeLineChart=function(){"use strict";function a(x){return x.each(function(x){function I(){d3.select(a.container).style("cursor","ew-resize")}function J(){G.x=d3.event.x,G.i=Math.round(F.invert(G.x)),L()}function K(){d3.select(a.container).style("cursor","auto"),z.index=G.i,D.stateChange(z)}function L(){db.data([G]);var b=a.transitionDuration();a.transitionDuration(0),a.update(),a.transitionDuration(b)}var M=d3.select(this).classed("nv-chart-"+y,!0),N=this,O=(n||parseInt(M.style("width"))||960)-l.left-l.right,P=(o||parseInt(M.style("height"))||400)-l.top-l.bottom;if(a.update=function(){M.transition().duration(E).call(a)},a.container=this,z.disabled=x.map(function(a){return!!a.disabled}),!A){var Q;A={};for(Q in z)A[Q]=z[Q]instanceof Array?z[Q].slice(0):z[Q]}var R=d3.behavior.drag().on("dragstart",I).on("drag",J).on("dragend",K);if(!(x&&x.length&&x.filter(function(a){return a.values.length}).length)){var S=M.selectAll(".nv-noData").data([B]);return S.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),S.attr("x",l.left+O/2).attr("y",l.top+P/2).text(function(a){return a}),a}if(M.selectAll(".nv-noData").remove(),d=f.xScale(),e=f.yScale(),w)f.yDomain(null);else{var T=x.filter(function(a){return!a.disabled}).map(function(a){var b=d3.extent(a.values,f.y());return b[0]<-.95&&(b[0]=-.95),[(b[0]-b[1])/(1+b[1]),(b[1]-b[0])/(1+b[0])]}),U=[d3.min(T,function(a){return a[0]}),d3.max(T,function(a){return a[1]})];f.yDomain(U)}F.domain([0,x[0].values.length-1]).range([0,O]).clamp(!0);var x=b(G.i,x),V=v?"none":"all",W=M.selectAll("g.nv-wrap.nv-cumulativeLine").data([x]),X=W.enter().append("g").attr("class","nvd3 nv-wrap nv-cumulativeLine").append("g"),Y=W.select("g");
-if(X.append("g").attr("class","nv-interactive"),X.append("g").attr("class","nv-x nv-axis").style("pointer-events","none"),X.append("g").attr("class","nv-y nv-axis"),X.append("g").attr("class","nv-background"),X.append("g").attr("class","nv-linesWrap").style("pointer-events",V),X.append("g").attr("class","nv-avgLinesWrap").style("pointer-events","none"),X.append("g").attr("class","nv-legendWrap"),X.append("g").attr("class","nv-controlsWrap"),p&&(i.width(O),Y.select(".nv-legendWrap").datum(x).call(i),l.top!=i.height()&&(l.top=i.height(),P=(o||parseInt(M.style("height"))||400)-l.top-l.bottom),Y.select(".nv-legendWrap").attr("transform","translate(0,"+-l.top+")")),u){var Z=[{key:"Re-scale y-axis",disabled:!w}];j.width(140).color(["#444","#444","#444"]),Y.select(".nv-controlsWrap").datum(Z).attr("transform","translate(0,"+-l.top+")").call(j)}W.attr("transform","translate("+l.left+","+l.top+")"),s&&Y.select(".nv-y.nv-axis").attr("transform","translate("+O+",0)");var $=x.filter(function(a){return a.tempDisabled});W.select(".tempDisabled").remove(),$.length&&W.append("text").attr("class","tempDisabled").attr("x",O/2).attr("y","-.71em").style("text-anchor","end").text($.map(function(a){return a.key}).join(", ")+" values cannot be calculated for this time period."),v&&(k.width(O).height(P).margin({left:l.left,top:l.top}).svgContainer(M).xScale(d),W.select(".nv-interactive").call(k)),X.select(".nv-background").append("rect"),Y.select(".nv-background rect").attr("width",O).attr("height",P),f.y(function(a){return a.display.y}).width(O).height(P).color(x.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!x[b].disabled&&!x[b].tempDisabled}));var _=Y.select(".nv-linesWrap").datum(x.filter(function(a){return!a.disabled&&!a.tempDisabled}));_.call(f),x.forEach(function(a,b){a.seriesIndex=b});var ab=x.filter(function(a){return!a.disabled&&!!C(a)}),bb=Y.select(".nv-avgLinesWrap").selectAll("line").data(ab,function(a){return a.key}),cb=function(a){var b=e(C(a));return 0>b?0:b>P?P:b};bb.enter().append("line").style("stroke-width",2).style("stroke-dasharray","10,10").style("stroke",function(a){return f.color()(a,a.seriesIndex)}).attr("x1",0).attr("x2",O).attr("y1",cb).attr("y2",cb),bb.style("stroke-opacity",function(a){var b=e(C(a));return 0>b||b>P?0:1}).attr("x1",0).attr("x2",O).attr("y1",cb).attr("y2",cb),bb.exit().remove();var db=_.selectAll(".nv-indexLine").data([G]);db.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(R),db.attr("transform",function(a){return"translate("+F(a.i)+",0)"}).attr("height",P),q&&(g.scale(d).ticks(Math.min(x[0].values.length,O/70)).tickSize(-P,0),Y.select(".nv-x.nv-axis").attr("transform","translate(0,"+e.range()[0]+")"),d3.transition(Y.select(".nv-x.nv-axis")).call(g)),r&&(h.scale(e).ticks(P/36).tickSize(-O,0),d3.transition(Y.select(".nv-y.nv-axis")).call(h)),Y.select(".nv-background rect").on("click",function(){G.x=d3.mouse(this)[0],G.i=Math.round(F.invert(G.x)),z.index=G.i,D.stateChange(z),L()}),f.dispatch.on("elementClick",function(a){G.i=a.pointIndex,G.x=F(G.i),z.index=G.i,D.stateChange(z),L()}),j.dispatch.on("legendClick",function(b){b.disabled=!b.disabled,w=!b.disabled,z.rescaleY=w,D.stateChange(z),a.update()}),i.dispatch.on("stateChange",function(b){z.disabled=b.disabled,D.stateChange(z),a.update()}),k.dispatch.on("elementMousemove",function(b){f.clearHighlights();var d,e,i,j=[];if(x.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(g,h){e=c.interactiveBisect(g.values,b.pointXValue,a.x()),f.highlightPoint(h,e,!0);var k=g.values[e];"undefined"!=typeof k&&("undefined"==typeof d&&(d=k),"undefined"==typeof i&&(i=a.xScale()(a.x()(k,e))),j.push({key:g.key,value:a.y()(k,e),color:m(g,g.seriesIndex)}))}),j.length>2){var n=a.yScale().invert(b.mouseY),o=Math.abs(a.yScale().domain()[0]-a.yScale().domain()[1]),p=.03*o,q=c.nearestValueIndex(j.map(function(a){return a.value}),n,p);null!==q&&(j[q].highlight=!0)}var r=g.tickFormat()(a.x()(d,e),e);k.tooltip.position({left:i+l.left,top:b.mouseY+l.top}).chartContainer(N.parentNode).enabled(t).valueFormatter(function(a){return h.tickFormat()(a)}).data({value:r,series:j})(),k.renderGuideLine(i)}),k.dispatch.on("elementMouseout",function(){D.tooltipHide(),f.clearHighlights()}),D.on("tooltipShow",function(a){t&&H(a,N.parentNode)}),D.on("changeState",function(b){"undefined"!=typeof b.disabled&&(x.forEach(function(a,c){a.disabled=b.disabled[c]}),z.disabled=b.disabled),"undefined"!=typeof b.index&&(G.i=b.index,G.x=F(G.i),z.index=b.index,db.data([G])),"undefined"!=typeof b.rescaleY&&(w=b.rescaleY),a.update()})}),a}function b(a,b){return b.map(function(b){if(!b.values)return b;var c=f.y()(b.values[a],a);return-.95>c?(b.tempDisabled=!0,b):(b.tempDisabled=!1,b.values=b.values.map(function(a,b){return a.display={y:(f.y()(a,b)-c)/(1+c)},a}),b)})}var d,e,f=c.models.line(),g=c.models.axis(),h=c.models.axis(),i=c.models.legend(),j=c.models.legend(),k=c.interactiveGuideline(),l={top:30,right:30,bottom:50,left:60},m=c.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){return""+a+" "+""+c+" at "+b+"
"},y=f.id(),z={index:0,rescaleY:w},A=null,B="No Data Available.",C=function(a){return a.average},D=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),E=250;g.orient("bottom").tickPadding(7),h.orient(s?"right":"left"),j.updateState(!1);var F=d3.scale.linear(),G={i:0,x:0},H=function(b,d){var e=b.pos[0]+(d.offsetLeft||0),i=b.pos[1]+(d.offsetTop||0),j=g.tickFormat()(f.x()(b.point,b.pointIndex)),k=h.tickFormat()(f.y()(b.point,b.pointIndex)),l=x(b.series.key,j,k,b,a);c.tooltip.show([e,i],l,null,null,d)};return 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&&c.tooltip.cleanup()}),a.dispatch=D,a.lines=f,a.legend=i,a.xAxis=g,a.yAxis=h,a.interactiveLayer=k,d3.rebind(a,f,"defined","isArea","x","y","xScale","yScale","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(l.top="undefined"!=typeof b.top?b.top:l.top,l.right="undefined"!=typeof b.right?b.right:l.right,l.bottom="undefined"!=typeof b.bottom?b.bottom:l.bottom,l.left="undefined"!=typeof b.left?b.left:l.left,a):l},a.width=function(b){return arguments.length?(n=b,a):n},a.height=function(b){return arguments.length?(o=b,a):o},a.color=function(b){return arguments.length?(m=c.utils.getColor(b),i.color(m),a):m},a.rescaleY=function(b){return arguments.length?(w=b,a):w},a.showControls=function(b){return arguments.length?(u=b,a):u},a.useInteractiveGuideline=function(b){return arguments.length?(v=b,b===!0&&(a.interactive(!1),a.useVoronoi(!1)),a):v},a.showLegend=function(b){return arguments.length?(p=b,a):p},a.showXAxis=function(b){return arguments.length?(q=b,a):q},a.showYAxis=function(b){return arguments.length?(r=b,a):r},a.rightAlignYAxis=function(b){return arguments.length?(s=b,h.orient(b?"right":"left"),a):s},a.tooltips=function(b){return arguments.length?(t=b,a):t},a.tooltipContent=function(b){return arguments.length?(x=b,a):x},a.state=function(b){return arguments.length?(z=b,a):z},a.defaultState=function(b){return arguments.length?(A=b,a):A},a.noData=function(b){return arguments.length?(B=b,a):B},a.average=function(b){return arguments.length?(C=b,a):C},a.transitionDuration=function(b){return arguments.length?(E=b,a):E},a},c.models.discreteBar=function(){"use strict";function a(c){return c.each(function(a){var c=j-i.left-i.right,l=k-i.top-i.bottom,w=d3.select(this);a.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var x=b&&d?[]:a.map(function(a){return a.values.map(function(a,b){return{x:o(a,b),y:p(a,b),y0:a.y0}})});m.domain(b||d3.merge(x).map(function(a){return a.x})).rangeBands(e||[0,c],.1),n.domain(d||d3.extent(d3.merge(x).map(function(a){return a.y}).concat(q))),s?n.range(f||[l-(n.domain()[0]<0?12:0),n.domain()[1]>0?12:0]):n.range(f||[l,0]),g=g||m,h=h||n.copy().range([n(0),n(0)]);var y=w.selectAll("g.nv-wrap.nv-discretebar").data([a]),z=y.enter().append("g").attr("class","nvd3 nv-wrap nv-discretebar"),A=z.append("g");y.select("g"),A.append("g").attr("class","nv-groups"),y.attr("transform","translate("+i.left+","+i.top+")");var B=y.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().transition().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),B.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),B.transition().style("stroke-opacity",1).style("fill-opacity",.75);var C=B.selectAll("g.nv-bar").data(function(a){return a.values});C.exit().remove();var D=C.enter().append("g").attr("transform",function(a,b){return"translate("+(m(o(a,b))+.05*m.rangeBand())+", "+n(0)+")"}).on("mouseover",function(b,c){d3.select(this).classed("hover",!0),u.elementMouseover({value:p(b,c),point:b,series:a[b.series],pos:[m(o(b,c))+m.rangeBand()*(b.series+.5)/a.length,n(p(b,c))],pointIndex:c,seriesIndex:b.series,e:d3.event})}).on("mouseout",function(b,c){d3.select(this).classed("hover",!1),u.elementMouseout({value:p(b,c),point:b,series:a[b.series],pointIndex:c,seriesIndex:b.series,e:d3.event})}).on("click",function(b,c){u.elementClick({value:p(b,c),point:b,series:a[b.series],pos:[m(o(b,c))+m.rangeBand()*(b.series+.5)/a.length,n(p(b,c))],pointIndex:c,seriesIndex:b.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(b,c){u.elementDblClick({value:p(b,c),point:b,series:a[b.series],pos:[m(o(b,c))+m.rangeBand()*(b.series+.5)/a.length,n(p(b,c))],pointIndex:c,seriesIndex:b.series,e:d3.event}),d3.event.stopPropagation()});D.append("rect").attr("height",0).attr("width",.9*m.rangeBand()/a.length),s?(D.append("text").attr("text-anchor","middle"),C.select("text").text(function(a,b){return t(p(a,b))}).transition().attr("x",.9*m.rangeBand()/2).attr("y",function(a,b){return p(a,b)<0?n(p(a,b))-n(0)+12:-4})):C.selectAll("text").remove(),C.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).transition().attr("width",.9*m.rangeBand()/a.length),C.transition().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()}),a}var b,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=c.utils.defaultColor(),s=!1,t=d3.format(",.2f"),u=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout"),v="discreteBar";return a.dispatch=u,a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(o=b,a):o},a.y=function(b){return arguments.length?(p=b,a):p},a.margin=function(b){return arguments.length?(i.top="undefined"!=typeof b.top?b.top:i.top,i.right="undefined"!=typeof b.right?b.right:i.right,i.bottom="undefined"!=typeof b.bottom?b.bottom:i.bottom,i.left="undefined"!=typeof b.left?b.left:i.left,a):i},a.width=function(b){return arguments.length?(j=b,a):j},a.height=function(b){return arguments.length?(k=b,a):k},a.xScale=function(b){return arguments.length?(m=b,a):m},a.yScale=function(b){return arguments.length?(n=b,a):n},a.xDomain=function(c){return arguments.length?(b=c,a):b},a.yDomain=function(b){return arguments.length?(d=b,a):d},a.xRange=function(b){return arguments.length?(e=b,a):e},a.yRange=function(b){return arguments.length?(f=b,a):f},a.forceY=function(b){return arguments.length?(q=b,a):q},a.color=function(b){return arguments.length?(r=c.utils.getColor(b),a):r},a.id=function(b){return arguments.length?(l=b,a):l},a.showValues=function(b){return arguments.length?(s=b,a):s},a.valueFormat=function(b){return arguments.length?(t=b,a):t},a.rectClass=function(b){return arguments.length?(v=b,a):v},a},c.models.discreteBarChart=function(){"use strict";function a(c){return c.each(function(c){var k=d3.select(this),q=this,v=(i||parseInt(k.style("width"))||960)-h.left-h.right,w=(j||parseInt(k.style("height"))||400)-h.top-h.bottom;if(a.update=function(){s.beforeUpdate(),k.transition().duration(t).call(a)},a.container=this,!(c&&c.length&&c.filter(function(a){return a.values.length}).length)){var x=k.selectAll(".nv-noData").data([r]);return x.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),x.attr("x",h.left+v/2).attr("y",h.top+w/2).text(function(a){return a}),a}k.selectAll(".nv-noData").remove(),b=e.xScale(),d=e.yScale().clamp(!0);var y=k.selectAll("g.nv-wrap.nv-discreteBarWithAxes").data([c]),z=y.enter().append("g").attr("class","nvd3 nv-wrap nv-discreteBarWithAxes").append("g"),A=z.append("defs"),B=y.select("g");z.append("g").attr("class","nv-x nv-axis"),z.append("g").attr("class","nv-y nv-axis").append("g").attr("class","nv-zeroLine").append("line"),z.append("g").attr("class","nv-barsWrap"),B.attr("transform","translate("+h.left+","+h.top+")"),n&&B.select(".nv-y.nv-axis").attr("transform","translate("+v+",0)"),e.width(v).height(w);var C=B.select(".nv-barsWrap").datum(c.filter(function(a){return!a.disabled}));if(C.transition().call(e),A.append("clipPath").attr("id","nv-x-label-clip-"+e.id()).append("rect"),B.select("#nv-x-label-clip-"+e.id()+" rect").attr("width",b.rangeBand()*(o?2:1)).attr("height",16).attr("x",-b.rangeBand()/(o?1:2)),l){f.scale(b).ticks(v/100).tickSize(-w,0),B.select(".nv-x.nv-axis").attr("transform","translate(0,"+(d.range()[0]+(e.showValues()&&d.domain()[0]<0?16:0))+")"),B.select(".nv-x.nv-axis").transition().call(f);var D=B.select(".nv-x.nv-axis").selectAll("g");o&&D.selectAll("text").attr("transform",function(a,b,c){return"translate(0,"+(0==c%2?"5":"17")+")"})}m&&(g.scale(d).ticks(w/36).tickSize(-v,0),B.select(".nv-y.nv-axis").transition().call(g)),B.select(".nv-zeroLine line").attr("x1",0).attr("x2",v).attr("y1",d(0)).attr("y2",d(0)),s.on("tooltipShow",function(a){p&&u(a,q.parentNode)})}),a}var b,d,e=c.models.discreteBar(),f=c.models.axis(),g=c.models.axis(),h={top:15,right:10,bottom:50,left:60},i=null,j=null,k=c.utils.getColor(),l=!0,m=!0,n=!1,o=!1,p=!0,q=function(a,b,c){return""+b+" "+""+c+"
"},r="No Data Available.",s=d3.dispatch("tooltipShow","tooltipHide","beforeUpdate"),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(b,d){var h=b.pos[0]+(d.offsetLeft||0),i=b.pos[1]+(d.offsetTop||0),j=f.tickFormat()(e.x()(b.point,b.pointIndex)),k=g.tickFormat()(e.y()(b.point,b.pointIndex)),l=q(b.series.key,j,k,b,a);c.tooltip.show([h,i],l,b.value<0?"n":"s",null,d)};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&&c.tooltip.cleanup()}),a.dispatch=s,a.discretebar=e,a.xAxis=f,a.yAxis=g,d3.rebind(a,e,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","id","showValues","valueFormat"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(h.top="undefined"!=typeof b.top?b.top:h.top,h.right="undefined"!=typeof b.right?b.right:h.right,h.bottom="undefined"!=typeof b.bottom?b.bottom:h.bottom,h.left="undefined"!=typeof b.left?b.left:h.left,a):h},a.width=function(b){return arguments.length?(i=b,a):i},a.height=function(b){return arguments.length?(j=b,a):j},a.color=function(b){return arguments.length?(k=c.utils.getColor(b),e.color(k),a):k},a.showXAxis=function(b){return arguments.length?(l=b,a):l},a.showYAxis=function(b){return arguments.length?(m=b,a):m},a.rightAlignYAxis=function(b){return arguments.length?(n=b,g.orient(b?"right":"left"),a):n},a.staggerLabels=function(b){return arguments.length?(o=b,a):o},a.tooltips=function(b){return arguments.length?(p=b,a):p},a.tooltipContent=function(b){return arguments.length?(q=b,a):q},a.noData=function(b){return arguments.length?(r=b,a):r},a.transitionDuration=function(b){return arguments.length?(t=b,a):t},a},c.models.distribution=function(){"use strict";function a(c){return c.each(function(a){var c=(e-("x"===g?d.left+d.right:d.top+d.bottom),"x"==g?"y":"x"),k=d3.select(this);b=b||j;var l=k.selectAll("g.nv-distribution").data([a]),m=l.enter().append("g").attr("class","nvd3 nv-distribution");m.append("g");var n=l.select("g");l.attr("transform","translate("+d.left+","+d.top+")");var o=n.selectAll("g.nv-dist").data(function(a){return a},function(a){return a.key});o.enter().append("g"),o.attr("class",function(a,b){return"nv-dist nv-series-"+b}).style("stroke",function(a,b){return i(a,b)});var p=o.selectAll("line.nv-dist"+g).data(function(a){return a.values});p.enter().append("line").attr(g+"1",function(a,c){return b(h(a,c))}).attr(g+"2",function(a,c){return b(h(a,c))}),o.exit().selectAll("line.nv-dist"+g).transition().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(),p.attr("class",function(a,b){return"nv-dist"+g+" nv-dist"+g+"-"+b}).attr(c+"1",0).attr(c+"2",f),p.transition().attr(g+"1",function(a,b){return j(h(a,b))}).attr(g+"2",function(a,b){return j(h(a,b))}),b=j.copy()}),a}var b,d={top:0,right:0,bottom:0,left:0},e=400,f=8,g="x",h=function(a){return a[g]},i=c.utils.defaultColor(),j=d3.scale.linear();return a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(d.top="undefined"!=typeof b.top?b.top:d.top,d.right="undefined"!=typeof b.right?b.right:d.right,d.bottom="undefined"!=typeof b.bottom?b.bottom:d.bottom,d.left="undefined"!=typeof b.left?b.left:d.left,a):d},a.width=function(b){return arguments.length?(e=b,a):e},a.axis=function(b){return arguments.length?(g=b,a):g},a.size=function(b){return arguments.length?(f=b,a):f},a.getData=function(b){return arguments.length?(h=d3.functor(b),a):h},a.scale=function(b){return arguments.length?(j=b,a):j},a.color=function(b){return arguments.length?(i=c.utils.getColor(b),a):i},a},c.models.historicalBarChart=function(){"use strict";function a(c){return c.each(function(r){var y=d3.select(this),z=this,A=(k||parseInt(y.style("width"))||960)-i.left-i.right,B=(l||parseInt(y.style("height"))||400)-i.top-i.bottom;if(a.update=function(){y.transition().duration(w).call(a)},a.container=this,s.disabled=r.map(function(a){return!!a.disabled}),!t){var C;t={};for(C in s)t[C]=s[C]instanceof Array?s[C].slice(0):s[C]}if(!(r&&r.length&&r.filter(function(a){return a.values.length}).length)){var D=y.selectAll(".nv-noData").data([u]);return D.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),D.attr("x",i.left+A/2).attr("y",i.top+B/2).text(function(a){return a}),a}y.selectAll(".nv-noData").remove(),b=e.xScale(),d=e.yScale();var E=y.selectAll("g.nv-wrap.nv-historicalBarChart").data([r]),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"),m&&(h.width(A),G.select(".nv-legendWrap").datum(r).call(h),i.top!=h.height()&&(i.top=h.height(),B=(l||parseInt(y.style("height"))||400)-i.top-i.bottom),E.select(".nv-legendWrap").attr("transform","translate(0,"+-i.top+")")),E.attr("transform","translate("+i.left+","+i.top+")"),p&&G.select(".nv-y.nv-axis").attr("transform","translate("+A+",0)"),e.width(A).height(B).color(r.map(function(a,b){return a.color||j(a,b)}).filter(function(a,b){return!r[b].disabled}));var H=G.select(".nv-barsWrap").datum(r.filter(function(a){return!a.disabled}));H.transition().call(e),n&&(f.scale(b).tickSize(-B,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),G.select(".nv-x.nv-axis").transition().call(f)),o&&(g.scale(d).ticks(B/36).tickSize(-A,0),G.select(".nv-y.nv-axis").transition().call(g)),h.dispatch.on("legendClick",function(b){b.disabled=!b.disabled,r.filter(function(a){return!a.disabled}).length||r.map(function(a){return a.disabled=!1,E.selectAll(".nv-series").classed("disabled",!1),a}),s.disabled=r.map(function(a){return!!a.disabled}),v.stateChange(s),c.transition().call(a)}),h.dispatch.on("legendDblclick",function(b){r.forEach(function(a){a.disabled=!0}),b.disabled=!1,s.disabled=r.map(function(a){return!!a.disabled}),v.stateChange(s),a.update()}),v.on("tooltipShow",function(a){q&&x(a,z.parentNode)}),v.on("changeState",function(b){"undefined"!=typeof b.disabled&&(r.forEach(function(a,c){a.disabled=b.disabled[c]}),s.disabled=b.disabled),a.update()})}),a}var b,d,e=c.models.historicalBar(),f=c.models.axis(),g=c.models.axis(),h=c.models.legend(),i={top:30,right:90,bottom:50,left:90},j=c.utils.defaultColor(),k=null,l=null,m=!1,n=!0,o=!0,p=!1,q=!0,r=function(a,b,c){return""+a+" "+""+c+" at "+b+"
"},s={},t=null,u="No Data Available.",v=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),w=250;f.orient("bottom").tickPadding(7),g.orient(p?"right":"left");var x=function(b,d){if(d){var h=d3.select(d).select("svg"),i=h.node()?h.attr("viewBox"):null;if(i){i=i.split(" ");var j=parseInt(h.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=f.tickFormat()(e.x()(b.point,b.pointIndex)),n=g.tickFormat()(e.y()(b.point,b.pointIndex)),o=r(b.series.key,m,n,b,a);c.tooltip.show([k,l],o,null,null,d)};return e.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+i.left,a.pos[1]+i.top],v.tooltipShow(a)}),e.dispatch.on("elementMouseout.tooltip",function(a){v.tooltipHide(a)}),v.on("tooltipHide",function(){q&&c.tooltip.cleanup()}),a.dispatch=v,a.bars=e,a.legend=h,a.xAxis=f,a.yAxis=g,d3.rebind(a,e,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id","interpolate","highlightPoint","clearHighlights","interactive"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(i.top="undefined"!=typeof b.top?b.top:i.top,i.right="undefined"!=typeof b.right?b.right:i.right,i.bottom="undefined"!=typeof b.bottom?b.bottom:i.bottom,i.left="undefined"!=typeof b.left?b.left:i.left,a):i},a.width=function(b){return arguments.length?(k=b,a):k},a.height=function(b){return arguments.length?(l=b,a):l},a.color=function(b){return arguments.length?(j=c.utils.getColor(b),h.color(j),a):j},a.showLegend=function(b){return arguments.length?(m=b,a):m},a.showXAxis=function(b){return arguments.length?(n=b,a):n},a.showYAxis=function(b){return arguments.length?(o=b,a):o},a.rightAlignYAxis=function(b){return arguments.length?(p=b,g.orient(b?"right":"left"),a):p},a.tooltips=function(b){return arguments.length?(q=b,a):q},a.tooltipContent=function(b){return arguments.length?(r=b,a):r},a.state=function(b){return arguments.length?(s=b,a):s},a.defaultState=function(b){return arguments.length?(t=b,a):t},a.noData=function(b){return arguments.length?(u=b,a):u},a.transitionDuration=function(b){return arguments.length?(w=b,a):w},a},c.models.indentedTree=function(){"use strict";function a(b){return b.each(function(b){function c(b,d,e){return d3.event.stopPropagation(),d3.event.shiftKey&&!e?(d3.event.shiftKey=!1,b.values&&b.values.forEach(function(a){(a.values||a._values)&&c(a,0,!0)}),!0):g(b)?(b.values?(b._values=b.values,b.values=null):(b.values=b._values,b._values=null),a.update(),void 0):!0}function d(a){return a._values&&a._values.length?n:a.values&&a.values.length?o:""}function f(a){return a._values&&a._values.length}function g(a){var b=a.values||a._values;return b&&b.length}var s=1,t=d3.select(this),u=d3.layout.tree().children(function(a){return a.values}).size([e,k]);a.update=function(){t.transition().duration(600).call(a)},b[0]||(b[0]={key:j});var v=u.nodes(b[0]),w=d3.select(this).selectAll("div").data([[v]]),x=w.enter().append("div").attr("class","nvd3 nv-wrap nv-indentedtree"),y=x.append("table"),z=w.select("table").attr("width","100%").attr("class",m);if(h){var A=y.append("thead"),B=A.append("tr");l.forEach(function(a){B.append("th").attr("width",a.width?a.width:"10%").style("text-align","numeric"==a.type?"right":"left").append("span").text(a.label)})}var C=z.selectAll("tbody").data(function(a){return a});C.enter().append("tbody"),s=d3.max(v,function(a){return a.depth}),u.size([e,s*k]);var D=C.selectAll("tr").data(function(a){return a.filter(function(a){return i&&!a.children?i(a):!0})},function(a){return a.id||a.id||++r});D.exit().remove(),D.select("img.nv-treeicon").attr("src",d).classed("folded",f);var E=D.enter().append("tr");l.forEach(function(a,b){var e=E.append("td").style("padding-left",function(a){return(b?0:a.depth*k+12+(d(a)?0:16))+"px"},"important").style("text-align","numeric"==a.type?"right":"left");0==b&&e.append("img").classed("nv-treeicon",!0).classed("nv-folded",f).attr("src",d).style("width","14px").style("height","14px").style("padding","0 1px").style("display",function(a){return d(a)?"inline-block":"none"}).on("click",c),e.each(function(c){!b&&q(c)?d3.select(this).append("a").attr("href",q).attr("class",d3.functor(a.classes)).append("span"):d3.select(this).append("span"),d3.select(this).select("span").attr("class",d3.functor(a.classes)).text(function(b){return a.format?a.format(b):b[a.key]||"-"})}),a.showCount&&(e.append("span").attr("class","nv-childrenCount"),D.selectAll("span.nv-childrenCount").text(function(a){return a.values&&a.values.length||a._values&&a._values.length?"("+(a.values&&a.values.filter(function(a){return i?i(a):!0}).length||a._values&&a._values.filter(function(a){return i?i(a):!0}).length||0)+")":""}))}),D.order().on("click",function(a){p.elementClick({row:this,data:a,pos:[a.x,a.y]})}).on("dblclick",function(a){p.elementDblclick({row:this,data:a,pos:[a.x,a.y]})}).on("mouseover",function(a){p.elementMouseover({row:this,data:a,pos:[a.x,a.y]})}).on("mouseout",function(a){p.elementMouseout({row:this,data:a,pos:[a.x,a.y]})})}),a}var b={top:0,right:0,bottom:0,left:0},d=960,e=500,f=c.utils.defaultColor(),g=Math.floor(1e4*Math.random()),h=!0,i=!1,j="No Data Available.",k=20,l=[{key:"key",label:"Name",type:"text"}],m=null,n="images/grey-plus.png",o="images/grey-minus.png",p=d3.dispatch("elementClick","elementDblclick","elementMouseover","elementMouseout"),q=function(a){return a.url},r=0;return a.options=c.utils.optionsFunc.bind(a),a.margin=function(c){return arguments.length?(b.top="undefined"!=typeof c.top?c.top:b.top,b.right="undefined"!=typeof c.right?c.right:b.right,b.bottom="undefined"!=typeof c.bottom?c.bottom:b.bottom,b.left="undefined"!=typeof c.left?c.left:b.left,a):b},a.width=function(b){return arguments.length?(d=b,a):d},a.height=function(b){return arguments.length?(e=b,a):e},a.color=function(b){return arguments.length?(f=c.utils.getColor(b),scatter.color(f),a):f},a.id=function(b){return arguments.length?(g=b,a):g},a.header=function(b){return arguments.length?(h=b,a):h},a.noData=function(b){return arguments.length?(j=b,a):j},a.filterZero=function(b){return arguments.length?(i=b,a):i},a.columns=function(b){return arguments.length?(l=b,a):l},a.tableClass=function(b){return arguments.length?(m=b,a):m},a.iconOpen=function(b){return arguments.length?(n=b,a):n},a.iconClose=function(b){return arguments.length?(o=b,a):o},a.getUrl=function(b){return arguments.length?(q=b,a):q},a},c.models.legend=function(){"use strict";function a(m){return m.each(function(a){var m=d-b.left-b.right,n=d3.select(this),o=n.selectAll("g.nv-legend").data([a]);o.enter().append("g").attr("class","nvd3 nv-legend").append("g");var p=o.select("g");o.attr("transform","translate("+b.left+","+b.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(b,c){l.legendClick(b,c),j&&(k?(a.forEach(function(a){a.disabled=!0}),b.disabled=!1):(b.disabled=!b.disabled,a.every(function(a){return a.disabled})&&a.forEach(function(a){a.disabled=!1})),l.stateChange({disabled:a.map(function(a){return!!a.disabled})}))}).on("dblclick",function(b,c){l.legendDblclick(b,c),j&&(a.forEach(function(a){a.disabled=!0}),b.disabled=!1,l.stateChange({disabled:a.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("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(){var a,b=d3.select(this).select("text");try{a=b.node().getComputedTextLength()}catch(d){a=c.utils.calcApproxTextWidth(b)}s.push(a+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){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))+")"}),i?p.attr("transform","translate("+(d-b.right-u)+","+b.top+")"):p.attr("transform","translate(0,"+b.top+")"),e=b.top+b.bottom+20*Math.ceil(s.length/t)}else{var A,B=5,C=5,D=0;q.attr("transform",function(){var a=d3.select(this).select("text").node().getComputedTextLength()+28;return A=C,dD&&(D=C),"translate("+A+","+B+")"}),p.attr("transform","translate("+(d-b.right-D)+","+b.top+")"),e=b.top+b.bottom+B+15}}),a}var b={top:5,right:0,bottom:5,left:0},d=400,e=20,f=function(a){return a.key},g=c.utils.defaultColor(),h=!0,i=!0,j=!0,k=!1,l=d3.dispatch("legendClick","legendDblclick","legendMouseover","legendMouseout","stateChange");return a.dispatch=l,a.options=c.utils.optionsFunc.bind(a),a.margin=function(c){return arguments.length?(b.top="undefined"!=typeof c.top?c.top:b.top,b.right="undefined"!=typeof c.right?c.right:b.right,b.bottom="undefined"!=typeof c.bottom?c.bottom:b.bottom,b.left="undefined"!=typeof c.left?c.left:b.left,a):b},a.width=function(b){return arguments.length?(d=b,a):d},a.height=function(b){return arguments.length?(e=b,a):e},a.key=function(b){return arguments.length?(f=b,a):f},a.color=function(b){return arguments.length?(g=c.utils.getColor(b),a):g},a.align=function(b){return arguments.length?(h=b,a):h},a.rightAlign=function(b){return arguments.length?(i=b,a):i},a.updateState=function(b){return arguments.length?(j=b,a):j},a.radioButtonMode=function(b){return arguments.length?(k=b,a):k},a},c.models.line=function(){"use strict";function a(r){return r.each(function(a){var r=g-f.left-f.right,s=h-f.top-f.bottom,t=d3.select(this);b=e.xScale(),d=e.yScale(),p=p||b,q=q||d;var u=t.selectAll("g.nv-wrap.nv-line").data([a]),v=u.enter().append("g").attr("class","nvd3 nv-wrap nv-line"),w=v.append("defs"),x=v.append("g"),y=u.select("g");x.append("g").attr("class","nv-groups"),x.append("g").attr("class","nv-scatterWrap"),u.attr("transform","translate("+f.left+","+f.top+")"),e.width(r).height(s);var z=u.select(".nv-scatterWrap");z.transition().call(e),w.append("clipPath").attr("id","nv-edge-clip-"+e.id()).append("rect"),u.select("#nv-edge-clip-"+e.id()+" rect").attr("width",r).attr("height",s),y.attr("clip-path",n?"url(#nv-edge-clip-"+e.id()+")":""),z.attr("clip-path",n?"url(#nv-edge-clip-"+e.id()+")":"");
-var A=u.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});A.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),A.exit().remove(),A.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)}),A.transition().style("stroke-opacity",1).style("fill-opacity",.5);var B=A.selectAll("path.nv-area").data(function(a){return m(a)?[a]:[]});B.enter().append("path").attr("class","nv-area").attr("d",function(a){return d3.svg.area().interpolate(o).defined(l).x(function(a,b){return c.utils.NaNtoZero(p(j(a,b)))}).y0(function(a,b){return c.utils.NaNtoZero(q(k(a,b)))}).y1(function(){return q(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[a.values])}),A.exit().selectAll("path.nv-area").remove(),B.transition().attr("d",function(a){return d3.svg.area().interpolate(o).defined(l).x(function(a,d){return c.utils.NaNtoZero(b(j(a,d)))}).y0(function(a,b){return c.utils.NaNtoZero(d(k(a,b)))}).y1(function(){return d(d.domain()[0]<=0?d.domain()[1]>=0?0:d.domain()[1]:d.domain()[0])}).apply(this,[a.values])});var C=A.selectAll("path.nv-line").data(function(a){return[a.values]});C.enter().append("path").attr("class","nv-line").attr("d",d3.svg.line().interpolate(o).defined(l).x(function(a,b){return c.utils.NaNtoZero(p(j(a,b)))}).y(function(a,b){return c.utils.NaNtoZero(q(k(a,b)))})),C.transition().attr("d",d3.svg.line().interpolate(o).defined(l).x(function(a,d){return c.utils.NaNtoZero(b(j(a,d)))}).y(function(a,b){return c.utils.NaNtoZero(d(k(a,b)))})),p=b.copy(),q=d.copy()}),a}var b,d,e=c.models.scatter(),f={top:0,right:0,bottom:0,left:0},g=960,h=500,i=c.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";e.size(16).sizeDomain([16,256]);var p,q;return a.dispatch=e.dispatch,a.scatter=e,d3.rebind(a,e,"id","interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","padData","highlightPoint","clearHighlights"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(f.top="undefined"!=typeof b.top?b.top:f.top,f.right="undefined"!=typeof b.right?b.right:f.right,f.bottom="undefined"!=typeof b.bottom?b.bottom:f.bottom,f.left="undefined"!=typeof b.left?b.left:f.left,a):f},a.width=function(b){return arguments.length?(g=b,a):g},a.height=function(b){return arguments.length?(h=b,a):h},a.x=function(b){return arguments.length?(j=b,e.x(b),a):j},a.y=function(b){return arguments.length?(k=b,e.y(b),a):k},a.clipEdge=function(b){return arguments.length?(n=b,a):n},a.color=function(b){return arguments.length?(i=c.utils.getColor(b),e.color(i),a):i},a.interpolate=function(b){return arguments.length?(o=b,a):o},a.defined=function(b){return arguments.length?(l=b,a):l},a.isArea=function(b){return arguments.length?(m=d3.functor(b),a):m},a},c.models.lineChart=function(){"use strict";function a(t){return t.each(function(t){var A=d3.select(this),B=this,C=(l||parseInt(A.style("width"))||960)-j.left-j.right,D=(m||parseInt(A.style("height"))||400)-j.top-j.bottom;if(a.update=function(){A.transition().duration(y).call(a)},a.container=this,u.disabled=t.map(function(a){return!!a.disabled}),!v){var E;v={};for(E in u)v[E]=u[E]instanceof Array?u[E].slice(0):u[E]}if(!(t&&t.length&&t.filter(function(a){return a.values.length}).length)){var F=A.selectAll(".nv-noData").data([w]);return F.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),F.attr("x",j.left+C/2).attr("y",j.top+D/2).text(function(a){return a}),a}A.selectAll(".nv-noData").remove(),b=e.xScale(),d=e.yScale();var G=A.selectAll("g.nv-wrap.nv-lineChart").data([t]),H=G.enter().append("g").attr("class","nvd3 nv-wrap nv-lineChart").append("g"),I=G.select("g");H.append("rect").style("opacity",0),H.append("g").attr("class","nv-x nv-axis"),H.append("g").attr("class","nv-y nv-axis"),H.append("g").attr("class","nv-linesWrap"),H.append("g").attr("class","nv-legendWrap"),H.append("g").attr("class","nv-interactive"),I.select("rect").attr("width",C).attr("height",D),n&&(h.width(C),I.select(".nv-legendWrap").datum(t).call(h),j.top!=h.height()&&(j.top=h.height(),D=(m||parseInt(A.style("height"))||400)-j.top-j.bottom),G.select(".nv-legendWrap").attr("transform","translate(0,"+-j.top+")")),G.attr("transform","translate("+j.left+","+j.top+")"),q&&I.select(".nv-y.nv-axis").attr("transform","translate("+C+",0)"),r&&(i.width(C).height(D).margin({left:j.left,top:j.top}).svgContainer(A).xScale(b),G.select(".nv-interactive").call(i)),e.width(C).height(D).color(t.map(function(a,b){return a.color||k(a,b)}).filter(function(a,b){return!t[b].disabled}));var J=I.select(".nv-linesWrap").datum(t.filter(function(a){return!a.disabled}));J.transition().call(e),o&&(f.scale(b).ticks(C/100).tickSize(-D,0),I.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),I.select(".nv-x.nv-axis").transition().call(f)),p&&(g.scale(d).ticks(D/36).tickSize(-C,0),I.select(".nv-y.nv-axis").transition().call(g)),h.dispatch.on("stateChange",function(b){u=b,x.stateChange(u),a.update()}),i.dispatch.on("elementMousemove",function(b){e.clearHighlights();var d,h,l,m=[];if(t.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=c.interactiveBisect(f.values,b.pointXValue,a.x()),e.highlightPoint(g,h,!0);var i=f.values[h];"undefined"!=typeof i&&("undefined"==typeof d&&(d=i),"undefined"==typeof l&&(l=a.xScale()(a.x()(i,h))),m.push({key:f.key,value:a.y()(i,h),color:k(f,f.seriesIndex)}))}),m.length>2){var n=a.yScale().invert(b.mouseY),o=Math.abs(a.yScale().domain()[0]-a.yScale().domain()[1]),p=.03*o,q=c.nearestValueIndex(m.map(function(a){return a.value}),n,p);null!==q&&(m[q].highlight=!0)}var r=f.tickFormat()(a.x()(d,h));i.tooltip.position({left:l+j.left,top:b.mouseY+j.top}).chartContainer(B.parentNode).enabled(s).valueFormatter(function(a){return g.tickFormat()(a)}).data({value:r,series:m})(),i.renderGuideLine(l)}),i.dispatch.on("elementMouseout",function(){x.tooltipHide(),e.clearHighlights()}),x.on("tooltipShow",function(a){s&&z(a,B.parentNode)}),x.on("changeState",function(b){"undefined"!=typeof b.disabled&&(t.forEach(function(a,c){a.disabled=b.disabled[c]}),u.disabled=b.disabled),a.update()})}),a}var b,d,e=c.models.line(),f=c.models.axis(),g=c.models.axis(),h=c.models.legend(),i=c.interactiveGuideline(),j={top:30,right:20,bottom:50,left:60},k=c.utils.defaultColor(),l=null,m=null,n=!0,o=!0,p=!0,q=!1,r=!1,s=!0,t=function(a,b,c){return""+a+" "+""+c+" at "+b+"
"},u={},v=null,w="No Data Available.",x=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),y=250;f.orient("bottom").tickPadding(7),g.orient(q?"right":"left");var z=function(b,d){var h=b.pos[0]+(d.offsetLeft||0),i=b.pos[1]+(d.offsetTop||0),j=f.tickFormat()(e.x()(b.point,b.pointIndex)),k=g.tickFormat()(e.y()(b.point,b.pointIndex)),l=t(b.series.key,j,k,b,a);c.tooltip.show([h,i],l,null,null,d)};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&&c.tooltip.cleanup()}),a.dispatch=x,a.lines=e,a.legend=h,a.xAxis=f,a.yAxis=g,a.interactiveLayer=i,d3.rebind(a,e,"defined","isArea","x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","useVoronoi","id","interpolate"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(j.top="undefined"!=typeof b.top?b.top:j.top,j.right="undefined"!=typeof b.right?b.right:j.right,j.bottom="undefined"!=typeof b.bottom?b.bottom:j.bottom,j.left="undefined"!=typeof b.left?b.left:j.left,a):j},a.width=function(b){return arguments.length?(l=b,a):l},a.height=function(b){return arguments.length?(m=b,a):m},a.color=function(b){return arguments.length?(k=c.utils.getColor(b),h.color(k),a):k},a.showLegend=function(b){return arguments.length?(n=b,a):n},a.showXAxis=function(b){return arguments.length?(o=b,a):o},a.showYAxis=function(b){return arguments.length?(p=b,a):p},a.rightAlignYAxis=function(b){return arguments.length?(q=b,g.orient(b?"right":"left"),a):q},a.useInteractiveGuideline=function(b){return arguments.length?(r=b,b===!0&&(a.interactive(!1),a.useVoronoi(!1)),a):r},a.tooltips=function(b){return arguments.length?(s=b,a):s},a.tooltipContent=function(b){return arguments.length?(t=b,a):t},a.state=function(b){return arguments.length?(u=b,a):u},a.defaultState=function(b){return arguments.length?(v=b,a):v},a.noData=function(b){return arguments.length?(w=b,a):w},a.transitionDuration=function(b){return arguments.length?(y=b,a):y},a},c.models.linePlusBarChart=function(){"use strict";function a(c){return c.each(function(c){var o=d3.select(this),p=this,t=(m||parseInt(o.style("width"))||960)-l.left-l.right,z=(n||parseInt(o.style("height"))||400)-l.top-l.bottom;if(a.update=function(){o.transition().call(a)},u.disabled=c.map(function(a){return!!a.disabled}),!v){var A;v={};for(A in u)v[A]=u[A]instanceof Array?u[A].slice(0):u[A]}if(!(c&&c.length&&c.filter(function(a){return a.values.length}).length)){var B=o.selectAll(".nv-noData").data([w]);return B.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),B.attr("x",l.left+t/2).attr("y",l.top+z/2).text(function(a){return a}),a}o.selectAll(".nv-noData").remove();var C=c.filter(function(a){return!a.disabled&&a.bar}),D=c.filter(function(a){return!a.bar});b=D.filter(function(a){return!a.disabled}).length&&D.filter(function(a){return!a.disabled})[0].values.length?f.xScale():g.xScale(),d=g.yScale(),e=f.yScale();var E=d3.select(this).selectAll("g.nv-wrap.nv-linePlusBar").data([c]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),G=E.select("g");F.append("g").attr("class","nv-x nv-axis"),F.append("g").attr("class","nv-y1 nv-axis"),F.append("g").attr("class","nv-y2 nv-axis"),F.append("g").attr("class","nv-barsWrap"),F.append("g").attr("class","nv-linesWrap"),F.append("g").attr("class","nv-legendWrap"),r&&(k.width(t/2),G.select(".nv-legendWrap").datum(c.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?" (left axis)":" (right axis)"),a})).call(k),l.top!=k.height()&&(l.top=k.height(),z=(n||parseInt(o.style("height"))||400)-l.top-l.bottom),G.select(".nv-legendWrap").attr("transform","translate("+t/2+","+-l.top+")")),E.attr("transform","translate("+l.left+","+l.top+")"),f.width(t).height(z).color(c.map(function(a,b){return a.color||q(a,b)}).filter(function(a,b){return!c[b].disabled&&!c[b].bar})),g.width(t).height(z).color(c.map(function(a,b){return a.color||q(a,b)}).filter(function(a,b){return!c[b].disabled&&c[b].bar}));var H=G.select(".nv-barsWrap").datum(C.length?C:[{values:[]}]),I=G.select(".nv-linesWrap").datum(D[0]&&!D[0].disabled?D:[{values:[]}]);d3.transition(H).call(g),d3.transition(I).call(f),h.scale(b).ticks(t/100).tickSize(-z,0),G.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),d3.transition(G.select(".nv-x.nv-axis")).call(h),i.scale(d).ticks(z/36).tickSize(-t,0),d3.transition(G.select(".nv-y1.nv-axis")).style("opacity",C.length?1:0).call(i),j.scale(e).ticks(z/36).tickSize(C.length?0:-t,0),G.select(".nv-y2.nv-axis").style("opacity",D.length?1:0).attr("transform","translate("+t+",0)"),d3.transition(G.select(".nv-y2.nv-axis")).call(j),k.dispatch.on("stateChange",function(b){u=b,x.stateChange(u),a.update()}),x.on("tooltipShow",function(a){s&&y(a,p.parentNode)}),x.on("changeState",function(b){"undefined"!=typeof b.disabled&&(c.forEach(function(a,c){a.disabled=b.disabled[c]}),u.disabled=b.disabled),a.update()})}),a}var b,d,e,f=c.models.line(),g=c.models.historicalBar(),h=c.models.axis(),i=c.models.axis(),j=c.models.axis(),k=c.models.legend(),l={top:30,right:60,bottom:50,left:60},m=null,n=null,o=function(a){return a.x},p=function(a){return a.y},q=c.utils.defaultColor(),r=!0,s=!0,t=function(a,b,c){return""+a+" "+""+c+" at "+b+"
"},u={},v=null,w="No Data Available.",x=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState");g.padData(!0),f.clipEdge(!1).padData(!0),h.orient("bottom").tickPadding(7).highlightZero(!1),i.orient("left"),j.orient("right");var y=function(b,d){var e=b.pos[0]+(d.offsetLeft||0),g=b.pos[1]+(d.offsetTop||0),k=h.tickFormat()(f.x()(b.point,b.pointIndex)),l=(b.series.bar?i:j).tickFormat()(f.y()(b.point,b.pointIndex)),m=t(b.series.key,k,l,b,a);c.tooltip.show([e,g],m,b.value<0?"n":"s",null,d)};return f.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+l.left,a.pos[1]+l.top],x.tooltipShow(a)}),f.dispatch.on("elementMouseout.tooltip",function(a){x.tooltipHide(a)}),g.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+l.left,a.pos[1]+l.top],x.tooltipShow(a)}),g.dispatch.on("elementMouseout.tooltip",function(a){x.tooltipHide(a)}),x.on("tooltipHide",function(){s&&c.tooltip.cleanup()}),a.dispatch=x,a.legend=k,a.lines=f,a.bars=g,a.xAxis=h,a.y1Axis=i,a.y2Axis=j,d3.rebind(a,f,"defined","size","clipVoronoi","interpolate"),a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(o=b,f.x(b),g.x(b),a):o},a.y=function(b){return arguments.length?(p=b,f.y(b),g.y(b),a):p},a.margin=function(b){return arguments.length?(l.top="undefined"!=typeof b.top?b.top:l.top,l.right="undefined"!=typeof b.right?b.right:l.right,l.bottom="undefined"!=typeof b.bottom?b.bottom:l.bottom,l.left="undefined"!=typeof b.left?b.left:l.left,a):l},a.width=function(b){return arguments.length?(m=b,a):m},a.height=function(b){return arguments.length?(n=b,a):n},a.color=function(b){return arguments.length?(q=c.utils.getColor(b),k.color(q),a):q},a.showLegend=function(b){return arguments.length?(r=b,a):r},a.tooltips=function(b){return arguments.length?(s=b,a):s},a.tooltipContent=function(b){return arguments.length?(t=b,a):t},a.state=function(b){return arguments.length?(u=b,a):u},a.defaultState=function(b){return arguments.length?(v=b,a):v},a.noData=function(b){return arguments.length?(w=b,a):w},a},c.models.lineWithFocusChart=function(){"use strict";function a(c){return c.each(function(c){function x(a){var b=+("e"==a),c=b?1:-1,d=I/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+"Z"+"M"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function C(){n.empty()||n.extent(v),Q.data([n.empty()?e.domain():v]).each(function(a){var c=e(a[0])-b.range()[0],d=b.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 D(){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}),C();var b=M.select(".nv-focus .nv-linesWrap").datum(c.filter(function(a){return!a.disabled}).map(function(b){return{key:b.key,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),M.select(".nv-focus .nv-x.nv-axis").transition().duration(A).call(i),M.select(".nv-focus .nv-y.nv-axis").transition().duration(A).call(j)}}var E=d3.select(this),F=this,G=(r||parseInt(E.style("width"))||960)-o.left-o.right,H=(s||parseInt(E.style("height"))||400)-o.top-o.bottom-t,I=t-p.top-p.bottom;if(a.update=function(){E.transition().duration(A).call(a)},a.container=this,!(c&&c.length&&c.filter(function(a){return a.values.length}).length)){var J=E.selectAll(".nv-noData").data([y]);return J.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),J.attr("x",o.left+G/2).attr("y",o.top+H/2).text(function(a){return a}),a}E.selectAll(".nv-noData").remove(),b=g.xScale(),d=g.yScale(),e=h.xScale(),f=h.yScale();var K=E.selectAll("g.nv-wrap.nv-lineWithFocusChart").data([c]),L=K.enter().append("g").attr("class","nvd3 nv-wrap nv-lineWithFocusChart").append("g"),M=K.select("g");L.append("g").attr("class","nv-legendWrap");var N=L.append("g").attr("class","nv-focus");N.append("g").attr("class","nv-x nv-axis"),N.append("g").attr("class","nv-y nv-axis"),N.append("g").attr("class","nv-linesWrap");var O=L.append("g").attr("class","nv-context");O.append("g").attr("class","nv-x nv-axis"),O.append("g").attr("class","nv-y nv-axis"),O.append("g").attr("class","nv-linesWrap"),O.append("g").attr("class","nv-brushBackground"),O.append("g").attr("class","nv-x nv-brush"),u&&(m.width(G),M.select(".nv-legendWrap").datum(c).call(m),o.top!=m.height()&&(o.top=m.height(),H=(s||parseInt(E.style("height"))||400)-o.top-o.bottom-t),M.select(".nv-legendWrap").attr("transform","translate(0,"+-o.top+")")),K.attr("transform","translate("+o.left+","+o.top+")"),g.width(G).height(H).color(c.map(function(a,b){return a.color||q(a,b)}).filter(function(a,b){return!c[b].disabled})),h.defined(g.defined()).width(G).height(I).color(c.map(function(a,b){return a.color||q(a,b)}).filter(function(a,b){return!c[b].disabled})),M.select(".nv-context").attr("transform","translate(0,"+(H+o.bottom+p.top)+")");var P=M.select(".nv-context .nv-linesWrap").datum(c.filter(function(a){return!a.disabled}));d3.transition(P).call(h),i.scale(b).ticks(G/100).tickSize(-H,0),j.scale(d).ticks(H/36).tickSize(-G,0),M.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+H+")"),n.x(e).on("brush",function(){var b=a.transitionDuration();a.transitionDuration(0),D(),a.transitionDuration(b)}),v&&n.extent(v);var Q=M.select(".nv-brushBackground").selectAll("g").data([v||n.extent()]),R=Q.enter().append("g");R.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",I),R.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",I);var S=M.select(".nv-x.nv-brush").call(n);S.selectAll("rect").attr("height",I),S.selectAll(".resize").append("path").attr("d",x),D(),k.scale(e).ticks(G/100).tickSize(-I,0),M.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),d3.transition(M.select(".nv-context .nv-x.nv-axis")).call(k),l.scale(f).ticks(I/36).tickSize(-G,0),d3.transition(M.select(".nv-context .nv-y.nv-axis")).call(l),M.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),m.dispatch.on("stateChange",function(){a.update()}),z.on("tooltipShow",function(a){w&&B(a,F.parentNode)})}),a}var b,d,e,f,g=c.models.line(),h=c.models.line(),i=c.models.axis(),j=c.models.axis(),k=c.models.axis(),l=c.models.axis(),m=c.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=c.utils.defaultColor(),r=null,s=null,t=100,u=!0,v=null,w=!0,x=function(a,b,c){return""+a+" "+""+c+" at "+b+"
"},y="No Data Available.",z=d3.dispatch("tooltipShow","tooltipHide","brush"),A=250;g.clipEdge(!0),h.interactive(!1),i.orient("bottom").tickPadding(5),j.orient("left"),k.orient("bottom").tickPadding(5),l.orient("left");var B=function(b,d){var e=b.pos[0]+(d.offsetLeft||0),f=b.pos[1]+(d.offsetTop||0),h=i.tickFormat()(g.x()(b.point,b.pointIndex)),k=j.tickFormat()(g.y()(b.point,b.pointIndex)),l=x(b.series.key,h,k,b,a);c.tooltip.show([e,f],l,null,null,d)};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&&c.tooltip.cleanup()}),a.dispatch=z,a.legend=m,a.lines=g,a.lines2=h,a.xAxis=i,a.yAxis=j,a.x2Axis=k,a.y2Axis=l,d3.rebind(a,g,"defined","isArea","size","xDomain","yDomain","xRange","yRange","forceX","forceY","interactive","clipEdge","clipVoronoi","id"),a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(g.x(b),h.x(b),a):g.x},a.y=function(b){return arguments.length?(g.y(b),h.y(b),a):g.y},a.margin=function(b){return arguments.length?(o.top="undefined"!=typeof b.top?b.top:o.top,o.right="undefined"!=typeof b.right?b.right:o.right,o.bottom="undefined"!=typeof b.bottom?b.bottom:o.bottom,o.left="undefined"!=typeof b.left?b.left:o.left,a):o},a.margin2=function(b){return arguments.length?(p=b,a):p},a.width=function(b){return arguments.length?(r=b,a):r},a.height=function(b){return arguments.length?(s=b,a):s},a.height2=function(b){return arguments.length?(t=b,a):t},a.color=function(b){return arguments.length?(q=c.utils.getColor(b),m.color(q),a):q},a.showLegend=function(b){return arguments.length?(u=b,a):u},a.tooltips=function(b){return arguments.length?(w=b,a):w},a.tooltipContent=function(b){return arguments.length?(x=b,a):x},a.interpolate=function(b){return arguments.length?(g.interpolate(b),h.interpolate(b),a):g.interpolate()},a.noData=function(b){return arguments.length?(y=b,a):y},a.xTickFormat=function(b){return arguments.length?(i.tickFormat(b),k.tickFormat(b),a):i.tickFormat()},a.yTickFormat=function(b){return arguments.length?(j.tickFormat(b),l.tickFormat(b),a):j.tickFormat()},a.brushExtent=function(b){return arguments.length?(v=b,a):v},a.transitionDuration=function(b){return arguments.length?(A=b,a):A},a},c.models.linePlusBarWithFocusChart=function(){"use strict";function a(c){return c.each(function(c){function G(a){var b=+("e"==a),c=b?1:-1,d=R/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+"Z"+"M"+2.5*c+","+(d+8)+"V"+(2*d-8)+"M"+4.5*c+","+(d+8)+"V"+(2*d-8)}function L(){u.empty()||u.extent(E),cb.data([u.empty()?e.domain():E]).each(function(a){var b=e(a[0])-e.range()[0],c=e.range()[1]-e(a[1]);d3.select(this).select(".left").attr("width",0>b?0:b),d3.select(this).select(".right").attr("x",e(a[1])).attr("width",0>c?0:c)})}function M(){E=u.empty()?null:u.extent(),b=u.empty()?e.domain():u.extent(),I.brush({extent:b,brush:u}),L(),l.width(P).height(Q).color(c.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!c[b].disabled&&c[b].bar})),j.width(P).height(Q).color(c.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!c[b].disabled&&!c[b].bar}));var a=Z.select(".nv-focus .nv-barsWrap").datum(T.length?T.map(function(a){return{key:a.key,values:a.values.filter(function(a,c){return l.x()(a,c)>=b[0]&&l.x()(a,c)<=b[1]})}}):[{values:[]}]),h=Z.select(".nv-focus .nv-linesWrap").datum(U[0].disabled?[{values:[]}]:U.map(function(a){return{key:a.key,values:a.values.filter(function(a,c){return j.x()(a,c)>=b[0]&&j.x()(a,c)<=b[1]})}}));d=T.length?l.xScale():j.xScale(),n.scale(d).ticks(P/100).tickSize(-Q,0),n.domain([Math.ceil(b[0]),Math.floor(b[1])]),Z.select(".nv-x.nv-axis").transition().duration(J).call(n),a.transition().duration(J).call(l),h.transition().duration(J).call(j),Z.select(".nv-focus .nv-x.nv-axis").attr("transform","translate(0,"+f.range()[0]+")"),p.scale(f).ticks(Q/36).tickSize(-P,0),Z.select(".nv-focus .nv-y1.nv-axis").style("opacity",T.length?1:0),q.scale(g).ticks(Q/36).tickSize(T.length?0:-P,0),Z.select(".nv-focus .nv-y2.nv-axis").style("opacity",U.length?1:0).attr("transform","translate("+d.range()[1]+",0)"),Z.select(".nv-focus .nv-y1.nv-axis").transition().duration(J).call(p),Z.select(".nv-focus .nv-y2.nv-axis").transition().duration(J).call(q)}var N=d3.select(this),O=this,P=(x||parseInt(N.style("width"))||960)-v.left-v.right,Q=(y||parseInt(N.style("height"))||400)-v.top-v.bottom-z,R=z-w.top-w.bottom;if(a.update=function(){N.transition().duration(J).call(a)},a.container=this,!(c&&c.length&&c.filter(function(a){return a.values.length}).length)){var S=N.selectAll(".nv-noData").data([H]);return S.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),S.attr("x",v.left+P/2).attr("y",v.top+Q/2).text(function(a){return a}),a}N.selectAll(".nv-noData").remove();var T=c.filter(function(a){return!a.disabled&&a.bar}),U=c.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 V=c.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)}})}),W=c.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,P]),e.domain(d3.extent(d3.merge(V.concat(W)),function(a){return a.x})).range([0,P]);var X=N.selectAll("g.nv-wrap.nv-linePlusBar").data([c]),Y=X.enter().append("g").attr("class","nvd3 nv-wrap nv-linePlusBar").append("g"),Z=X.select("g");Y.append("g").attr("class","nv-legendWrap");var $=Y.append("g").attr("class","nv-focus");$.append("g").attr("class","nv-x nv-axis"),$.append("g").attr("class","nv-y1 nv-axis"),$.append("g").attr("class","nv-y2 nv-axis"),$.append("g").attr("class","nv-barsWrap"),$.append("g").attr("class","nv-linesWrap");var _=Y.append("g").attr("class","nv-context");_.append("g").attr("class","nv-x nv-axis"),_.append("g").attr("class","nv-y1 nv-axis"),_.append("g").attr("class","nv-y2 nv-axis"),_.append("g").attr("class","nv-barsWrap"),_.append("g").attr("class","nv-linesWrap"),_.append("g").attr("class","nv-brushBackground"),_.append("g").attr("class","nv-x nv-brush"),D&&(t.width(P/2),Z.select(".nv-legendWrap").datum(c.map(function(a){return a.originalKey=void 0===a.originalKey?a.key:a.originalKey,a.key=a.originalKey+(a.bar?" (left axis)":" (right axis)"),a})).call(t),v.top!=t.height()&&(v.top=t.height(),Q=(y||parseInt(N.style("height"))||400)-v.top-v.bottom-z),Z.select(".nv-legendWrap").attr("transform","translate("+P/2+","+-v.top+")")),X.attr("transform","translate("+v.left+","+v.top+")"),m.width(P).height(R).color(c.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!c[b].disabled&&c[b].bar})),k.width(P).height(R).color(c.map(function(a,b){return a.color||C(a,b)}).filter(function(a,b){return!c[b].disabled&&!c[b].bar}));var ab=Z.select(".nv-context .nv-barsWrap").datum(T.length?T:[{values:[]}]),bb=Z.select(".nv-context .nv-linesWrap").datum(U[0].disabled?[{values:[]}]:U);Z.select(".nv-context").attr("transform","translate(0,"+(Q+v.bottom+w.top)+")"),ab.transition().call(m),bb.transition().call(k),u.x(e).on("brush",M),E&&u.extent(E);var cb=Z.select(".nv-brushBackground").selectAll("g").data([E||u.extent()]),db=cb.enter().append("g");db.append("rect").attr("class","left").attr("x",0).attr("y",0).attr("height",R),db.append("rect").attr("class","right").attr("x",0).attr("y",0).attr("height",R);var eb=Z.select(".nv-x.nv-brush").call(u);eb.selectAll("rect").attr("height",R),eb.selectAll(".resize").append("path").attr("d",G),o.ticks(P/100).tickSize(-R,0),Z.select(".nv-context .nv-x.nv-axis").attr("transform","translate(0,"+h.range()[0]+")"),Z.select(".nv-context .nv-x.nv-axis").transition().call(o),r.scale(h).ticks(R/36).tickSize(-P,0),Z.select(".nv-context .nv-y1.nv-axis").style("opacity",T.length?1:0).attr("transform","translate(0,"+e.range()[0]+")"),Z.select(".nv-context .nv-y1.nv-axis").transition().call(r),s.scale(i).ticks(R/36).tickSize(T.length?0:-P,0),Z.select(".nv-context .nv-y2.nv-axis").style("opacity",U.length?1:0).attr("transform","translate("+e.range()[1]+",0)"),Z.select(".nv-context .nv-y2.nv-axis").transition().call(s),t.dispatch.on("stateChange",function(){a.update()}),I.on("tooltipShow",function(a){F&&K(a,O.parentNode)}),M()}),a}var b,d,e,f,g,h,i,j=c.models.line(),k=c.models.line(),l=c.models.historicalBar(),m=c.models.historicalBar(),n=c.models.axis(),o=c.models.axis(),p=c.models.axis(),q=c.models.axis(),r=c.models.axis(),s=c.models.axis(),t=c.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=100,A=function(a){return a.x},B=function(a){return a.y},C=c.utils.defaultColor(),D=!0,E=null,F=!0,G=function(a,b,c){return""+a+" "+""+c+" at "+b+"
"},H="No Data Available.",I=d3.dispatch("tooltipShow","tooltipHide","brush"),J=0;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 K=function(d,e){b&&(d.pointIndex+=Math.ceil(b[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=G(d.series.key,h,i,d,a);c.tooltip.show([f,g],k,d.value<0?"n":"s",null,e)};return j.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+v.left,a.pos[1]+v.top],I.tooltipShow(a)}),j.dispatch.on("elementMouseout.tooltip",function(a){I.tooltipHide(a)}),l.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+v.left,a.pos[1]+v.top],I.tooltipShow(a)}),l.dispatch.on("elementMouseout.tooltip",function(a){I.tooltipHide(a)}),I.on("tooltipHide",function(){F&&c.tooltip.cleanup()}),a.dispatch=I,a.legend=t,a.lines=j,a.lines2=k,a.bars=l,a.bars2=m,a.xAxis=n,a.x2Axis=o,a.y1Axis=p,a.y2Axis=q,a.y3Axis=r,a.y4Axis=s,d3.rebind(a,j,"defined","size","clipVoronoi","interpolate"),a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(A=b,j.x(b),l.x(b),a):A},a.y=function(b){return arguments.length?(B=b,j.y(b),l.y(b),a):B},a.margin=function(b){return arguments.length?(v.top="undefined"!=typeof b.top?b.top:v.top,v.right="undefined"!=typeof b.right?b.right:v.right,v.bottom="undefined"!=typeof b.bottom?b.bottom:v.bottom,v.left="undefined"!=typeof b.left?b.left:v.left,a):v},a.width=function(b){return arguments.length?(x=b,a):x},a.height=function(b){return arguments.length?(y=b,a):y},a.color=function(b){return arguments.length?(C=c.utils.getColor(b),t.color(C),a):C},a.showLegend=function(b){return arguments.length?(D=b,a):D},a.tooltips=function(b){return arguments.length?(F=b,a):F},a.tooltipContent=function(b){return arguments.length?(G=b,a):G},a.noData=function(b){return arguments.length?(H=b,a):H},a.brushExtent=function(b){return arguments.length?(E=b,a):E},a},c.models.multiBar=function(){"use strict";function a(c){return c.each(function(a){var c=k-j.left-j.right,B=l-j.top-j.bottom,C=d3.select(this);w&&a.length&&(w=[{values:a[0].values.map(function(a){return{x:a.x,y:0,series:a.series,size:.01}})}]),t&&(a=d3.layout.stack().offset(u).values(function(a){return a.values}).y(q)(!a.length&&w?w:a)),a.forEach(function(a,b){a.values.forEach(function(a){a.series=b})}),t&&a[0].values.map(function(b,c){var d=0,e=0;a.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 D=d&&e?[]:a.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(D).map(function(a){return a.x})).rangeBands(f||[0,c],z),n.domain(e||d3.extent(d3.merge(D).map(function(a){return t?a.y>0?a.y1:a.y1+a.y:a.y}).concat(r))).range(g||[B,0]),m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]):m.domain([-1,1])),n.domain()[0]===n.domain()[1]&&(n.domain()[0]?n.domain([n.domain()[0]+.01*n.domain()[0],n.domain()[1]-.01*n.domain()[1]]):n.domain([-1,1])),h=h||m,i=i||n;var E=C.selectAll("g.nv-wrap.nv-multibar").data([a]),F=E.enter().append("g").attr("class","nvd3 nv-wrap nv-multibar"),G=F.append("defs"),H=F.append("g"),I=E.select("g");H.append("g").attr("class","nv-groups"),E.attr("transform","translate("+j.left+","+j.top+")"),G.append("clipPath").attr("id","nv-edge-clip-"+o).append("rect"),E.select("#nv-edge-clip-"+o+" rect").attr("width",c).attr("height",B),I.attr("clip-path",s?"url(#nv-edge-clip-"+o+")":"");var J=E.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().transition().selectAll("rect.nv-bar").delay(function(b,c){return c*y/a[0].values.length}).attr("y",function(a){return t?i(a.y0):i(0)}).attr("height",0).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 v(a,b)}).style("stroke",function(a,b){return v(a,b)}),J.transition().style("stroke-opacity",1).style("fill-opacity",.75);var K=J.selectAll("rect.nv-bar").data(function(b){return w&&!a.length?w.values:b.values});K.exit().remove(),K.enter().append("rect").attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).attr("x",function(b,c,d){return t?0:d*m.rangeBand()/a.length}).attr("y",function(a){return i(t?a.y0:0)}).attr("height",0).attr("width",m.rangeBand()/(t?1:a.length)).attr("transform",function(a,b){return"translate("+m(p(a,b))+",0)"}),K.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(b,c){d3.select(this).classed("hover",!0),A.elementMouseover({value:q(b,c),point:b,series:a[b.series],pos:[m(p(b,c))+m.rangeBand()*(t?a.length/2:b.series+.5)/a.length,n(q(b,c)+(t?b.y0:0))],pointIndex:c,seriesIndex:b.series,e:d3.event})}).on("mouseout",function(b,c){d3.select(this).classed("hover",!1),A.elementMouseout({value:q(b,c),point:b,series:a[b.series],pointIndex:c,seriesIndex:b.series,e:d3.event})}).on("click",function(b,c){A.elementClick({value:q(b,c),point:b,series:a[b.series],pos:[m(p(b,c))+m.rangeBand()*(t?a.length/2:b.series+.5)/a.length,n(q(b,c)+(t?b.y0:0))],pointIndex:c,seriesIndex:b.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(b,c){A.elementDblClick({value:q(b,c),point:b,series:a[b.series],pos:[m(p(b,c))+m.rangeBand()*(t?a.length/2:b.series+.5)/a.length,n(q(b,c)+(t?b.y0:0))],pointIndex:c,seriesIndex:b.series,e:d3.event}),d3.event.stopPropagation()}),K.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}).transition().attr("transform",function(a,b){return"translate("+m(p(a,b))+",0)"}),x&&(b||(b=a.map(function(){return!0})),K.style("fill",function(a,c,d){return d3.rgb(x(a,c)).darker(b.map(function(a,b){return b}).filter(function(a,c){return!b[c]})[d]).toString()}).style("stroke",function(a,c,d){return d3.rgb(x(a,c)).darker(b.map(function(a,b){return b}).filter(function(a,c){return!b[c]})[d]).toString()})),t?K.transition().delay(function(b,c){return c*y/a[0].values.length}).attr("y",function(a){return n(t?a.y1:0)}).attr("height",function(a){return Math.max(Math.abs(n(a.y+(t?a.y0:0))-n(t?a.y0:0)),1)}).attr("x",function(b){return t?0:b.series*m.rangeBand()/a.length}).attr("width",m.rangeBand()/(t?1:a.length)):K.transition().delay(function(b,c){return c*y/a[0].values.length}).attr("x",function(b){return b.series*m.rangeBand()/a.length}).attr("width",m.rangeBand()/a.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()}),a}var b,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=c.utils.defaultColor(),w=!1,x=null,y=1200,z=.1,A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return a.dispatch=A,a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(p=b,a):p},a.y=function(b){return arguments.length?(q=b,a):q},a.margin=function(b){return arguments.length?(j.top="undefined"!=typeof b.top?b.top:j.top,j.right="undefined"!=typeof b.right?b.right:j.right,j.bottom="undefined"!=typeof b.bottom?b.bottom:j.bottom,j.left="undefined"!=typeof b.left?b.left:j.left,a):j},a.width=function(b){return arguments.length?(k=b,a):k},a.height=function(b){return arguments.length?(l=b,a):l},a.xScale=function(b){return arguments.length?(m=b,a):m},a.yScale=function(b){return arguments.length?(n=b,a):n},a.xDomain=function(b){return arguments.length?(d=b,a):d},a.yDomain=function(b){return arguments.length?(e=b,a):e},a.xRange=function(b){return arguments.length?(f=b,a):f},a.yRange=function(b){return arguments.length?(g=b,a):g},a.forceY=function(b){return arguments.length?(r=b,a):r},a.stacked=function(b){return arguments.length?(t=b,a):t},a.stackOffset=function(b){return arguments.length?(u=b,a):u},a.clipEdge=function(b){return arguments.length?(s=b,a):s},a.color=function(b){return arguments.length?(v=c.utils.getColor(b),a):v},a.barColor=function(b){return arguments.length?(x=c.utils.getColor(b),a):x},a.disabled=function(c){return arguments.length?(b=c,a):b},a.id=function(b){return arguments.length?(o=b,a):o},a.hideable=function(b){return arguments.length?(w=b,a):w},a.delay=function(b){return arguments.length?(y=b,a):y},a.groupSpacing=function(b){return arguments.length?(z=b,a):z},a},c.models.multiBarChart=function(){"use strict";function a(c){return c.each(function(c){var w=d3.select(this),E=this,F=(k||parseInt(w.style("width"))||960)-j.left-j.right,G=(l||parseInt(w.style("height"))||400)-j.top-j.bottom;if(a.update=function(){w.transition().duration(C).call(a)},a.container=this,x.disabled=c.map(function(a){return!!a.disabled}),!y){var H;y={};for(H in x)y[H]=x[H]instanceof Array?x[H].slice(0):x[H]}if(!(c&&c.length&&c.filter(function(a){return a.values.length}).length)){var I=w.selectAll(".nv-noData").data([z]);return I.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),I.attr("x",j.left+F/2).attr("y",j.top+G/2).text(function(a){return a}),a}w.selectAll(".nv-noData").remove(),b=e.xScale(),d=e.yScale();var J=w.selectAll("g.nv-wrap.nv-multiBarWithLegend").data([c]),K=J.enter().append("g").attr("class","nvd3 nv-wrap nv-multiBarWithLegend").append("g"),L=J.select("g");if(K.append("g").attr("class","nv-x nv-axis"),K.append("g").attr("class","nv-y nv-axis"),K.append("g").attr("class","nv-barsWrap"),K.append("g").attr("class","nv-legendWrap"),K.append("g").attr("class","nv-controlsWrap"),o&&(h.width(F-B()),e.barColor()&&c.forEach(function(a,b){a.color=d3.rgb("#ccc").darker(1.5*b).toString()}),L.select(".nv-legendWrap").datum(c).call(h),j.top!=h.height()&&(j.top=h.height(),G=(l||parseInt(w.style("height"))||400)-j.top-j.bottom),L.select(".nv-legendWrap").attr("transform","translate("+B()+","+-j.top+")")),n){var M=[{key:"Grouped",disabled:e.stacked()},{key:"Stacked",disabled:!e.stacked()}];i.width(B()).color(["#444","#444","#444"]),L.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+-j.top+")").call(i)}J.attr("transform","translate("+j.left+","+j.top+")"),r&&L.select(".nv-y.nv-axis").attr("transform","translate("+F+",0)"),e.disabled(c.map(function(a){return a.disabled})).width(F).height(G).color(c.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!c[b].disabled}));var N=L.select(".nv-barsWrap").datum(c.filter(function(a){return!a.disabled}));if(N.transition().call(e),p){f.scale(b).ticks(F/100).tickSize(-G,0),L.select(".nv-x.nv-axis").attr("transform","translate(0,"+d.range()[0]+")"),L.select(".nv-x.nv-axis").transition().call(f);var O=L.select(".nv-x.nv-axis > g").selectAll("g");if(O.selectAll("line, text").style("opacity",1),t){var P=function(a,b){return"translate("+a+","+b+")"},Q=5,R=17;O.selectAll("text").attr("transform",function(a,b,c){return P(0,0==c%2?Q:R)});var S=d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;L.selectAll(".nv-x.nv-axis .nv-axisMaxMin text").attr("transform",function(a,b){return P(0,0===b||0!==S%2?R:Q)})}s&&O.filter(function(a,b){return 0!==b%Math.ceil(c[0].values.length/(F/100))}).selectAll("text, line").style("opacity",0),u&&O.selectAll(".tick text").attr("transform","rotate("+u+" 0,0)").style("text-anchor",u>0?"start":"end"),L.select(".nv-x.nv-axis").selectAll("g.nv-axisMaxMin text").style("opacity",1)}q&&(g.scale(d).ticks(G/36).tickSize(-F,0),L.select(".nv-y.nv-axis").transition().call(g)),h.dispatch.on("stateChange",function(b){x=b,A.stateChange(x),a.update()}),i.dispatch.on("legendClick",function(b){if(b.disabled){switch(M=M.map(function(a){return a.disabled=!0,a}),b.disabled=!1,b.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}x.stacked=e.stacked(),A.stateChange(x),a.update()}}),A.on("tooltipShow",function(a){v&&D(a,E.parentNode)}),A.on("changeState",function(b){"undefined"!=typeof b.disabled&&(c.forEach(function(a,c){a.disabled=b.disabled[c]}),x.disabled=b.disabled),"undefined"!=typeof b.stacked&&(e.stacked(b.stacked),x.stacked=b.stacked),a.update()})}),a}var b,d,e=c.models.multiBar(),f=c.models.axis(),g=c.models.axis(),h=c.models.legend(),i=c.models.legend(),j={top:30,right:20,bottom:50,left:60},k=null,l=null,m=c.utils.defaultColor(),n=!0,o=!0,p=!0,q=!0,r=!1,s=!0,t=!1,u=0,v=!0,w=function(a,b,c){return""+a+" "+""+c+" on "+b+"
"},x={stacked:!1},y=null,z="No Data Available.",A=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),B=function(){return n?180:0},C=250;e.stacked(!1),f.orient("bottom").tickPadding(7).highlightZero(!0).showMaxMin(!1).tickFormat(function(a){return a}),g.orient(r?"right":"left").tickFormat(d3.format(",.1f")),i.updateState(!1);var D=function(b,d){var h=b.pos[0]+(d.offsetLeft||0),i=b.pos[1]+(d.offsetTop||0),j=f.tickFormat()(e.x()(b.point,b.pointIndex)),k=g.tickFormat()(e.y()(b.point,b.pointIndex)),l=w(b.series.key,j,k,b,a);c.tooltip.show([h,i],l,b.value<0?"n":"s",null,d)};return e.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+j.left,a.pos[1]+j.top],A.tooltipShow(a)}),e.dispatch.on("elementMouseout.tooltip",function(a){A.tooltipHide(a)}),A.on("tooltipHide",function(){v&&c.tooltip.cleanup()}),a.dispatch=A,a.multibar=e,a.legend=h,a.xAxis=f,a.yAxis=g,d3.rebind(a,e,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","stacked","stackOffset","delay","barColor","groupSpacing"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(j.top="undefined"!=typeof b.top?b.top:j.top,j.right="undefined"!=typeof b.right?b.right:j.right,j.bottom="undefined"!=typeof b.bottom?b.bottom:j.bottom,j.left="undefined"!=typeof b.left?b.left:j.left,a):j},a.width=function(b){return arguments.length?(k=b,a):k},a.height=function(b){return arguments.length?(l=b,a):l},a.color=function(b){return arguments.length?(m=c.utils.getColor(b),h.color(m),a):m},a.showControls=function(b){return arguments.length?(n=b,a):n},a.showLegend=function(b){return arguments.length?(o=b,a):o},a.showXAxis=function(b){return arguments.length?(p=b,a):p},a.showYAxis=function(b){return arguments.length?(q=b,a):q},a.rightAlignYAxis=function(b){return arguments.length?(r=b,g.orient(b?"right":"left"),a):r},a.reduceXTicks=function(b){return arguments.length?(s=b,a):s},a.rotateLabels=function(b){return arguments.length?(u=b,a):u},a.staggerLabels=function(b){return arguments.length?(t=b,a):t},a.tooltip=function(b){return arguments.length?(w=b,a):w},a.tooltips=function(b){return arguments.length?(v=b,a):v},a.tooltipContent=function(b){return arguments.length?(w=b,a):w},a.state=function(b){return arguments.length?(x=b,a):x},a.defaultState=function(b){return arguments.length?(y=b,a):y},a.noData=function(b){return arguments.length?(z=b,a):z},a.transitionDuration=function(b){return arguments.length?(C=b,a):C},a},c.models.multiBarHorizontal=function(){"use strict";function a(c){return c.each(function(a){var c=k-j.left-j.right,m=l-j.top-j.bottom;d3.select(this),u&&(a=d3.layout.stack().offset("zero").values(function(a){return a.values}).y(q)(a)),a.forEach(function(a,b){a.values.forEach(function(a){a.series=b})}),u&&a[0].values.map(function(b,c){var d=0,e=0;a.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 z=d&&e?[]:a.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(z).map(function(a){return a.x})).rangeBands(f||[0,m],.1),o.domain(e||d3.extent(d3.merge(z).map(function(a){return u?a.y>0?a.y1+a.y:a.y1:a.y}).concat(r))),v&&!u?o.range(g||[o.domain()[0]<0?x:0,c-(o.domain()[1]>0?x:0)]):o.range(g||[0,c]),h=h||n,i=i||d3.scale.linear().domain(o.domain()).range([o(0),o(0)]);var B=d3.select(this).selectAll("g.nv-wrap.nv-multibarHorizontal").data([a]),C=B.enter().append("g").attr("class","nvd3 nv-wrap nv-multibarHorizontal");C.append("defs");var D=C.append("g");B.select("g"),D.append("g").attr("class","nv-groups"),B.attr("transform","translate("+j.left+","+j.top+")");var E=B.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a,b){return b});E.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),E.exit().transition().style("stroke-opacity",1e-6).style("fill-opacity",1e-6).remove(),E.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}).style("fill",function(a,b){return s(a,b)}).style("stroke",function(a,b){return s(a,b)}),E.transition().style("stroke-opacity",1).style("fill-opacity",.75);var F=E.selectAll("g.nv-bar").data(function(a){return a.values});F.exit().remove();var G=F.enter().append("g").attr("transform",function(b,c,d){return"translate("+i(u?b.y0:0)+","+(u?0:d*n.rangeBand()/a.length+n(p(b,c)))+")"});G.append("rect").attr("width",0).attr("height",n.rangeBand()/(u?1:a.length)),F.on("mouseover",function(b,c){d3.select(this).classed("hover",!0),A.elementMouseover({value:q(b,c),point:b,series:a[b.series],pos:[o(q(b,c)+(u?b.y0:0)),n(p(b,c))+n.rangeBand()*(u?a.length/2:b.series+.5)/a.length],pointIndex:c,seriesIndex:b.series,e:d3.event})}).on("mouseout",function(b,c){d3.select(this).classed("hover",!1),A.elementMouseout({value:q(b,c),point:b,series:a[b.series],pointIndex:c,seriesIndex:b.series,e:d3.event})}).on("click",function(b,c){A.elementClick({value:q(b,c),point:b,series:a[b.series],pos:[n(p(b,c))+n.rangeBand()*(u?a.length/2:b.series+.5)/a.length,o(q(b,c)+(u?b.y0:0))],pointIndex:c,seriesIndex:b.series,e:d3.event}),d3.event.stopPropagation()}).on("dblclick",function(b,c){A.elementDblClick({value:q(b,c),point:b,series:a[b.series],pos:[n(p(b,c))+n.rangeBand()*(u?a.length/2:b.series+.5)/a.length,o(q(b,c)+(u?b.y0:0))],pointIndex:c,seriesIndex:b.series,e:d3.event}),d3.event.stopPropagation()}),G.append("text"),v&&!u?(F.select("text").attr("text-anchor",function(a,b){return q(a,b)<0?"end":"start"}).attr("y",n.rangeBand()/(2*a.length)).attr("dy",".32em").text(function(a,b){return y(q(a,b))}),F.transition().select("text").attr("x",function(a,b){return q(a,b)<0?-4:o(q(a,b))-o(0)+4})):F.selectAll("text").text(""),w&&!u?(G.append("text").classed("nv-bar-label",!0),F.select("text.nv-bar-label").attr("text-anchor",function(a,b){return q(a,b)<0?"start":"end"}).attr("y",n.rangeBand()/(2*a.length)).attr("dy",".32em").text(function(a,b){return p(a,b)}),F.transition().select("text.nv-bar-label").attr("x",function(a,b){return q(a,b)<0?o(0)-o(q(a,b))+4:-4})):F.selectAll("text.nv-bar-label").text(""),F.attr("class",function(a,b){return q(a,b)<0?"nv-bar negative":"nv-bar positive"}),t&&(b||(b=a.map(function(){return!0})),F.style("fill",function(a,c,d){return d3.rgb(t(a,c)).darker(b.map(function(a,b){return b}).filter(function(a,c){return!b[c]})[d]).toString()}).style("stroke",function(a,c,d){return d3.rgb(t(a,c)).darker(b.map(function(a,b){return b}).filter(function(a,c){return!b[c]})[d]).toString()})),u?F.transition().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()):F.transition().attr("transform",function(b,c){return"translate("+(q(b,c)<0?o(q(b,c)):o(0))+","+(b.series*n.rangeBand()/a.length+n(p(b,c)))+")"}).select("rect").attr("height",n.rangeBand()/a.length).attr("width",function(a,b){return Math.max(Math.abs(o(q(a,b))-o(0)),1)}),h=n.copy(),i=o.copy()}),a}var b,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=c.utils.defaultColor(),t=null,u=!1,v=!1,w=!1,x=60,y=d3.format(",.2f"),z=1200,A=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return a.dispatch=A,a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(p=b,a):p},a.y=function(b){return arguments.length?(q=b,a):q},a.margin=function(b){return arguments.length?(j.top="undefined"!=typeof b.top?b.top:j.top,j.right="undefined"!=typeof b.right?b.right:j.right,j.bottom="undefined"!=typeof b.bottom?b.bottom:j.bottom,j.left="undefined"!=typeof b.left?b.left:j.left,a):j},a.width=function(b){return arguments.length?(k=b,a):k},a.height=function(b){return arguments.length?(l=b,a):l},a.xScale=function(b){return arguments.length?(n=b,a):n},a.yScale=function(b){return arguments.length?(o=b,a):o},a.xDomain=function(b){return arguments.length?(d=b,a):d},a.yDomain=function(b){return arguments.length?(e=b,a):e},a.xRange=function(b){return arguments.length?(f=b,a):f},a.yRange=function(b){return arguments.length?(g=b,a):g},a.forceY=function(b){return arguments.length?(r=b,a):r},a.stacked=function(b){return arguments.length?(u=b,a):u},a.color=function(b){return arguments.length?(s=c.utils.getColor(b),a):s},a.barColor=function(b){return arguments.length?(t=c.utils.getColor(b),a):t},a.disabled=function(c){return arguments.length?(b=c,a):b},a.id=function(b){return arguments.length?(m=b,a):m},a.delay=function(b){return arguments.length?(z=b,a):z},a.showValues=function(b){return arguments.length?(v=b,a):v},a.showBarLabels=function(b){return arguments.length?(w=b,a):w},a.valueFormat=function(b){return arguments.length?(y=b,a):y},a.valuePadding=function(b){return arguments.length?(x=b,a):x},a},c.models.multiBarHorizontalChart=function(){"use strict";function a(c){return c.each(function(c){var r=d3.select(this),t=this,B=(k||parseInt(r.style("width"))||960)-j.left-j.right,C=(l||parseInt(r.style("height"))||400)-j.top-j.bottom;if(a.update=function(){r.transition().duration(z).call(a)},a.container=this,u.disabled=c.map(function(a){return!!a.disabled}),!v){var D;v={};for(D in u)v[D]=u[D]instanceof Array?u[D].slice(0):u[D]}if(!(c&&c.length&&c.filter(function(a){return a.values.length}).length)){var E=r.selectAll(".nv-noData").data([w]);return E.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),E.attr("x",j.left+B/2).attr("y",j.top+C/2).text(function(a){return a}),a}r.selectAll(".nv-noData").remove(),b=e.xScale(),d=e.yScale();var F=r.selectAll("g.nv-wrap.nv-multiBarHorizontalChart").data([c]),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"),o&&(h.width(B-y()),e.barColor()&&c.forEach(function(a,b){a.color=d3.rgb("#ccc").darker(1.5*b).toString()}),H.select(".nv-legendWrap").datum(c).call(h),j.top!=h.height()&&(j.top=h.height(),C=(l||parseInt(r.style("height"))||400)-j.top-j.bottom),H.select(".nv-legendWrap").attr("transform","translate("+y()+","+-j.top+")")),n){var I=[{key:"Grouped",disabled:e.stacked()},{key:"Stacked",disabled:!e.stacked()}];i.width(y()).color(["#444","#444","#444"]),H.select(".nv-controlsWrap").datum(I).attr("transform","translate(0,"+-j.top+")").call(i)}F.attr("transform","translate("+j.left+","+j.top+")"),e.disabled(c.map(function(a){return a.disabled})).width(B).height(C).color(c.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!c[b].disabled}));var J=H.select(".nv-barsWrap").datum(c.filter(function(a){return!a.disabled}));if(J.transition().call(e),p){f.scale(b).ticks(C/24).tickSize(-B,0),H.select(".nv-x.nv-axis").transition().call(f);var K=H.select(".nv-x.nv-axis").selectAll("g");K.selectAll("line, text")}q&&(g.scale(d).ticks(B/100).tickSize(-C,0),H.select(".nv-y.nv-axis").attr("transform","translate(0,"+C+")"),H.select(".nv-y.nv-axis").transition().call(g)),H.select(".nv-zeroLine line").attr("x1",d(0)).attr("x2",d(0)).attr("y1",0).attr("y2",-C),h.dispatch.on("stateChange",function(b){u=b,x.stateChange(u),a.update()}),i.dispatch.on("legendClick",function(b){if(b.disabled){switch(I=I.map(function(a){return a.disabled=!0,a}),b.disabled=!1,b.key){case"Grouped":e.stacked(!1);break;case"Stacked":e.stacked(!0)}u.stacked=e.stacked(),x.stateChange(u),a.update()}}),x.on("tooltipShow",function(a){s&&A(a,t.parentNode)}),x.on("changeState",function(b){"undefined"!=typeof b.disabled&&(c.forEach(function(a,c){a.disabled=b.disabled[c]}),u.disabled=b.disabled),"undefined"!=typeof b.stacked&&(e.stacked(b.stacked),u.stacked=b.stacked),a.update()})}),a}var b,d,e=c.models.multiBarHorizontal(),f=c.models.axis(),g=c.models.axis(),h=c.models.legend().height(30),i=c.models.legend().height(30),j={top:30,right:20,bottom:50,left:60},k=null,l=null,m=c.utils.defaultColor(),n=!0,o=!0,p=!0,q=!0,r=!1,s=!0,t=function(a,b,c){return""+a+" - "+b+" "+""+c+"
"},u={stacked:r},v=null,w="No Data Available.",x=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),y=function(){return n?180:0},z=250;e.stacked(r),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 A=function(b,d){var h=b.pos[0]+(d.offsetLeft||0),i=b.pos[1]+(d.offsetTop||0),j=f.tickFormat()(e.x()(b.point,b.pointIndex)),k=g.tickFormat()(e.y()(b.point,b.pointIndex)),l=t(b.series.key,j,k,b,a);c.tooltip.show([h,i],l,b.value<0?"e":"w",null,d)};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&&c.tooltip.cleanup()}),a.dispatch=x,a.multibar=e,a.legend=h,a.xAxis=f,a.yAxis=g,d3.rebind(a,e,"x","y","xDomain","yDomain","xRange","yRange","forceX","forceY","clipEdge","id","delay","showValues","showBarLabels","valueFormat","stacked","barColor"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(j.top="undefined"!=typeof b.top?b.top:j.top,j.right="undefined"!=typeof b.right?b.right:j.right,j.bottom="undefined"!=typeof b.bottom?b.bottom:j.bottom,j.left="undefined"!=typeof b.left?b.left:j.left,a):j},a.width=function(b){return arguments.length?(k=b,a):k},a.height=function(b){return arguments.length?(l=b,a):l},a.color=function(b){return arguments.length?(m=c.utils.getColor(b),h.color(m),a):m},a.showControls=function(b){return arguments.length?(n=b,a):n},a.showLegend=function(b){return arguments.length?(o=b,a):o},a.showXAxis=function(b){return arguments.length?(p=b,a):p},a.showYAxis=function(b){return arguments.length?(q=b,a):q},a.tooltip=function(b){return arguments.length?(t=b,a):t},a.tooltips=function(b){return arguments.length?(s=b,a):s},a.tooltipContent=function(b){return arguments.length?(t=b,a):t},a.state=function(b){return arguments.length?(u=b,a):u},a.defaultState=function(b){return arguments.length?(v=b,a):v},a.noData=function(b){return arguments.length?(w=b,a):w},a.transitionDuration=function(b){return arguments.length?(z=b,a):z},a},c.models.multiChart=function(){"use strict";function a(c){return c.each(function(c){var l=d3.select(this),A=this;a.update=function(){l.transition().call(a)},a.container=this;var B=(h||parseInt(l.style("width"))||960)-f.left-f.right,C=(i||parseInt(l.style("height"))||400)-f.top-f.bottom,D=c.filter(function(a){return!a.disabled&&"line"==a.type&&1==a.yAxis}),E=c.filter(function(a){return!a.disabled&&"line"==a.type&&2==a.yAxis}),F=c.filter(function(a){return!a.disabled&&"bar"==a.type&&1==a.yAxis}),G=c.filter(function(a){return!a.disabled&&"bar"==a.type&&2==a.yAxis}),H=c.filter(function(a){return!a.disabled&&"area"==a.type&&1==a.yAxis}),I=c.filter(function(a){return!a.disabled&&"area"==a.type&&2==a.yAxis}),J=c.filter(function(a){return!a.disabled&&1==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})}),K=c.filter(function(a){return!a.disabled&&2==a.yAxis}).map(function(a){return a.values.map(function(a){return{x:a.x,y:a.y}})});b.domain(d3.extent(d3.merge(J.concat(K)),function(a){return a.x})).range([0,B]);var L=l.selectAll("g.wrap.multiChart").data([c]),M=L.enter().append("g").attr("class","wrap nvd3 multiChart").append("g");M.append("g").attr("class","x axis"),M.append("g").attr("class","y1 axis"),M.append("g").attr("class","y2 axis"),M.append("g").attr("class","lines1Wrap"),M.append("g").attr("class","lines2Wrap"),M.append("g").attr("class","bars1Wrap"),M.append("g").attr("class","bars2Wrap"),M.append("g").attr("class","stack1Wrap"),M.append("g").attr("class","stack2Wrap"),M.append("g").attr("class","legendWrap");var N=L.select("g");j&&(x.width(B/2),N.select(".legendWrap").datum(c.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(x),f.top!=x.height()&&(f.top=x.height(),C=(i||parseInt(l.style("height"))||400)-f.top-f.bottom),N.select(".legendWrap").attr("transform","translate("+B/2+","+-f.top+")")),o.width(B).height(C).interpolate("monotone").color(c.map(function(a,b){return a.color||g[b%g.length]}).filter(function(a,b){return!c[b].disabled&&1==c[b].yAxis&&"line"==c[b].type})),p.width(B).height(C).interpolate("monotone").color(c.map(function(a,b){return a.color||g[b%g.length]}).filter(function(a,b){return!c[b].disabled&&2==c[b].yAxis&&"line"==c[b].type})),q.width(B).height(C).color(c.map(function(a,b){return a.color||g[b%g.length]}).filter(function(a,b){return!c[b].disabled&&1==c[b].yAxis&&"bar"==c[b].type})),r.width(B).height(C).color(c.map(function(a,b){return a.color||g[b%g.length]}).filter(function(a,b){return!c[b].disabled&&2==c[b].yAxis&&"bar"==c[b].type})),s.width(B).height(C).color(c.map(function(a,b){return a.color||g[b%g.length]}).filter(function(a,b){return!c[b].disabled&&1==c[b].yAxis&&"area"==c[b].type})),t.width(B).height(C).color(c.map(function(a,b){return a.color||g[b%g.length]}).filter(function(a,b){return!c[b].disabled&&2==c[b].yAxis&&"area"==c[b].type})),N.attr("transform","translate("+f.left+","+f.top+")");var O=N.select(".lines1Wrap").datum(D),P=N.select(".bars1Wrap").datum(F),Q=N.select(".stack1Wrap").datum(H),R=N.select(".lines2Wrap").datum(E),S=N.select(".bars2Wrap").datum(G),T=N.select(".stack2Wrap").datum(I),U=H.length?H.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}]):[],V=I.length?I.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}]):[];m.domain(d||d3.extent(d3.merge(J).concat(U),function(a){return a.y})).range([0,C]),n.domain(e||d3.extent(d3.merge(K).concat(V),function(a){return a.y})).range([0,C]),o.yDomain(m.domain()),q.yDomain(m.domain()),s.yDomain(m.domain()),p.yDomain(n.domain()),r.yDomain(n.domain()),t.yDomain(n.domain()),H.length&&d3.transition(Q).call(s),I.length&&d3.transition(T).call(t),F.length&&d3.transition(P).call(q),G.length&&d3.transition(S).call(r),D.length&&d3.transition(O).call(o),E.length&&d3.transition(R).call(p),u.ticks(B/100).tickSize(-C,0),N.select(".x.axis").attr("transform","translate(0,"+C+")"),d3.transition(N.select(".x.axis")).call(u),v.ticks(C/36).tickSize(-B,0),d3.transition(N.select(".y1.axis")).call(v),w.ticks(C/36).tickSize(-B,0),d3.transition(N.select(".y2.axis")).call(w),N.select(".y2.axis").style("opacity",K.length?1:0).attr("transform","translate("+b.range()[1]+",0)"),x.dispatch.on("stateChange",function(){a.update()}),y.on("tooltipShow",function(a){k&&z(a,A.parentNode)})}),a}var b,d,e,f={top:30,right:20,bottom:50,left:60},g=d3.scale.category20().range(),h=null,i=null,j=!0,k=!0,l=function(a,b,c){return""+a+" "+""+c+" at "+b+"
"},b=d3.scale.linear(),m=d3.scale.linear(),n=d3.scale.linear(),o=c.models.line().yScale(m),p=c.models.line().yScale(n),q=c.models.multiBar().stacked(!1).yScale(m),r=c.models.multiBar().stacked(!1).yScale(n),s=c.models.stackedArea().yScale(m),t=c.models.stackedArea().yScale(n),u=c.models.axis().scale(b).orient("bottom").tickPadding(5),v=c.models.axis().scale(m).orient("left"),w=c.models.axis().scale(n).orient("right"),x=c.models.legend().height(30),y=d3.dispatch("tooltipShow","tooltipHide"),z=function(b,d){var e=b.pos[0]+(d.offsetLeft||0),f=b.pos[1]+(d.offsetTop||0),g=u.tickFormat()(o.x()(b.point,b.pointIndex)),h=(2==b.series.yAxis?w:v).tickFormat()(o.y()(b.point,b.pointIndex)),i=l(b.series.key,g,h,b,a);c.tooltip.show([e,f],i,void 0,void 0,d.offsetParent)};return o.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],y.tooltipShow(a)}),o.dispatch.on("elementMouseout.tooltip",function(a){y.tooltipHide(a)}),p.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],y.tooltipShow(a)}),p.dispatch.on("elementMouseout.tooltip",function(a){y.tooltipHide(a)}),q.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],y.tooltipShow(a)}),q.dispatch.on("elementMouseout.tooltip",function(a){y.tooltipHide(a)}),r.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],y.tooltipShow(a)}),r.dispatch.on("elementMouseout.tooltip",function(a){y.tooltipHide(a)}),s.dispatch.on("tooltipShow",function(a){return Math.round(100*s.y()(a.point))?(a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],y.tooltipShow(a),void 0):(setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1)}),s.dispatch.on("tooltipHide",function(a){y.tooltipHide(a)}),t.dispatch.on("tooltipShow",function(a){return Math.round(100*t.y()(a.point))?(a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],y.tooltipShow(a),void 0):(setTimeout(function(){d3.selectAll(".point.hover").classed("hover",!1)},0),!1)}),t.dispatch.on("tooltipHide",function(a){y.tooltipHide(a)}),o.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],y.tooltipShow(a)}),o.dispatch.on("elementMouseout.tooltip",function(a){y.tooltipHide(a)}),p.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+f.left,a.pos[1]+f.top],y.tooltipShow(a)}),p.dispatch.on("elementMouseout.tooltip",function(a){y.tooltipHide(a)}),y.on("tooltipHide",function(){k&&c.tooltip.cleanup()}),a.dispatch=y,a.lines1=o,a.lines2=p,a.bars1=q,a.bars2=r,a.stack1=s,a.stack2=t,a.xAxis=u,a.yAxis1=v,a.yAxis2=w,a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(getX=b,o.x(b),q.x(b),a):getX},a.y=function(b){return arguments.length?(getY=b,o.y(b),q.y(b),a):getY},a.yDomain1=function(b){return arguments.length?(d=b,a):d},a.yDomain2=function(b){return arguments.length?(e=b,a):e},a.margin=function(b){return arguments.length?(f=b,a):f},a.width=function(b){return arguments.length?(h=b,a):h},a.height=function(b){return arguments.length?(i=b,a):i},a.color=function(b){return arguments.length?(g=b,x.color(b),a):g},a.showLegend=function(b){return arguments.length?(j=b,a):j},a.tooltips=function(b){return arguments.length?(k=b,a):k},a.tooltipContent=function(b){return arguments.length?(l=b,a):l},a},c.models.ohlcBar=function(){"use strict";function a(c){return c.each(function(a){var c=h-g.left-g.right,w=i-g.top-g.bottom,y=d3.select(this);k.domain(b||d3.extent(a[0].values.map(m).concat(s))),u?k.range(e||[.5*c/a[0].values.length,c*(a[0].values.length-.5)/a[0].values.length]):k.range(e||[0,c]),l.domain(d||[d3.min(a[0].values.map(r).concat(t)),d3.max(a[0].values.map(q).concat(t))]).range(f||[w,0]),k.domain()[0]===k.domain()[1]&&(k.domain()[0]?k.domain([k.domain()[0]-.01*k.domain()[0],k.domain()[1]+.01*k.domain()[1]]):k.domain([-1,1])),l.domain()[0]===l.domain()[1]&&(l.domain()[0]?l.domain([l.domain()[0]+.01*l.domain()[0],l.domain()[1]-.01*l.domain()[1]]):l.domain([-1,1]));var z=d3.select(this).selectAll("g.nv-wrap.nv-ohlcBar").data([a[0].values]),A=z.enter().append("g").attr("class","nvd3 nv-wrap nv-ohlcBar"),B=A.append("defs"),C=A.append("g"),D=z.select("g");
-C.append("g").attr("class","nv-ticks"),z.attr("transform","translate("+g.left+","+g.top+")"),y.on("click",function(a,b){x.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",c).attr("height",w),D.attr("clip-path",v?"url(#nv-chart-clip-path-"+j+")":"");var E=z.select(".nv-ticks").selectAll(".nv-tick").data(function(a){return a});E.exit().remove(),E.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(b,d){var e=.9*(c/a[0].values.length);return"m0,0l0,"+(l(o(b,d))-l(q(b,d)))+"l"+-e/2+",0l"+e/2+",0l0,"+(l(r(b,d))-l(o(b,d)))+"l0,"+(l(p(b,d))-l(r(b,d)))+"l"+e/2+",0l"+-e/2+",0z"}).attr("transform",function(a,b){return"translate("+k(m(a,b))+","+l(q(a,b))+")"}).on("mouseover",function(b,c){d3.select(this).classed("hover",!0),x.elementMouseover({point:b,series:a[0],pos:[k(m(b,c)),l(n(b,c))],pointIndex:c,seriesIndex:0,e:d3.event})}).on("mouseout",function(b,c){d3.select(this).classed("hover",!1),x.elementMouseout({point:b,series:a[0],pointIndex:c,seriesIndex:0,e:d3.event})}).on("click",function(a,b){x.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){x.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("class",function(a,b,c){return(o(a,b)>p(a,b)?"nv-tick negative":"nv-tick positive")+" nv-tick-"+c+"-"+b}),d3.transition(E).attr("transform",function(a,b){return"translate("+k(m(a,b))+","+l(q(a,b))+")"}).attr("d",function(b,d){var e=.9*(c/a[0].values.length);return"m0,0l0,"+(l(o(b,d))-l(q(b,d)))+"l"+-e/2+",0l"+e/2+",0l0,"+(l(r(b,d))-l(o(b,d)))+"l0,"+(l(p(b,d))-l(r(b,d)))+"l"+e/2+",0l"+-e/2+",0z"})}),a}var b,d,e,f,g={top:0,right:0,bottom:0,left:0},h=960,i=500,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=c.utils.defaultColor(),x=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return a.dispatch=x,a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(m=b,a):m},a.y=function(b){return arguments.length?(n=b,a):n},a.open=function(b){return arguments.length?(o=b,a):o},a.close=function(b){return arguments.length?(p=b,a):p},a.high=function(b){return arguments.length?(q=b,a):q},a.low=function(b){return arguments.length?(r=b,a):r},a.margin=function(b){return arguments.length?(g.top="undefined"!=typeof b.top?b.top:g.top,g.right="undefined"!=typeof b.right?b.right:g.right,g.bottom="undefined"!=typeof b.bottom?b.bottom:g.bottom,g.left="undefined"!=typeof b.left?b.left:g.left,a):g},a.width=function(b){return arguments.length?(h=b,a):h},a.height=function(b){return arguments.length?(i=b,a):i},a.xScale=function(b){return arguments.length?(k=b,a):k},a.yScale=function(b){return arguments.length?(l=b,a):l},a.xDomain=function(c){return arguments.length?(b=c,a):b},a.yDomain=function(b){return arguments.length?(d=b,a):d},a.xRange=function(b){return arguments.length?(e=b,a):e},a.yRange=function(b){return arguments.length?(f=b,a):f},a.forceX=function(b){return arguments.length?(s=b,a):s},a.forceY=function(b){return arguments.length?(t=b,a):t},a.padData=function(b){return arguments.length?(u=b,a):u},a.clipEdge=function(b){return arguments.length?(v=b,a):v},a.color=function(b){return arguments.length?(w=c.utils.getColor(b),a):w},a.id=function(b){return arguments.length?(j=b,a):j},a},c.models.pie=function(){"use strict";function a(c){return c.each(function(a){function c(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 E(b(a))}}var i=e-b.left-b.right,l=f-b.top-b.bottom,x=Math.min(i,l)/2,y=x-x/5,z=d3.select(this),A=z.selectAll(".nv-wrap.nv-pie").data(a),B=A.enter().append("g").attr("class","nvd3 nv-wrap nv-pie nv-chart-"+j),C=B.append("g"),D=A.select("g");C.append("g").attr("class","nv-pie"),C.append("g").attr("class","nv-pieLabels"),A.attr("transform","translate("+b.left+","+b.top+")"),D.select(".nv-pie").attr("transform","translate("+i/2+","+l/2+")"),D.select(".nv-pieLabels").attr("transform","translate("+i/2+","+l/2+")"),z.on("click",function(a,b){w.chartClick({data:a,index:b,pos:d3.event,id:j})});var E=d3.svg.arc().outerRadius(y);t&&E.startAngle(t),u&&E.endAngle(u),r&&E.innerRadius(x*v);var F=d3.layout.pie().sort(null).value(function(a){return a.disabled?0:h(a)}),G=A.select(".nv-pie").selectAll(".nv-slice").data(F),H=A.select(".nv-pieLabels").selectAll(".nv-label").data(F);G.exit().remove(),H.exit().remove();var I=G.enter().append("g").attr("class","nv-slice").on("mouseover",function(a,b){d3.select(this).classed("hover",!0),w.elementMouseover({label:g(a.data),value:h(a.data),point:a.data,pointIndex:b,pos:[d3.event.pageX,d3.event.pageY],id:j})}).on("mouseout",function(a,b){d3.select(this).classed("hover",!1),w.elementMouseout({label:g(a.data),value:h(a.data),point:a.data,index:b,id:j})}).on("click",function(a,b){w.elementClick({label:g(a.data),value:h(a.data),point:a.data,index:b,pos:d3.event,id:j}),d3.event.stopPropagation()}).on("dblclick",function(a,b){w.elementDblClick({label:g(a.data),value:h(a.data),point:a.data,index:b,pos:d3.event,id:j}),d3.event.stopPropagation()});if(G.attr("fill",function(a,b){return k(a,b)}).attr("stroke",function(a,b){return k(a,b)}),I.append("path").each(function(a){this._current=a}),G.select("path").transition().attr("d",E).attrTween("d",c),m){var J=d3.svg.arc().innerRadius(0);n&&(J=E),o&&(J=d3.svg.arc().outerRadius(E.outerRadius())),H.enter().append("g").classed("nv-label",!0).each(function(a){var b=d3.select(this);b.attr("transform",function(a){if(s){a.outerRadius=y+10,a.innerRadius=y+15;var b=(a.startAngle+a.endAngle)/2*(180/Math.PI);return(a.startAngle+a.endAngle)/2q?c[p]:""})}}),a}var b={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=function(a){return a.description},j=Math.floor(1e4*Math.random()),k=c.utils.defaultColor(),l=d3.format(",.2f"),m=!0,n=!0,o=!1,p="key",q=.02,r=!1,s=!1,t=!1,u=!1,v=.5,w=d3.dispatch("chartClick","elementClick","elementDblClick","elementMouseover","elementMouseout");return a.dispatch=w,a.options=c.utils.optionsFunc.bind(a),a.margin=function(c){return arguments.length?(b.top="undefined"!=typeof c.top?c.top:b.top,b.right="undefined"!=typeof c.right?c.right:b.right,b.bottom="undefined"!=typeof c.bottom?c.bottom:b.bottom,b.left="undefined"!=typeof c.left?c.left:b.left,a):b},a.width=function(b){return arguments.length?(e=b,a):e},a.height=function(b){return arguments.length?(f=b,a):f},a.values=function(){return c.log("pie.values() is no longer supported."),a},a.x=function(b){return arguments.length?(g=b,a):g},a.y=function(b){return arguments.length?(h=d3.functor(b),a):h},a.description=function(b){return arguments.length?(i=b,a):i},a.showLabels=function(b){return arguments.length?(m=b,a):m},a.labelSunbeamLayout=function(b){return arguments.length?(s=b,a):s},a.donutLabelsOutside=function(b){return arguments.length?(o=b,a):o},a.pieLabelsOutside=function(b){return arguments.length?(n=b,a):n},a.labelType=function(b){return arguments.length?(p=b,p=p||"key",a):p},a.donut=function(b){return arguments.length?(r=b,a):r},a.donutRatio=function(b){return arguments.length?(v=b,a):v},a.startAngle=function(b){return arguments.length?(t=b,a):t},a.endAngle=function(b){return arguments.length?(u=b,a):u},a.id=function(b){return arguments.length?(j=b,a):j},a.color=function(b){return arguments.length?(k=c.utils.getColor(b),a):k},a.valueFormat=function(b){return arguments.length?(l=b,a):l},a.labelThreshold=function(b){return arguments.length?(q=b,a):q},a},c.models.pieChart=function(){"use strict";function a(c){return c.each(function(c){var i=d3.select(this),j=(f||parseInt(i.style("width"))||960)-e.left-e.right,k=(g||parseInt(i.style("height"))||400)-e.top-e.bottom;if(a.update=function(){i.transition().call(a)},a.container=this,l.disabled=c.map(function(a){return!!a.disabled}),!m){var p;m={};for(p in l)m[p]=l[p]instanceof Array?l[p].slice(0):l[p]}if(!c||!c.length){var q=i.selectAll(".nv-noData").data([n]);return q.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),q.attr("x",e.left+j/2).attr("y",e.top+k/2).text(function(a){return a}),a}i.selectAll(".nv-noData").remove();var r=i.selectAll("g.nv-wrap.nv-pieChart").data([c]),s=r.enter().append("g").attr("class","nvd3 nv-wrap nv-pieChart").append("g"),t=r.select("g");s.append("g").attr("class","nv-pieWrap"),s.append("g").attr("class","nv-legendWrap"),h&&(d.width(j).key(b.x()),r.select(".nv-legendWrap").datum(c).call(d),e.top!=d.height()&&(e.top=d.height(),k=(g||parseInt(i.style("height"))||400)-e.top-e.bottom),r.select(".nv-legendWrap").attr("transform","translate(0,"+-e.top+")")),r.attr("transform","translate("+e.left+","+e.top+")"),b.width(j).height(k);var u=t.select(".nv-pieWrap").datum([c]);d3.transition(u).call(b),d.dispatch.on("stateChange",function(b){l=b,o.stateChange(l),a.update()}),b.dispatch.on("elementMouseout.tooltip",function(a){o.tooltipHide(a)}),o.on("changeState",function(b){"undefined"!=typeof b.disabled&&(c.forEach(function(a,c){a.disabled=b.disabled[c]}),l.disabled=b.disabled),a.update()})}),a}var b=c.models.pie(),d=c.models.legend(),e={top:30,right:20,bottom:20,left:20},f=null,g=null,h=!0,i=c.utils.defaultColor(),j=!0,k=function(a,b){return""+a+" "+""+b+"
"},l={},m=null,n="No Data Available.",o=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),p=function(d,e){var f=b.description()(d.point)||b.x()(d.point),g=d.pos[0]+(e&&e.offsetLeft||0),h=d.pos[1]+(e&&e.offsetTop||0),i=b.valueFormat()(b.y()(d.point)),j=k(f,i,d,a);c.tooltip.show([g,h],j,d.value<0?"n":"s",null,e)};return b.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+e.left,a.pos[1]+e.top],o.tooltipShow(a)}),o.on("tooltipShow",function(a){j&&p(a)}),o.on("tooltipHide",function(){j&&c.tooltip.cleanup()}),a.legend=d,a.dispatch=o,a.pie=b,d3.rebind(a,b,"valueFormat","values","x","y","description","id","showLabels","donutLabelsOutside","pieLabelsOutside","labelType","donut","donutRatio","labelThreshold"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(e.top="undefined"!=typeof b.top?b.top:e.top,e.right="undefined"!=typeof b.right?b.right:e.right,e.bottom="undefined"!=typeof b.bottom?b.bottom:e.bottom,e.left="undefined"!=typeof b.left?b.left:e.left,a):e},a.width=function(b){return arguments.length?(f=b,a):f},a.height=function(b){return arguments.length?(g=b,a):g},a.color=function(e){return arguments.length?(i=c.utils.getColor(e),d.color(i),b.color(i),a):i},a.showLegend=function(b){return arguments.length?(h=b,a):h},a.tooltips=function(b){return arguments.length?(j=b,a):j},a.tooltipContent=function(b){return arguments.length?(k=b,a):k},a.state=function(b){return arguments.length?(l=b,a):l},a.defaultState=function(b){return arguments.length?(m=b,a):m},a.noData=function(b){return arguments.length?(n=b,a):n},a},c.models.scatter=function(){"use strict";function a(O){return O.each(function(a){function O(){if(!w)return!1;var b=d3.merge(a.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 y(a[4],b)})}));if(M===!0){if(C){var c=T.select("defs").selectAll(".nv-point-clips").data([k]).enter();c.append("clipPath").attr("class","nv-point-clips").attr("id","nv-points-clip-"+k);var d=T.select("#nv-points-clip-"+k).selectAll("circle").data(b);d.enter().append("circle").attr("r",D),d.exit().remove(),d.attr("cx",function(a){return a[0]}).attr("cy",function(a){return a[1]}),T.select(".nv-point-paths").attr("clip-path","url(#nv-points-clip-"+k+")")}b.length&&(b.push([l.range()[0]-20,m.range()[0]-20,null,null]),b.push([l.range()[1]+20,m.range()[1]+20,null,null]),b.push([l.range()[0]-20,m.range()[0]+20,null,null]),b.push([l.range()[1]+20,m.range()[1]-20,null,null]));var e=d3.geom.polygon([[-10,-10],[-10,i+10],[h+10,i+10],[h+10,-10]]),f=d3.geom.voronoi(b).map(function(a,c){return{data:e.clip(a),series:b[c][2],point:b[c][3]}}),j=T.select(".nv-point-paths").selectAll("path").data(f);j.enter().append("path").attr("class",function(a,b){return"nv-path-"+b}),j.exit().remove(),j.attr("d",function(a){return 0===a.data.length?"M 0 0":"M"+a.data.join("L")+"Z"});var n=function(b,c){if(N)return 0;var d=a[b.series];if("undefined"!=typeof d){var e=d.values[b.point];c({point:e,series:d,pos:[l(o(e,b.point))+g.left,m(p(e,b.point))+g.top],seriesIndex:b.series,pointIndex:b.point})}};j.on("click",function(a){n(a,L.elementClick)}).on("mouseover",function(a){n(a,L.elementMouseover)}).on("mouseout",function(a){n(a,L.elementMouseout)})}else T.select(".nv-groups").selectAll(".nv-group").selectAll(".nv-point").on("click",function(b,c){if(N||!a[b.series])return 0;var d=a[b.series],e=d.values[c];L.elementClick({point:e,series:d,pos:[l(o(e,c))+g.left,m(p(e,c))+g.top],seriesIndex:b.series,pointIndex:c})}).on("mouseover",function(b,c){if(N||!a[b.series])return 0;var d=a[b.series],e=d.values[c];L.elementMouseover({point:e,series:d,pos:[l(o(e,c))+g.left,m(p(e,c))+g.top],seriesIndex:b.series,pointIndex:c})}).on("mouseout",function(b,c){if(N||!a[b.series])return 0;var d=a[b.series],e=d.values[c];L.elementMouseout({point:e,series:d,seriesIndex:b.series,pointIndex:c})});N=!1}var P=h-g.left-g.right,Q=i-g.top-g.bottom,R=d3.select(this);a.forEach(function(a,b){a.values.forEach(function(a){a.series=b})});var S=E&&F&&I?[]:d3.merge(a.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(E||d3.extent(S.map(function(a){return a.x}).concat(t))),z&&a[0]?l.range(G||[(P*A+P)/(2*a[0].values.length),P-P*(1+A)/(2*a[0].values.length)]):l.range(G||[0,P]),m.domain(F||d3.extent(S.map(function(a){return a.y}).concat(u))).range(H||[Q,0]),n.domain(I||d3.extent(S.map(function(a){return a.size}).concat(v))).range(J||[16,256]),(l.domain()[0]===l.domain()[1]||m.domain()[0]===m.domain()[1])&&(K=!0),l.domain()[0]===l.domain()[1]&&(l.domain()[0]?l.domain([l.domain()[0]-.01*l.domain()[0],l.domain()[1]+.01*l.domain()[1]]):l.domain([-1,1])),m.domain()[0]===m.domain()[1]&&(m.domain()[0]?m.domain([m.domain()[0]-.01*m.domain()[0],m.domain()[1]+.01*m.domain()[1]]):m.domain([-1,1])),isNaN(l.domain()[0])&&l.domain([-1,1]),isNaN(m.domain()[0])&&m.domain([-1,1]),b=b||l,d=d||m,e=e||n;var T=R.selectAll("g.nv-wrap.nv-scatter").data([a]),U=T.enter().append("g").attr("class","nvd3 nv-wrap nv-scatter nv-chart-"+k+(K?" nv-single-point":"")),V=U.append("defs"),W=U.append("g"),X=T.select("g");W.append("g").attr("class","nv-groups"),W.append("g").attr("class","nv-point-paths"),T.attr("transform","translate("+g.left+","+g.top+")"),V.append("clipPath").attr("id","nv-edge-clip-"+k).append("rect"),T.select("#nv-edge-clip-"+k+" rect").attr("width",P).attr("height",Q),X.attr("clip-path",B?"url(#nv-edge-clip-"+k+")":""),N=!0;var Y=T.select(".nv-groups").selectAll(".nv-group").data(function(a){return a},function(a){return a.key});if(Y.enter().append("g").style("stroke-opacity",1e-6).style("fill-opacity",1e-6),Y.exit().remove(),Y.attr("class",function(a,b){return"nv-group nv-series-"+b}).classed("hover",function(a){return a.hover}),Y.transition().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),s){var Z=Y.selectAll("circle.nv-point").data(function(a){return a.values},x);Z.enter().append("circle").style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("cx",function(a,d){return c.utils.NaNtoZero(b(o(a,d)))}).attr("cy",function(a,b){return c.utils.NaNtoZero(d(p(a,b)))}).attr("r",function(a,b){return Math.sqrt(n(q(a,b))/Math.PI)}),Z.exit().remove(),Y.exit().selectAll("path.nv-point").transition().attr("cx",function(a,b){return c.utils.NaNtoZero(l(o(a,b)))}).attr("cy",function(a,b){return c.utils.NaNtoZero(m(p(a,b)))}).remove(),Z.each(function(a,b){d3.select(this).classed("nv-point",!0).classed("nv-point-"+b,!0).classed("hover",!1)}),Z.transition().attr("cx",function(a,b){return c.utils.NaNtoZero(l(o(a,b)))}).attr("cy",function(a,b){return c.utils.NaNtoZero(m(p(a,b)))}).attr("r",function(a,b){return Math.sqrt(n(q(a,b))/Math.PI)})}else{var Z=Y.selectAll("path.nv-point").data(function(a){return a.values});Z.enter().append("path").style("fill",function(a){return a.color}).style("stroke",function(a){return a.color}).attr("transform",function(a,c){return"translate("+b(o(a,c))+","+d(p(a,c))+")"}).attr("d",d3.svg.symbol().type(r).size(function(a,b){return n(q(a,b))})),Z.exit().remove(),Y.exit().selectAll("path.nv-point").transition().attr("transform",function(a,b){return"translate("+l(o(a,b))+","+m(p(a,b))+")"}).remove(),Z.each(function(a,b){d3.select(this).classed("nv-point",!0).classed("nv-point-"+b,!0).classed("hover",!1)}),Z.transition().attr("transform",function(a,b){return"translate("+l(o(a,b))+","+m(p(a,b))+")"}).attr("d",d3.svg.symbol().type(r).size(function(a,b){return n(q(a,b))}))}clearTimeout(f),f=setTimeout(O,300),b=l.copy(),d=m.copy(),e=n.copy()}),a}var b,d,e,f,g={top:0,right:0,bottom:0,left:0},h=960,i=500,j=c.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=!0,t=[],u=[],v=[],w=!0,x=null,y=function(a){return!a.notActive},z=!1,A=.1,B=!1,C=!0,D=function(){return 25},E=null,F=null,G=null,H=null,I=null,J=null,K=!1,L=d3.dispatch("elementClick","elementMouseover","elementMouseout"),M=!0,N=!1;return a.clearHighlights=function(){d3.selectAll(".nv-chart-"+k+" .nv-point.hover").classed("hover",!1)},a.highlightPoint=function(a,b,c){d3.select(".nv-chart-"+k+" .nv-series-"+a+" .nv-point-"+b).classed("hover",c)},L.on("elementMouseover.point",function(b){w&&a.highlightPoint(b.seriesIndex,b.pointIndex,!0)}),L.on("elementMouseout.point",function(b){w&&a.highlightPoint(b.seriesIndex,b.pointIndex,!1)}),a.dispatch=L,a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(o=d3.functor(b),a):o},a.y=function(b){return arguments.length?(p=d3.functor(b),a):p},a.size=function(b){return arguments.length?(q=d3.functor(b),a):q},a.margin=function(b){return arguments.length?(g.top="undefined"!=typeof b.top?b.top:g.top,g.right="undefined"!=typeof b.right?b.right:g.right,g.bottom="undefined"!=typeof b.bottom?b.bottom:g.bottom,g.left="undefined"!=typeof b.left?b.left:g.left,a):g},a.width=function(b){return arguments.length?(h=b,a):h},a.height=function(b){return arguments.length?(i=b,a):i},a.xScale=function(b){return arguments.length?(l=b,a):l},a.yScale=function(b){return arguments.length?(m=b,a):m},a.zScale=function(b){return arguments.length?(n=b,a):n},a.xDomain=function(b){return arguments.length?(E=b,a):E},a.yDomain=function(b){return arguments.length?(F=b,a):F},a.sizeDomain=function(b){return arguments.length?(I=b,a):I},a.xRange=function(b){return arguments.length?(G=b,a):G},a.yRange=function(b){return arguments.length?(H=b,a):H},a.sizeRange=function(b){return arguments.length?(J=b,a):J},a.forceX=function(b){return arguments.length?(t=b,a):t},a.forceY=function(b){return arguments.length?(u=b,a):u},a.forceSize=function(b){return arguments.length?(v=b,a):v},a.interactive=function(b){return arguments.length?(w=b,a):w},a.pointKey=function(b){return arguments.length?(x=b,a):x},a.pointActive=function(b){return arguments.length?(y=b,a):y},a.padData=function(b){return arguments.length?(z=b,a):z},a.padDataOuter=function(b){return arguments.length?(A=b,a):A},a.clipEdge=function(b){return arguments.length?(B=b,a):B},a.clipVoronoi=function(b){return arguments.length?(C=b,a):C},a.useVoronoi=function(b){return arguments.length?(M=b,M===!1&&(C=!1),a):M},a.clipRadius=function(b){return arguments.length?(D=b,a):D},a.color=function(b){return arguments.length?(j=c.utils.getColor(b),a):j},a.shape=function(b){return arguments.length?(r=b,a):r},a.onlyCircles=function(b){return arguments.length?(s=b,a):s},a.id=function(b){return arguments.length?(k=b,a):k},a.singlePoint=function(b){return arguments.length?(K=b,a):K},a},c.models.scatterChart=function(){"use strict";function a(c){return c.each(function(c){function B(){if(z)return U.select(".nv-point-paths").style("pointer-events","all"),!1;U.select(".nv-point-paths").style("pointer-events","none");var a=d3.mouse(this);n.distortion(y).focus(a[0]),o.distortion(y).focus(a[1]),U.select(".nv-scatterWrap").call(b),u&&U.select(".nv-x.nv-axis").call(d),v&&U.select(".nv-y.nv-axis").call(e),U.select(".nv-distributionX").datum(c.filter(function(a){return!a.disabled})).call(h),U.select(".nv-distributionY").datum(c.filter(function(a){return!a.disabled})).call(i)}var C=d3.select(this),D=this,N=(k||parseInt(C.style("width"))||960)-j.left-j.right,O=(l||parseInt(C.style("height"))||400)-j.top-j.bottom;if(a.update=function(){C.transition().duration(I).call(a)},a.container=this,E.disabled=c.map(function(a){return!!a.disabled}),!F){var P;F={};for(P in E)F[P]=E[P]instanceof Array?E[P].slice(0):E[P]}if(!(c&&c.length&&c.filter(function(a){return a.values.length}).length)){var Q=C.selectAll(".nv-noData").data([H]);return Q.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),Q.attr("x",j.left+N/2).attr("y",j.top+O/2).text(function(a){return a}),a}C.selectAll(".nv-noData").remove(),J=J||n,K=K||o;var R=C.selectAll("g.nv-wrap.nv-scatterChart").data([c]),S=R.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+b.id()),T=S.append("g"),U=R.select("g");if(T.append("rect").attr("class","nvd3 nv-background"),T.append("g").attr("class","nv-x nv-axis"),T.append("g").attr("class","nv-y nv-axis"),T.append("g").attr("class","nv-scatterWrap"),T.append("g").attr("class","nv-distWrap"),T.append("g").attr("class","nv-legendWrap"),T.append("g").attr("class","nv-controlsWrap"),t){var V=x?N/2:N;f.width(V),R.select(".nv-legendWrap").datum(c).call(f),j.top!=f.height()&&(j.top=f.height(),O=(l||parseInt(C.style("height"))||400)-j.top-j.bottom),R.select(".nv-legendWrap").attr("transform","translate("+(N-V)+","+-j.top+")")}if(x&&(g.width(180).color(["#444"]),U.select(".nv-controlsWrap").datum(M).attr("transform","translate(0,"+-j.top+")").call(g)),R.attr("transform","translate("+j.left+","+j.top+")"),w&&U.select(".nv-y.nv-axis").attr("transform","translate("+N+",0)"),b.width(N).height(O).color(c.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!c[b].disabled})),0!==p&&b.xDomain(null),0!==q&&b.yDomain(null),R.select(".nv-scatterWrap").datum(c.filter(function(a){return!a.disabled})).call(b),0!==p){var W=n.domain()[1]-n.domain()[0];b.xDomain([n.domain()[0]-p*W,n.domain()[1]+p*W])}if(0!==q){var X=o.domain()[1]-o.domain()[0];b.yDomain([o.domain()[0]-q*X,o.domain()[1]+q*X])}(0!==q||0!==p)&&R.select(".nv-scatterWrap").datum(c.filter(function(a){return!a.disabled})).call(b),u&&(d.scale(n).ticks(d.ticks()&&d.ticks().length?d.ticks():N/100).tickSize(-O,0),U.select(".nv-x.nv-axis").attr("transform","translate(0,"+o.range()[0]+")").call(d)),v&&(e.scale(o).ticks(e.ticks()&&e.ticks().length?e.ticks():O/36).tickSize(-N,0),U.select(".nv-y.nv-axis").call(e)),r&&(h.getData(b.x()).scale(n).width(N).color(c.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!c[b].disabled})),T.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),U.select(".nv-distributionX").attr("transform","translate(0,"+o.range()[0]+")").datum(c.filter(function(a){return!a.disabled})).call(h)),s&&(i.getData(b.y()).scale(o).width(O).color(c.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!c[b].disabled})),T.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),U.select(".nv-distributionY").attr("transform","translate("+(w?N:-i.size())+",0)").datum(c.filter(function(a){return!a.disabled})).call(i)),d3.fisheye&&(U.select(".nv-background").attr("width",N).attr("height",O),U.select(".nv-background").on("mousemove",B),U.select(".nv-background").on("click",function(){z=!z}),b.dispatch.on("elementClick.freezeFisheye",function(){z=!z})),g.dispatch.on("legendClick",function(c){c.disabled=!c.disabled,y=c.disabled?0:2.5,U.select(".nv-background").style("pointer-events",c.disabled?"none":"all"),U.select(".nv-point-paths").style("pointer-events",c.disabled?"all":"none"),c.disabled?(n.distortion(y).focus(0),o.distortion(y).focus(0),U.select(".nv-scatterWrap").call(b),U.select(".nv-x.nv-axis").call(d),U.select(".nv-y.nv-axis").call(e)):z=!1,a.update()}),f.dispatch.on("stateChange",function(b){E.disabled=b.disabled,G.stateChange(E),a.update()}),b.dispatch.on("elementMouseover.tooltip",function(a){d3.select(".nv-chart-"+b.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",function(){return a.pos[1]-O}),d3.select(".nv-chart-"+b.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.pos[0]+h.size()),a.pos=[a.pos[0]+j.left,a.pos[1]+j.top],G.tooltipShow(a)}),G.on("tooltipShow",function(a){A&&L(a,D.parentNode)}),G.on("changeState",function(b){"undefined"!=typeof b.disabled&&(c.forEach(function(a,c){a.disabled=b.disabled[c]}),E.disabled=b.disabled),a.update()}),J=n.copy(),K=o.copy()}),a}var b=c.models.scatter(),d=c.models.axis(),e=c.models.axis(),f=c.models.legend(),g=c.models.legend(),h=c.models.distribution(),i=c.models.distribution(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=c.utils.defaultColor(),n=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):b.xScale(),o=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):b.yScale(),p=0,q=0,r=!1,s=!1,t=!0,u=!0,v=!0,w=!1,x=!!d3.fisheye,y=0,z=!1,A=!0,B=function(a,b){return""+b+" "},C=function(a,b,c){return""+c+" "},D=null,E={},F=null,G=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),H="No Data Available.",I=250;b.xScale(n).yScale(o),d.orient("bottom").tickPadding(10),e.orient(w?"right":"left").tickPadding(10),h.axis("x"),i.axis("y"),g.updateState(!1);var J,K,L=function(f,g){var h=f.pos[0]+(g.offsetLeft||0),i=f.pos[1]+(g.offsetTop||0),k=f.pos[0]+(g.offsetLeft||0),l=o.range()[0]+j.top+(g.offsetTop||0),m=n.range()[0]+j.left+(g.offsetLeft||0),p=f.pos[1]+(g.offsetTop||0),q=d.tickFormat()(b.x()(f.point,f.pointIndex)),r=e.tickFormat()(b.y()(f.point,f.pointIndex));null!=B&&c.tooltip.show([k,l],B(f.series.key,q,r,f,a),"n",1,g,"x-nvtooltip"),null!=C&&c.tooltip.show([m,p],C(f.series.key,q,r,f,a),"e",1,g,"y-nvtooltip"),null!=D&&c.tooltip.show([h,i],D(f.series.key,q,r,f,a),f.value<0?"n":"s",null,g)},M=[{key:"Magnify",disabled:!0}];return b.dispatch.on("elementMouseout.tooltip",function(a){G.tooltipHide(a),d3.select(".nv-chart-"+b.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),d3.select(".nv-chart-"+b.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",i.size())}),G.on("tooltipHide",function(){A&&c.tooltip.cleanup()}),a.dispatch=G,a.scatter=b,a.legend=f,a.controls=g,a.xAxis=d,a.yAxis=e,a.distX=h,a.distY=i,d3.rebind(a,b,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(j.top="undefined"!=typeof b.top?b.top:j.top,j.right="undefined"!=typeof b.right?b.right:j.right,j.bottom="undefined"!=typeof b.bottom?b.bottom:j.bottom,j.left="undefined"!=typeof b.left?b.left:j.left,a):j},a.width=function(b){return arguments.length?(k=b,a):k},a.height=function(b){return arguments.length?(l=b,a):l},a.color=function(b){return arguments.length?(m=c.utils.getColor(b),f.color(m),h.color(m),i.color(m),a):m},a.showDistX=function(b){return arguments.length?(r=b,a):r},a.showDistY=function(b){return arguments.length?(s=b,a):s},a.showControls=function(b){return arguments.length?(x=b,a):x},a.showLegend=function(b){return arguments.length?(t=b,a):t},a.showXAxis=function(b){return arguments.length?(u=b,a):u},a.showYAxis=function(b){return arguments.length?(v=b,a):v},a.rightAlignYAxis=function(b){return arguments.length?(w=b,e.orient(b?"right":"left"),a):w},a.fisheye=function(b){return arguments.length?(y=b,a):y},a.xPadding=function(b){return arguments.length?(p=b,a):p},a.yPadding=function(b){return arguments.length?(q=b,a):q},a.tooltips=function(b){return arguments.length?(A=b,a):A},a.tooltipContent=function(b){return arguments.length?(D=b,a):D},a.tooltipXContent=function(b){return arguments.length?(B=b,a):B},a.tooltipYContent=function(b){return arguments.length?(C=b,a):C},a.state=function(b){return arguments.length?(E=b,a):E},a.defaultState=function(b){return arguments.length?(F=b,a):F},a.noData=function(b){return arguments.length?(H=b,a):H},a.transitionDuration=function(b){return arguments.length?(I=b,a):I},a},c.models.scatterPlusLineChart=function(){"use strict";function a(c){return c.each(function(c){function z(){if(x)return S.select(".nv-point-paths").style("pointer-events","all"),!1;S.select(".nv-point-paths").style("pointer-events","none");var a=d3.mouse(this);n.distortion(w).focus(a[0]),o.distortion(w).focus(a[1]),S.select(".nv-scatterWrap").datum(c.filter(function(a){return!a.disabled})).call(b),s&&S.select(".nv-x.nv-axis").call(d),t&&S.select(".nv-y.nv-axis").call(e),S.select(".nv-distributionX").datum(c.filter(function(a){return!a.disabled})).call(h),S.select(".nv-distributionY").datum(c.filter(function(a){return!a.disabled})).call(i)}var A=d3.select(this),B=this,L=(k||parseInt(A.style("width"))||960)-j.left-j.right,M=(l||parseInt(A.style("height"))||400)-j.top-j.bottom;if(a.update=function(){A.transition().duration(G).call(a)},a.container=this,C.disabled=c.map(function(a){return!!a.disabled}),!D){var N;D={};for(N in C)D[N]=C[N]instanceof Array?C[N].slice(0):C[N]}if(!(c&&c.length&&c.filter(function(a){return a.values.length}).length)){var O=A.selectAll(".nv-noData").data([F]);return O.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),O.attr("x",j.left+L/2).attr("y",j.top+M/2).text(function(a){return a}),a}A.selectAll(".nv-noData").remove(),n=b.xScale(),o=b.yScale(),H=H||n,I=I||o;var P=A.selectAll("g.nv-wrap.nv-scatterChart").data([c]),Q=P.enter().append("g").attr("class","nvd3 nv-wrap nv-scatterChart nv-chart-"+b.id()),R=Q.append("g"),S=P.select("g");R.append("rect").attr("class","nvd3 nv-background").style("pointer-events","none"),R.append("g").attr("class","nv-x nv-axis"),R.append("g").attr("class","nv-y nv-axis"),R.append("g").attr("class","nv-scatterWrap"),R.append("g").attr("class","nv-regressionLinesWrap"),R.append("g").attr("class","nv-distWrap"),R.append("g").attr("class","nv-legendWrap"),R.append("g").attr("class","nv-controlsWrap"),P.attr("transform","translate("+j.left+","+j.top+")"),u&&S.select(".nv-y.nv-axis").attr("transform","translate("+L+",0)"),r&&(f.width(L/2),P.select(".nv-legendWrap").datum(c).call(f),j.top!=f.height()&&(j.top=f.height(),M=(l||parseInt(A.style("height"))||400)-j.top-j.bottom),P.select(".nv-legendWrap").attr("transform","translate("+L/2+","+-j.top+")")),v&&(g.width(180).color(["#444"]),S.select(".nv-controlsWrap").datum(K).attr("transform","translate(0,"+-j.top+")").call(g)),b.width(L).height(M).color(c.map(function(a,b){return a.color||m(a,b)
-}).filter(function(a,b){return!c[b].disabled})),P.select(".nv-scatterWrap").datum(c.filter(function(a){return!a.disabled})).call(b),P.select(".nv-regressionLinesWrap").attr("clip-path","url(#nv-edge-clip-"+b.id()+")");var T=P.select(".nv-regressionLinesWrap").selectAll(".nv-regLines").data(function(a){return a});T.enter().append("g").attr("class","nv-regLines");var U=T.selectAll(".nv-regLine").data(function(a){return[a]});U.enter().append("line").attr("class","nv-regLine").style("stroke-opacity",0),U.transition().attr("x1",n.range()[0]).attr("x2",n.range()[1]).attr("y1",function(a){return o(n.domain()[0]*a.slope+a.intercept)}).attr("y2",function(a){return o(n.domain()[1]*a.slope+a.intercept)}).style("stroke",function(a,b,c){return m(a,c)}).style("stroke-opacity",function(a){return a.disabled||"undefined"==typeof a.slope||"undefined"==typeof a.intercept?0:1}),s&&(d.scale(n).ticks(d.ticks()?d.ticks():L/100).tickSize(-M,0),S.select(".nv-x.nv-axis").attr("transform","translate(0,"+o.range()[0]+")").call(d)),t&&(e.scale(o).ticks(e.ticks()?e.ticks():M/36).tickSize(-L,0),S.select(".nv-y.nv-axis").call(e)),p&&(h.getData(b.x()).scale(n).width(L).color(c.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!c[b].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionX"),S.select(".nv-distributionX").attr("transform","translate(0,"+o.range()[0]+")").datum(c.filter(function(a){return!a.disabled})).call(h)),q&&(i.getData(b.y()).scale(o).width(M).color(c.map(function(a,b){return a.color||m(a,b)}).filter(function(a,b){return!c[b].disabled})),R.select(".nv-distWrap").append("g").attr("class","nv-distributionY"),S.select(".nv-distributionY").attr("transform","translate("+(u?L:-i.size())+",0)").datum(c.filter(function(a){return!a.disabled})).call(i)),d3.fisheye&&(S.select(".nv-background").attr("width",L).attr("height",M),S.select(".nv-background").on("mousemove",z),S.select(".nv-background").on("click",function(){x=!x}),b.dispatch.on("elementClick.freezeFisheye",function(){x=!x})),g.dispatch.on("legendClick",function(c){c.disabled=!c.disabled,w=c.disabled?0:2.5,S.select(".nv-background").style("pointer-events",c.disabled?"none":"all"),S.select(".nv-point-paths").style("pointer-events",c.disabled?"all":"none"),c.disabled?(n.distortion(w).focus(0),o.distortion(w).focus(0),S.select(".nv-scatterWrap").call(b),S.select(".nv-x.nv-axis").call(d),S.select(".nv-y.nv-axis").call(e)):x=!1,a.update()}),f.dispatch.on("stateChange",function(b){C=b,E.stateChange(C),a.update()}),b.dispatch.on("elementMouseover.tooltip",function(a){d3.select(".nv-chart-"+b.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",a.pos[1]-M),d3.select(".nv-chart-"+b.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",a.pos[0]+h.size()),a.pos=[a.pos[0]+j.left,a.pos[1]+j.top],E.tooltipShow(a)}),E.on("tooltipShow",function(a){y&&J(a,B.parentNode)}),E.on("changeState",function(b){"undefined"!=typeof b.disabled&&(c.forEach(function(a,c){a.disabled=b.disabled[c]}),C.disabled=b.disabled),a.update()}),H=n.copy(),I=o.copy()}),a}var b=c.models.scatter(),d=c.models.axis(),e=c.models.axis(),f=c.models.legend(),g=c.models.legend(),h=c.models.distribution(),i=c.models.distribution(),j={top:30,right:20,bottom:50,left:75},k=null,l=null,m=c.utils.defaultColor(),n=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):b.xScale(),o=d3.fisheye?d3.fisheye.scale(d3.scale.linear).distortion(0):b.yScale(),p=!1,q=!1,r=!0,s=!0,t=!0,u=!1,v=!!d3.fisheye,w=0,x=!1,y=!0,z=function(a,b){return""+b+" "},A=function(a,b,c){return""+c+" "},B=function(a,b,c,d){return""+a+" "+""+d+"
"},C={},D=null,E=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),F="No Data Available.",G=250;b.xScale(n).yScale(o),d.orient("bottom").tickPadding(10),e.orient(u?"right":"left").tickPadding(10),h.axis("x"),i.axis("y"),g.updateState(!1);var H,I,J=function(f,g){var h=f.pos[0]+(g.offsetLeft||0),i=f.pos[1]+(g.offsetTop||0),k=f.pos[0]+(g.offsetLeft||0),l=o.range()[0]+j.top+(g.offsetTop||0),m=n.range()[0]+j.left+(g.offsetLeft||0),p=f.pos[1]+(g.offsetTop||0),q=d.tickFormat()(b.x()(f.point,f.pointIndex)),r=e.tickFormat()(b.y()(f.point,f.pointIndex));null!=z&&c.tooltip.show([k,l],z(f.series.key,q,r,f,a),"n",1,g,"x-nvtooltip"),null!=A&&c.tooltip.show([m,p],A(f.series.key,q,r,f,a),"e",1,g,"y-nvtooltip"),null!=B&&c.tooltip.show([h,i],B(f.series.key,q,r,f.point.tooltip,f,a),f.value<0?"n":"s",null,g)},K=[{key:"Magnify",disabled:!0}];return b.dispatch.on("elementMouseout.tooltip",function(a){E.tooltipHide(a),d3.select(".nv-chart-"+b.id()+" .nv-series-"+a.seriesIndex+" .nv-distx-"+a.pointIndex).attr("y1",0),d3.select(".nv-chart-"+b.id()+" .nv-series-"+a.seriesIndex+" .nv-disty-"+a.pointIndex).attr("x2",i.size())}),E.on("tooltipHide",function(){y&&c.tooltip.cleanup()}),a.dispatch=E,a.scatter=b,a.legend=f,a.controls=g,a.xAxis=d,a.yAxis=e,a.distX=h,a.distY=i,d3.rebind(a,b,"id","interactive","pointActive","x","y","shape","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","sizeRange","forceX","forceY","forceSize","clipVoronoi","clipRadius","useVoronoi"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(j.top="undefined"!=typeof b.top?b.top:j.top,j.right="undefined"!=typeof b.right?b.right:j.right,j.bottom="undefined"!=typeof b.bottom?b.bottom:j.bottom,j.left="undefined"!=typeof b.left?b.left:j.left,a):j},a.width=function(b){return arguments.length?(k=b,a):k},a.height=function(b){return arguments.length?(l=b,a):l},a.color=function(b){return arguments.length?(m=c.utils.getColor(b),f.color(m),h.color(m),i.color(m),a):m},a.showDistX=function(b){return arguments.length?(p=b,a):p},a.showDistY=function(b){return arguments.length?(q=b,a):q},a.showControls=function(b){return arguments.length?(v=b,a):v},a.showLegend=function(b){return arguments.length?(r=b,a):r},a.showXAxis=function(b){return arguments.length?(s=b,a):s},a.showYAxis=function(b){return arguments.length?(t=b,a):t},a.rightAlignYAxis=function(b){return arguments.length?(u=b,e.orient(b?"right":"left"),a):u},a.fisheye=function(b){return arguments.length?(w=b,a):w},a.tooltips=function(b){return arguments.length?(y=b,a):y},a.tooltipContent=function(b){return arguments.length?(B=b,a):B},a.tooltipXContent=function(b){return arguments.length?(z=b,a):z},a.tooltipYContent=function(b){return arguments.length?(A=b,a):A},a.state=function(b){return arguments.length?(C=b,a):C},a.defaultState=function(b){return arguments.length?(D=b,a):D},a.noData=function(b){return arguments.length?(F=b,a):F},a.transitionDuration=function(b){return arguments.length?(G=b,a):G},a},c.models.sparkline=function(){"use strict";function a(c){return c.each(function(a){var c=h-g.left-g.right,j=i-g.top-g.bottom,p=d3.select(this);k.domain(b||d3.extent(a,m)).range(e||[0,c]),l.domain(d||d3.extent(a,n)).range(f||[j,0]);var q=p.selectAll("g.nv-wrap.nv-sparkline").data([a]),r=q.enter().append("g").attr("class","nvd3 nv-wrap nv-sparkline");r.append("g"),q.select("g"),q.attr("transform","translate("+g.left+","+g.top+")");var s=q.selectAll("path").data(function(a){return[a]});s.enter().append("path"),s.exit().remove(),s.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 t=q.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})});t.enter().append("circle"),t.exit().remove(),t.attr("cx",function(a){return k(m(a,a.pointIndex))}).attr("cy",function(a){return l(n(a,a.pointIndex))}).attr("r",2).attr("class",function(a){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"})}),a}var b,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=c.utils.getColor(["#000"]);return a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(g.top="undefined"!=typeof b.top?b.top:g.top,g.right="undefined"!=typeof b.right?b.right:g.right,g.bottom="undefined"!=typeof b.bottom?b.bottom:g.bottom,g.left="undefined"!=typeof b.left?b.left:g.left,a):g},a.width=function(b){return arguments.length?(h=b,a):h},a.height=function(b){return arguments.length?(i=b,a):i},a.x=function(b){return arguments.length?(m=d3.functor(b),a):m},a.y=function(b){return arguments.length?(n=d3.functor(b),a):n},a.xScale=function(b){return arguments.length?(k=b,a):k},a.yScale=function(b){return arguments.length?(l=b,a):l},a.xDomain=function(c){return arguments.length?(b=c,a):b},a.yDomain=function(b){return arguments.length?(d=b,a):d},a.xRange=function(b){return arguments.length?(e=b,a):e},a.yRange=function(b){return arguments.length?(f=b,a):f},a.animate=function(b){return arguments.length?(j=b,a):j},a.color=function(b){return arguments.length?(o=c.utils.getColor(b),a):o},a},c.models.sparklinePlus=function(){"use strict";function a(c){return c.each(function(m){function q(){if(!j){var a=A.selectAll(".nv-hoverValue").data(i),c=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("+b(e.x()(m[a],a))+",0)"}).transition().duration(250).style("stroke-opacity",1).style("fill-opacity",1),i.length&&(c.append("line").attr("x1",0).attr("y1",-f.top).attr("x2",0).attr("y2",u),c.append("text").attr("class","nv-xValue").attr("x",-6).attr("y",-f.top).attr("text-anchor","end").attr("dy",".9em"),A.select(".nv-hoverValue .nv-xValue").text(k(e.x()(m[i[0]],i[0]))),c.append("text").attr("class","nv-yValue").attr("x",6).attr("y",-f.top).attr("text-anchor","start").attr("dy",".9em"),A.select(".nv-hoverValue .nv-yValue").text(l(e.y()(m[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]=g}for(c=0;f>c;++c)h[c]=0;return h}}),a}var b,d,e={top:0,right:0,bottom:0,left:0},f=960,g=500,h=c.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=c.models.scatter(),r=d3.dispatch("tooltipShow","tooltipHide","areaClick","areaMouseover","areaMouseout");return q.size(2.2).sizeDomain([2.2,2.2]),q.dispatch.on("elementClick.area",function(a){r.areaClick(a)}),q.dispatch.on("elementMouseover.tooltip",function(a){a.pos=[a.pos[0]+e.left,a.pos[1]+e.top],r.tooltipShow(a)}),q.dispatch.on("elementMouseout.tooltip",function(a){r.tooltipHide(a)}),a.dispatch=r,a.scatter=q,d3.rebind(a,q,"interactive","size","xScale","yScale","zScale","xDomain","yDomain","xRange","yRange","sizeDomain","forceX","forceY","forceSize","clipVoronoi","useVoronoi","clipRadius","highlightPoint","clearHighlights"),a.options=c.utils.optionsFunc.bind(a),a.x=function(b){return arguments.length?(j=d3.functor(b),a):j},a.y=function(b){return arguments.length?(k=d3.functor(b),a):k},a.margin=function(b){return arguments.length?(e.top="undefined"!=typeof b.top?b.top:e.top,e.right="undefined"!=typeof b.right?b.right:e.right,e.bottom="undefined"!=typeof b.bottom?b.bottom:e.bottom,e.left="undefined"!=typeof b.left?b.left:e.left,a):e},a.width=function(b){return arguments.length?(f=b,a):f},a.height=function(b){return arguments.length?(g=b,a):g},a.clipEdge=function(b){return arguments.length?(p=b,a):p},a.color=function(b){return arguments.length?(h=c.utils.getColor(b),a):h},a.offset=function(b){return arguments.length?(m=b,a):m},a.order=function(b){return arguments.length?(n=b,a):n},a.style=function(b){if(!arguments.length)return l;switch(l=b){case"stack":a.offset("zero"),a.order("default");break;case"stream":a.offset("wiggle"),a.order("inside-out");break;case"stream-center":a.offset("silhouette"),a.order("inside-out");break;case"expand":a.offset("expand"),a.order("default");break;case"stack_percent":a.offset(a.d3_stackedOffset_stackPercent),a.order("default")}return a},a.interpolate=function(b){return arguments.length?(o=b,a):o},a},c.models.stackedAreaChart=function(){"use strict";function a(v){return v.each(function(v){var G=d3.select(this),H=this,I=(l||parseInt(G.style("width"))||960)-k.left-k.right,J=(m||parseInt(G.style("height"))||400)-k.top-k.bottom;if(a.update=function(){G.transition().duration(E).call(a)},a.container=this,x.disabled=v.map(function(a){return!!a.disabled}),!y){var K;y={};for(K in x)y[K]=x[K]instanceof Array?x[K].slice(0):x[K]}if(!(v&&v.length&&v.filter(function(a){return a.values.length}).length)){var L=G.selectAll(".nv-noData").data([z]);return L.enter().append("text").attr("class","nvd3 nv-noData").attr("dy","-.7em").style("text-anchor","middle"),L.attr("x",k.left+I/2).attr("y",k.top+J/2).text(function(a){return a}),a}G.selectAll(".nv-noData").remove(),b=e.xScale(),d=e.yScale();var M=G.selectAll("g.nv-wrap.nv-stackedAreaChart").data([v]),N=M.enter().append("g").attr("class","nvd3 nv-wrap nv-stackedAreaChart").append("g"),O=M.select("g");if(N.append("rect").style("opacity",0),N.append("g").attr("class","nv-x nv-axis"),N.append("g").attr("class","nv-y nv-axis"),N.append("g").attr("class","nv-stackedWrap"),N.append("g").attr("class","nv-legendWrap"),N.append("g").attr("class","nv-controlsWrap"),N.append("g").attr("class","nv-interactive"),O.select("rect").attr("width",I).attr("height",J),p){var P=o?I-B:I;h.width(P),O.select(".nv-legendWrap").datum(v).call(h),k.top!=h.height()&&(k.top=h.height(),J=(m||parseInt(G.style("height"))||400)-k.top-k.bottom),O.select(".nv-legendWrap").attr("transform","translate("+(I-P)+","+-k.top+")")}if(o){var Q=[{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=260*(C.length/3),Q=Q.filter(function(a){return-1!==C.indexOf(a.metaKey)}),i.width(B).color(["#444","#444","#444"]),O.select(".nv-controlsWrap").datum(Q).call(i),k.top!=Math.max(i.height(),h.height())&&(k.top=Math.max(i.height(),h.height()),J=(m||parseInt(G.style("height"))||400)-k.top-k.bottom),O.select(".nv-controlsWrap").attr("transform","translate(0,"+-k.top+")")}M.attr("transform","translate("+k.left+","+k.top+")"),s&&O.select(".nv-y.nv-axis").attr("transform","translate("+I+",0)"),t&&(j.width(I).height(J).margin({left:k.left,top:k.top}).svgContainer(G).xScale(b),M.select(".nv-interactive").call(j)),e.width(I).height(J);var R=O.select(".nv-stackedWrap").datum(v);R.transition().call(e),q&&(f.scale(b).ticks(I/100).tickSize(-J,0),O.select(".nv-x.nv-axis").attr("transform","translate(0,"+J+")"),O.select(".nv-x.nv-axis").transition().duration(0).call(f)),r&&(g.scale(d).ticks("wiggle"==e.offset()?0:J/36).tickSize(-I,0).setTickFormat("expand"==e.style()||"stack_percent"==e.style()?d3.format("%"):w),O.select(".nv-y.nv-axis").transition().duration(0).call(g)),e.dispatch.on("areaClick.toggle",function(b){1===v.filter(function(a){return!a.disabled}).length?v.forEach(function(a){a.disabled=!1}):v.forEach(function(a,c){a.disabled=c!=b.seriesIndex}),x.disabled=v.map(function(a){return!!a.disabled}),A.stateChange(x),a.update()}),h.dispatch.on("stateChange",function(b){x.disabled=b.disabled,A.stateChange(x),a.update()}),i.dispatch.on("legendClick",function(b){b.disabled&&(Q=Q.map(function(a){return a.disabled=!0,a}),b.disabled=!1,e.style(b.style),x.style=e.style(),A.stateChange(x),a.update())}),j.dispatch.on("elementMousemove",function(b){e.clearHighlights();var d,h,i,l=[];if(v.filter(function(a,b){return a.seriesIndex=b,!a.disabled}).forEach(function(f,g){h=c.interactiveBisect(f.values,b.pointXValue,a.x()),e.highlightPoint(g,h,!0);var j=f.values[h];if("undefined"!=typeof j){"undefined"==typeof d&&(d=j),"undefined"==typeof i&&(i=a.xScale()(a.x()(j,h)));var k="expand"==e.style()?j.display.y:a.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=a.yScale().invert(b.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?(o=b,void 0):void 0}),null!=o&&(l[o].highlight=!0)}var p=f.tickFormat()(a.x()(d,h)),q="expand"==e.style()?function(a){return d3.format(".1%")(a)}:function(a){return g.tickFormat()(a)};j.tooltip.position({left:i+k.left,top:b.mouseY+k.top}).chartContainer(H.parentNode).enabled(u).valueFormatter(q).data({value:p,series:l})(),j.renderGuideLine(i)}),j.dispatch.on("elementMouseout",function(){A.tooltipHide(),e.clearHighlights()}),A.on("tooltipShow",function(a){u&&F(a,H.parentNode)}),A.on("changeState",function(b){"undefined"!=typeof b.disabled&&(v.forEach(function(a,c){a.disabled=b.disabled[c]}),x.disabled=b.disabled),"undefined"!=typeof b.style&&e.style(b.style),a.update()})}),a}var b,d,e=c.models.stackedArea(),f=c.models.axis(),g=c.models.axis(),h=c.models.legend(),i=c.models.legend(),j=c.interactiveGuideline(),k={top:30,right:25,bottom:50,left:60},l=null,m=null,n=c.utils.defaultColor(),o=!0,p=!0,q=!0,r=!0,s=!1,t=!1,u=!0,v=function(a,b,c){return""+a+" "+""+c+" on "+b+"
"},w=d3.format(",.2f"),x={style:e.style()},y=null,z="No Data Available.",A=d3.dispatch("tooltipShow","tooltipHide","stateChange","changeState"),B=250,C=["Stacked","Stream","Expanded"],D={},E=250;f.orient("bottom").tickPadding(7),g.orient(s?"right":"left"),i.updateState(!1);var F=function(b,d){var h=b.pos[0]+(d.offsetLeft||0),i=b.pos[1]+(d.offsetTop||0),j=f.tickFormat()(e.x()(b.point,b.pointIndex)),k=g.tickFormat()(e.y()(b.point,b.pointIndex)),l=v(b.series.key,j,k,b,a);c.tooltip.show([h,i],l,b.value<0?"n":"s",null,d)};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&&c.tooltip.cleanup()}),a.dispatch=A,a.stacked=e,a.legend=h,a.controls=i,a.xAxis=f,a.yAxis=g,a.interactiveLayer=j,d3.rebind(a,e,"x","y","size","xScale","yScale","xDomain","yDomain","xRange","yRange","sizeDomain","interactive","useVoronoi","offset","order","style","clipEdge","forceX","forceY","forceSize","interpolate"),a.options=c.utils.optionsFunc.bind(a),a.margin=function(b){return arguments.length?(k.top="undefined"!=typeof b.top?b.top:k.top,k.right="undefined"!=typeof b.right?b.right:k.right,k.bottom="undefined"!=typeof b.bottom?b.bottom:k.bottom,k.left="undefined"!=typeof b.left?b.left:k.left,a):k},a.width=function(b){return arguments.length?(l=b,a):l},a.height=function(b){return arguments.length?(m=b,a):m},a.color=function(b){return arguments.length?(n=c.utils.getColor(b),h.color(n),e.color(n),a):n},a.showControls=function(b){return arguments.length?(o=b,a):o},a.showLegend=function(b){return arguments.length?(p=b,a):p},a.showXAxis=function(b){return arguments.length?(q=b,a):q},a.showYAxis=function(b){return arguments.length?(r=b,a):r},a.rightAlignYAxis=function(b){return arguments.length?(s=b,g.orient(b?"right":"left"),a):s},a.useInteractiveGuideline=function(b){return arguments.length?(t=b,b===!0&&(a.interactive(!1),a.useVoronoi(!1)),a):t},a.tooltip=function(b){return arguments.length?(v=b,a):v},a.tooltips=function(b){return arguments.length?(u=b,a):u},a.tooltipContent=function(b){return arguments.length?(v=b,a):v},a.state=function(b){return arguments.length?(x=b,a):x},a.defaultState=function(b){return arguments.length?(y=b,a):y},a.noData=function(b){return arguments.length?(z=b,a):z},a.transitionDuration=function(b){return arguments.length?(E=b,a):E},a.controlsData=function(b){return arguments.length?(C=b,a):C},a.controlLabels=function(b){return arguments.length?"object"!=typeof b?D:(D=b,a):D},g.setTickFormat=g.tickFormat,g.tickFormat=function(a){return arguments.length?(w=a,g):w},a}}();
\ No newline at end of file
diff --git a/modoboa/extensions/stats/static/stats/js/rickshaw.js b/modoboa/extensions/stats/static/stats/js/rickshaw.js
new file mode 100644
index 000000000..e9924a43a
--- /dev/null
+++ b/modoboa/extensions/stats/static/stats/js/rickshaw.js
@@ -0,0 +1,3 @@
+var Rickshaw={namespace:function(namespace,obj){var parts=namespace.split(".");var parent=Rickshaw;for(var i=1,length=parts.length;i=3){if(s.data[2].xthis.window.xMax)isInRange=false;return isInRange}return true};this.onUpdate=function(callback){this.updateCallbacks.push(callback)};this.onConfigure=function(callback){this.configureCallbacks.push(callback)};this.registerRenderer=function(renderer){this._renderers=this._renderers||{};this._renderers[renderer.name]=renderer};this.configure=function(args){this.config=this.config||{};if(args.width||args.height){this.setSize(args)}Rickshaw.keys(this.defaults).forEach(function(k){this.config[k]=k in args?args[k]:k in this?this[k]:this.defaults[k]},this);Rickshaw.keys(this.config).forEach(function(k){this[k]=this.config[k]},this);var renderer=args.renderer||this.renderer&&this.renderer.name||"stack";this.setRenderer(renderer,args);this.configureCallbacks.forEach(function(callback){callback(args)})};this.setRenderer=function(r,args){if(typeof r=="function"){this.renderer=new r({graph:self});this.registerRenderer(this.renderer)}else{if(!this._renderers[r]){throw"couldn't find renderer "+r}this.renderer=this._renderers[r]}if(typeof args=="object"){this.renderer.configure(args)}};this.setSize=function(args){args=args||{};if(typeof window!==undefined){var style=window.getComputedStyle(this.element,null);var elementWidth=parseInt(style.getPropertyValue("width"),10);var elementHeight=parseInt(style.getPropertyValue("height"),10)}this.width=args.width||elementWidth||400;this.height=args.height||elementHeight||250;this.vis&&this.vis.attr("width",this.width).attr("height",this.height)};this.initialize(args)};Rickshaw.namespace("Rickshaw.Fixtures.Color");Rickshaw.Fixtures.Color=function(){this.schemes={};this.schemes.spectrum14=["#ecb796","#dc8f70","#b2a470","#92875a","#716c49","#d2ed82","#bbe468","#a1d05d","#e7cbe6","#d8aad6","#a888c2","#9dc2d3","#649eb9","#387aa3"].reverse();this.schemes.spectrum2000=["#57306f","#514c76","#646583","#738394","#6b9c7d","#84b665","#a7ca50","#bfe746","#e2f528","#fff726","#ecdd00","#d4b11d","#de8800","#de4800","#c91515","#9a0000","#7b0429","#580839","#31082b"];this.schemes.spectrum2001=["#2f243f","#3c2c55","#4a3768","#565270","#6b6b7c","#72957f","#86ad6e","#a1bc5e","#b8d954","#d3e04e","#ccad2a","#cc8412","#c1521d","#ad3821","#8a1010","#681717","#531e1e","#3d1818","#320a1b"];this.schemes.classic9=["#423d4f","#4a6860","#848f39","#a2b73c","#ddcb53","#c5a32f","#7d5836","#963b20","#7c2626","#491d37","#2f254a"].reverse();this.schemes.httpStatus={503:"#ea5029",502:"#d23f14",500:"#bf3613",410:"#efacea",409:"#e291dc",403:"#f457e8",408:"#e121d2",401:"#b92dae",405:"#f47ceb",404:"#a82a9f",400:"#b263c6",301:"#6fa024",302:"#87c32b",307:"#a0d84c",304:"#28b55c",200:"#1a4f74",206:"#27839f",201:"#52adc9",202:"#7c979f",203:"#a5b8bd",204:"#c1cdd1"};this.schemes.colorwheel=["#b5b6a9","#858772","#785f43","#96557e","#4682b4","#65b9ac","#73c03a","#cb513a"].reverse();this.schemes.cool=["#5e9d2f","#73c03a","#4682b4","#7bc3b8","#a9884e","#c1b266","#a47493","#c09fb5"];this.schemes.munin=["#00cc00","#0066b3","#ff8000","#ffcc00","#330099","#990099","#ccff00","#ff0000","#808080","#008f00","#00487d","#b35a00","#b38f00","#6b006b","#8fb300","#b30000","#bebebe","#80ff80","#80c9ff","#ffc080","#ffe680","#aa80ff","#ee00cc","#ff8080","#666600","#ffbfff","#00ffcc","#cc6699","#999900"]};Rickshaw.namespace("Rickshaw.Fixtures.RandomData");Rickshaw.Fixtures.RandomData=function(timeInterval){var addData;timeInterval=timeInterval||1;var lastRandomValue=200;var timeBase=Math.floor((new Date).getTime()/1e3);this.addData=function(data){var randomValue=Math.random()*100+15+lastRandomValue;var index=data[0].length;var counter=1;data.forEach(function(series){var randomVariance=Math.random()*20;var v=randomValue/25+counter++ +(Math.cos(index*counter*11/960)+2)*15+(Math.cos(index/7)+2)*7+(Math.cos(index/17)+2)*1;series.push({x:index*timeInterval+timeBase,y:v+randomVariance})});lastRandomValue=randomValue*.85};this.removeData=function(data){data.forEach(function(series){series.shift()});timeBase+=timeInterval}};Rickshaw.namespace("Rickshaw.Fixtures.Time");Rickshaw.Fixtures.Time=function(){var self=this;this.months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];this.units=[{name:"decade",seconds:86400*365.25*10,formatter:function(d){return parseInt(d.getUTCFullYear()/10,10)*10}},{name:"year",seconds:86400*365.25,formatter:function(d){return d.getUTCFullYear()}},{name:"month",seconds:86400*30.5,formatter:function(d){return self.months[d.getUTCMonth()]}},{name:"week",seconds:86400*7,formatter:function(d){return self.formatDate(d)}},{name:"day",seconds:86400,formatter:function(d){return d.getUTCDate()}},{name:"6 hour",seconds:3600*6,formatter:function(d){return self.formatTime(d)}},{name:"hour",seconds:3600,formatter:function(d){return self.formatTime(d)}},{name:"15 minute",seconds:60*15,formatter:function(d){return self.formatTime(d)}},{name:"minute",seconds:60,formatter:function(d){return d.getUTCMinutes()}},{name:"15 second",seconds:15,formatter:function(d){return d.getUTCSeconds()+"s"}},{name:"second",seconds:1,formatter:function(d){return d.getUTCSeconds()+"s"}},{name:"decisecond",seconds:1/10,formatter:function(d){return d.getUTCMilliseconds()+"ms"}},{name:"centisecond",seconds:1/100,formatter:function(d){return d.getUTCMilliseconds()+"ms"}}];this.unit=function(unitName){return this.units.filter(function(unit){return unitName==unit.name}).shift()};this.formatDate=function(d){return d3.time.format("%b %e")(d)};this.formatTime=function(d){return d.toUTCString().match(/(\d+:\d+):/)[1]};this.ceil=function(time,unit){var date,floor,year;if(unit.name=="month"){date=new Date(time*1e3);floor=Date.UTC(date.getUTCFullYear(),date.getUTCMonth())/1e3;if(floor==time)return time;year=date.getUTCFullYear();var month=date.getUTCMonth();if(month==11){month=0;year=year+1}else{month+=1}return Date.UTC(year,month)/1e3}if(unit.name=="year"){date=new Date(time*1e3);floor=Date.UTC(date.getUTCFullYear(),0)/1e3;if(floor==time)return time;year=date.getUTCFullYear()+1;return Date.UTC(year,0)/1e3}return Math.ceil(time/unit.seconds)*unit.seconds}};Rickshaw.namespace("Rickshaw.Fixtures.Time.Local");Rickshaw.Fixtures.Time.Local=function(){var self=this;this.months=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];this.units=[{name:"decade",seconds:86400*365.25*10,formatter:function(d){return parseInt(d.getFullYear()/10,10)*10}},{name:"year",seconds:86400*365.25,formatter:function(d){return d.getFullYear()}},{name:"month",seconds:86400*30.5,formatter:function(d){return self.months[d.getMonth()]}},{name:"week",seconds:86400*7,formatter:function(d){return self.formatDate(d)}},{name:"day",seconds:86400,formatter:function(d){return d.getDate()}},{name:"6 hour",seconds:3600*6,formatter:function(d){return self.formatTime(d)}},{name:"hour",seconds:3600,formatter:function(d){return self.formatTime(d)}},{name:"15 minute",seconds:60*15,formatter:function(d){return self.formatTime(d)}},{name:"minute",seconds:60,formatter:function(d){return d.getMinutes()}},{name:"15 second",seconds:15,formatter:function(d){return d.getSeconds()+"s"}},{name:"second",seconds:1,formatter:function(d){return d.getSeconds()+"s"}},{name:"decisecond",seconds:1/10,formatter:function(d){return d.getMilliseconds()+"ms"}},{name:"centisecond",seconds:1/100,formatter:function(d){return d.getMilliseconds()+"ms"}}];this.unit=function(unitName){return this.units.filter(function(unit){return unitName==unit.name}).shift()};this.formatDate=function(d){return d3.time.format("%b %e")(d)};this.formatTime=function(d){return d.toString().match(/(\d+:\d+):/)[1]};this.ceil=function(time,unit){var date,floor,year;if(unit.name=="day"){var nearFuture=new Date((time+unit.seconds-1)*1e3);var rounded=new Date(0);rounded.setMilliseconds(0);rounded.setSeconds(0);rounded.setMinutes(0);rounded.setHours(0);rounded.setDate(nearFuture.getDate());rounded.setMonth(nearFuture.getMonth());rounded.setFullYear(nearFuture.getFullYear());return rounded.getTime()/1e3}if(unit.name=="month"){date=new Date(time*1e3);floor=new Date(date.getFullYear(),date.getMonth()).getTime()/1e3;if(floor==time)return time;year=date.getFullYear();var month=date.getMonth();if(month==11){month=0;year=year+1}else{month+=1}return new Date(year,month).getTime()/1e3}if(unit.name=="year"){date=new Date(time*1e3);floor=new Date(date.getUTCFullYear(),0).getTime()/1e3;if(floor==time)return time;year=date.getFullYear()+1;return new Date(year,0).getTime()/1e3}return Math.ceil(time/unit.seconds)*unit.seconds}};Rickshaw.namespace("Rickshaw.Fixtures.Number");Rickshaw.Fixtures.Number.formatKMBT=function(y){var abs_y=Math.abs(y);if(abs_y>=1e12){return y/1e12+"T"}else if(abs_y>=1e9){return y/1e9+"B"}else if(abs_y>=1e6){return y/1e6+"M"}else if(abs_y>=1e3){return y/1e3+"K"}else if(abs_y<1&&y>0){return y.toFixed(2)}else if(abs_y===0){return""}else{return y}};Rickshaw.Fixtures.Number.formatBase1024KMGTP=function(y){var abs_y=Math.abs(y);if(abs_y>=0x4000000000000){return y/0x4000000000000+"P"}else if(abs_y>=1099511627776){return y/1099511627776+"T"}else if(abs_y>=1073741824){return y/1073741824+"G"}else if(abs_y>=1048576){return y/1048576+"M"}else if(abs_y>=1024){return y/1024+"K"}else if(abs_y<1&&y>0){return y.toFixed(2)}else if(abs_y===0){return""}else{return y}};Rickshaw.namespace("Rickshaw.Color.Palette");Rickshaw.Color.Palette=function(args){var color=new Rickshaw.Fixtures.Color;args=args||{};this.schemes={};this.scheme=color.schemes[args.scheme]||args.scheme||color.schemes.colorwheel;this.runningIndex=0;this.generatorIndex=0;if(args.interpolatedStopCount){var schemeCount=this.scheme.length-1;var i,j,scheme=[];for(i=0;iself.graph.x.range()[1]){if(annotation.element){annotation.line.classList.add("offscreen");annotation.element.style.display="none"}annotation.boxes.forEach(function(box){if(box.rangeElement)box.rangeElement.classList.add("offscreen")});return}if(!annotation.element){var element=annotation.element=document.createElement("div");element.classList.add("annotation");this.elements.timeline.appendChild(element);element.addEventListener("click",function(e){element.classList.toggle("active");annotation.line.classList.toggle("active");annotation.boxes.forEach(function(box){if(box.rangeElement)box.rangeElement.classList.toggle("active")})},false)}annotation.element.style.left=left+"px";annotation.element.style.display="block";annotation.boxes.forEach(function(box){var element=box.element;if(!element){element=box.element=document.createElement("div");element.classList.add("content");element.innerHTML=box.content;annotation.element.appendChild(element);annotation.line=document.createElement("div");annotation.line.classList.add("annotation_line");self.graph.element.appendChild(annotation.line);if(box.end){box.rangeElement=document.createElement("div");box.rangeElement.classList.add("annotation_range");self.graph.element.appendChild(box.rangeElement)}}if(box.end){var annotationRangeStart=left;var annotationRangeEnd=Math.min(self.graph.x(box.end),self.graph.x.range()[1]);if(annotationRangeStart>annotationRangeEnd){annotationRangeEnd=left;annotationRangeStart=Math.max(self.graph.x(box.end),self.graph.x.range()[0])}var annotationRangeWidth=annotationRangeEnd-annotationRangeStart;box.rangeElement.style.left=annotationRangeStart+"px";box.rangeElement.style.width=annotationRangeWidth+"px";box.rangeElement.classList.remove("offscreen")}annotation.line.classList.remove("offscreen");annotation.line.style.left=left+"px"})},this)};this.graph.onUpdate(function(){self.update()})};Rickshaw.namespace("Rickshaw.Graph.Axis.Time");Rickshaw.Graph.Axis.Time=function(args){var self=this;this.graph=args.graph;this.elements=[];this.ticksTreatment=args.ticksTreatment||"plain";this.fixedTimeUnit=args.timeUnit;var time=args.timeFixture||new Rickshaw.Fixtures.Time;this.appropriateTimeUnit=function(){var unit;var units=time.units;var domain=this.graph.x.domain();var rangeSeconds=domain[1]-domain[0];units.forEach(function(u){if(Math.floor(rangeSeconds/u.seconds)>=2){unit=unit||u}});return unit||time.units[time.units.length-1]};this.tickOffsets=function(){var domain=this.graph.x.domain();var unit=this.fixedTimeUnit||this.appropriateTimeUnit();var count=Math.ceil((domain[1]-domain[0])/unit.seconds);var runningTick=domain[0];var offsets=[];for(var i=0;iself.graph.x.range()[1])return;var element=document.createElement("div");element.style.left=self.graph.x(o.value)+"px";element.classList.add("x_tick");element.classList.add(self.ticksTreatment);var title=document.createElement("div");title.classList.add("title");title.innerHTML=o.unit.formatter(new Date(o.value*1e3));element.appendChild(title);self.graph.element.appendChild(element);self.elements.push(element)})};this.graph.onUpdate(function(){self.render()})};Rickshaw.namespace("Rickshaw.Graph.Axis.X");Rickshaw.Graph.Axis.X=function(args){var self=this;var berthRate=.1;this.initialize=function(args){this.graph=args.graph;this.orientation=args.orientation||"top";this.pixelsPerTick=args.pixelsPerTick||75;if(args.ticks)this.staticTicks=args.ticks;if(args.tickValues)this.tickValues=args.tickValues;this.tickSize=args.tickSize||4;this.ticksTreatment=args.ticksTreatment||"plain";if(args.element){this.element=args.element;this._discoverSize(args.element,args);this.vis=d3.select(args.element).append("svg:svg").attr("height",this.height).attr("width",this.width).attr("class","rickshaw_graph x_axis_d3");this.element=this.vis[0][0];this.element.style.position="relative";this.setSize({width:args.width,height:args.height})}else{this.vis=this.graph.vis}this.graph.onUpdate(function(){self.render()})};this.setSize=function(args){args=args||{};if(!this.element)return;this._discoverSize(this.element.parentNode,args);this.vis.attr("height",this.height).attr("width",this.width*(1+berthRate));var berth=Math.floor(this.width*berthRate/2);this.element.style.left=-1*berth+"px"};this.render=function(){if(this._renderWidth!==undefined&&this.graph.width!==this._renderWidth)this.setSize({auto:true});var axis=d3.svg.axis().scale(this.graph.x).orient(this.orientation);axis.tickFormat(args.tickFormat||function(x){return x});if(this.tickValues)axis.tickValues(this.tickValues);this.ticks=this.staticTicks||Math.floor(this.graph.width/this.pixelsPerTick);var berth=Math.floor(this.width*berthRate/2)||0;var transform;if(this.orientation=="top"){var yOffset=this.height||this.graph.height;transform="translate("+berth+","+yOffset+")"}else{transform="translate("+berth+", 0)"}if(this.element){this.vis.selectAll("*").remove()}this.vis.append("svg:g").attr("class",["x_ticks_d3",this.ticksTreatment].join(" ")).attr("transform",transform).call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(this.tickSize));var gridSize=(this.orientation=="bottom"?1:-1)*this.graph.height;this.graph.vis.append("svg:g").attr("class","x_grid_d3").call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(gridSize)).selectAll("text").each(function(){this.parentNode.setAttribute("data-x-value",this.textContent)});this._renderHeight=this.graph.height};this._discoverSize=function(element,args){if(typeof window!=="undefined"){var style=window.getComputedStyle(element,null);var elementHeight=parseInt(style.getPropertyValue("height"),10);if(!args.auto){var elementWidth=parseInt(style.getPropertyValue("width"),10)}}this.width=(args.width||elementWidth||this.graph.width)*(1+berthRate);this.height=args.height||elementHeight||40};this.initialize(args)};Rickshaw.namespace("Rickshaw.Graph.Axis.Y");Rickshaw.Graph.Axis.Y=Rickshaw.Class.create({initialize:function(args){this.graph=args.graph;this.orientation=args.orientation||"right";this.pixelsPerTick=args.pixelsPerTick||75;if(args.ticks)this.staticTicks=args.ticks;if(args.tickValues)this.tickValues=args.tickValues;this.tickSize=args.tickSize||4;this.ticksTreatment=args.ticksTreatment||"plain";this.tickFormat=args.tickFormat||function(y){return y};this.berthRate=.1;if(args.element){this.element=args.element;this.vis=d3.select(args.element).append("svg:svg").attr("class","rickshaw_graph y_axis");this.element=this.vis[0][0];this.element.style.position="relative";this.setSize({width:args.width,height:args.height})}else{this.vis=this.graph.vis}var self=this;this.graph.onUpdate(function(){self.render()})},setSize:function(args){args=args||{};if(!this.element)return;if(typeof window!=="undefined"){var style=window.getComputedStyle(this.element.parentNode,null);var elementWidth=parseInt(style.getPropertyValue("width"),10);if(!args.auto){var elementHeight=parseInt(style.getPropertyValue("height"),10)}}this.width=args.width||elementWidth||this.graph.width*this.berthRate;this.height=args.height||elementHeight||this.graph.height;this.vis.attr("width",this.width).attr("height",this.height*(1+this.berthRate));var berth=this.height*this.berthRate;if(this.orientation=="left"){this.element.style.top=-1*berth+"px"}},render:function(){if(this._renderHeight!==undefined&&this.graph.height!==this._renderHeight)this.setSize({auto:true});this.ticks=this.staticTicks||Math.floor(this.graph.height/this.pixelsPerTick);var axis=this._drawAxis(this.graph.y);this._drawGrid(axis);this._renderHeight=this.graph.height},_drawAxis:function(scale){var axis=d3.svg.axis().scale(scale).orient(this.orientation);axis.tickFormat(this.tickFormat);if(this.tickValues)axis.tickValues(this.tickValues);if(this.orientation=="left"){var berth=this.height*this.berthRate;var transform="translate("+this.width+", "+berth+")"}if(this.element){this.vis.selectAll("*").remove()}this.vis.append("svg:g").attr("class",["y_ticks",this.ticksTreatment].join(" ")).attr("transform",transform).call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(this.tickSize));return axis},_drawGrid:function(axis){var gridSize=(this.orientation=="right"?1:-1)*this.graph.width;this.graph.vis.append("svg:g").attr("class","y_grid").call(axis.ticks(this.ticks).tickSubdivide(0).tickSize(gridSize)).selectAll("text").each(function(){this.parentNode.setAttribute("data-y-value",this.textContent)})}});Rickshaw.namespace("Rickshaw.Graph.Axis.Y.Scaled");Rickshaw.Graph.Axis.Y.Scaled=Rickshaw.Class.create(Rickshaw.Graph.Axis.Y,{initialize:function($super,args){if(typeof args.scale==="undefined"){throw new Error("Scaled requires scale")}this.scale=args.scale;if(typeof args.grid==="undefined"){this.grid=true
+}else{this.grid=args.grid}$super(args)},_drawAxis:function($super,scale){var domain=this.scale.domain();var renderDomain=this.graph.renderer.domain().y;var extents=[Math.min.apply(Math,domain),Math.max.apply(Math,domain)];var extentMap=d3.scale.linear().domain([0,1]).range(extents);var adjExtents=[extentMap(renderDomain[0]),extentMap(renderDomain[1])];var adjustment=d3.scale.linear().domain(extents).range(adjExtents);var adjustedScale=this.scale.copy().domain(domain.map(adjustment)).range(scale.range());return $super(adjustedScale)},_drawGrid:function($super,axis){if(this.grid){$super(axis)}}});Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Highlight");Rickshaw.Graph.Behavior.Series.Highlight=function(args){this.graph=args.graph;this.legend=args.legend;var self=this;var colorSafe={};var activeLine=null;var disabledColor=args.disabledColor||function(seriesColor){return d3.interpolateRgb(seriesColor,d3.rgb("#d8d8d8"))(.8).toString()};this.addHighlightEvents=function(l){l.element.addEventListener("mouseover",function(e){if(activeLine)return;else activeLine=l;self.legend.lines.forEach(function(line){if(l===line){if(self.graph.renderer.unstack&&(line.series.renderer?line.series.renderer.unstack:true)){var seriesIndex=self.graph.series.indexOf(line.series);line.originalIndex=seriesIndex;var series=self.graph.series.splice(seriesIndex,1)[0];self.graph.series.push(series)}return}colorSafe[line.series.name]=colorSafe[line.series.name]||line.series.color;line.series.color=disabledColor(line.series.color)});self.graph.update()},false);l.element.addEventListener("mouseout",function(e){if(!activeLine)return;else activeLine=null;self.legend.lines.forEach(function(line){if(l===line&&line.hasOwnProperty("originalIndex")){var series=self.graph.series.pop();self.graph.series.splice(line.originalIndex,0,series);delete line.originalIndex}if(colorSafe[line.series.name]){line.series.color=colorSafe[line.series.name]}});self.graph.update()},false)};if(this.legend){this.legend.lines.forEach(function(l){self.addHighlightEvents(l)})}};Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Order");Rickshaw.Graph.Behavior.Series.Order=function(args){this.graph=args.graph;this.legend=args.legend;var self=this;if(typeof window.$=="undefined"){throw"couldn't find jQuery at window.$"}if(typeof window.$.ui=="undefined"){throw"couldn't find jQuery UI at window.$.ui"}$(function(){$(self.legend.list).sortable({containment:"parent",tolerance:"pointer",update:function(event,ui){var series=[];$(self.legend.list).find("li").each(function(index,item){if(!item.series)return;series.push(item.series)});for(var i=self.graph.series.length-1;i>=0;i--){self.graph.series[i]=series.shift()}self.graph.update()}});$(self.legend.list).disableSelection()});this.graph.onUpdate(function(){var h=window.getComputedStyle(self.legend.element).height;self.legend.element.style.height=h})};Rickshaw.namespace("Rickshaw.Graph.Behavior.Series.Toggle");Rickshaw.Graph.Behavior.Series.Toggle=function(args){this.graph=args.graph;this.legend=args.legend;var self=this;this.addAnchor=function(line){var anchor=document.createElement("a");anchor.innerHTML="✔";anchor.classList.add("action");line.element.insertBefore(anchor,line.element.firstChild);anchor.onclick=function(e){if(line.series.disabled){line.series.enable();line.element.classList.remove("disabled")}else{if(this.graph.series.filter(function(s){return!s.disabled}).length<=1)return;line.series.disable();line.element.classList.add("disabled")}}.bind(this);var label=line.element.getElementsByTagName("span")[0];label.onclick=function(e){var disableAllOtherLines=line.series.disabled;if(!disableAllOtherLines){for(var i=0;idomainX){dataIndex=Math.abs(domainX-data[i].x)0){alignables.forEach(function(el){el.classList.remove("left");el.classList.add("right")});var rightAlignError=this._calcLayoutError(alignables);if(rightAlignError>leftAlignError){alignables.forEach(function(el){el.classList.remove("right");el.classList.add("left")})}}if(typeof this.onRender=="function"){this.onRender(args)}},_calcLayoutError:function(alignables){var parentRect=this.element.parentNode.getBoundingClientRect();var error=0;var alignRight=alignables.forEach(function(el){var rect=el.getBoundingClientRect();if(!rect.width){return}if(rect.right>parentRect.right){error+=rect.right-parentRect.right}if(rect.left=self.previewWidth){frameAfterDrag[0]-=frameAfterDrag[1]-self.previewWidth;frameAfterDrag[1]=self.previewWidth}}self.graphs.forEach(function(graph){var domainScale=d3.scale.linear().interpolate(d3.interpolateRound).domain([0,self.previewWidth]).range(graph.dataDomain());var windowAfterDrag=[domainScale(frameAfterDrag[0]),domainScale(frameAfterDrag[1])];if(frameAfterDrag[0]===0){windowAfterDrag[0]=undefined}if(frameAfterDrag[1]===self.previewWidth){windowAfterDrag[1]=undefined}graph.window.xMin=windowAfterDrag[0];graph.window.xMax=windowAfterDrag[1];graph.update()})}function onMousedown(){drag.target=d3.event.target;drag.start=self._getClientXFromEvent(d3.event,drag);self.frameBeforeDrag=self.currentFrame.slice();d3.event.preventDefault?d3.event.preventDefault():d3.event.returnValue=false;d3.select(document).on("mousemove.rickshaw_range_slider_preview",onMousemove);d3.select(document).on("mouseup.rickshaw_range_slider_preview",onMouseup);d3.select(document).on("touchmove.rickshaw_range_slider_preview",onMousemove);d3.select(document).on("touchend.rickshaw_range_slider_preview",onMouseup);d3.select(document).on("touchcancel.rickshaw_range_slider_preview",onMouseup)}function onMousedownLeftHandle(datum,index){drag.left=true;onMousedown()}function onMousedownRightHandle(datum,index){drag.right=true;onMousedown()}function onMousedownMiddleHandle(datum,index){drag.left=true;drag.right=true;drag.rigid=true;onMousedown()}function onMouseup(datum,index){d3.select(document).on("mousemove.rickshaw_range_slider_preview",null);d3.select(document).on("mouseup.rickshaw_range_slider_preview",null);d3.select(document).on("touchmove.rickshaw_range_slider_preview",null);d3.select(document).on("touchend.rickshaw_range_slider_preview",null);d3.select(document).on("touchcancel.rickshaw_range_slider_preview",null);delete self.frameBeforeDrag;drag.left=false;drag.right=false;drag.rigid=false}element.select("rect.left_handle").on("mousedown",onMousedownLeftHandle);element.select("rect.right_handle").on("mousedown",onMousedownRightHandle);element.select("rect.middle_handle").on("mousedown",onMousedownMiddleHandle);element.select("rect.left_handle").on("touchstart",onMousedownLeftHandle);element.select("rect.right_handle").on("touchstart",onMousedownRightHandle);element.select("rect.middle_handle").on("touchstart",onMousedownMiddleHandle)},_getClientXFromEvent:function(event,drag){switch(event.type){case"touchstart":case"touchmove":var touchList=event.changedTouches;var touch=null;for(var touchIndex=0;touchIndexyMax)yMax=y});if(!series.length)return;if(series[0].xxMax)xMax=series[series.length-1].x});xMin-=(xMax-xMin)*this.padding.left;xMax+=(xMax-xMin)*this.padding.right;yMin=this.graph.min==="auto"?yMin:this.graph.min||0;yMax=this.graph.max===undefined?yMax:this.graph.max;if(this.graph.min==="auto"||yMin<0){yMin-=(yMax-yMin)*this.padding.bottom}if(this.graph.max===undefined){yMax+=(yMax-yMin)*this.padding.top}return{x:[xMin,xMax],y:[yMin,yMax]}},render:function(args){args=args||{};var graph=this.graph;var series=args.series||graph.series;var vis=args.vis||graph.vis;vis.selectAll("*").remove();var data=series.filter(function(s){return!s.disabled}).map(function(s){return s.stack});var pathNodes=vis.selectAll("path.path").data(data).enter().append("svg:path").classed("path",true).attr("d",this.seriesPathFactory());if(this.stroke){var strokeNodes=vis.selectAll("path.stroke").data(data).enter().append("svg:path").classed("stroke",true).attr("d",this.seriesStrokeFactory())}var i=0;series.forEach(function(series){if(series.disabled)return;series.path=pathNodes[0][i];if(this.stroke)series.stroke=strokeNodes[0][i];this._styleSeries(series);i++},this)},_styleSeries:function(series){var fill=this.fill?series.color:"none";var stroke=this.stroke?series.color:"none";series.path.setAttribute("fill",fill);series.path.setAttribute("stroke",stroke);series.path.setAttribute("stroke-width",this.strokeWidth);if(series.className){d3.select(series.path).classed(series.className,true)}if(series.className&&this.stroke){d3.select(series.stroke).classed(series.className,true)}},configure:function(args){args=args||{};Rickshaw.keys(this.defaults()).forEach(function(key){if(!args.hasOwnProperty(key)){this[key]=this[key]||this.graph[key]||this.defaults()[key];return}if(typeof this.defaults()[key]=="object"){Rickshaw.keys(this.defaults()[key]).forEach(function(k){this[key][k]=args[key][k]!==undefined?args[key][k]:this[key][k]!==undefined?this[key][k]:this.defaults()[key][k]},this)}else{this[key]=args[key]!==undefined?args[key]:this[key]!==undefined?this[key]:this.graph[key]!==undefined?this.graph[key]:this.defaults()[key]}},this)},setStrokeWidth:function(strokeWidth){if(strokeWidth!==undefined){this.strokeWidth=strokeWidth}},setTension:function(tension){if(tension!==undefined){this.tension=tension}}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Line");Rickshaw.Graph.Renderer.Line=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"line",defaults:function($super){return Rickshaw.extend($super(),{unstack:true,fill:false,stroke:true})},seriesPathFactory:function(){var graph=this.graph;var factory=d3.svg.line().x(function(d){return graph.x(d.x)}).y(function(d){return graph.y(d.y)}).interpolate(this.graph.interpolation).tension(this.tension);factory.defined&&factory.defined(function(d){return d.y!==null});return factory}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Stack");Rickshaw.Graph.Renderer.Stack=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"stack",defaults:function($super){return Rickshaw.extend($super(),{fill:true,stroke:false,unstack:false})},seriesPathFactory:function(){var graph=this.graph;var factory=d3.svg.area().x(function(d){return graph.x(d.x)}).y0(function(d){return graph.y(d.y0)}).y1(function(d){return graph.y(d.y+d.y0)}).interpolate(this.graph.interpolation).tension(this.tension);factory.defined&&factory.defined(function(d){return d.y!==null});return factory}});Rickshaw.namespace("Rickshaw.Graph.Renderer.Bar");Rickshaw.Graph.Renderer.Bar=Rickshaw.Class.create(Rickshaw.Graph.Renderer,{name:"bar",defaults:function($super){var defaults=Rickshaw.extend($super(),{gapSize:.05,unstack:false});delete defaults.tension;return defaults},initialize:function($super,args){args=args||{};this.gapSize=args.gapSize||this.gapSize;$super(args)},domain:function($super){var domain=$super();var frequentInterval=this._frequentInterval(this.graph.stackedData.slice(-1).shift());domain.x[1]+=Number(frequentInterval.magnitude);return domain},barWidth:function(series){var frequentInterval=this._frequentInterval(series.stack);var barWidth=this.graph.x(series.stack[0].x+frequentInterval.magnitude*(1-this.gapSize));return barWidth},render:function(args){args=args||{};var graph=this.graph;var series=args.series||graph.series;var vis=args.vis||graph.vis;vis.selectAll("*").remove();var barWidth=this.barWidth(series.active()[0]);var barXOffset=0;var activeSeriesCount=series.filter(function(s){return!s.disabled}).length;var seriesBarWidth=this.unstack?barWidth/activeSeriesCount:barWidth;var transform=function(d){var matrix=[1,0,0,d.y<0?-1:1,0,d.y<0?graph.y.magnitude(Math.abs(d.y))*2:0];return"matrix("+matrix.join(",")+")"};series.forEach(function(series){if(series.disabled)return;var barWidth=this.barWidth(series);var nodes=vis.selectAll("path").data(series.stack.filter(function(d){return d.y!==null})).enter().append("svg:rect").attr("x",function(d){return graph.x(d.x)+barXOffset}).attr("y",function(d){return graph.y(d.y0+Math.abs(d.y))*(d.y<0?-1:1)}).attr("width",seriesBarWidth).attr("height",function(d){return graph.y.magnitude(Math.abs(d.y))}).attr("transform",transform);Array.prototype.forEach.call(nodes[0],function(n){n.setAttribute("fill",series.color)});if(this.unstack)barXOffset+=seriesBarWidth},this)},_frequentInterval:function(data){var intervalCounts={};for(var i=0;i0){this[0].data.forEach(function(plot){item.data.push({x:plot.x,y:0})})}else if(item.data.length===0){item.data.push({x:this.timeBase-(this.timeInterval||0),y:0})}this.push(item);if(this.legend){this.legend.addLine(this.itemByName(item.name))}},addData:function(data,x){var index=this.getIndex();Rickshaw.keys(data).forEach(function(name){if(!this.itemByName(name)){this.addItem({name:name})}},this);this.forEach(function(item){item.data.push({x:x||(index*this.timeInterval||1)+this.timeBase,y:data[item.name]||0})},this)},getIndex:function(){return this[0]&&this[0].data&&this[0].data.length?this[0].data.length:0},itemByName:function(name){for(var i=0;i1;i--){this.currentSize+=1;this.currentIndex+=1;this.forEach(function(item){item.data.unshift({x:((i-1)*this.timeInterval||1)+this.timeBase,y:0,i:i})},this)}}},addData:function($super,data,x){$super(data,x);this.currentSize+=1;this.currentIndex+=1;if(this.maxDataPoints!==undefined){while(this.currentSize>this.maxDataPoints){this.dropData()}}},dropData:function(){this.forEach(function(item){item.data.splice(0,1)});this.currentSize-=1},getIndex:function(){return this.currentIndex}});
\ No newline at end of file
diff --git a/modoboa/extensions/stats/static/stats/js/stats.js b/modoboa/extensions/stats/static/stats/js/stats.js
index 0580c0a2c..a6d73c711 100644
--- a/modoboa/extensions/stats/static/stats/js/stats.js
+++ b/modoboa/extensions/stats/static/stats/js/stats.js
@@ -6,7 +6,7 @@ Stats.prototype = {
constructor: Stats,
defaults: {
- deflocation: "d3graphs/",
+ deflocation: "graphs/",
language: "en"
},
@@ -80,26 +80,12 @@ Stats.prototype = {
},
graphs_cb: function(data) {
- /*if (data.content) {
- $(".tab-pane.active").html(data.content);
- }*/
- var $container = $("#graphs_mailtraffic");
- $.each(data.graphs, function(id, data) {
- var chart = nv.models.stackedAreaChart();
- //var $svg = $(" ", {id: id});
-
- //$container.append($svg);
- chart.xAxis.axisLabel('Time (s)')
- .tickFormat(d3.format(',r'));
- chart.yAxis.axisLabel('Mail')
- .tickFormat(d3.format('.02f'));
- d3.select('#' + id + ' svg')
- .datum(data)
- .transition().duration(500)
- .call(chart);
-
- //nv.utils.windowResize(chart.update);
- });
+ //this.graphicset = new GraphicSet("#gset", data);
+ if (this.graphic === undefined) {
+ this.graphic = new Graphic(data, {});
+ } else {
+ this.graphic.update(data);
+ }
},
search_domain: function(value) {
diff --git a/modoboa/extensions/stats/templates/stats/graphs.html b/modoboa/extensions/stats/templates/stats/graphs.html
deleted file mode 100644
index 1ea4c5867..000000000
--- a/modoboa/extensions/stats/templates/stats/graphs.html
+++ /dev/null
@@ -1,6 +0,0 @@
-{% load i18n %}
-{% for name in graphs %}
-
-
-{% endfor %}
diff --git a/modoboa/extensions/stats/templates/stats/index.html b/modoboa/extensions/stats/templates/stats/index.html
index 6a13362aa..7fc0ced86 100644
--- a/modoboa/extensions/stats/templates/stats/index.html
+++ b/modoboa/extensions/stats/templates/stats/index.html
@@ -1,13 +1,17 @@
{% extends "twocols.html" %}{% load i18n %}{% load url from future %}
{% block pagetitle %}{% trans "Graphical statistics" %}{% endblock %}
{% block html_head %}
-
+
-
-
+
+
+
+
+