Path: blob/master/sandbox/RFinance2014/libraries/widgets/nvd3/js/nv.d3.js
1433 views
(function(){12var nv = window.nv || {};345nv.version = '1.1.10b';6nv.dev = true //set false when in production78window.nv = nv;910nv.tooltip = {}; // For the tooltip system11nv.utils = {}; // Utility subsystem12nv.models = {}; //stores all the possible models/components13nv.charts = {}; //stores all the ready to use charts14nv.graphs = []; //stores all the graphs currently on the page15nv.logs = {}; //stores some statistics and potential error messages1617nv.dispatch = d3.dispatch('render_start', 'render_end');1819// *************************************************************************20// Development render timers - disabled if dev = false2122if (nv.dev) {23nv.dispatch.on('render_start', function(e) {24nv.logs.startTime = +new Date();25});2627nv.dispatch.on('render_end', function(e) {28nv.logs.endTime = +new Date();29nv.logs.totalTime = nv.logs.endTime - nv.logs.startTime;30nv.log('total', nv.logs.totalTime); // used for development, to keep track of graph generation times31});32}3334// ********************************************35// Public Core NV functions3637// Logs all arguments, and returns the last so you can test things in place38// Note: in IE8 console.log is an object not a function, and if modernizr is used39// then calling Function.prototype.bind with with anything other than a function40// causes a TypeError to be thrown.41nv.log = function() {42if (nv.dev && console.log && console.log.apply)43console.log.apply(console, arguments)44else if (nv.dev && typeof console.log == "function" && Function.prototype.bind) {45var log = Function.prototype.bind.call(console.log, console);46log.apply(console, arguments);47}48return arguments[arguments.length - 1];49};505152nv.render = function render(step) {53step = step || 1; // number of graphs to generate in each timeout loop5455nv.render.active = true;56nv.dispatch.render_start();5758setTimeout(function() {59var chart, graph;6061for (var i = 0; i < step && (graph = nv.render.queue[i]); i++) {62chart = graph.generate();63if (typeof graph.callback == typeof(Function)) graph.callback(chart);64nv.graphs.push(chart);65}6667nv.render.queue.splice(0, i);6869if (nv.render.queue.length) setTimeout(arguments.callee, 0);70else { nv.render.active = false; nv.dispatch.render_end(); }71}, 0);72};7374nv.render.active = false;75nv.render.queue = [];7677nv.addGraph = function(obj) {78if (typeof arguments[0] === typeof(Function))79obj = {generate: arguments[0], callback: arguments[1]};8081nv.render.queue.push(obj);8283if (!nv.render.active) nv.render();84};8586nv.identity = function(d) { return d; };8788nv.strip = function(s) { return s.replace(/(\s|&)/g,''); };8990function daysInMonth(month,year) {91return (new Date(year, month+1, 0)).getDate();92}9394function d3_time_range(floor, step, number) {95return function(t0, t1, dt) {96var time = floor(t0), times = [];97if (time < t0) step(time);98if (dt > 1) {99while (time < t1) {100var date = new Date(+time);101if ((number(date) % dt === 0)) times.push(date);102step(time);103}104} else {105while (time < t1) { times.push(new Date(+time)); step(time); }106}107return times;108};109}110111d3.time.monthEnd = function(date) {112return new Date(date.getFullYear(), date.getMonth(), 0);113};114115d3.time.monthEnds = d3_time_range(d3.time.monthEnd, function(date) {116date.setUTCDate(date.getUTCDate() + 1);117date.setDate(daysInMonth(date.getMonth() + 1, date.getFullYear()));118}, function(date) {119return date.getMonth();120}121);122123/* Utility class to handle creation of an interactive layer.124This places a rectangle on top of the chart. When you mouse move over it, it sends a dispatch125containing the X-coordinate. It can also render a vertical line where the mouse is located.126127dispatch.elementMousemove is the important event to latch onto. It is fired whenever the mouse moves over128the rectangle. The dispatch is given one object which contains the mouseX/Y location.129It also has 'pointXValue', which is the conversion of mouseX to the x-axis scale.130*/131nv.interactiveGuideline = function() {132"use strict";133var tooltip = nv.models.tooltip();134//Public settings135var width = null136, height = null137//Please pass in the bounding chart's top and left margins138//This is important for calculating the correct mouseX/Y positions.139, margin = {left: 0, top: 0}140, xScale = d3.scale.linear()141, yScale = d3.scale.linear()142, dispatch = d3.dispatch('elementMousemove', 'elementMouseout')143, showGuideLine = true144, svgContainer = null145//Must pass in the bounding chart's <svg> container.146//The mousemove event is attached to this container.147;148149//Private variables150var isMSIE = navigator.userAgent.indexOf("MSIE") !== -1 //Check user-agent for Microsoft Internet Explorer.151;152153154function layer(selection) {155selection.each(function(data) {156var container = d3.select(this);157158var availableWidth = (width || 960), availableHeight = (height || 400);159160var wrap = container.selectAll("g.nv-wrap.nv-interactiveLineLayer").data([data]);161var wrapEnter = wrap.enter()162.append("g").attr("class", " nv-wrap nv-interactiveLineLayer");163164165wrapEnter.append("g").attr("class","nv-interactiveGuideLine");166167if (!svgContainer) {168return;169}170171function mouseHandler() {172var d3mouse = d3.mouse(this);173var mouseX = d3mouse[0];174var mouseY = d3mouse[1];175var subtractMargin = true;176var mouseOutAnyReason = false;177if (isMSIE) {178/*179D3.js (or maybe SVG.getScreenCTM) has a nasty bug in Internet Explorer 10.180d3.mouse() returns incorrect X,Y mouse coordinates when mouse moving181over a rect in IE 10.182However, d3.event.offsetX/Y also returns the mouse coordinates183relative to the triggering <rect>. So we use offsetX/Y on IE.184*/185mouseX = d3.event.offsetX;186mouseY = d3.event.offsetY;187188/*189On IE, if you attach a mouse event listener to the <svg> container,190it will actually trigger it for all the child elements (like <path>, <circle>, etc).191When this happens on IE, the offsetX/Y is set to where ever the child element192is located.193As a result, we do NOT need to subtract margins to figure out the mouse X/Y194position under this scenario. Removing the line below *will* cause195the interactive layer to not work right on IE.196*/197if(d3.event.target.tagName !== "svg")198subtractMargin = false;199200if (d3.event.target.className.baseVal.match("nv-legend"))201mouseOutAnyReason = true;202203}204205if(subtractMargin) {206mouseX -= margin.left;207mouseY -= margin.top;208}209210/* If mouseX/Y is outside of the chart's bounds,211trigger a mouseOut event.212*/213if (mouseX < 0 || mouseY < 0214|| mouseX > availableWidth || mouseY > availableHeight215|| (d3.event.relatedTarget && d3.event.relatedTarget.ownerSVGElement === undefined)216|| mouseOutAnyReason217)218{219if (isMSIE) {220if (d3.event.relatedTarget221&& d3.event.relatedTarget.ownerSVGElement === undefined222&& d3.event.relatedTarget.className.match(tooltip.nvPointerEventsClass)) {223return;224}225}226dispatch.elementMouseout({227mouseX: mouseX,228mouseY: mouseY229});230layer.renderGuideLine(null); //hide the guideline231return;232}233234var pointXValue = xScale.invert(mouseX);235dispatch.elementMousemove({236mouseX: mouseX,237mouseY: mouseY,238pointXValue: pointXValue239});240}241242svgContainer243.on("mousemove",mouseHandler, true)244.on("mouseout",mouseHandler,true)245;246247//Draws a vertical guideline at the given X postion.248layer.renderGuideLine = function(x) {249if (!showGuideLine) return;250var line = wrap.select(".nv-interactiveGuideLine")251.selectAll("line")252.data((x != null) ? [nv.utils.NaNtoZero(x)] : [], String);253254line.enter()255.append("line")256.attr("class", "nv-guideline")257.attr("x1", function(d) { return d;})258.attr("x2", function(d) { return d;})259.attr("y1", availableHeight)260.attr("y2",0)261;262line.exit().remove();263264}265});266}267268layer.dispatch = dispatch;269layer.tooltip = tooltip;270271layer.margin = function(_) {272if (!arguments.length) return margin;273margin.top = typeof _.top != 'undefined' ? _.top : margin.top;274margin.left = typeof _.left != 'undefined' ? _.left : margin.left;275return layer;276};277278layer.width = function(_) {279if (!arguments.length) return width;280width = _;281return layer;282};283284layer.height = function(_) {285if (!arguments.length) return height;286height = _;287return layer;288};289290layer.xScale = function(_) {291if (!arguments.length) return xScale;292xScale = _;293return layer;294};295296layer.showGuideLine = function(_) {297if (!arguments.length) return showGuideLine;298showGuideLine = _;299return layer;300};301302layer.svgContainer = function(_) {303if (!arguments.length) return svgContainer;304svgContainer = _;305return layer;306};307308309return layer;310};311312/* Utility class that uses d3.bisect to find the index in a given array, where a search value can be inserted.313This is different from normal bisectLeft; this function finds the nearest index to insert the search value.314315For instance, lets say your array is [1,2,3,5,10,30], and you search for 28.316Normal d3.bisectLeft will return 4, because 28 is inserted after the number 10. But interactiveBisect will return 5317because 28 is closer to 30 than 10.318319Unit tests can be found in: interactiveBisectTest.html320321Has the following known issues:322* Will not work if the data points move backwards (ie, 10,9,8,7, etc) or if the data points are in random order.323* Won't work if there are duplicate x coordinate values.324*/325nv.interactiveBisect = function (values, searchVal, xAccessor) {326"use strict";327if (! values instanceof Array) return null;328if (typeof xAccessor !== 'function') xAccessor = function(d,i) { return d.x;}329330var bisect = d3.bisector(xAccessor).left;331var index = d3.max([0, bisect(values,searchVal) - 1]);332var currentValue = xAccessor(values[index], index);333if (typeof currentValue === 'undefined') currentValue = index;334335if (currentValue === searchVal) return index; //found exact match336337var nextIndex = d3.min([index+1, values.length - 1]);338var nextValue = xAccessor(values[nextIndex], nextIndex);339if (typeof nextValue === 'undefined') nextValue = nextIndex;340341if (Math.abs(nextValue - searchVal) >= Math.abs(currentValue - searchVal))342return index;343else344return nextIndex345};/* Tooltip rendering model for nvd3 charts.346window.nv.models.tooltip is the updated,new way to render tooltips.347348window.nv.tooltip.show is the old tooltip code.349window.nv.tooltip.* also has various helper methods.350*/351(function() {352"use strict";353window.nv.tooltip = {};354355/* Model which can be instantiated to handle tooltip rendering.356Example usage:357var tip = nv.models.tooltip().gravity('w').distance(23)358.data(myDataObject);359360tip(); //just invoke the returned function to render tooltip.361*/362window.nv.models.tooltip = function() {363var content = null //HTML contents of the tooltip. If null, the content is generated via the data variable.364, data = null /* Tooltip data. If data is given in the proper format, a consistent tooltip is generated.365Format of data:366{367key: "Date",368value: "August 2009",369series: [370{371key: "Series 1",372value: "Value 1",373color: "#000"374},375{376key: "Series 2",377value: "Value 2",378color: "#00f"379}380]381382}383384*/385, gravity = 'w' //Can be 'n','s','e','w'. Determines how tooltip is positioned.386, distance = 50 //Distance to offset tooltip from the mouse location.387, snapDistance = 25 //Tolerance allowed before tooltip is moved from its current position (creates 'snapping' effect)388, fixedTop = null //If not null, this fixes the top position of the tooltip.389, classes = null //Attaches additional CSS classes to the tooltip DIV that is created.390, chartContainer = null //Parent DIV, of the SVG Container that holds the chart.391, position = {left: null, top: null} //Relative position of the tooltip inside chartContainer.392, enabled = true //True -> tooltips are rendered. False -> don't render tooltips.393//Generates a unique id when you create a new tooltip() object394, id = "nvtooltip-" + Math.floor(Math.random() * 100000)395;396397//CSS class to specify whether element should not have mouse events.398var nvPointerEventsClass = "nv-pointer-events-none";399400//Format function for the tooltip values column401var valueFormatter = function(d,i) {402return d;403};404405//Format function for the tooltip header value.406var headerFormatter = function(d) {407return d;408};409410//By default, the tooltip model renders a beautiful table inside a DIV.411//You can override this function if a custom tooltip is desired.412var contentGenerator = function(d) {413if (content != null) return content;414415if (d == null) return '';416417var html = "<table><thead><tr><td colspan='3'><strong class='x-value'>" + headerFormatter(d.value) + "</strong></td></tr></thead><tbody>";418if (d.series instanceof Array) {419d.series.forEach(function(item, i) {420html += "<tr>";421html += "<td class='legend-color-guide'><div style='background-color: " + item.color + ";'></div></td>";422html += "<td class='key'>" + item.key + ":</td>";423html += "<td class='value'>" + valueFormatter(item.value,i) + "</td></tr>";424});425}426html += "</tbody></table>";427return html;428};429430var dataSeriesExists = function(d) {431if (d && d.series && d.series.length > 0) return true;432433return false;434};435436//In situations where the chart is in a 'viewBox', re-position the tooltip based on how far chart is zoomed.437function convertViewBoxRatio() {438if (chartContainer) {439var svg = d3.select(chartContainer);440if (svg.node().tagName !== "svg") {441svg = svg.select("svg");442}443var viewBox = (svg.node()) ? svg.attr('viewBox') : null;444if (viewBox) {445viewBox = viewBox.split(' ');446var ratio = parseInt(svg.style('width')) / viewBox[2];447448position.left = position.left * ratio;449position.top = position.top * ratio;450}451}452}453454//Creates new tooltip container, or uses existing one on DOM.455function getTooltipContainer(newContent) {456var body;457if (chartContainer)458body = d3.select(chartContainer);459else460body = d3.select("body");461462var container = body.select(".nvtooltip");463if (container.node() === null) {464//Create new tooltip div if it doesn't exist on DOM.465container = body.append("div")466.attr("class", "nvtooltip " + (classes? classes: "xy-tooltip"))467.attr("id",id)468;469}470471472container.node().innerHTML = newContent;473container.style("top",0).style("left",0).style("opacity",0);474container.selectAll("div, table, td, tr").classed(nvPointerEventsClass,true)475container.classed(nvPointerEventsClass,true);476return container.node();477}478479480481//Draw the tooltip onto the DOM.482function nvtooltip() {483if (!enabled) return;484if (!dataSeriesExists(data)) return;485486convertViewBoxRatio();487488var left = position.left;489var top = (fixedTop != null) ? fixedTop : position.top;490var container = getTooltipContainer(contentGenerator(data));491492if (chartContainer) {493var svgComp = chartContainer.getElementsByTagName("svg")[0];494var boundRect = (svgComp) ? svgComp.getBoundingClientRect() : chartContainer.getBoundingClientRect();495var svgOffset = {left:0,top:0};496if (svgComp) {497var svgBound = svgComp.getBoundingClientRect();498var chartBound = chartContainer.getBoundingClientRect();499svgOffset.top = Math.abs(svgBound.top - chartBound.top);500svgOffset.left = Math.abs(svgBound.left - chartBound.left);501}502//If the parent container is an overflow <div> with scrollbars, subtract the scroll offsets.503//You need to also add any offset between the <svg> element and its containing <div>504//Finally, add any offset of the containing <div> on the whole page.505left += chartContainer.offsetLeft + svgOffset.left - 2*chartContainer.scrollLeft;506top += chartContainer.offsetTop + svgOffset.top - 2*chartContainer.scrollTop;507}508509if (snapDistance && snapDistance > 0) {510top = Math.floor(top/snapDistance) * snapDistance;511}512513nv.tooltip.calcTooltipPosition([left,top], gravity, distance, container);514return nvtooltip;515};516517nvtooltip.nvPointerEventsClass = nvPointerEventsClass;518519nvtooltip.content = function(_) {520if (!arguments.length) return content;521content = _;522return nvtooltip;523};524525nvtooltip.contentGenerator = function(_) {526if (!arguments.length) return contentGenerator;527if (typeof _ === 'function') {528contentGenerator = _;529}530return nvtooltip;531};532533nvtooltip.data = function(_) {534if (!arguments.length) return data;535data = _;536return nvtooltip;537};538539nvtooltip.gravity = function(_) {540if (!arguments.length) return gravity;541gravity = _;542return nvtooltip;543};544545nvtooltip.distance = function(_) {546if (!arguments.length) return distance;547distance = _;548return nvtooltip;549};550551nvtooltip.snapDistance = function(_) {552if (!arguments.length) return snapDistance;553snapDistance = _;554return nvtooltip;555};556557nvtooltip.classes = function(_) {558if (!arguments.length) return classes;559classes = _;560return nvtooltip;561};562563nvtooltip.chartContainer = function(_) {564if (!arguments.length) return chartContainer;565chartContainer = _;566return nvtooltip;567};568569nvtooltip.position = function(_) {570if (!arguments.length) return position;571position.left = (typeof _.left !== 'undefined') ? _.left : position.left;572position.top = (typeof _.top !== 'undefined') ? _.top : position.top;573return nvtooltip;574};575576nvtooltip.fixedTop = function(_) {577if (!arguments.length) return fixedTop;578fixedTop = _;579return nvtooltip;580};581582nvtooltip.enabled = function(_) {583if (!arguments.length) return enabled;584enabled = _;585return nvtooltip;586};587588nvtooltip.valueFormatter = function(_) {589if (!arguments.length) return valueFormatter;590if (typeof _ === 'function') {591valueFormatter = _;592}593return nvtooltip;594};595596nvtooltip.headerFormatter = function(_) {597if (!arguments.length) return headerFormatter;598if (typeof _ === 'function') {599headerFormatter = _;600}601return nvtooltip;602};603604//id() is a read-only function. You can't use it to set the id.605nvtooltip.id = function() {606return id;607};608609610return nvtooltip;611};612613614//Original tooltip.show function. Kept for backward compatibility.615// pos = [left,top]616nv.tooltip.show = function(pos, content, gravity, dist, parentContainer, classes) {617618//Create new tooltip div if it doesn't exist on DOM.619var container = document.createElement('div');620container.className = 'nvtooltip ' + (classes ? classes : 'xy-tooltip');621622var body = parentContainer;623if ( !parentContainer || parentContainer.tagName.match(/g|svg/i)) {624//If the parent element is an SVG element, place tooltip in the <body> element.625body = document.getElementsByTagName('body')[0];626}627628container.style.left = 0;629container.style.top = 0;630container.style.opacity = 0;631container.innerHTML = content;632body.appendChild(container);633634//If the parent container is an overflow <div> with scrollbars, subtract the scroll offsets.635if (parentContainer) {636pos[0] = pos[0] - parentContainer.scrollLeft;637pos[1] = pos[1] - parentContainer.scrollTop;638}639nv.tooltip.calcTooltipPosition(pos, gravity, dist, container);640};641642//Looks up the ancestry of a DOM element, and returns the first NON-svg node.643nv.tooltip.findFirstNonSVGParent = function(Elem) {644while(Elem.tagName.match(/^g|svg$/i) !== null) {645Elem = Elem.parentNode;646}647return Elem;648};649650//Finds the total offsetTop of a given DOM element.651//Looks up the entire ancestry of an element, up to the first relatively positioned element.652nv.tooltip.findTotalOffsetTop = function ( Elem, initialTop ) {653var offsetTop = initialTop;654655do {656if( !isNaN( Elem.offsetTop ) ) {657offsetTop += (Elem.offsetTop);658}659} while( Elem = Elem.offsetParent );660return offsetTop;661};662663//Finds the total offsetLeft of a given DOM element.664//Looks up the entire ancestry of an element, up to the first relatively positioned element.665nv.tooltip.findTotalOffsetLeft = function ( Elem, initialLeft) {666var offsetLeft = initialLeft;667668do {669if( !isNaN( Elem.offsetLeft ) ) {670offsetLeft += (Elem.offsetLeft);671}672} while( Elem = Elem.offsetParent );673return offsetLeft;674};675676//Global utility function to render a tooltip on the DOM.677//pos = [left,top] coordinates of where to place the tooltip, relative to the SVG chart container.678//gravity = how to orient the tooltip679//dist = how far away from the mouse to place tooltip680//container = tooltip DIV681nv.tooltip.calcTooltipPosition = function(pos, gravity, dist, container) {682683var height = parseInt(container.offsetHeight),684width = parseInt(container.offsetWidth),685windowWidth = nv.utils.windowSize().width,686windowHeight = nv.utils.windowSize().height,687scrollTop = window.pageYOffset,688scrollLeft = window.pageXOffset,689left, top;690691windowHeight = window.innerWidth >= document.body.scrollWidth ? windowHeight : windowHeight - 16;692windowWidth = window.innerHeight >= document.body.scrollHeight ? windowWidth : windowWidth - 16;693694gravity = gravity || 's';695dist = dist || 20;696697var tooltipTop = function ( Elem ) {698return nv.tooltip.findTotalOffsetTop(Elem, top);699};700701var tooltipLeft = function ( Elem ) {702return nv.tooltip.findTotalOffsetLeft(Elem,left);703};704705switch (gravity) {706case 'e':707left = pos[0] - width - dist;708top = pos[1] - (height / 2);709var tLeft = tooltipLeft(container);710var tTop = tooltipTop(container);711if (tLeft < scrollLeft) left = pos[0] + dist > scrollLeft ? pos[0] + dist : scrollLeft - tLeft + left;712if (tTop < scrollTop) top = scrollTop - tTop + top;713if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;714break;715case 'w':716left = pos[0] + dist;717top = pos[1] - (height / 2);718var tLeft = tooltipLeft(container);719var tTop = tooltipTop(container);720if (tLeft + width > windowWidth) left = pos[0] - width - dist;721if (tTop < scrollTop) top = scrollTop + 5;722if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;723break;724case 'n':725left = pos[0] - (width / 2) - 5;726top = pos[1] + dist;727var tLeft = tooltipLeft(container);728var tTop = tooltipTop(container);729if (tLeft < scrollLeft) left = scrollLeft + 5;730if (tLeft + width > windowWidth) left = left - width/2 + 5;731if (tTop + height > scrollTop + windowHeight) top = scrollTop + windowHeight - tTop + top - height;732break;733case 's':734left = pos[0] - (width / 2);735top = pos[1] - height - dist;736var tLeft = tooltipLeft(container);737var tTop = tooltipTop(container);738if (tLeft < scrollLeft) left = scrollLeft + 5;739if (tLeft + width > windowWidth) left = left - width/2 + 5;740if (scrollTop > tTop) top = scrollTop;741break;742case 'none':743left = pos[0];744top = pos[1] - dist;745var tLeft = tooltipLeft(container);746var tTop = tooltipTop(container);747break;748}749750751container.style.left = left+'px';752container.style.top = top+'px';753container.style.opacity = 1;754container.style.position = 'absolute';755756return container;757};758759//Global utility function to remove tooltips from the DOM.760nv.tooltip.cleanup = function() {761762// Find the tooltips, mark them for removal by this class (so others cleanups won't find it)763var tooltips = document.getElementsByClassName('nvtooltip');764var purging = [];765while(tooltips.length) {766purging.push(tooltips[0]);767tooltips[0].style.transitionDelay = '0 !important';768tooltips[0].style.opacity = 0;769tooltips[0].className = 'nvtooltip-pending-removal';770}771772setTimeout(function() {773774while (purging.length) {775var removeMe = purging.pop();776removeMe.parentNode.removeChild(removeMe);777}778}, 500);779};780781})();782783nv.utils.windowSize = function() {784// Sane defaults785var size = {width: 640, height: 480};786787// Earlier IE uses Doc.body788if (document.body && document.body.offsetWidth) {789size.width = document.body.offsetWidth;790size.height = document.body.offsetHeight;791}792793// IE can use depending on mode it is in794if (document.compatMode=='CSS1Compat' &&795document.documentElement &&796document.documentElement.offsetWidth ) {797size.width = document.documentElement.offsetWidth;798size.height = document.documentElement.offsetHeight;799}800801// Most recent browsers use802if (window.innerWidth && window.innerHeight) {803size.width = window.innerWidth;804size.height = window.innerHeight;805}806return (size);807};808809810811// Easy way to bind multiple functions to window.onresize812// TODO: give a way to remove a function after its bound, other than removing all of them813nv.utils.windowResize = function(fun){814if (fun === undefined) return;815var oldresize = window.onresize;816817window.onresize = function(e) {818if (typeof oldresize == 'function') oldresize(e);819fun(e);820}821}822823// Backwards compatible way to implement more d3-like coloring of graphs.824// If passed an array, wrap it in a function which implements the old default825// behavior826nv.utils.getColor = function(color) {827if (!arguments.length) return nv.utils.defaultColor(); //if you pass in nothing, get default colors back828829if( Object.prototype.toString.call( color ) === '[object Array]' )830return function(d, i) { return d.color || color[i % color.length]; };831else832return color;833//can't really help it if someone passes rubbish as color834}835836// Default color chooser uses the index of an object as before.837nv.utils.defaultColor = function() {838var colors = d3.scale.category20().range();839return function(d, i) { return d.color || colors[i % colors.length] };840}841842843// Returns a color function that takes the result of 'getKey' for each series and844// looks for a corresponding color from the dictionary,845nv.utils.customTheme = function(dictionary, getKey, defaultColors) {846getKey = getKey || function(series) { return series.key }; // use default series.key if getKey is undefined847defaultColors = defaultColors || d3.scale.category20().range(); //default color function848849var defIndex = defaultColors.length; //current default color (going in reverse)850851return function(series, index) {852var key = getKey(series);853854if (!defIndex) defIndex = defaultColors.length; //used all the default colors, start over855856if (typeof dictionary[key] !== "undefined")857return (typeof dictionary[key] === "function") ? dictionary[key]() : dictionary[key];858else859return defaultColors[--defIndex]; // no match in dictionary, use default color860}861}862863864865// From the PJAX example on d3js.org, while this is not really directly needed866// it's a very cool method for doing pjax, I may expand upon it a little bit,867// open to suggestions on anything that may be useful868nv.utils.pjax = function(links, content) {869d3.selectAll(links).on("click", function() {870history.pushState(this.href, this.textContent, this.href);871load(this.href);872d3.event.preventDefault();873});874875function load(href) {876d3.html(href, function(fragment) {877var target = d3.select(content).node();878target.parentNode.replaceChild(d3.select(fragment).select(content).node(), target);879nv.utils.pjax(links, content);880});881}882883d3.select(window).on("popstate", function() {884if (d3.event.state) load(d3.event.state);885});886}887888/* For situations where we want to approximate the width in pixels for an SVG:text element.889Most common instance is when the element is in a display:none; container.890Forumla is : text.length * font-size * constant_factor891*/892nv.utils.calcApproxTextWidth = function (svgTextElem) {893if (svgTextElem instanceof d3.selection) {894var fontSize = parseInt(svgTextElem.style("font-size").replace("px",""));895var textLength = svgTextElem.text().length;896897return textLength * fontSize * 0.5;898}899return 0;900};901902/* Numbers that are undefined, null or NaN, convert them to zeros.903*/904nv.utils.NaNtoZero = function(n) {905if (typeof n !== 'number'906|| isNaN(n)907|| n === null908|| n === Infinity) return 0;909910return n;911};912913/*914Snippet of code you can insert into each nv.models.* to give you the ability to915do things like:916chart.options({917showXAxis: true,918tooltips: true919});920921To enable in the chart:922chart.options = nv.utils.optionsFunc.bind(chart);923*/924nv.utils.optionsFunc = function(args) {925if (args) {926d3.map(args).forEach((function(key,value) {927if (typeof this[key] === "function") {928this[key](value);929}930}).bind(this));931}932return this;933};nv.models.axis = function() {934"use strict";935//============================================================936// Public Variables with Default Settings937//------------------------------------------------------------938939var axis = d3.svg.axis()940;941942var margin = {top: 0, right: 0, bottom: 0, left: 0}943, width = 75 //only used for tickLabel currently944, height = 60 //only used for tickLabel currently945, scale = d3.scale.linear()946, axisLabelText = null947, showMaxMin = true //TODO: showMaxMin should be disabled on all ordinal scaled axes948, highlightZero = true949, rotateLabels = 0950, rotateYLabel = true951, staggerLabels = false952, isOrdinal = false953, ticks = null954;955956axis957.scale(scale)958.orient('bottom')959.tickFormat(function(d) { return d })960;961962//============================================================963964965//============================================================966// Private Variables967//------------------------------------------------------------968969var scale0;970971//============================================================972973974function chart(selection) {975selection.each(function(data) {976var container = d3.select(this);977978979//------------------------------------------------------------980// Setup containers and skeleton of chart981982var wrap = container.selectAll('g.nv-wrap.nv-axis').data([data]);983var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-axis');984var gEnter = wrapEnter.append('g');985var g = wrap.select('g')986987//------------------------------------------------------------988989990if (ticks !== null)991axis.ticks(ticks);992else if (axis.orient() == 'top' || axis.orient() == 'bottom')993axis.ticks(Math.abs(scale.range()[1] - scale.range()[0]) / 100);994995996//TODO: consider calculating width/height based on whether or not label is added, for reference in charts using this component997998999g.transition().call(axis);10001001scale0 = scale0 || axis.scale();10021003var fmt = axis.tickFormat();1004if (fmt == null) {1005fmt = scale0.tickFormat();1006}10071008var axisLabel = g.selectAll('text.nv-axislabel')1009.data([axisLabelText || null]);1010axisLabel.exit().remove();1011switch (axis.orient()) {1012case 'top':1013axisLabel.enter().append('text').attr('class', 'nv-axislabel');1014var w = (scale.range().length==2) ? scale.range()[1] : (scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]));1015axisLabel1016.attr('text-anchor', 'middle')1017.attr('y', 0)1018.attr('x', w/2);1019if (showMaxMin) {1020var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')1021.data(scale.domain());1022axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text');1023axisMaxMin.exit().remove();1024axisMaxMin1025.attr('transform', function(d,i) {1026return 'translate(' + scale(d) + ',0)'1027})1028.select('text')1029.attr('dy', '0em')1030.attr('y', -axis.tickPadding())1031.attr('text-anchor', 'middle')1032.text(function(d,i) {1033var v = fmt(d);1034return ('' + v).match('NaN') ? '' : v;1035});1036axisMaxMin.transition()1037.attr('transform', function(d,i) {1038return 'translate(' + scale.range()[i] + ',0)'1039});1040}1041break;1042case 'bottom':1043var xLabelMargin = 36;1044var maxTextWidth = 30;1045var xTicks = g.selectAll('g').select("text");1046if (rotateLabels%360) {1047//Calculate the longest xTick width1048xTicks.each(function(d,i){1049var width = this.getBBox().width;1050if(width > maxTextWidth) maxTextWidth = width;1051});1052//Convert to radians before calculating sin. Add 30 to margin for healthy padding.1053var sin = Math.abs(Math.sin(rotateLabels*Math.PI/180));1054var xLabelMargin = (sin ? sin*maxTextWidth : maxTextWidth)+30;1055//Rotate all xTicks1056xTicks1057.attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' })1058.style('text-anchor', rotateLabels%360 > 0 ? 'start' : 'end');1059}1060axisLabel.enter().append('text').attr('class', 'nv-axislabel');1061var w = (scale.range().length==2) ? scale.range()[1] : (scale.range()[scale.range().length-1]+(scale.range()[1]-scale.range()[0]));1062axisLabel1063.attr('text-anchor', 'middle')1064.attr('y', xLabelMargin)1065.attr('x', w/2);1066if (showMaxMin) {1067//if (showMaxMin && !isOrdinal) {1068var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')1069//.data(scale.domain())1070.data([scale.domain()[0], scale.domain()[scale.domain().length - 1]]);1071axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text');1072axisMaxMin.exit().remove();1073axisMaxMin1074.attr('transform', function(d,i) {1075return 'translate(' + (scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0)) + ',0)'1076})1077.select('text')1078.attr('dy', '.71em')1079.attr('y', axis.tickPadding())1080.attr('transform', function(d,i,j) { return 'rotate(' + rotateLabels + ' 0,0)' })1081.style('text-anchor', rotateLabels ? (rotateLabels%360 > 0 ? 'start' : 'end') : 'middle')1082.text(function(d,i) {1083var v = fmt(d);1084return ('' + v).match('NaN') ? '' : v;1085});1086axisMaxMin.transition()1087.attr('transform', function(d,i) {1088//return 'translate(' + scale.range()[i] + ',0)'1089//return 'translate(' + scale(d) + ',0)'1090return 'translate(' + (scale(d) + (isOrdinal ? scale.rangeBand() / 2 : 0)) + ',0)'1091});1092}1093if (staggerLabels)1094xTicks1095.attr('transform', function(d,i) { return 'translate(0,' + (i % 2 == 0 ? '0' : '12') + ')' });10961097break;1098case 'right':1099axisLabel.enter().append('text').attr('class', 'nv-axislabel');1100axisLabel1101.style('text-anchor', rotateYLabel ? 'middle' : 'begin')1102.attr('transform', rotateYLabel ? 'rotate(90)' : '')1103.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 chart1104.attr('x', rotateYLabel ? (scale.range()[0] / 2) : axis.tickPadding());1105if (showMaxMin) {1106var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')1107.data(scale.domain());1108axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text')1109.style('opacity', 0);1110axisMaxMin.exit().remove();1111axisMaxMin1112.attr('transform', function(d,i) {1113return 'translate(0,' + scale(d) + ')'1114})1115.select('text')1116.attr('dy', '.32em')1117.attr('y', 0)1118.attr('x', axis.tickPadding())1119.style('text-anchor', 'start')1120.text(function(d,i) {1121var v = fmt(d);1122return ('' + v).match('NaN') ? '' : v;1123});1124axisMaxMin.transition()1125.attr('transform', function(d,i) {1126return 'translate(0,' + scale.range()[i] + ')'1127})1128.select('text')1129.style('opacity', 1);1130}1131break;1132case 'left':1133/*1134//For dynamically placing the label. Can be used with dynamically-sized chart axis margins1135var yTicks = g.selectAll('g').select("text");1136yTicks.each(function(d,i){1137var labelPadding = this.getBBox().width + axis.tickPadding() + 16;1138if(labelPadding > width) width = labelPadding;1139});1140*/1141axisLabel.enter().append('text').attr('class', 'nv-axislabel');1142axisLabel1143.style('text-anchor', rotateYLabel ? 'middle' : 'end')1144.attr('transform', rotateYLabel ? 'rotate(-90)' : '')1145.attr('y', rotateYLabel ? (-Math.max(margin.left,width) + 12) : -10) //TODO: consider calculating this based on largest tick width... OR at least expose this on chart1146.attr('x', rotateYLabel ? (-scale.range()[0] / 2) : -axis.tickPadding());1147if (showMaxMin) {1148var axisMaxMin = wrap.selectAll('g.nv-axisMaxMin')1149.data(scale.domain());1150axisMaxMin.enter().append('g').attr('class', 'nv-axisMaxMin').append('text')1151.style('opacity', 0);1152axisMaxMin.exit().remove();1153axisMaxMin1154.attr('transform', function(d,i) {1155return 'translate(0,' + scale0(d) + ')'1156})1157.select('text')1158.attr('dy', '.32em')1159.attr('y', 0)1160.attr('x', -axis.tickPadding())1161.attr('text-anchor', 'end')1162.text(function(d,i) {1163var v = fmt(d);1164return ('' + v).match('NaN') ? '' : v;1165});1166axisMaxMin.transition()1167.attr('transform', function(d,i) {1168return 'translate(0,' + scale.range()[i] + ')'1169})1170.select('text')1171.style('opacity', 1);1172}1173break;1174}1175axisLabel1176.text(function(d) { return d });117711781179if (showMaxMin && (axis.orient() === 'left' || axis.orient() === 'right')) {1180//check if max and min overlap other values, if so, hide the values that overlap1181g.selectAll('g') // the g's wrapping each tick1182.each(function(d,i) {1183d3.select(this).select('text').attr('opacity', 1);1184if (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!1185if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL1186d3.select(this).attr('opacity', 0);11871188d3.select(this).select('text').attr('opacity', 0); // Don't remove the ZERO line!!1189}1190});11911192//if Max and Min = 0 only show min, Issue #2811193if (scale.domain()[0] == scale.domain()[1] && scale.domain()[0] == 0)1194wrap.selectAll('g.nv-axisMaxMin')1195.style('opacity', function(d,i) { return !i ? 1 : 0 });11961197}11981199if (showMaxMin && (axis.orient() === 'top' || axis.orient() === 'bottom')) {1200var maxMinRange = [];1201wrap.selectAll('g.nv-axisMaxMin')1202.each(function(d,i) {1203try {1204if (i) // i== 1, max position1205maxMinRange.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)1206else // i==0, min position1207maxMinRange.push(scale(d) + this.getBBox().width + 4)1208}catch (err) {1209if (i) // i== 1, max position1210maxMinRange.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)1211else // i==0, min position1212maxMinRange.push(scale(d) + 4)1213}1214});1215g.selectAll('g') // the g's wrapping each tick1216.each(function(d,i) {1217if (scale(d) < maxMinRange[0] || scale(d) > maxMinRange[1]) {1218if (d > 1e-10 || d < -1e-10) // accounts for minor floating point errors... though could be problematic if the scale is EXTREMELY SMALL1219d3.select(this).remove();1220else1221d3.select(this).select('text').remove(); // Don't remove the ZERO line!!1222}1223});1224}122512261227//highlight zero line ... Maybe should not be an option and should just be in CSS?1228if (highlightZero)1229g.selectAll('.tick')1230.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 technique1231.classed('zero', true);12321233//store old scales for use in transitions on update1234scale0 = scale.copy();12351236});12371238return chart;1239}124012411242//============================================================1243// Expose Public Variables1244//------------------------------------------------------------12451246// expose chart's sub-components1247chart.axis = axis;12481249d3.rebind(chart, axis, 'orient', 'tickValues', 'tickSubdivide', 'tickSize', 'tickPadding', 'tickFormat');1250d3.rebind(chart, scale, 'domain', 'range', 'rangeBand', 'rangeBands'); //these are also accessible by chart.scale(), but added common ones directly for ease of use12511252chart.options = nv.utils.optionsFunc.bind(chart);12531254chart.margin = function(_) {1255if(!arguments.length) return margin;1256margin.top = typeof _.top != 'undefined' ? _.top : margin.top;1257margin.right = typeof _.right != 'undefined' ? _.right : margin.right;1258margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;1259margin.left = typeof _.left != 'undefined' ? _.left : margin.left;1260return chart;1261}12621263chart.width = function(_) {1264if (!arguments.length) return width;1265width = _;1266return chart;1267};12681269chart.ticks = function(_) {1270if (!arguments.length) return ticks;1271ticks = _;1272return chart;1273};12741275chart.height = function(_) {1276if (!arguments.length) return height;1277height = _;1278return chart;1279};12801281chart.axisLabel = function(_) {1282if (!arguments.length) return axisLabelText;1283axisLabelText = _;1284return chart;1285}12861287chart.showMaxMin = function(_) {1288if (!arguments.length) return showMaxMin;1289showMaxMin = _;1290return chart;1291}12921293chart.highlightZero = function(_) {1294if (!arguments.length) return highlightZero;1295highlightZero = _;1296return chart;1297}12981299chart.scale = function(_) {1300if (!arguments.length) return scale;1301scale = _;1302axis.scale(scale);1303isOrdinal = typeof scale.rangeBands === 'function';1304d3.rebind(chart, scale, 'domain', 'range', 'rangeBand', 'rangeBands');1305return chart;1306}13071308chart.rotateYLabel = function(_) {1309if(!arguments.length) return rotateYLabel;1310rotateYLabel = _;1311return chart;1312}13131314chart.rotateLabels = function(_) {1315if(!arguments.length) return rotateLabels;1316rotateLabels = _;1317return chart;1318}13191320chart.staggerLabels = function(_) {1321if (!arguments.length) return staggerLabels;1322staggerLabels = _;1323return chart;1324};13251326//============================================================132713281329return chart;1330}13311332// Chart design based on the recommendations of Stephen Few. Implementation1333// based on the work of Clint Ivy, Jamie Love, and Jason Davies.1334// http://projects.instantcognition.com/protovis/bulletchart/13351336nv.models.bullet = function() {1337"use strict";1338//============================================================1339// Public Variables with Default Settings1340//------------------------------------------------------------13411342var margin = {top: 0, right: 0, bottom: 0, left: 0}1343, orient = 'left' // TODO top & bottom1344, reverse = false1345, ranges = function(d) { return d.ranges }1346, markers = function(d) { return d.markers }1347, measures = function(d) { return d.measures }1348, rangeLabels = function(d) { return d.rangeLabels ? d.rangeLabels : [] }1349, markerLabels = function(d) { return d.markerLabels ? d.markerLabels : [] }1350, measureLabels = function(d) { return d.measureLabels ? d.measureLabels : [] }1351, forceX = [0] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)1352, width = 3801353, height = 301354, tickFormat = null1355, color = nv.utils.getColor(['#1f77b4'])1356, dispatch = d3.dispatch('elementMouseover', 'elementMouseout')1357;13581359//============================================================136013611362function chart(selection) {1363selection.each(function(d, i) {1364var availableWidth = width - margin.left - margin.right,1365availableHeight = height - margin.top - margin.bottom,1366container = d3.select(this);13671368var rangez = ranges.call(this, d, i).slice().sort(d3.descending),1369markerz = markers.call(this, d, i).slice().sort(d3.descending),1370measurez = measures.call(this, d, i).slice().sort(d3.descending),1371rangeLabelz = rangeLabels.call(this, d, i).slice(),1372markerLabelz = markerLabels.call(this, d, i).slice(),1373measureLabelz = measureLabels.call(this, d, i).slice();137413751376//------------------------------------------------------------1377// Setup Scales13781379// Compute the new x-scale.1380var x1 = d3.scale.linear()1381.domain( d3.extent(d3.merge([forceX, rangez])) )1382.range(reverse ? [availableWidth, 0] : [0, availableWidth]);13831384// Retrieve the old x-scale, if this is an update.1385var x0 = this.__chart__ || d3.scale.linear()1386.domain([0, Infinity])1387.range(x1.range());13881389// Stash the new scale.1390this.__chart__ = x1;139113921393var rangeMin = d3.min(rangez), //rangez[2]1394rangeMax = d3.max(rangez), //rangez[0]1395rangeAvg = rangez[1];13961397//------------------------------------------------------------139813991400//------------------------------------------------------------1401// Setup containers and skeleton of chart14021403var wrap = container.selectAll('g.nv-wrap.nv-bullet').data([d]);1404var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bullet');1405var gEnter = wrapEnter.append('g');1406var g = wrap.select('g');14071408gEnter.append('rect').attr('class', 'nv-range nv-rangeMax');1409gEnter.append('rect').attr('class', 'nv-range nv-rangeAvg');1410gEnter.append('rect').attr('class', 'nv-range nv-rangeMin');1411gEnter.append('rect').attr('class', 'nv-measure');1412gEnter.append('path').attr('class', 'nv-markerTriangle');14131414wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');14151416//------------------------------------------------------------1417141814191420var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)1421w1 = function(d) { return Math.abs(x1(d) - x1(0)) };1422var xp0 = function(d) { return d < 0 ? x0(d) : x0(0) },1423xp1 = function(d) { return d < 0 ? x1(d) : x1(0) };142414251426g.select('rect.nv-rangeMax')1427.attr('height', availableHeight)1428.attr('width', w1(rangeMax > 0 ? rangeMax : rangeMin))1429.attr('x', xp1(rangeMax > 0 ? rangeMax : rangeMin))1430.datum(rangeMax > 0 ? rangeMax : rangeMin)1431/*1432.attr('x', rangeMin < 0 ?1433rangeMax > 0 ?1434x1(rangeMin)1435: x1(rangeMax)1436: x1(0))1437*/14381439g.select('rect.nv-rangeAvg')1440.attr('height', availableHeight)1441.attr('width', w1(rangeAvg))1442.attr('x', xp1(rangeAvg))1443.datum(rangeAvg)1444/*1445.attr('width', rangeMax <= 0 ?1446x1(rangeMax) - x1(rangeAvg)1447: x1(rangeAvg) - x1(rangeMin))1448.attr('x', rangeMax <= 0 ?1449x1(rangeAvg)1450: x1(rangeMin))1451*/14521453g.select('rect.nv-rangeMin')1454.attr('height', availableHeight)1455.attr('width', w1(rangeMax))1456.attr('x', xp1(rangeMax))1457.attr('width', w1(rangeMax > 0 ? rangeMin : rangeMax))1458.attr('x', xp1(rangeMax > 0 ? rangeMin : rangeMax))1459.datum(rangeMax > 0 ? rangeMin : rangeMax)1460/*1461.attr('width', rangeMax <= 0 ?1462x1(rangeAvg) - x1(rangeMin)1463: x1(rangeMax) - x1(rangeAvg))1464.attr('x', rangeMax <= 0 ?1465x1(rangeMin)1466: x1(rangeAvg))1467*/14681469g.select('rect.nv-measure')1470.style('fill', color)1471.attr('height', availableHeight / 3)1472.attr('y', availableHeight / 3)1473.attr('width', measurez < 0 ?1474x1(0) - x1(measurez[0])1475: x1(measurez[0]) - x1(0))1476.attr('x', xp1(measurez))1477.on('mouseover', function() {1478dispatch.elementMouseover({1479value: measurez[0],1480label: measureLabelz[0] || 'Current',1481pos: [x1(measurez[0]), availableHeight/2]1482})1483})1484.on('mouseout', function() {1485dispatch.elementMouseout({1486value: measurez[0],1487label: measureLabelz[0] || 'Current'1488})1489})14901491var h3 = availableHeight / 6;1492if (markerz[0]) {1493g.selectAll('path.nv-markerTriangle')1494.attr('transform', function(d) { return 'translate(' + x1(markerz[0]) + ',' + (availableHeight / 2) + ')' })1495.attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z')1496.on('mouseover', function() {1497dispatch.elementMouseover({1498value: markerz[0],1499label: markerLabelz[0] || 'Previous',1500pos: [x1(markerz[0]), availableHeight/2]1501})1502})1503.on('mouseout', function() {1504dispatch.elementMouseout({1505value: markerz[0],1506label: markerLabelz[0] || 'Previous'1507})1508});1509} else {1510g.selectAll('path.nv-markerTriangle').remove();1511}151215131514wrap.selectAll('.nv-range')1515.on('mouseover', function(d,i) {1516var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum");15171518dispatch.elementMouseover({1519value: d,1520label: label,1521pos: [x1(d), availableHeight/2]1522})1523})1524.on('mouseout', function(d,i) {1525var label = rangeLabelz[i] || (!i ? "Maximum" : i == 1 ? "Mean" : "Minimum");15261527dispatch.elementMouseout({1528value: d,1529label: label1530})1531})15321533/* // THIS IS THE PREVIOUS BULLET IMPLEMENTATION, WILL REMOVE SHORTLY1534// Update the range rects.1535var range = g.selectAll('rect.nv-range')1536.data(rangez);15371538range.enter().append('rect')1539.attr('class', function(d, i) { return 'nv-range nv-s' + i; })1540.attr('width', w0)1541.attr('height', availableHeight)1542.attr('x', reverse ? x0 : 0)1543.on('mouseover', function(d,i) {1544dispatch.elementMouseover({1545value: d,1546label: (i <= 0) ? 'Maximum' : (i > 1) ? 'Minimum' : 'Mean', //TODO: make these labels a variable1547pos: [x1(d), availableHeight/2]1548})1549})1550.on('mouseout', function(d,i) {1551dispatch.elementMouseout({1552value: d,1553label: (i <= 0) ? 'Minimum' : (i >=1) ? 'Maximum' : 'Mean' //TODO: make these labels a variable1554})1555})15561557d3.transition(range)1558.attr('x', reverse ? x1 : 0)1559.attr('width', w1)1560.attr('height', availableHeight);156115621563// Update the measure rects.1564var measure = g.selectAll('rect.nv-measure')1565.data(measurez);15661567measure.enter().append('rect')1568.attr('class', function(d, i) { return 'nv-measure nv-s' + i; })1569.style('fill', function(d,i) { return color(d,i ) })1570.attr('width', w0)1571.attr('height', availableHeight / 3)1572.attr('x', reverse ? x0 : 0)1573.attr('y', availableHeight / 3)1574.on('mouseover', function(d) {1575dispatch.elementMouseover({1576value: d,1577label: 'Current', //TODO: make these labels a variable1578pos: [x1(d), availableHeight/2]1579})1580})1581.on('mouseout', function(d) {1582dispatch.elementMouseout({1583value: d,1584label: 'Current' //TODO: make these labels a variable1585})1586})15871588d3.transition(measure)1589.attr('width', w1)1590.attr('height', availableHeight / 3)1591.attr('x', reverse ? x1 : 0)1592.attr('y', availableHeight / 3);1593159415951596// Update the marker lines.1597var marker = g.selectAll('path.nv-markerTriangle')1598.data(markerz);15991600var h3 = availableHeight / 6;1601marker.enter().append('path')1602.attr('class', 'nv-markerTriangle')1603.attr('transform', function(d) { return 'translate(' + x0(d) + ',' + (availableHeight / 2) + ')' })1604.attr('d', 'M0,' + h3 + 'L' + h3 + ',' + (-h3) + ' ' + (-h3) + ',' + (-h3) + 'Z')1605.on('mouseover', function(d,i) {1606dispatch.elementMouseover({1607value: d,1608label: 'Previous',1609pos: [x1(d), availableHeight/2]1610})1611})1612.on('mouseout', function(d,i) {1613dispatch.elementMouseout({1614value: d,1615label: 'Previous'1616})1617});16181619d3.transition(marker)1620.attr('transform', function(d) { return 'translate(' + (x1(d) - x1(0)) + ',' + (availableHeight / 2) + ')' });16211622marker.exit().remove();1623*/16241625});16261627// d3.timer.flush(); // Not needed?16281629return chart;1630}163116321633//============================================================1634// Expose Public Variables1635//------------------------------------------------------------16361637chart.dispatch = dispatch;16381639chart.options = nv.utils.optionsFunc.bind(chart);16401641// left, right, top, bottom1642chart.orient = function(_) {1643if (!arguments.length) return orient;1644orient = _;1645reverse = orient == 'right' || orient == 'bottom';1646return chart;1647};16481649// ranges (bad, satisfactory, good)1650chart.ranges = function(_) {1651if (!arguments.length) return ranges;1652ranges = _;1653return chart;1654};16551656// markers (previous, goal)1657chart.markers = function(_) {1658if (!arguments.length) return markers;1659markers = _;1660return chart;1661};16621663// measures (actual, forecast)1664chart.measures = function(_) {1665if (!arguments.length) return measures;1666measures = _;1667return chart;1668};16691670chart.forceX = function(_) {1671if (!arguments.length) return forceX;1672forceX = _;1673return chart;1674};16751676chart.width = function(_) {1677if (!arguments.length) return width;1678width = _;1679return chart;1680};16811682chart.height = function(_) {1683if (!arguments.length) return height;1684height = _;1685return chart;1686};16871688chart.margin = function(_) {1689if (!arguments.length) return margin;1690margin.top = typeof _.top != 'undefined' ? _.top : margin.top;1691margin.right = typeof _.right != 'undefined' ? _.right : margin.right;1692margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;1693margin.left = typeof _.left != 'undefined' ? _.left : margin.left;1694return chart;1695};16961697chart.tickFormat = function(_) {1698if (!arguments.length) return tickFormat;1699tickFormat = _;1700return chart;1701};17021703chart.color = function(_) {1704if (!arguments.length) return color;1705color = nv.utils.getColor(_);1706return chart;1707};17081709//============================================================171017111712return chart;1713};1714171517161717// Chart design based on the recommendations of Stephen Few. Implementation1718// based on the work of Clint Ivy, Jamie Love, and Jason Davies.1719// http://projects.instantcognition.com/protovis/bulletchart/1720nv.models.bulletChart = function() {1721"use strict";1722//============================================================1723// Public Variables with Default Settings1724//------------------------------------------------------------17251726var bullet = nv.models.bullet()1727;17281729var orient = 'left' // TODO top & bottom1730, reverse = false1731, margin = {top: 5, right: 40, bottom: 20, left: 120}1732, ranges = function(d) { return d.ranges }1733, markers = function(d) { return d.markers }1734, measures = function(d) { return d.measures }1735, width = null1736, height = 551737, tickFormat = null1738, tooltips = true1739, tooltip = function(key, x, y, e, graph) {1740return '<h3>' + x + '</h3>' +1741'<p>' + y + '</p>'1742}1743, noData = 'No Data Available.'1744, dispatch = d3.dispatch('tooltipShow', 'tooltipHide')1745;17461747//============================================================174817491750//============================================================1751// Private Variables1752//------------------------------------------------------------17531754var showTooltip = function(e, offsetElement) {1755var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ) + margin.left,1756top = e.pos[1] + ( offsetElement.offsetTop || 0) + margin.top,1757content = tooltip(e.key, e.label, e.value, e, chart);17581759nv.tooltip.show([left, top], content, e.value < 0 ? 'e' : 'w', null, offsetElement);1760};17611762//============================================================176317641765function chart(selection) {1766selection.each(function(d, i) {1767var container = d3.select(this);17681769var availableWidth = (width || parseInt(container.style('width')) || 960)1770- margin.left - margin.right,1771availableHeight = height - margin.top - margin.bottom,1772that = this;177317741775chart.update = function() { chart(selection) };1776chart.container = this;17771778//------------------------------------------------------------1779// Display No Data message if there's nothing to show.17801781if (!d || !ranges.call(this, d, i)) {1782var noDataText = container.selectAll('.nv-noData').data([noData]);17831784noDataText.enter().append('text')1785.attr('class', 'nvd3 nv-noData')1786.attr('dy', '-.7em')1787.style('text-anchor', 'middle');17881789noDataText1790.attr('x', margin.left + availableWidth / 2)1791.attr('y', 18 + margin.top + availableHeight / 2)1792.text(function(d) { return d });17931794return chart;1795} else {1796container.selectAll('.nv-noData').remove();1797}17981799//------------------------------------------------------------1800180118021803var rangez = ranges.call(this, d, i).slice().sort(d3.descending),1804markerz = markers.call(this, d, i).slice().sort(d3.descending),1805measurez = measures.call(this, d, i).slice().sort(d3.descending);180618071808//------------------------------------------------------------1809// Setup containers and skeleton of chart18101811var wrap = container.selectAll('g.nv-wrap.nv-bulletChart').data([d]);1812var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-bulletChart');1813var gEnter = wrapEnter.append('g');1814var g = wrap.select('g');18151816gEnter.append('g').attr('class', 'nv-bulletWrap');1817gEnter.append('g').attr('class', 'nv-titles');18181819wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');18201821//------------------------------------------------------------182218231824// Compute the new x-scale.1825var x1 = d3.scale.linear()1826.domain([0, Math.max(rangez[0], markerz[0], measurez[0])]) // TODO: need to allow forceX and forceY, and xDomain, yDomain1827.range(reverse ? [availableWidth, 0] : [0, availableWidth]);18281829// Retrieve the old x-scale, if this is an update.1830var x0 = this.__chart__ || d3.scale.linear()1831.domain([0, Infinity])1832.range(x1.range());18331834// Stash the new scale.1835this.__chart__ = x1;18361837/*1838// Derive width-scales from the x-scales.1839var w0 = bulletWidth(x0),1840w1 = bulletWidth(x1);18411842function bulletWidth(x) {1843var x0 = x(0);1844return function(d) {1845return Math.abs(x(d) - x(0));1846};1847}18481849function bulletTranslate(x) {1850return function(d) {1851return 'translate(' + x(d) + ',0)';1852};1853}1854*/18551856var w0 = function(d) { return Math.abs(x0(d) - x0(0)) }, // TODO: could optimize by precalculating x0(0) and x1(0)1857w1 = function(d) { return Math.abs(x1(d) - x1(0)) };185818591860var title = gEnter.select('.nv-titles').append('g')1861.attr('text-anchor', 'end')1862.attr('transform', 'translate(-6,' + (height - margin.top - margin.bottom) / 2 + ')');1863title.append('text')1864.attr('class', 'nv-title')1865.text(function(d) { return d.title; });18661867title.append('text')1868.attr('class', 'nv-subtitle')1869.attr('dy', '1em')1870.text(function(d) { return d.subtitle; });1871187218731874bullet1875.width(availableWidth)1876.height(availableHeight)18771878var bulletWrap = g.select('.nv-bulletWrap');18791880d3.transition(bulletWrap).call(bullet);1881188218831884// Compute the tick format.1885var format = tickFormat || x1.tickFormat( availableWidth / 100 );18861887// Update the tick groups.1888var tick = g.selectAll('g.nv-tick')1889.data(x1.ticks( availableWidth / 50 ), function(d) {1890return this.textContent || format(d);1891});18921893// Initialize the ticks with the old scale, x0.1894var tickEnter = tick.enter().append('g')1895.attr('class', 'nv-tick')1896.attr('transform', function(d) { return 'translate(' + x0(d) + ',0)' })1897.style('opacity', 1e-6);18981899tickEnter.append('line')1900.attr('y1', availableHeight)1901.attr('y2', availableHeight * 7 / 6);19021903tickEnter.append('text')1904.attr('text-anchor', 'middle')1905.attr('dy', '1em')1906.attr('y', availableHeight * 7 / 6)1907.text(format);190819091910// Transition the updating ticks to the new scale, x1.1911var tickUpdate = d3.transition(tick)1912.attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' })1913.style('opacity', 1);19141915tickUpdate.select('line')1916.attr('y1', availableHeight)1917.attr('y2', availableHeight * 7 / 6);19181919tickUpdate.select('text')1920.attr('y', availableHeight * 7 / 6);19211922// Transition the exiting ticks to the new scale, x1.1923d3.transition(tick.exit())1924.attr('transform', function(d) { return 'translate(' + x1(d) + ',0)' })1925.style('opacity', 1e-6)1926.remove();192719281929//============================================================1930// Event Handling/Dispatching (in chart's scope)1931//------------------------------------------------------------19321933dispatch.on('tooltipShow', function(e) {1934e.key = d.title;1935if (tooltips) showTooltip(e, that.parentNode);1936});19371938//============================================================19391940});19411942d3.timer.flush();19431944return chart;1945}194619471948//============================================================1949// Event Handling/Dispatching (out of chart's scope)1950//------------------------------------------------------------19511952bullet.dispatch.on('elementMouseover.tooltip', function(e) {1953dispatch.tooltipShow(e);1954});19551956bullet.dispatch.on('elementMouseout.tooltip', function(e) {1957dispatch.tooltipHide(e);1958});19591960dispatch.on('tooltipHide', function() {1961if (tooltips) nv.tooltip.cleanup();1962});19631964//============================================================196519661967//============================================================1968// Expose Public Variables1969//------------------------------------------------------------19701971chart.dispatch = dispatch;1972chart.bullet = bullet;19731974d3.rebind(chart, bullet, 'color');19751976chart.options = nv.utils.optionsFunc.bind(chart);19771978// left, right, top, bottom1979chart.orient = function(x) {1980if (!arguments.length) return orient;1981orient = x;1982reverse = orient == 'right' || orient == 'bottom';1983return chart;1984};19851986// ranges (bad, satisfactory, good)1987chart.ranges = function(x) {1988if (!arguments.length) return ranges;1989ranges = x;1990return chart;1991};19921993// markers (previous, goal)1994chart.markers = function(x) {1995if (!arguments.length) return markers;1996markers = x;1997return chart;1998};19992000// measures (actual, forecast)2001chart.measures = function(x) {2002if (!arguments.length) return measures;2003measures = x;2004return chart;2005};20062007chart.width = function(x) {2008if (!arguments.length) return width;2009width = x;2010return chart;2011};20122013chart.height = function(x) {2014if (!arguments.length) return height;2015height = x;2016return chart;2017};20182019chart.margin = function(_) {2020if (!arguments.length) return margin;2021margin.top = typeof _.top != 'undefined' ? _.top : margin.top;2022margin.right = typeof _.right != 'undefined' ? _.right : margin.right;2023margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;2024margin.left = typeof _.left != 'undefined' ? _.left : margin.left;2025return chart;2026};20272028chart.tickFormat = function(x) {2029if (!arguments.length) return tickFormat;2030tickFormat = x;2031return chart;2032};20332034chart.tooltips = function(_) {2035if (!arguments.length) return tooltips;2036tooltips = _;2037return chart;2038};20392040chart.tooltipContent = function(_) {2041if (!arguments.length) return tooltip;2042tooltip = _;2043return chart;2044};20452046chart.noData = function(_) {2047if (!arguments.length) return noData;2048noData = _;2049return chart;2050};20512052//============================================================205320542055return chart;2056};2057205820592060nv.models.cumulativeLineChart = function() {2061"use strict";2062//============================================================2063// Public Variables with Default Settings2064//------------------------------------------------------------20652066var lines = nv.models.line()2067, xAxis = nv.models.axis()2068, yAxis = nv.models.axis()2069, legend = nv.models.legend()2070, controls = nv.models.legend()2071, interactiveLayer = nv.interactiveGuideline()2072;20732074var margin = {top: 30, right: 30, bottom: 50, left: 60}2075, color = nv.utils.defaultColor()2076, width = null2077, height = null2078, showLegend = true2079, showXAxis = true2080, showYAxis = true2081, rightAlignYAxis = false2082, tooltips = true2083, showControls = true2084, useInteractiveGuideline = false2085, rescaleY = true2086, tooltip = function(key, x, y, e, graph) {2087return '<h3>' + key + '</h3>' +2088'<p>' + y + ' at ' + x + '</p>'2089}2090, x //can be accessed via chart.xScale()2091, y //can be accessed via chart.yScale()2092, id = lines.id()2093, state = { index: 0, rescaleY: rescaleY }2094, defaultState = null2095, noData = 'No Data Available.'2096, average = function(d) { return d.average }2097, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')2098, transitionDuration = 2502099;21002101xAxis2102.orient('bottom')2103.tickPadding(7)2104;2105yAxis2106.orient((rightAlignYAxis) ? 'right' : 'left')2107;21082109//============================================================2110controls.updateState(false);21112112//============================================================2113// Private Variables2114//------------------------------------------------------------21152116var dx = d3.scale.linear()2117, index = {i: 0, x: 0}2118;21192120var showTooltip = function(e, offsetElement) {2121var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),2122top = e.pos[1] + ( offsetElement.offsetTop || 0),2123x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),2124y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)),2125content = tooltip(e.series.key, x, y, e, chart);21262127nv.tooltip.show([left, top], content, null, null, offsetElement);2128};21292130/*2131//Moved to see if we can get better behavior to fix issue #3152132var indexDrag = d3.behavior.drag()2133.on('dragstart', dragStart)2134.on('drag', dragMove)2135.on('dragend', dragEnd);21362137function dragStart(d,i) {2138d3.select(chart.container)2139.style('cursor', 'ew-resize');2140}21412142function dragMove(d,i) {2143d.x += d3.event.dx;2144d.i = Math.round(dx.invert(d.x));21452146d3.select(this).attr('transform', 'translate(' + dx(d.i) + ',0)');2147chart.update();2148}21492150function dragEnd(d,i) {2151d3.select(chart.container)2152.style('cursor', 'auto');2153chart.update();2154}2155*/21562157//============================================================215821592160function chart(selection) {2161selection.each(function(data) {2162var container = d3.select(this).classed('nv-chart-' + id, true),2163that = this;21642165var availableWidth = (width || parseInt(container.style('width')) || 960)2166- margin.left - margin.right,2167availableHeight = (height || parseInt(container.style('height')) || 400)2168- margin.top - margin.bottom;216921702171chart.update = function() { container.transition().duration(transitionDuration).call(chart) };2172chart.container = this;21732174//set state.disabled2175state.disabled = data.map(function(d) { return !!d.disabled });21762177if (!defaultState) {2178var key;2179defaultState = {};2180for (key in state) {2181if (state[key] instanceof Array)2182defaultState[key] = state[key].slice(0);2183else2184defaultState[key] = state[key];2185}2186}21872188var indexDrag = d3.behavior.drag()2189.on('dragstart', dragStart)2190.on('drag', dragMove)2191.on('dragend', dragEnd);219221932194function dragStart(d,i) {2195d3.select(chart.container)2196.style('cursor', 'ew-resize');2197}21982199function dragMove(d,i) {2200index.x = d3.event.x;2201index.i = Math.round(dx.invert(index.x));2202updateZero();2203}22042205function dragEnd(d,i) {2206d3.select(chart.container)2207.style('cursor', 'auto');22082209// update state and send stateChange with new index2210state.index = index.i;2211dispatch.stateChange(state);2212}22132214//------------------------------------------------------------2215// Display No Data message if there's nothing to show.22162217if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {2218var noDataText = container.selectAll('.nv-noData').data([noData]);22192220noDataText.enter().append('text')2221.attr('class', 'nvd3 nv-noData')2222.attr('dy', '-.7em')2223.style('text-anchor', 'middle');22242225noDataText2226.attr('x', margin.left + availableWidth / 2)2227.attr('y', margin.top + availableHeight / 2)2228.text(function(d) { return d });22292230return chart;2231} else {2232container.selectAll('.nv-noData').remove();2233}22342235//------------------------------------------------------------223622372238//------------------------------------------------------------2239// Setup Scales22402241x = lines.xScale();2242y = lines.yScale();224322442245if (!rescaleY) {2246var seriesDomains = data2247.filter(function(series) { return !series.disabled })2248.map(function(series,i) {2249var initialDomain = d3.extent(series.values, lines.y());22502251//account for series being disabled when losing 95% or more2252if (initialDomain[0] < -.95) initialDomain[0] = -.95;22532254return [2255(initialDomain[0] - initialDomain[1]) / (1 + initialDomain[1]),2256(initialDomain[1] - initialDomain[0]) / (1 + initialDomain[0])2257];2258});22592260var completeDomain = [2261d3.min(seriesDomains, function(d) { return d[0] }),2262d3.max(seriesDomains, function(d) { return d[1] })2263]22642265lines.yDomain(completeDomain);2266} else {2267lines.yDomain(null);2268}226922702271dx .domain([0, data[0].values.length - 1]) //Assumes all series have same length2272.range([0, availableWidth])2273.clamp(true);22742275//------------------------------------------------------------227622772278var data = indexify(index.i, data);227922802281//------------------------------------------------------------2282// Setup containers and skeleton of chart2283var interactivePointerEvents = (useInteractiveGuideline) ? "none" : "all";2284var wrap = container.selectAll('g.nv-wrap.nv-cumulativeLine').data([data]);2285var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-cumulativeLine').append('g');2286var g = wrap.select('g');22872288gEnter.append('g').attr('class', 'nv-interactive');2289gEnter.append('g').attr('class', 'nv-x nv-axis').style("pointer-events","none");2290gEnter.append('g').attr('class', 'nv-y nv-axis');2291gEnter.append('g').attr('class', 'nv-background');2292gEnter.append('g').attr('class', 'nv-linesWrap').style("pointer-events",interactivePointerEvents);2293gEnter.append('g').attr('class', 'nv-avgLinesWrap').style("pointer-events","none");2294gEnter.append('g').attr('class', 'nv-legendWrap');2295gEnter.append('g').attr('class', 'nv-controlsWrap');229622972298//------------------------------------------------------------2299// Legend23002301if (showLegend) {2302legend.width(availableWidth);23032304g.select('.nv-legendWrap')2305.datum(data)2306.call(legend);23072308if ( margin.top != legend.height()) {2309margin.top = legend.height();2310availableHeight = (height || parseInt(container.style('height')) || 400)2311- margin.top - margin.bottom;2312}23132314g.select('.nv-legendWrap')2315.attr('transform', 'translate(0,' + (-margin.top) +')')2316}23172318//------------------------------------------------------------231923202321//------------------------------------------------------------2322// Controls23232324if (showControls) {2325var controlsData = [2326{ key: 'Re-scale y-axis', disabled: !rescaleY }2327];23282329controls.width(140).color(['#444', '#444', '#444']);2330g.select('.nv-controlsWrap')2331.datum(controlsData)2332.attr('transform', 'translate(0,' + (-margin.top) +')')2333.call(controls);2334}23352336//------------------------------------------------------------233723382339wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');23402341if (rightAlignYAxis) {2342g.select(".nv-y.nv-axis")2343.attr("transform", "translate(" + availableWidth + ",0)");2344}23452346// Show error if series goes below 100%2347var tempDisabled = data.filter(function(d) { return d.tempDisabled });23482349wrap.select('.tempDisabled').remove(); //clean-up and prevent duplicates2350if (tempDisabled.length) {2351wrap.append('text').attr('class', 'tempDisabled')2352.attr('x', availableWidth / 2)2353.attr('y', '-.71em')2354.style('text-anchor', 'end')2355.text(tempDisabled.map(function(d) { return d.key }).join(', ') + ' values cannot be calculated for this time period.');2356}23572358//------------------------------------------------------------2359// Main Chart Component(s)23602361//------------------------------------------------------------2362//Set up interactive layer2363if (useInteractiveGuideline) {2364interactiveLayer2365.width(availableWidth)2366.height(availableHeight)2367.margin({left:margin.left,top:margin.top})2368.svgContainer(container)2369.xScale(x);2370wrap.select(".nv-interactive").call(interactiveLayer);2371}23722373gEnter.select('.nv-background')2374.append('rect');23752376g.select('.nv-background rect')2377.attr('width', availableWidth)2378.attr('height', availableHeight);23792380lines2381//.x(function(d) { return d.x })2382.y(function(d) { return d.display.y })2383.width(availableWidth)2384.height(availableHeight)2385.color(data.map(function(d,i) {2386return d.color || color(d, i);2387}).filter(function(d,i) { return !data[i].disabled && !data[i].tempDisabled; }));2388238923902391var linesWrap = g.select('.nv-linesWrap')2392.datum(data.filter(function(d) { return !d.disabled && !d.tempDisabled }));23932394//d3.transition(linesWrap).call(lines);2395linesWrap.call(lines);23962397/*Handle average lines [AN-612] ----------------------------*/23982399//Store a series index number in the data array.2400data.forEach(function(d,i) {2401d.seriesIndex = i;2402});24032404var avgLineData = data.filter(function(d) {2405return !d.disabled && !!average(d);2406});24072408var avgLines = g.select(".nv-avgLinesWrap").selectAll("line")2409.data(avgLineData, function(d) { return d.key; });24102411var getAvgLineY = function(d) {2412//If average lines go off the svg element, clamp them to the svg bounds.2413var yVal = y(average(d));2414if (yVal < 0) return 0;2415if (yVal > availableHeight) return availableHeight;2416return yVal;2417};24182419avgLines.enter()2420.append('line')2421.style('stroke-width',2)2422.style('stroke-dasharray','10,10')2423.style('stroke',function (d,i) {2424return lines.color()(d,d.seriesIndex);2425})2426.attr('x1',0)2427.attr('x2',availableWidth)2428.attr('y1', getAvgLineY)2429.attr('y2', getAvgLineY);24302431avgLines2432.style('stroke-opacity',function(d){2433//If average lines go offscreen, make them transparent2434var yVal = y(average(d));2435if (yVal < 0 || yVal > availableHeight) return 0;2436return 1;2437})2438.attr('x1',0)2439.attr('x2',availableWidth)2440.attr('y1', getAvgLineY)2441.attr('y2', getAvgLineY);24422443avgLines.exit().remove();24442445//Create index line -----------------------------------------24462447var indexLine = linesWrap.selectAll('.nv-indexLine')2448.data([index]);2449indexLine.enter().append('rect').attr('class', 'nv-indexLine')2450.attr('width', 3)2451.attr('x', -2)2452.attr('fill', 'red')2453.attr('fill-opacity', .5)2454.style("pointer-events","all")2455.call(indexDrag)24562457indexLine2458.attr('transform', function(d) { return 'translate(' + dx(d.i) + ',0)' })2459.attr('height', availableHeight)24602461//------------------------------------------------------------246224632464//------------------------------------------------------------2465// Setup Axes24662467if (showXAxis) {2468xAxis2469.scale(x)2470//Suggest how many ticks based on the chart width and D3 should listen (70 is the optimal number for MM/DD/YY dates)2471.ticks( Math.min(data[0].values.length,availableWidth/70) )2472.tickSize(-availableHeight, 0);24732474g.select('.nv-x.nv-axis')2475.attr('transform', 'translate(0,' + y.range()[0] + ')');2476d3.transition(g.select('.nv-x.nv-axis'))2477.call(xAxis);2478}247924802481if (showYAxis) {2482yAxis2483.scale(y)2484.ticks( availableHeight / 36 )2485.tickSize( -availableWidth, 0);24862487d3.transition(g.select('.nv-y.nv-axis'))2488.call(yAxis);2489}2490//------------------------------------------------------------249124922493//============================================================2494// Event Handling/Dispatching (in chart's scope)2495//------------------------------------------------------------249624972498function updateZero() {2499indexLine2500.data([index]);25012502//When dragging the index line, turn off line transitions.2503// Then turn them back on when done dragging.2504var oldDuration = chart.transitionDuration();2505chart.transitionDuration(0);2506chart.update();2507chart.transitionDuration(oldDuration);2508}25092510g.select('.nv-background rect')2511.on('click', function() {2512index.x = d3.mouse(this)[0];2513index.i = Math.round(dx.invert(index.x));25142515// update state and send stateChange with new index2516state.index = index.i;2517dispatch.stateChange(state);25182519updateZero();2520});25212522lines.dispatch.on('elementClick', function(e) {2523index.i = e.pointIndex;2524index.x = dx(index.i);25252526// update state and send stateChange with new index2527state.index = index.i;2528dispatch.stateChange(state);25292530updateZero();2531});25322533controls.dispatch.on('legendClick', function(d,i) {2534d.disabled = !d.disabled;2535rescaleY = !d.disabled;25362537state.rescaleY = rescaleY;2538dispatch.stateChange(state);2539chart.update();2540});254125422543legend.dispatch.on('stateChange', function(newState) {2544state.disabled = newState.disabled;2545dispatch.stateChange(state);2546chart.update();2547});25482549interactiveLayer.dispatch.on('elementMousemove', function(e) {2550lines.clearHighlights();2551var singlePoint, pointIndex, pointXLocation, allData = [];2552data2553.filter(function(series, i) {2554series.seriesIndex = i;2555return !series.disabled;2556})2557.forEach(function(series,i) {2558pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());2559lines.highlightPoint(i, pointIndex, true);2560var point = series.values[pointIndex];2561if (typeof point === 'undefined') return;2562if (typeof singlePoint === 'undefined') singlePoint = point;2563if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));2564allData.push({2565key: series.key,2566value: chart.y()(point, pointIndex),2567color: color(series,series.seriesIndex)2568});2569});25702571var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));2572interactiveLayer.tooltip2573.position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})2574.chartContainer(that.parentNode)2575.enabled(tooltips)2576.valueFormatter(function(d,i) {2577return yAxis.tickFormat()(d);2578})2579.data(2580{2581value: xValue,2582series: allData2583}2584)();25852586interactiveLayer.renderGuideLine(pointXLocation);25872588});25892590interactiveLayer.dispatch.on("elementMouseout",function(e) {2591dispatch.tooltipHide();2592lines.clearHighlights();2593});25942595dispatch.on('tooltipShow', function(e) {2596if (tooltips) showTooltip(e, that.parentNode);2597});259825992600// Update chart from a state object passed to event handler2601dispatch.on('changeState', function(e) {26022603if (typeof e.disabled !== 'undefined') {2604data.forEach(function(series,i) {2605series.disabled = e.disabled[i];2606});26072608state.disabled = e.disabled;2609}261026112612if (typeof e.index !== 'undefined') {2613index.i = e.index;2614index.x = dx(index.i);26152616state.index = e.index;26172618indexLine2619.data([index]);2620}262126222623if (typeof e.rescaleY !== 'undefined') {2624rescaleY = e.rescaleY;2625}26262627chart.update();2628});26292630//============================================================26312632});26332634return chart;2635}263626372638//============================================================2639// Event Handling/Dispatching (out of chart's scope)2640//------------------------------------------------------------26412642lines.dispatch.on('elementMouseover.tooltip', function(e) {2643e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];2644dispatch.tooltipShow(e);2645});26462647lines.dispatch.on('elementMouseout.tooltip', function(e) {2648dispatch.tooltipHide(e);2649});26502651dispatch.on('tooltipHide', function() {2652if (tooltips) nv.tooltip.cleanup();2653});26542655//============================================================265626572658//============================================================2659// Expose Public Variables2660//------------------------------------------------------------26612662// expose chart's sub-components2663chart.dispatch = dispatch;2664chart.lines = lines;2665chart.legend = legend;2666chart.xAxis = xAxis;2667chart.yAxis = yAxis;2668chart.interactiveLayer = interactiveLayer;26692670d3.rebind(chart, lines, 'defined', 'isArea', 'x', 'y', 'xScale','yScale', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi','useVoronoi', 'id');26712672chart.options = nv.utils.optionsFunc.bind(chart);26732674chart.margin = function(_) {2675if (!arguments.length) return margin;2676margin.top = typeof _.top != 'undefined' ? _.top : margin.top;2677margin.right = typeof _.right != 'undefined' ? _.right : margin.right;2678margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;2679margin.left = typeof _.left != 'undefined' ? _.left : margin.left;2680return chart;2681};26822683chart.width = function(_) {2684if (!arguments.length) return width;2685width = _;2686return chart;2687};26882689chart.height = function(_) {2690if (!arguments.length) return height;2691height = _;2692return chart;2693};26942695chart.color = function(_) {2696if (!arguments.length) return color;2697color = nv.utils.getColor(_);2698legend.color(color);2699return chart;2700};27012702chart.rescaleY = function(_) {2703if (!arguments.length) return rescaleY;2704rescaleY = _2705return rescaleY;2706};27072708chart.showControls = function(_) {2709if (!arguments.length) return showControls;2710showControls = _;2711return chart;2712};27132714chart.useInteractiveGuideline = function(_) {2715if(!arguments.length) return useInteractiveGuideline;2716useInteractiveGuideline = _;2717if (_ === true) {2718chart.interactive(false);2719chart.useVoronoi(false);2720}2721return chart;2722};27232724chart.showLegend = function(_) {2725if (!arguments.length) return showLegend;2726showLegend = _;2727return chart;2728};27292730chart.showXAxis = function(_) {2731if (!arguments.length) return showXAxis;2732showXAxis = _;2733return chart;2734};27352736chart.showYAxis = function(_) {2737if (!arguments.length) return showYAxis;2738showYAxis = _;2739return chart;2740};27412742chart.rightAlignYAxis = function(_) {2743if(!arguments.length) return rightAlignYAxis;2744rightAlignYAxis = _;2745yAxis.orient( (_) ? 'right' : 'left');2746return chart;2747};27482749chart.tooltips = function(_) {2750if (!arguments.length) return tooltips;2751tooltips = _;2752return chart;2753};27542755chart.tooltipContent = function(_) {2756if (!arguments.length) return tooltip;2757tooltip = _;2758return chart;2759};27602761chart.state = function(_) {2762if (!arguments.length) return state;2763state = _;2764return chart;2765};27662767chart.defaultState = function(_) {2768if (!arguments.length) return defaultState;2769defaultState = _;2770return chart;2771};27722773chart.noData = function(_) {2774if (!arguments.length) return noData;2775noData = _;2776return chart;2777};27782779chart.average = function(_) {2780if(!arguments.length) return average;2781average = _;2782return chart;2783};27842785chart.transitionDuration = function(_) {2786if (!arguments.length) return transitionDuration;2787transitionDuration = _;2788return chart;2789};27902791//============================================================279227932794//============================================================2795// Functions2796//------------------------------------------------------------27972798/* Normalize the data according to an index point. */2799function indexify(idx, data) {2800return data.map(function(line, i) {2801if (!line.values) {2802return line;2803}2804var v = lines.y()(line.values[idx], idx);28052806//TODO: implement check below, and disable series if series loses 100% or more cause divide by 0 issue2807if (v < -.95) {2808//if a series loses more than 100%, calculations fail.. anything close can cause major distortion (but is mathematically correct till it hits 100)2809line.tempDisabled = true;2810return line;2811}28122813line.tempDisabled = false;28142815line.values = line.values.map(function(point, pointIndex) {2816point.display = {'y': (lines.y()(point, pointIndex) - v) / (1 + v) };2817return point;2818})28192820return line;2821})2822}28232824//============================================================282528262827return chart;2828}2829//TODO: consider deprecating by adding necessary features to multiBar model2830nv.models.discreteBar = function() {2831"use strict";2832//============================================================2833// Public Variables with Default Settings2834//------------------------------------------------------------28352836var margin = {top: 0, right: 0, bottom: 0, left: 0}2837, width = 9602838, height = 5002839, id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one2840, x = d3.scale.ordinal()2841, y = d3.scale.linear()2842, getX = function(d) { return d.x }2843, getY = function(d) { return d.y }2844, forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove2845, color = nv.utils.defaultColor()2846, showValues = false2847, valueFormat = d3.format(',.2f')2848, xDomain2849, yDomain2850, xRange2851, yRange2852, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')2853, rectClass = 'discreteBar'2854;28552856//============================================================285728582859//============================================================2860// Private Variables2861//------------------------------------------------------------28622863var x0, y0;28642865//============================================================286628672868function chart(selection) {2869selection.each(function(data) {2870var availableWidth = width - margin.left - margin.right,2871availableHeight = height - margin.top - margin.bottom,2872container = d3.select(this);287328742875//add series index to each data point for reference2876data = data.map(function(series, i) {2877series.values = series.values.map(function(point) {2878point.series = i;2879return point;2880});2881return series;2882});288328842885//------------------------------------------------------------2886// Setup Scales28872888// remap and flatten the data for use in calculating the scales' domains2889var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate2890data.map(function(d) {2891return d.values.map(function(d,i) {2892return { x: getX(d,i), y: getY(d,i), y0: d.y0 }2893})2894});28952896x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))2897.rangeBands(xRange || [0, availableWidth], .1);28982899y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y }).concat(forceY)));290029012902// If showValues, pad the Y axis range to account for label height2903if (showValues) y.range(yRange || [availableHeight - (y.domain()[0] < 0 ? 12 : 0), y.domain()[1] > 0 ? 12 : 0]);2904else y.range(yRange || [availableHeight, 0]);29052906//store old scales if they exist2907x0 = x0 || x;2908y0 = y0 || y.copy().range([y(0),y(0)]);29092910//------------------------------------------------------------291129122913//------------------------------------------------------------2914// Setup containers and skeleton of chart29152916var wrap = container.selectAll('g.nv-wrap.nv-discretebar').data([data]);2917var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discretebar');2918var gEnter = wrapEnter.append('g');2919var g = wrap.select('g');29202921gEnter.append('g').attr('class', 'nv-groups');29222923wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');29242925//------------------------------------------------------------2926292729282929//TODO: by definition, the discrete bar should not have multiple groups, will modify/remove later2930var groups = wrap.select('.nv-groups').selectAll('.nv-group')2931.data(function(d) { return d }, function(d) { return d.key });2932groups.enter().append('g')2933.style('stroke-opacity', 1e-6)2934.style('fill-opacity', 1e-6);2935groups.exit()2936.transition()2937.style('stroke-opacity', 1e-6)2938.style('fill-opacity', 1e-6)2939.remove();2940groups2941.attr('class', function(d,i) { return 'nv-group nv-series-' + i })2942.classed('hover', function(d) { return d.hover });2943groups2944.transition()2945.style('stroke-opacity', 1)2946.style('fill-opacity', .75);294729482949var bars = groups.selectAll('g.nv-bar')2950.data(function(d) { return d.values });29512952bars.exit().remove();295329542955var barsEnter = bars.enter().append('g')2956.attr('transform', function(d,i,j) {2957return 'translate(' + (x(getX(d,i)) + x.rangeBand() * .05 ) + ', ' + y(0) + ')'2958})2959.on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here2960d3.select(this).classed('hover', true);2961dispatch.elementMouseover({2962value: getY(d,i),2963point: d,2964series: data[d.series],2965pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted2966pointIndex: i,2967seriesIndex: d.series,2968e: d3.event2969});2970})2971.on('mouseout', function(d,i) {2972d3.select(this).classed('hover', false);2973dispatch.elementMouseout({2974value: getY(d,i),2975point: d,2976series: data[d.series],2977pointIndex: i,2978seriesIndex: d.series,2979e: d3.event2980});2981})2982.on('click', function(d,i) {2983dispatch.elementClick({2984value: getY(d,i),2985point: d,2986series: data[d.series],2987pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted2988pointIndex: i,2989seriesIndex: d.series,2990e: d3.event2991});2992d3.event.stopPropagation();2993})2994.on('dblclick', function(d,i) {2995dispatch.elementDblClick({2996value: getY(d,i),2997point: d,2998series: data[d.series],2999pos: [x(getX(d,i)) + (x.rangeBand() * (d.series + .5) / data.length), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted3000pointIndex: i,3001seriesIndex: d.series,3002e: d3.event3003});3004d3.event.stopPropagation();3005});30063007barsEnter.append('rect')3008.attr('height', 0)3009.attr('width', x.rangeBand() * .9 / data.length )30103011if (showValues) {3012barsEnter.append('text')3013.attr('text-anchor', 'middle')3014;30153016bars.select('text')3017.text(function(d,i) { return valueFormat(getY(d,i)) })3018.transition()3019.attr('x', x.rangeBand() * .9 / 2)3020.attr('y', function(d,i) { return getY(d,i) < 0 ? y(getY(d,i)) - y(0) + 12 : -4 })30213022;3023} else {3024bars.selectAll('text').remove();3025}30263027bars3028.attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive' })3029.style('fill', function(d,i) { return d.color || color(d,i) })3030.style('stroke', function(d,i) { return d.color || color(d,i) })3031.select('rect')3032.attr('class', rectClass)3033.transition()3034.attr('width', x.rangeBand() * .9 / data.length);3035bars.transition()3036//.delay(function(d,i) { return i * 1200 / data[0].values.length })3037.attr('transform', function(d,i) {3038var left = x(getX(d,i)) + x.rangeBand() * .05,3039top = getY(d,i) < 0 ?3040y(0) :3041y(0) - y(getY(d,i)) < 1 ?3042y(0) - 1 : //make 1 px positive bars show up above y=03043y(getY(d,i));30443045return 'translate(' + left + ', ' + top + ')'3046})3047.select('rect')3048.attr('height', function(d,i) {3049return Math.max(Math.abs(y(getY(d,i)) - y((yDomain && yDomain[0]) || 0)) || 1)3050});305130523053//store old scales for use in transitions on update3054x0 = x.copy();3055y0 = y.copy();30563057});30583059return chart;3060}306130623063//============================================================3064// Expose Public Variables3065//------------------------------------------------------------30663067chart.dispatch = dispatch;30683069chart.options = nv.utils.optionsFunc.bind(chart);30703071chart.x = function(_) {3072if (!arguments.length) return getX;3073getX = _;3074return chart;3075};30763077chart.y = function(_) {3078if (!arguments.length) return getY;3079getY = _;3080return chart;3081};30823083chart.margin = function(_) {3084if (!arguments.length) return margin;3085margin.top = typeof _.top != 'undefined' ? _.top : margin.top;3086margin.right = typeof _.right != 'undefined' ? _.right : margin.right;3087margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;3088margin.left = typeof _.left != 'undefined' ? _.left : margin.left;3089return chart;3090};30913092chart.width = function(_) {3093if (!arguments.length) return width;3094width = _;3095return chart;3096};30973098chart.height = function(_) {3099if (!arguments.length) return height;3100height = _;3101return chart;3102};31033104chart.xScale = function(_) {3105if (!arguments.length) return x;3106x = _;3107return chart;3108};31093110chart.yScale = function(_) {3111if (!arguments.length) return y;3112y = _;3113return chart;3114};31153116chart.xDomain = function(_) {3117if (!arguments.length) return xDomain;3118xDomain = _;3119return chart;3120};31213122chart.yDomain = function(_) {3123if (!arguments.length) return yDomain;3124yDomain = _;3125return chart;3126};31273128chart.xRange = function(_) {3129if (!arguments.length) return xRange;3130xRange = _;3131return chart;3132};31333134chart.yRange = function(_) {3135if (!arguments.length) return yRange;3136yRange = _;3137return chart;3138};31393140chart.forceY = function(_) {3141if (!arguments.length) return forceY;3142forceY = _;3143return chart;3144};31453146chart.color = function(_) {3147if (!arguments.length) return color;3148color = nv.utils.getColor(_);3149return chart;3150};31513152chart.id = function(_) {3153if (!arguments.length) return id;3154id = _;3155return chart;3156};31573158chart.showValues = function(_) {3159if (!arguments.length) return showValues;3160showValues = _;3161return chart;3162};31633164chart.valueFormat= function(_) {3165if (!arguments.length) return valueFormat;3166valueFormat = _;3167return chart;3168};31693170chart.rectClass= function(_) {3171if (!arguments.length) return rectClass;3172rectClass = _;3173return chart;3174};3175//============================================================317631773178return chart;3179}31803181nv.models.discreteBarChart = function() {3182"use strict";3183//============================================================3184// Public Variables with Default Settings3185//------------------------------------------------------------31863187var discretebar = nv.models.discreteBar()3188, xAxis = nv.models.axis()3189, yAxis = nv.models.axis()3190;31913192var margin = {top: 15, right: 10, bottom: 50, left: 60}3193, width = null3194, height = null3195, color = nv.utils.getColor()3196, showXAxis = true3197, showYAxis = true3198, rightAlignYAxis = false3199, staggerLabels = false3200, tooltips = true3201, tooltip = function(key, x, y, e, graph) {3202return '<h3>' + x + '</h3>' +3203'<p>' + y + '</p>'3204}3205, x3206, y3207, noData = "No Data Available."3208, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'beforeUpdate')3209, transitionDuration = 2503210;32113212xAxis3213.orient('bottom')3214.highlightZero(false)3215.showMaxMin(false)3216.tickFormat(function(d) { return d })3217;3218yAxis3219.orient((rightAlignYAxis) ? 'right' : 'left')3220.tickFormat(d3.format(',.1f'))3221;32223223//============================================================322432253226//============================================================3227// Private Variables3228//------------------------------------------------------------32293230var showTooltip = function(e, offsetElement) {3231var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),3232top = e.pos[1] + ( offsetElement.offsetTop || 0),3233x = xAxis.tickFormat()(discretebar.x()(e.point, e.pointIndex)),3234y = yAxis.tickFormat()(discretebar.y()(e.point, e.pointIndex)),3235content = tooltip(e.series.key, x, y, e, chart);32363237nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);3238};32393240//============================================================324132423243function chart(selection) {3244selection.each(function(data) {3245var container = d3.select(this),3246that = this;32473248var availableWidth = (width || parseInt(container.style('width')) || 960)3249- margin.left - margin.right,3250availableHeight = (height || parseInt(container.style('height')) || 400)3251- margin.top - margin.bottom;325232533254chart.update = function() {3255dispatch.beforeUpdate();3256container.transition().duration(transitionDuration).call(chart);3257};3258chart.container = this;325932603261//------------------------------------------------------------3262// Display No Data message if there's nothing to show.32633264if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {3265var noDataText = container.selectAll('.nv-noData').data([noData]);32663267noDataText.enter().append('text')3268.attr('class', 'nvd3 nv-noData')3269.attr('dy', '-.7em')3270.style('text-anchor', 'middle');32713272noDataText3273.attr('x', margin.left + availableWidth / 2)3274.attr('y', margin.top + availableHeight / 2)3275.text(function(d) { return d });32763277return chart;3278} else {3279container.selectAll('.nv-noData').remove();3280}32813282//------------------------------------------------------------328332843285//------------------------------------------------------------3286// Setup Scales32873288x = discretebar.xScale();3289y = discretebar.yScale().clamp(true);32903291//------------------------------------------------------------329232933294//------------------------------------------------------------3295// Setup containers and skeleton of chart32963297var wrap = container.selectAll('g.nv-wrap.nv-discreteBarWithAxes').data([data]);3298var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-discreteBarWithAxes').append('g');3299var defsEnter = gEnter.append('defs');3300var g = wrap.select('g');33013302gEnter.append('g').attr('class', 'nv-x nv-axis');3303gEnter.append('g').attr('class', 'nv-y nv-axis');3304gEnter.append('g').attr('class', 'nv-barsWrap');33053306g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');33073308if (rightAlignYAxis) {3309g.select(".nv-y.nv-axis")3310.attr("transform", "translate(" + availableWidth + ",0)");3311}33123313//------------------------------------------------------------331433153316//------------------------------------------------------------3317// Main Chart Component(s)33183319discretebar3320.width(availableWidth)3321.height(availableHeight);332233233324var barsWrap = g.select('.nv-barsWrap')3325.datum(data.filter(function(d) { return !d.disabled }))33263327barsWrap.transition().call(discretebar);33283329//------------------------------------------------------------3330333133323333defsEnter.append('clipPath')3334.attr('id', 'nv-x-label-clip-' + discretebar.id())3335.append('rect');33363337g.select('#nv-x-label-clip-' + discretebar.id() + ' rect')3338.attr('width', x.rangeBand() * (staggerLabels ? 2 : 1))3339.attr('height', 16)3340.attr('x', -x.rangeBand() / (staggerLabels ? 1 : 2 ));334133423343//------------------------------------------------------------3344// Setup Axes33453346if (showXAxis) {3347xAxis3348.scale(x)3349.ticks( availableWidth / 100 )3350.tickSize(-availableHeight, 0);33513352g.select('.nv-x.nv-axis')3353.attr('transform', 'translate(0,' + (y.range()[0] + ((discretebar.showValues() && y.domain()[0] < 0) ? 16 : 0)) + ')');3354//d3.transition(g.select('.nv-x.nv-axis'))3355g.select('.nv-x.nv-axis').transition()3356.call(xAxis);335733583359var xTicks = g.select('.nv-x.nv-axis').selectAll('g');33603361if (staggerLabels) {3362xTicks3363.selectAll('text')3364.attr('transform', function(d,i,j) { return 'translate(0,' + (j % 2 == 0 ? '5' : '17') + ')' })3365}3366}33673368if (showYAxis) {3369yAxis3370.scale(y)3371.ticks( availableHeight / 36 )3372.tickSize( -availableWidth, 0);33733374g.select('.nv-y.nv-axis').transition()3375.call(yAxis);3376}33773378//------------------------------------------------------------337933803381//============================================================3382// Event Handling/Dispatching (in chart's scope)3383//------------------------------------------------------------33843385dispatch.on('tooltipShow', function(e) {3386if (tooltips) showTooltip(e, that.parentNode);3387});33883389//============================================================339033913392});33933394return chart;3395}33963397//============================================================3398// Event Handling/Dispatching (out of chart's scope)3399//------------------------------------------------------------34003401discretebar.dispatch.on('elementMouseover.tooltip', function(e) {3402e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];3403dispatch.tooltipShow(e);3404});34053406discretebar.dispatch.on('elementMouseout.tooltip', function(e) {3407dispatch.tooltipHide(e);3408});34093410dispatch.on('tooltipHide', function() {3411if (tooltips) nv.tooltip.cleanup();3412});34133414//============================================================341534163417//============================================================3418// Expose Public Variables3419//------------------------------------------------------------34203421// expose chart's sub-components3422chart.dispatch = dispatch;3423chart.discretebar = discretebar;3424chart.xAxis = xAxis;3425chart.yAxis = yAxis;34263427d3.rebind(chart, discretebar, 'x', 'y', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'id', 'showValues', 'valueFormat');34283429chart.options = nv.utils.optionsFunc.bind(chart);34303431chart.margin = function(_) {3432if (!arguments.length) return margin;3433margin.top = typeof _.top != 'undefined' ? _.top : margin.top;3434margin.right = typeof _.right != 'undefined' ? _.right : margin.right;3435margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;3436margin.left = typeof _.left != 'undefined' ? _.left : margin.left;3437return chart;3438};34393440chart.width = function(_) {3441if (!arguments.length) return width;3442width = _;3443return chart;3444};34453446chart.height = function(_) {3447if (!arguments.length) return height;3448height = _;3449return chart;3450};34513452chart.color = function(_) {3453if (!arguments.length) return color;3454color = nv.utils.getColor(_);3455discretebar.color(color);3456return chart;3457};34583459chart.showXAxis = function(_) {3460if (!arguments.length) return showXAxis;3461showXAxis = _;3462return chart;3463};34643465chart.showYAxis = function(_) {3466if (!arguments.length) return showYAxis;3467showYAxis = _;3468return chart;3469};34703471chart.rightAlignYAxis = function(_) {3472if(!arguments.length) return rightAlignYAxis;3473rightAlignYAxis = _;3474yAxis.orient( (_) ? 'right' : 'left');3475return chart;3476};34773478chart.staggerLabels = function(_) {3479if (!arguments.length) return staggerLabels;3480staggerLabels = _;3481return chart;3482};34833484chart.tooltips = function(_) {3485if (!arguments.length) return tooltips;3486tooltips = _;3487return chart;3488};34893490chart.tooltipContent = function(_) {3491if (!arguments.length) return tooltip;3492tooltip = _;3493return chart;3494};34953496chart.noData = function(_) {3497if (!arguments.length) return noData;3498noData = _;3499return chart;3500};35013502chart.transitionDuration = function(_) {3503if (!arguments.length) return transitionDuration;3504transitionDuration = _;3505return chart;3506};35073508//============================================================350935103511return chart;3512}35133514nv.models.distribution = function() {3515"use strict";3516//============================================================3517// Public Variables with Default Settings3518//------------------------------------------------------------35193520var margin = {top: 0, right: 0, bottom: 0, left: 0}3521, width = 400 //technically width or height depending on x or y....3522, size = 83523, axis = 'x' // 'x' or 'y'... horizontal or vertical3524, getData = function(d) { return d[axis] } // defaults d.x or d.y3525, color = nv.utils.defaultColor()3526, scale = d3.scale.linear()3527, domain3528;35293530//============================================================353135323533//============================================================3534// Private Variables3535//------------------------------------------------------------35363537var scale0;35383539//============================================================354035413542function chart(selection) {3543selection.each(function(data) {3544var availableLength = width - (axis === 'x' ? margin.left + margin.right : margin.top + margin.bottom),3545naxis = axis == 'x' ? 'y' : 'x',3546container = d3.select(this);354735483549//------------------------------------------------------------3550// Setup Scales35513552scale0 = scale0 || scale;35533554//------------------------------------------------------------355535563557//------------------------------------------------------------3558// Setup containers and skeleton of chart35593560var wrap = container.selectAll('g.nv-distribution').data([data]);3561var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-distribution');3562var gEnter = wrapEnter.append('g');3563var g = wrap.select('g');35643565wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')35663567//------------------------------------------------------------356835693570var distWrap = g.selectAll('g.nv-dist')3571.data(function(d) { return d }, function(d) { return d.key });35723573distWrap.enter().append('g');3574distWrap3575.attr('class', function(d,i) { return 'nv-dist nv-series-' + i })3576.style('stroke', function(d,i) { return color(d, i) });35773578var dist = distWrap.selectAll('line.nv-dist' + axis)3579.data(function(d) { return d.values })3580dist.enter().append('line')3581.attr(axis + '1', function(d,i) { return scale0(getData(d,i)) })3582.attr(axis + '2', function(d,i) { return scale0(getData(d,i)) })3583distWrap.exit().selectAll('line.nv-dist' + axis)3584.transition()3585.attr(axis + '1', function(d,i) { return scale(getData(d,i)) })3586.attr(axis + '2', function(d,i) { return scale(getData(d,i)) })3587.style('stroke-opacity', 0)3588.remove();3589dist3590.attr('class', function(d,i) { return 'nv-dist' + axis + ' nv-dist' + axis + '-' + i })3591.attr(naxis + '1', 0)3592.attr(naxis + '2', size);3593dist3594.transition()3595.attr(axis + '1', function(d,i) { return scale(getData(d,i)) })3596.attr(axis + '2', function(d,i) { return scale(getData(d,i)) })359735983599scale0 = scale.copy();36003601});36023603return chart;3604}360536063607//============================================================3608// Expose Public Variables3609//------------------------------------------------------------3610chart.options = nv.utils.optionsFunc.bind(chart);36113612chart.margin = function(_) {3613if (!arguments.length) return margin;3614margin.top = typeof _.top != 'undefined' ? _.top : margin.top;3615margin.right = typeof _.right != 'undefined' ? _.right : margin.right;3616margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;3617margin.left = typeof _.left != 'undefined' ? _.left : margin.left;3618return chart;3619};36203621chart.width = function(_) {3622if (!arguments.length) return width;3623width = _;3624return chart;3625};36263627chart.axis = function(_) {3628if (!arguments.length) return axis;3629axis = _;3630return chart;3631};36323633chart.size = function(_) {3634if (!arguments.length) return size;3635size = _;3636return chart;3637};36383639chart.getData = function(_) {3640if (!arguments.length) return getData;3641getData = d3.functor(_);3642return chart;3643};36443645chart.scale = function(_) {3646if (!arguments.length) return scale;3647scale = _;3648return chart;3649};36503651chart.color = function(_) {3652if (!arguments.length) return color;3653color = nv.utils.getColor(_);3654return chart;3655};3656//============================================================365736583659return chart;3660}3661//TODO: consider deprecating and using multibar with single series for this3662nv.models.historicalBar = function() {3663"use strict";3664//============================================================3665// Public Variables with Default Settings3666//------------------------------------------------------------36673668var margin = {top: 0, right: 0, bottom: 0, left: 0}3669, width = 9603670, height = 5003671, id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one3672, x = d3.scale.linear()3673, y = d3.scale.linear()3674, getX = function(d) { return d.x }3675, getY = function(d) { return d.y }3676, forceX = []3677, forceY = [0]3678, padData = false3679, clipEdge = true3680, color = nv.utils.defaultColor()3681, xDomain3682, yDomain3683, xRange3684, yRange3685, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')3686, interactive = true3687;36883689//============================================================369036913692function chart(selection) {3693selection.each(function(data) {3694var availableWidth = width - margin.left - margin.right,3695availableHeight = height - margin.top - margin.bottom,3696container = d3.select(this);369736983699//------------------------------------------------------------3700// Setup Scales37013702x .domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ))37033704if (padData)3705x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);3706else3707x.range(xRange || [0, availableWidth]);37083709y .domain(yDomain || d3.extent(data[0].values.map(getY).concat(forceY) ))3710.range(yRange || [availableHeight, 0]);37113712// If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point37133714if (x.domain()[0] === x.domain()[1])3715x.domain()[0] ?3716x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])3717: x.domain([-1,1]);37183719if (y.domain()[0] === y.domain()[1])3720y.domain()[0] ?3721y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])3722: y.domain([-1,1]);37233724//------------------------------------------------------------372537263727//------------------------------------------------------------3728// Setup containers and skeleton of chart37293730var wrap = container.selectAll('g.nv-wrap.nv-historicalBar-' + id).data([data[0].values]);3731var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBar-' + id);3732var defsEnter = wrapEnter.append('defs');3733var gEnter = wrapEnter.append('g');3734var g = wrap.select('g');37353736gEnter.append('g').attr('class', 'nv-bars');37373738wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');37393740//------------------------------------------------------------374137423743container3744.on('click', function(d,i) {3745dispatch.chartClick({3746data: d,3747index: i,3748pos: d3.event,3749id: id3750});3751});375237533754defsEnter.append('clipPath')3755.attr('id', 'nv-chart-clip-path-' + id)3756.append('rect');37573758wrap.select('#nv-chart-clip-path-' + id + ' rect')3759.attr('width', availableWidth)3760.attr('height', availableHeight);37613762g .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : '');3763376437653766var bars = wrap.select('.nv-bars').selectAll('.nv-bar')3767.data(function(d) { return d }, function(d,i) {return getX(d,i)});37683769bars.exit().remove();377037713772var barsEnter = bars.enter().append('rect')3773//.attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i })3774.attr('x', 0 )3775.attr('y', function(d,i) { return nv.utils.NaNtoZero(y(Math.max(0, getY(d,i)))) })3776.attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.abs(y(getY(d,i)) - y(0))) })3777.attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; })3778.on('mouseover', function(d,i) {3779if (!interactive) return;3780d3.select(this).classed('hover', true);3781dispatch.elementMouseover({3782point: d,3783series: data[0],3784pos: [x(getX(d,i)), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted3785pointIndex: i,3786seriesIndex: 0,3787e: d3.event3788});37893790})3791.on('mouseout', function(d,i) {3792if (!interactive) return;3793d3.select(this).classed('hover', false);3794dispatch.elementMouseout({3795point: d,3796series: data[0],3797pointIndex: i,3798seriesIndex: 0,3799e: d3.event3800});3801})3802.on('click', function(d,i) {3803if (!interactive) return;3804dispatch.elementClick({3805//label: d[label],3806value: getY(d,i),3807data: d,3808index: i,3809pos: [x(getX(d,i)), y(getY(d,i))],3810e: d3.event,3811id: id3812});3813d3.event.stopPropagation();3814})3815.on('dblclick', function(d,i) {3816if (!interactive) return;3817dispatch.elementDblClick({3818//label: d[label],3819value: getY(d,i),3820data: d,3821index: i,3822pos: [x(getX(d,i)), y(getY(d,i))],3823e: d3.event,3824id: id3825});3826d3.event.stopPropagation();3827});38283829bars3830.attr('fill', function(d,i) { return color(d, i); })3831.attr('class', function(d,i,j) { return (getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive') + ' nv-bar-' + j + '-' + i })3832.transition()3833.attr('transform', function(d,i) { return 'translate(' + (x(getX(d,i)) - availableWidth / data[0].values.length * .45) + ',0)'; })3834//TODO: better width calculations that don't assume always uniform data spacing;w3835.attr('width', (availableWidth / data[0].values.length) * .9 );383638373838bars.transition()3839.attr('y', function(d,i) {3840var rval = getY(d,i) < 0 ?3841y(0) :3842y(0) - y(getY(d,i)) < 1 ?3843y(0) - 1 :3844y(getY(d,i));3845return nv.utils.NaNtoZero(rval);3846})3847.attr('height', function(d,i) { return nv.utils.NaNtoZero(Math.max(Math.abs(y(getY(d,i)) - y(0)),1)) });38483849});38503851return chart;3852}38533854//Create methods to allow outside functions to highlight a specific bar.3855chart.highlightPoint = function(pointIndex, isHoverOver) {3856d3.select(".nv-historicalBar-" + id)3857.select(".nv-bars .nv-bar-0-" + pointIndex)3858.classed("hover", isHoverOver)3859;3860};38613862chart.clearHighlights = function() {3863d3.select(".nv-historicalBar-" + id)3864.select(".nv-bars .nv-bar.hover")3865.classed("hover", false)3866;3867};3868//============================================================3869// Expose Public Variables3870//------------------------------------------------------------38713872chart.dispatch = dispatch;38733874chart.options = nv.utils.optionsFunc.bind(chart);38753876chart.x = function(_) {3877if (!arguments.length) return getX;3878getX = _;3879return chart;3880};38813882chart.y = function(_) {3883if (!arguments.length) return getY;3884getY = _;3885return chart;3886};38873888chart.margin = function(_) {3889if (!arguments.length) return margin;3890margin.top = typeof _.top != 'undefined' ? _.top : margin.top;3891margin.right = typeof _.right != 'undefined' ? _.right : margin.right;3892margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;3893margin.left = typeof _.left != 'undefined' ? _.left : margin.left;3894return chart;3895};38963897chart.width = function(_) {3898if (!arguments.length) return width;3899width = _;3900return chart;3901};39023903chart.height = function(_) {3904if (!arguments.length) return height;3905height = _;3906return chart;3907};39083909chart.xScale = function(_) {3910if (!arguments.length) return x;3911x = _;3912return chart;3913};39143915chart.yScale = function(_) {3916if (!arguments.length) return y;3917y = _;3918return chart;3919};39203921chart.xDomain = function(_) {3922if (!arguments.length) return xDomain;3923xDomain = _;3924return chart;3925};39263927chart.yDomain = function(_) {3928if (!arguments.length) return yDomain;3929yDomain = _;3930return chart;3931};39323933chart.xRange = function(_) {3934if (!arguments.length) return xRange;3935xRange = _;3936return chart;3937};39383939chart.yRange = function(_) {3940if (!arguments.length) return yRange;3941yRange = _;3942return chart;3943};39443945chart.forceX = function(_) {3946if (!arguments.length) return forceX;3947forceX = _;3948return chart;3949};39503951chart.forceY = function(_) {3952if (!arguments.length) return forceY;3953forceY = _;3954return chart;3955};39563957chart.padData = function(_) {3958if (!arguments.length) return padData;3959padData = _;3960return chart;3961};39623963chart.clipEdge = function(_) {3964if (!arguments.length) return clipEdge;3965clipEdge = _;3966return chart;3967};39683969chart.color = function(_) {3970if (!arguments.length) return color;3971color = nv.utils.getColor(_);3972return chart;3973};39743975chart.id = function(_) {3976if (!arguments.length) return id;3977id = _;3978return chart;3979};39803981chart.interactive = function(_) {3982if(!arguments.length) return interactive;3983interactive = false;3984return chart;3985};39863987//============================================================398839893990return chart;3991}39923993nv.models.historicalBarChart = function() {3994"use strict";3995//============================================================3996// Public Variables with Default Settings3997//------------------------------------------------------------39983999var bars = nv.models.historicalBar()4000, xAxis = nv.models.axis()4001, yAxis = nv.models.axis()4002, legend = nv.models.legend()4003;400440054006var margin = {top: 30, right: 90, bottom: 50, left: 90}4007, color = nv.utils.defaultColor()4008, width = null4009, height = null4010, showLegend = false4011, showXAxis = true4012, showYAxis = true4013, rightAlignYAxis = false4014, tooltips = true4015, tooltip = function(key, x, y, e, graph) {4016return '<h3>' + key + '</h3>' +4017'<p>' + y + ' at ' + x + '</p>'4018}4019, x4020, y4021, state = {}4022, defaultState = null4023, noData = 'No Data Available.'4024, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')4025, transitionDuration = 2504026;40274028xAxis4029.orient('bottom')4030.tickPadding(7)4031;4032yAxis4033.orient( (rightAlignYAxis) ? 'right' : 'left')4034;40354036//============================================================403740384039//============================================================4040// Private Variables4041//------------------------------------------------------------40424043var showTooltip = function(e, offsetElement) {40444045// New addition to calculate position if SVG is scaled with viewBox, may move TODO: consider implementing everywhere else4046if (offsetElement) {4047var svg = d3.select(offsetElement).select('svg');4048var viewBox = (svg.node()) ? svg.attr('viewBox') : null;4049if (viewBox) {4050viewBox = viewBox.split(' ');4051var ratio = parseInt(svg.style('width')) / viewBox[2];4052e.pos[0] = e.pos[0] * ratio;4053e.pos[1] = e.pos[1] * ratio;4054}4055}40564057var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),4058top = e.pos[1] + ( offsetElement.offsetTop || 0),4059x = xAxis.tickFormat()(bars.x()(e.point, e.pointIndex)),4060y = yAxis.tickFormat()(bars.y()(e.point, e.pointIndex)),4061content = tooltip(e.series.key, x, y, e, chart);40624063nv.tooltip.show([left, top], content, null, null, offsetElement);4064};40654066//============================================================406740684069function chart(selection) {4070selection.each(function(data) {4071var container = d3.select(this),4072that = this;40734074var availableWidth = (width || parseInt(container.style('width')) || 960)4075- margin.left - margin.right,4076availableHeight = (height || parseInt(container.style('height')) || 400)4077- margin.top - margin.bottom;407840794080chart.update = function() { container.transition().duration(transitionDuration).call(chart) };4081chart.container = this;40824083//set state.disabled4084state.disabled = data.map(function(d) { return !!d.disabled });40854086if (!defaultState) {4087var key;4088defaultState = {};4089for (key in state) {4090if (state[key] instanceof Array)4091defaultState[key] = state[key].slice(0);4092else4093defaultState[key] = state[key];4094}4095}40964097//------------------------------------------------------------4098// Display noData message if there's nothing to show.40994100if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {4101var noDataText = container.selectAll('.nv-noData').data([noData]);41024103noDataText.enter().append('text')4104.attr('class', 'nvd3 nv-noData')4105.attr('dy', '-.7em')4106.style('text-anchor', 'middle');41074108noDataText4109.attr('x', margin.left + availableWidth / 2)4110.attr('y', margin.top + availableHeight / 2)4111.text(function(d) { return d });41124113return chart;4114} else {4115container.selectAll('.nv-noData').remove();4116}41174118//------------------------------------------------------------411941204121//------------------------------------------------------------4122// Setup Scales41234124x = bars.xScale();4125y = bars.yScale();41264127//------------------------------------------------------------412841294130//------------------------------------------------------------4131// Setup containers and skeleton of chart41324133var wrap = container.selectAll('g.nv-wrap.nv-historicalBarChart').data([data]);4134var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-historicalBarChart').append('g');4135var g = wrap.select('g');41364137gEnter.append('g').attr('class', 'nv-x nv-axis');4138gEnter.append('g').attr('class', 'nv-y nv-axis');4139gEnter.append('g').attr('class', 'nv-barsWrap');4140gEnter.append('g').attr('class', 'nv-legendWrap');41414142//------------------------------------------------------------414341444145//------------------------------------------------------------4146// Legend41474148if (showLegend) {4149legend.width(availableWidth);41504151g.select('.nv-legendWrap')4152.datum(data)4153.call(legend);41544155if ( margin.top != legend.height()) {4156margin.top = legend.height();4157availableHeight = (height || parseInt(container.style('height')) || 400)4158- margin.top - margin.bottom;4159}41604161wrap.select('.nv-legendWrap')4162.attr('transform', 'translate(0,' + (-margin.top) +')')4163}41644165//------------------------------------------------------------41664167wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');41684169if (rightAlignYAxis) {4170g.select(".nv-y.nv-axis")4171.attr("transform", "translate(" + availableWidth + ",0)");4172}417341744175//------------------------------------------------------------4176// Main Chart Component(s)41774178bars4179.width(availableWidth)4180.height(availableHeight)4181.color(data.map(function(d,i) {4182return d.color || color(d, i);4183}).filter(function(d,i) { return !data[i].disabled }));418441854186var barsWrap = g.select('.nv-barsWrap')4187.datum(data.filter(function(d) { return !d.disabled }))41884189barsWrap.transition().call(bars);41904191//------------------------------------------------------------419241934194//------------------------------------------------------------4195// Setup Axes41964197if (showXAxis) {4198xAxis4199.scale(x)4200.tickSize(-availableHeight, 0);42014202g.select('.nv-x.nv-axis')4203.attr('transform', 'translate(0,' + y.range()[0] + ')');4204g.select('.nv-x.nv-axis')4205.transition()4206.call(xAxis);4207}42084209if (showYAxis) {4210yAxis4211.scale(y)4212.ticks( availableHeight / 36 )4213.tickSize( -availableWidth, 0);42144215g.select('.nv-y.nv-axis')4216.transition()4217.call(yAxis);4218}4219//------------------------------------------------------------422042214222//============================================================4223// Event Handling/Dispatching (in chart's scope)4224//------------------------------------------------------------42254226legend.dispatch.on('legendClick', function(d,i) {4227d.disabled = !d.disabled;42284229if (!data.filter(function(d) { return !d.disabled }).length) {4230data.map(function(d) {4231d.disabled = false;4232wrap.selectAll('.nv-series').classed('disabled', false);4233return d;4234});4235}42364237state.disabled = data.map(function(d) { return !!d.disabled });4238dispatch.stateChange(state);42394240selection.transition().call(chart);4241});42424243legend.dispatch.on('legendDblclick', function(d) {4244//Double clicking should always enable current series, and disabled all others.4245data.forEach(function(d) {4246d.disabled = true;4247});4248d.disabled = false;42494250state.disabled = data.map(function(d) { return !!d.disabled });4251dispatch.stateChange(state);4252chart.update();4253});42544255dispatch.on('tooltipShow', function(e) {4256if (tooltips) showTooltip(e, that.parentNode);4257});425842594260dispatch.on('changeState', function(e) {42614262if (typeof e.disabled !== 'undefined') {4263data.forEach(function(series,i) {4264series.disabled = e.disabled[i];4265});42664267state.disabled = e.disabled;4268}42694270selection.call(chart);4271});42724273//============================================================42744275});42764277return chart;4278}427942804281//============================================================4282// Event Handling/Dispatching (out of chart's scope)4283//------------------------------------------------------------42844285bars.dispatch.on('elementMouseover.tooltip', function(e) {4286e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];4287dispatch.tooltipShow(e);4288});42894290bars.dispatch.on('elementMouseout.tooltip', function(e) {4291dispatch.tooltipHide(e);4292});42934294dispatch.on('tooltipHide', function() {4295if (tooltips) nv.tooltip.cleanup();4296});42974298//============================================================429943004301//============================================================4302// Expose Public Variables4303//------------------------------------------------------------43044305// expose chart's sub-components4306chart.dispatch = dispatch;4307chart.bars = bars;4308chart.legend = legend;4309chart.xAxis = xAxis;4310chart.yAxis = yAxis;43114312d3.rebind(chart, bars, 'defined', 'isArea', 'x', 'y', 'size', 'xScale', 'yScale',4313'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id', 'interpolate','highlightPoint','clearHighlights', 'interactive');43144315chart.options = nv.utils.optionsFunc.bind(chart);43164317chart.margin = function(_) {4318if (!arguments.length) return margin;4319margin.top = typeof _.top != 'undefined' ? _.top : margin.top;4320margin.right = typeof _.right != 'undefined' ? _.right : margin.right;4321margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;4322margin.left = typeof _.left != 'undefined' ? _.left : margin.left;4323return chart;4324};43254326chart.width = function(_) {4327if (!arguments.length) return width;4328width = _;4329return chart;4330};43314332chart.height = function(_) {4333if (!arguments.length) return height;4334height = _;4335return chart;4336};43374338chart.color = function(_) {4339if (!arguments.length) return color;4340color = nv.utils.getColor(_);4341legend.color(color);4342return chart;4343};43444345chart.showLegend = function(_) {4346if (!arguments.length) return showLegend;4347showLegend = _;4348return chart;4349};43504351chart.showXAxis = function(_) {4352if (!arguments.length) return showXAxis;4353showXAxis = _;4354return chart;4355};43564357chart.showYAxis = function(_) {4358if (!arguments.length) return showYAxis;4359showYAxis = _;4360return chart;4361};43624363chart.rightAlignYAxis = function(_) {4364if(!arguments.length) return rightAlignYAxis;4365rightAlignYAxis = _;4366yAxis.orient( (_) ? 'right' : 'left');4367return chart;4368};43694370chart.tooltips = function(_) {4371if (!arguments.length) return tooltips;4372tooltips = _;4373return chart;4374};43754376chart.tooltipContent = function(_) {4377if (!arguments.length) return tooltip;4378tooltip = _;4379return chart;4380};43814382chart.state = function(_) {4383if (!arguments.length) return state;4384state = _;4385return chart;4386};43874388chart.defaultState = function(_) {4389if (!arguments.length) return defaultState;4390defaultState = _;4391return chart;4392};43934394chart.noData = function(_) {4395if (!arguments.length) return noData;4396noData = _;4397return chart;4398};43994400chart.transitionDuration = function(_) {4401if (!arguments.length) return transitionDuration;4402transitionDuration = _;4403return chart;4404};44054406//============================================================440744084409return chart;4410}4411nv.models.indentedTree = function() {4412"use strict";4413//============================================================4414// Public Variables with Default Settings4415//------------------------------------------------------------44164417var margin = {top: 0, right: 0, bottom: 0, left: 0} //TODO: implement, maybe as margin on the containing div4418, width = 9604419, height = 5004420, color = nv.utils.defaultColor()4421, id = Math.floor(Math.random() * 10000)4422, header = true4423, filterZero = false4424, noData = "No Data Available."4425, childIndent = 204426, columns = [{key:'key', label: 'Name', type:'text'}] //TODO: consider functions like chart.addColumn, chart.removeColumn, instead of a block like this4427, tableClass = null4428, iconOpen = 'images/grey-plus.png' //TODO: consider removing this and replacing with a '+' or '-' unless user defines images4429, iconClose = 'images/grey-minus.png'4430, dispatch = d3.dispatch('elementClick', 'elementDblclick', 'elementMouseover', 'elementMouseout')4431, getUrl = function(d) { return d.url }4432;44334434//============================================================44354436var idx = 0;44374438function chart(selection) {4439selection.each(function(data) {4440var depth = 1,4441container = d3.select(this);44424443var tree = d3.layout.tree()4444.children(function(d) { return d.values })4445.size([height, childIndent]); //Not sure if this is needed now that the result is HTML44464447chart.update = function() { container.transition().duration(600).call(chart) };444844494450//------------------------------------------------------------4451// Display No Data message if there's nothing to show.4452if (!data[0]) data[0] = {key: noData};44534454//------------------------------------------------------------445544564457var nodes = tree.nodes(data[0]);44584459// nodes.map(function(d) {4460// d.id = i++;4461// })44624463//------------------------------------------------------------4464// Setup containers and skeleton of chart44654466var wrap = d3.select(this).selectAll('div').data([[nodes]]);4467var wrapEnter = wrap.enter().append('div').attr('class', 'nvd3 nv-wrap nv-indentedtree');4468var tableEnter = wrapEnter.append('table');4469var table = wrap.select('table').attr('width', '100%').attr('class', tableClass);44704471//------------------------------------------------------------447244734474if (header) {4475var thead = tableEnter.append('thead');44764477var theadRow1 = thead.append('tr');44784479columns.forEach(function(column) {4480theadRow14481.append('th')4482.attr('width', column.width ? column.width : '10%')4483.style('text-align', column.type == 'numeric' ? 'right' : 'left')4484.append('span')4485.text(column.label);4486});4487}448844894490var tbody = table.selectAll('tbody')4491.data(function(d) { return d });4492tbody.enter().append('tbody');4493449444954496//compute max generations4497depth = d3.max(nodes, function(node) { return node.depth });4498tree.size([height, depth * childIndent]); //TODO: see if this is necessary at all449945004501// Update the nodes…4502var node = tbody.selectAll('tr')4503// .data(function(d) { return d; }, function(d) { return d.id || (d.id == ++i)});4504.data(function(d) { return d.filter(function(d) { return (filterZero && !d.children) ? filterZero(d) : true; } )}, function(d,i) { return d.id || (d.id || ++idx)});4505//.style('display', 'table-row'); //TODO: see if this does anything45064507node.exit().remove();45084509node.select('img.nv-treeicon')4510.attr('src', icon)4511.classed('folded', folded);45124513var nodeEnter = node.enter().append('tr');451445154516columns.forEach(function(column, index) {45174518var nodeName = nodeEnter.append('td')4519.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 here4520.style('text-align', column.type == 'numeric' ? 'right' : 'left');452145224523if (index == 0) {4524nodeName.append('img')4525.classed('nv-treeicon', true)4526.classed('nv-folded', folded)4527.attr('src', icon)4528.style('width', '14px')4529.style('height', '14px')4530.style('padding', '0 1px')4531.style('display', function(d) { return icon(d) ? 'inline-block' : 'none'; })4532.on('click', click);4533}453445354536nodeName.each(function(d) {4537if (!index && getUrl(d))4538d3.select(this)4539.append('a')4540.attr('href',getUrl)4541.attr('class', d3.functor(column.classes))4542.append('span')4543else4544d3.select(this)4545.append('span')45464547d3.select(this).select('span')4548.attr('class', d3.functor(column.classes) )4549.text(function(d) { return column.format ? column.format(d) :4550(d[column.key] || '-') });4551});45524553if (column.showCount) {4554nodeName.append('span')4555.attr('class', 'nv-childrenCount');45564557node.selectAll('span.nv-childrenCount').text(function(d) {4558return ((d.values && d.values.length) || (d._values && d._values.length)) ? //If this is a parent4559'(' + ((d.values && (d.values.filter(function(d) { return filterZero ? filterZero(d) : true; }).length)) //If children are in values check its children and filter4560|| (d._values && d._values.filter(function(d) { return filterZero ? filterZero(d) : true; }).length) //Otherwise, do the same, but with the other name, _values...4561|| 0) + ')' //This is the catch-all in case there are no children after a filter4562: '' //If this is not a parent, just give an empty string4563});4564}45654566// if (column.click)4567// nodeName.select('span').on('click', column.click);45684569});45704571node4572.order()4573.on('click', function(d) {4574dispatch.elementClick({4575row: this, //TODO: decide whether or not this should be consistent with scatter/line events or should be an html link (a href)4576data: d,4577pos: [d.x, d.y]4578});4579})4580.on('dblclick', function(d) {4581dispatch.elementDblclick({4582row: this,4583data: d,4584pos: [d.x, d.y]4585});4586})4587.on('mouseover', function(d) {4588dispatch.elementMouseover({4589row: this,4590data: d,4591pos: [d.x, d.y]4592});4593})4594.on('mouseout', function(d) {4595dispatch.elementMouseout({4596row: this,4597data: d,4598pos: [d.x, d.y]4599});4600});46014602460346044605// Toggle children on click.4606function click(d, _, unshift) {4607d3.event.stopPropagation();46084609if(d3.event.shiftKey && !unshift) {4610//If you shift-click, it'll toggle fold all the children, instead of itself4611d3.event.shiftKey = false;4612d.values && d.values.forEach(function(node){4613if (node.values || node._values) {4614click(node, 0, true);4615}4616});4617return true;4618}4619if(!hasChildren(d)) {4620//download file4621//window.location.href = d.url;4622return true;4623}4624if (d.values) {4625d._values = d.values;4626d.values = null;4627} else {4628d.values = d._values;4629d._values = null;4630}4631chart.update();4632}463346344635function icon(d) {4636return (d._values && d._values.length) ? iconOpen : (d.values && d.values.length) ? iconClose : '';4637}46384639function folded(d) {4640return (d._values && d._values.length);4641}46424643function hasChildren(d) {4644var values = d.values || d._values;46454646return (values && values.length);4647}464846494650});46514652return chart;4653}465446554656//============================================================4657// Expose Public Variables4658//------------------------------------------------------------4659chart.options = nv.utils.optionsFunc.bind(chart);46604661chart.margin = function(_) {4662if (!arguments.length) return margin;4663margin.top = typeof _.top != 'undefined' ? _.top : margin.top;4664margin.right = typeof _.right != 'undefined' ? _.right : margin.right;4665margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;4666margin.left = typeof _.left != 'undefined' ? _.left : margin.left;4667return chart;4668};46694670chart.width = function(_) {4671if (!arguments.length) return width;4672width = _;4673return chart;4674};46754676chart.height = function(_) {4677if (!arguments.length) return height;4678height = _;4679return chart;4680};46814682chart.color = function(_) {4683if (!arguments.length) return color;4684color = nv.utils.getColor(_);4685scatter.color(color);4686return chart;4687};46884689chart.id = function(_) {4690if (!arguments.length) return id;4691id = _;4692return chart;4693};46944695chart.header = function(_) {4696if (!arguments.length) return header;4697header = _;4698return chart;4699};47004701chart.noData = function(_) {4702if (!arguments.length) return noData;4703noData = _;4704return chart;4705};47064707chart.filterZero = function(_) {4708if (!arguments.length) return filterZero;4709filterZero = _;4710return chart;4711};47124713chart.columns = function(_) {4714if (!arguments.length) return columns;4715columns = _;4716return chart;4717};47184719chart.tableClass = function(_) {4720if (!arguments.length) return tableClass;4721tableClass = _;4722return chart;4723};47244725chart.iconOpen = function(_){4726if (!arguments.length) return iconOpen;4727iconOpen = _;4728return chart;4729}47304731chart.iconClose = function(_){4732if (!arguments.length) return iconClose;4733iconClose = _;4734return chart;4735}47364737chart.getUrl = function(_){4738if (!arguments.length) return getUrl;4739getUrl = _;4740return chart;4741}47424743//============================================================474447454746return chart;4747};nv.models.legend = function() {4748"use strict";4749//============================================================4750// Public Variables with Default Settings4751//------------------------------------------------------------47524753var margin = {top: 5, right: 0, bottom: 5, left: 0}4754, width = 4004755, height = 204756, getKey = function(d) { return d.key }4757, color = nv.utils.defaultColor()4758, align = true4759, rightAlign = true4760, updateState = true //If true, legend will update data.disabled and trigger a 'stateChange' dispatch.4761, radioButtonMode = false //If true, clicking legend items will cause it to behave like a radio button. (only one can be selected at a time)4762, dispatch = d3.dispatch('legendClick', 'legendDblclick', 'legendMouseover', 'legendMouseout', 'stateChange')4763;47644765//============================================================476647674768function chart(selection) {4769selection.each(function(data) {4770var availableWidth = width - margin.left - margin.right,4771container = d3.select(this);477247734774//------------------------------------------------------------4775// Setup containers and skeleton of chart47764777var wrap = container.selectAll('g.nv-legend').data([data]);4778var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-legend').append('g');4779var g = wrap.select('g');47804781wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');47824783//------------------------------------------------------------478447854786var series = g.selectAll('.nv-series')4787.data(function(d) { return d });4788var seriesEnter = series.enter().append('g').attr('class', 'nv-series')4789.on('mouseover', function(d,i) {4790dispatch.legendMouseover(d,i); //TODO: Make consistent with other event objects4791})4792.on('mouseout', function(d,i) {4793dispatch.legendMouseout(d,i);4794})4795.on('click', function(d,i) {4796dispatch.legendClick(d,i);4797if (updateState) {4798if (radioButtonMode) {4799//Radio button mode: set every series to disabled,4800// and enable the clicked series.4801data.forEach(function(series) { series.disabled = true});4802d.disabled = false;4803}4804else {4805d.disabled = !d.disabled;4806if (data.every(function(series) { return series.disabled})) {4807//the default behavior of NVD3 legends is, if every single series4808// is disabled, turn all series' back on.4809data.forEach(function(series) { series.disabled = false});4810}4811}4812dispatch.stateChange({4813disabled: data.map(function(d) { return !!d.disabled })4814});4815}4816})4817.on('dblclick', function(d,i) {4818dispatch.legendDblclick(d,i);4819if (updateState) {4820//the default behavior of NVD3 legends, when double clicking one,4821// is to set all other series' to false, and make the double clicked series enabled.4822data.forEach(function(series) {4823series.disabled = true;4824});4825d.disabled = false;4826dispatch.stateChange({4827disabled: data.map(function(d) { return !!d.disabled })4828});4829}4830});4831seriesEnter.append('circle')4832.style('stroke-width', 2)4833.attr('class','nv-legend-symbol')4834.attr('r', 5);4835seriesEnter.append('text')4836.attr('text-anchor', 'start')4837.attr('class','nv-legend-text')4838.attr('dy', '.32em')4839.attr('dx', '8');4840series.classed('disabled', function(d) { return d.disabled });4841series.exit().remove();4842series.select('circle')4843.style('fill', function(d,i) { return d.color || color(d,i)})4844.style('stroke', function(d,i) { return d.color || color(d, i) });4845series.select('text').text(getKey);484648474848//TODO: implement fixed-width and max-width options (max-width is especially useful with the align option)48494850// NEW ALIGNING CODE, TODO: clean up4851if (align) {48524853var seriesWidths = [];4854series.each(function(d,i) {4855var legendText = d3.select(this).select('text');4856var nodeTextLength;4857try {4858nodeTextLength = legendText.node().getComputedTextLength();4859}4860catch(e) {4861nodeTextLength = nv.utils.calcApproxTextWidth(legendText);4862}48634864seriesWidths.push(nodeTextLength + 28); // 28 is ~ the width of the circle plus some padding4865});48664867var seriesPerRow = 0;4868var legendWidth = 0;4869var columnWidths = [];48704871while ( legendWidth < availableWidth && seriesPerRow < seriesWidths.length) {4872columnWidths[seriesPerRow] = seriesWidths[seriesPerRow];4873legendWidth += seriesWidths[seriesPerRow++];4874}4875if (seriesPerRow === 0) seriesPerRow = 1; //minimum of one series per row487648774878while ( legendWidth > availableWidth && seriesPerRow > 1 ) {4879columnWidths = [];4880seriesPerRow--;48814882for (var k = 0; k < seriesWidths.length; k++) {4883if (seriesWidths[k] > (columnWidths[k % seriesPerRow] || 0) )4884columnWidths[k % seriesPerRow] = seriesWidths[k];4885}48864887legendWidth = columnWidths.reduce(function(prev, cur, index, array) {4888return prev + cur;4889});4890}48914892var xPositions = [];4893for (var i = 0, curX = 0; i < seriesPerRow; i++) {4894xPositions[i] = curX;4895curX += columnWidths[i];4896}48974898series4899.attr('transform', function(d, i) {4900return 'translate(' + xPositions[i % seriesPerRow] + ',' + (5 + Math.floor(i / seriesPerRow) * 20) + ')';4901});49024903//position legend as far right as possible within the total width4904if (rightAlign) {4905g.attr('transform', 'translate(' + (width - margin.right - legendWidth) + ',' + margin.top + ')');4906}4907else {4908g.attr('transform', 'translate(0' + ',' + margin.top + ')');4909}49104911height = margin.top + margin.bottom + (Math.ceil(seriesWidths.length / seriesPerRow) * 20);49124913} else {49144915var ypos = 5,4916newxpos = 5,4917maxwidth = 0,4918xpos;4919series4920.attr('transform', function(d, i) {4921var length = d3.select(this).select('text').node().getComputedTextLength() + 28;4922xpos = newxpos;49234924if (width < margin.left + margin.right + xpos + length) {4925newxpos = xpos = 5;4926ypos += 20;4927}49284929newxpos += length;4930if (newxpos > maxwidth) maxwidth = newxpos;49314932return 'translate(' + xpos + ',' + ypos + ')';4933});49344935//position legend as far right as possible within the total width4936g.attr('transform', 'translate(' + (width - margin.right - maxwidth) + ',' + margin.top + ')');49374938height = margin.top + margin.bottom + ypos + 15;49394940}49414942});49434944return chart;4945}494649474948//============================================================4949// Expose Public Variables4950//------------------------------------------------------------49514952chart.dispatch = dispatch;4953chart.options = nv.utils.optionsFunc.bind(chart);49544955chart.margin = function(_) {4956if (!arguments.length) return margin;4957margin.top = typeof _.top != 'undefined' ? _.top : margin.top;4958margin.right = typeof _.right != 'undefined' ? _.right : margin.right;4959margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;4960margin.left = typeof _.left != 'undefined' ? _.left : margin.left;4961return chart;4962};49634964chart.width = function(_) {4965if (!arguments.length) return width;4966width = _;4967return chart;4968};49694970chart.height = function(_) {4971if (!arguments.length) return height;4972height = _;4973return chart;4974};49754976chart.key = function(_) {4977if (!arguments.length) return getKey;4978getKey = _;4979return chart;4980};49814982chart.color = function(_) {4983if (!arguments.length) return color;4984color = nv.utils.getColor(_);4985return chart;4986};49874988chart.align = function(_) {4989if (!arguments.length) return align;4990align = _;4991return chart;4992};49934994chart.rightAlign = function(_) {4995if (!arguments.length) return rightAlign;4996rightAlign = _;4997return chart;4998};49995000chart.updateState = function(_) {5001if (!arguments.length) return updateState;5002updateState = _;5003return chart;5004};50055006chart.radioButtonMode = function(_) {5007if (!arguments.length) return radioButtonMode;5008radioButtonMode = _;5009return chart;5010};50115012//============================================================501350145015return chart;5016}50175018nv.models.line = function() {5019"use strict";5020//============================================================5021// Public Variables with Default Settings5022//------------------------------------------------------------50235024var scatter = nv.models.scatter()5025;50265027var margin = {top: 0, right: 0, bottom: 0, left: 0}5028, width = 9605029, height = 5005030, color = nv.utils.defaultColor() // a function that returns a color5031, getX = function(d) { return d.x } // accessor to get the x value from a data point5032, getY = function(d) { return d.y } // accessor to get the y value from a data point5033, defined = function(d,i) { return !isNaN(getY(d,i)) && getY(d,i) !== null } // allows a line to be not continuous when it is not defined5034, isArea = function(d) { return d.area } // decides if a line is an area or just a line5035, clipEdge = false // if true, masks lines within x and y scale5036, x //can be accessed via chart.xScale()5037, y //can be accessed via chart.yScale()5038, interpolate = "linear" // controls the line interpolation5039;50405041scatter5042.size(16) // default size5043.sizeDomain([16,256]) //set to speed up calculation, needs to be unset if there is a custom size accessor5044;50455046//============================================================504750485049//============================================================5050// Private Variables5051//------------------------------------------------------------50525053var x0, y0 //used to store previous scales5054;50555056//============================================================505750585059function chart(selection) {5060selection.each(function(data) {5061var availableWidth = width - margin.left - margin.right,5062availableHeight = height - margin.top - margin.bottom,5063container = d3.select(this);50645065//------------------------------------------------------------5066// Setup Scales50675068x = scatter.xScale();5069y = scatter.yScale();50705071x0 = x0 || x;5072y0 = y0 || y;50735074//------------------------------------------------------------507550765077//------------------------------------------------------------5078// Setup containers and skeleton of chart50795080var wrap = container.selectAll('g.nv-wrap.nv-line').data([data]);5081var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-line');5082var defsEnter = wrapEnter.append('defs');5083var gEnter = wrapEnter.append('g');5084var g = wrap.select('g')50855086gEnter.append('g').attr('class', 'nv-groups');5087gEnter.append('g').attr('class', 'nv-scatterWrap');50885089wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');50905091//------------------------------------------------------------50925093509450955096scatter5097.width(availableWidth)5098.height(availableHeight)50995100var scatterWrap = wrap.select('.nv-scatterWrap');5101//.datum(data); // Data automatically trickles down from the wrap51025103scatterWrap.transition().call(scatter);5104510551065107defsEnter.append('clipPath')5108.attr('id', 'nv-edge-clip-' + scatter.id())5109.append('rect');51105111wrap.select('#nv-edge-clip-' + scatter.id() + ' rect')5112.attr('width', availableWidth)5113.attr('height', availableHeight);51145115g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');5116scatterWrap5117.attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + scatter.id() + ')' : '');51185119512051215122var groups = wrap.select('.nv-groups').selectAll('.nv-group')5123.data(function(d) { return d }, function(d) { return d.key });5124groups.enter().append('g')5125.style('stroke-opacity', 1e-6)5126.style('fill-opacity', 1e-6);5127groups.exit()5128.transition()5129.style('stroke-opacity', 1e-6)5130.style('fill-opacity', 1e-6)5131.remove();5132groups5133.attr('class', function(d,i) { return 'nv-group nv-series-' + i })5134.classed('hover', function(d) { return d.hover })5135.style('fill', function(d,i){ return color(d, i) })5136.style('stroke', function(d,i){ return color(d, i)});5137groups5138.transition()5139.style('stroke-opacity', 1)5140.style('fill-opacity', .5);5141514251435144var areaPaths = groups.selectAll('path.nv-area')5145.data(function(d) { return isArea(d) ? [d] : [] }); // this is done differently than lines because I need to check if series is an area5146areaPaths.enter().append('path')5147.attr('class', 'nv-area')5148.attr('d', function(d) {5149return d3.svg.area()5150.interpolate(interpolate)5151.defined(defined)5152.x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })5153.y0(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })5154.y1(function(d,i) { return y0( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })5155//.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this5156.apply(this, [d.values])5157});5158groups.exit().selectAll('path.nv-area')5159.remove();51605161areaPaths5162.transition()5163.attr('d', function(d) {5164return d3.svg.area()5165.interpolate(interpolate)5166.defined(defined)5167.x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })5168.y0(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })5169.y1(function(d,i) { return y( y.domain()[0] <= 0 ? y.domain()[1] >= 0 ? 0 : y.domain()[1] : y.domain()[0] ) })5170//.y1(function(d,i) { return y0(0) }) //assuming 0 is within y domain.. may need to tweak this5171.apply(this, [d.values])5172});5173517451755176var linePaths = groups.selectAll('path.nv-line')5177.data(function(d) { return [d.values] });5178linePaths.enter().append('path')5179.attr('class', 'nv-line')5180.attr('d',5181d3.svg.line()5182.interpolate(interpolate)5183.defined(defined)5184.x(function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })5185.y(function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })5186);5187groups.exit().selectAll('path.nv-line')5188.transition()5189.attr('d',5190d3.svg.line()5191.interpolate(interpolate)5192.defined(defined)5193.x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })5194.y(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })5195);5196linePaths5197.transition()5198.attr('d',5199d3.svg.line()5200.interpolate(interpolate)5201.defined(defined)5202.x(function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })5203.y(function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })5204);5205520652075208//store old scales for use in transitions on update5209x0 = x.copy();5210y0 = y.copy();52115212});52135214return chart;5215}521652175218//============================================================5219// Expose Public Variables5220//------------------------------------------------------------52215222chart.dispatch = scatter.dispatch;5223chart.scatter = scatter;52245225d3.rebind(chart, scatter, 'id', 'interactive', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'xRange', 'yRange',5226'sizeDomain', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'useVoronoi', 'clipRadius', 'padData','highlightPoint','clearHighlights');52275228chart.options = nv.utils.optionsFunc.bind(chart);52295230chart.margin = function(_) {5231if (!arguments.length) return margin;5232margin.top = typeof _.top != 'undefined' ? _.top : margin.top;5233margin.right = typeof _.right != 'undefined' ? _.right : margin.right;5234margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;5235margin.left = typeof _.left != 'undefined' ? _.left : margin.left;5236return chart;5237};52385239chart.width = function(_) {5240if (!arguments.length) return width;5241width = _;5242return chart;5243};52445245chart.height = function(_) {5246if (!arguments.length) return height;5247height = _;5248return chart;5249};52505251chart.x = function(_) {5252if (!arguments.length) return getX;5253getX = _;5254scatter.x(_);5255return chart;5256};52575258chart.y = function(_) {5259if (!arguments.length) return getY;5260getY = _;5261scatter.y(_);5262return chart;5263};52645265chart.clipEdge = function(_) {5266if (!arguments.length) return clipEdge;5267clipEdge = _;5268return chart;5269};52705271chart.color = function(_) {5272if (!arguments.length) return color;5273color = nv.utils.getColor(_);5274scatter.color(color);5275return chart;5276};52775278chart.interpolate = function(_) {5279if (!arguments.length) return interpolate;5280interpolate = _;5281return chart;5282};52835284chart.defined = function(_) {5285if (!arguments.length) return defined;5286defined = _;5287return chart;5288};52895290chart.isArea = function(_) {5291if (!arguments.length) return isArea;5292isArea = d3.functor(_);5293return chart;5294};52955296//============================================================529752985299return chart;5300}53015302nv.models.lineChart = function() {5303"use strict";5304//============================================================5305// Public Variables with Default Settings5306//------------------------------------------------------------53075308var lines = nv.models.line()5309, xAxis = nv.models.axis()5310, yAxis = nv.models.axis()5311, legend = nv.models.legend()5312, interactiveLayer = nv.interactiveGuideline()5313;53145315var margin = {top: 30, right: 20, bottom: 50, left: 60}5316, color = nv.utils.defaultColor()5317, width = null5318, height = null5319, showLegend = true5320, showXAxis = true5321, showYAxis = true5322, rightAlignYAxis = false5323, useInteractiveGuideline = false5324, tooltips = true5325, tooltip = function(key, x, y, e, graph) {5326return '<h3>' + key + '</h3>' +5327'<p>' + y + ' at ' + x + '</p>'5328}5329, x5330, y5331, state = {}5332, defaultState = null5333, noData = 'No Data Available.'5334, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')5335, transitionDuration = 2505336;53375338xAxis5339.orient('bottom')5340.tickPadding(7)5341;5342yAxis5343.orient((rightAlignYAxis) ? 'right' : 'left')5344;53455346//============================================================534753485349//============================================================5350// Private Variables5351//------------------------------------------------------------53525353var showTooltip = function(e, offsetElement) {5354var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),5355top = e.pos[1] + ( offsetElement.offsetTop || 0),5356x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),5357y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)),5358content = tooltip(e.series.key, x, y, e, chart);53595360nv.tooltip.show([left, top], content, null, null, offsetElement);5361};53625363//============================================================536453655366function chart(selection) {5367selection.each(function(data) {5368var container = d3.select(this),5369that = this;53705371var availableWidth = (width || parseInt(container.style('width')) || 960)5372- margin.left - margin.right,5373availableHeight = (height || parseInt(container.style('height')) || 400)5374- margin.top - margin.bottom;537553765377chart.update = function() { container.transition().duration(transitionDuration).call(chart) };5378chart.container = this;53795380//set state.disabled5381state.disabled = data.map(function(d) { return !!d.disabled });538253835384if (!defaultState) {5385var key;5386defaultState = {};5387for (key in state) {5388if (state[key] instanceof Array)5389defaultState[key] = state[key].slice(0);5390else5391defaultState[key] = state[key];5392}5393}53945395//------------------------------------------------------------5396// Display noData message if there's nothing to show.53975398if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {5399var noDataText = container.selectAll('.nv-noData').data([noData]);54005401noDataText.enter().append('text')5402.attr('class', 'nvd3 nv-noData')5403.attr('dy', '-.7em')5404.style('text-anchor', 'middle');54055406noDataText5407.attr('x', margin.left + availableWidth / 2)5408.attr('y', margin.top + availableHeight / 2)5409.text(function(d) { return d });54105411return chart;5412} else {5413container.selectAll('.nv-noData').remove();5414}54155416//------------------------------------------------------------541754185419//------------------------------------------------------------5420// Setup Scales54215422x = lines.xScale();5423y = lines.yScale();54245425//------------------------------------------------------------542654275428//------------------------------------------------------------5429// Setup containers and skeleton of chart54305431var wrap = container.selectAll('g.nv-wrap.nv-lineChart').data([data]);5432var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineChart').append('g');5433var g = wrap.select('g');54345435gEnter.append("rect").style("opacity",0);5436gEnter.append('g').attr('class', 'nv-x nv-axis');5437gEnter.append('g').attr('class', 'nv-y nv-axis');5438gEnter.append('g').attr('class', 'nv-linesWrap');5439gEnter.append('g').attr('class', 'nv-legendWrap');5440gEnter.append('g').attr('class', 'nv-interactive');54415442g.select("rect").attr("width",availableWidth).attr("height",availableHeight);5443//------------------------------------------------------------5444// Legend54455446if (showLegend) {5447legend.width(availableWidth);54485449g.select('.nv-legendWrap')5450.datum(data)5451.call(legend);54525453if ( margin.top != legend.height()) {5454margin.top = legend.height();5455availableHeight = (height || parseInt(container.style('height')) || 400)5456- margin.top - margin.bottom;5457}54585459wrap.select('.nv-legendWrap')5460.attr('transform', 'translate(0,' + (-margin.top) +')')5461}54625463//------------------------------------------------------------54645465wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');54665467if (rightAlignYAxis) {5468g.select(".nv-y.nv-axis")5469.attr("transform", "translate(" + availableWidth + ",0)");5470}54715472//------------------------------------------------------------5473// Main Chart Component(s)547454755476//------------------------------------------------------------5477//Set up interactive layer5478if (useInteractiveGuideline) {5479interactiveLayer5480.width(availableWidth)5481.height(availableHeight)5482.margin({left:margin.left, top:margin.top})5483.svgContainer(container)5484.xScale(x);5485wrap.select(".nv-interactive").call(interactiveLayer);5486}548754885489lines5490.width(availableWidth)5491.height(availableHeight)5492.color(data.map(function(d,i) {5493return d.color || color(d, i);5494}).filter(function(d,i) { return !data[i].disabled }));549554965497var linesWrap = g.select('.nv-linesWrap')5498.datum(data.filter(function(d) { return !d.disabled }))54995500linesWrap.transition().call(lines);55015502//------------------------------------------------------------550355045505//------------------------------------------------------------5506// Setup Axes55075508if (showXAxis) {5509xAxis5510.scale(x)5511.ticks( availableWidth / 100 )5512.tickSize(-availableHeight, 0);55135514g.select('.nv-x.nv-axis')5515.attr('transform', 'translate(0,' + y.range()[0] + ')');5516g.select('.nv-x.nv-axis')5517.transition()5518.call(xAxis);5519}55205521if (showYAxis) {5522yAxis5523.scale(y)5524.ticks( availableHeight / 36 )5525.tickSize( -availableWidth, 0);55265527g.select('.nv-y.nv-axis')5528.transition()5529.call(yAxis);5530}5531//------------------------------------------------------------553255335534//============================================================5535// Event Handling/Dispatching (in chart's scope)5536//------------------------------------------------------------55375538legend.dispatch.on('stateChange', function(newState) {5539state = newState;5540dispatch.stateChange(state);5541chart.update();5542});55435544interactiveLayer.dispatch.on('elementMousemove', function(e) {5545lines.clearHighlights();5546var singlePoint, pointIndex, pointXLocation, allData = [];5547data5548.filter(function(series, i) {5549series.seriesIndex = i;5550return !series.disabled;5551})5552.forEach(function(series,i) {5553pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());5554lines.highlightPoint(i, pointIndex, true);5555var point = series.values[pointIndex];5556if (typeof point === 'undefined') return;5557if (typeof singlePoint === 'undefined') singlePoint = point;5558if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));5559allData.push({5560key: series.key,5561value: chart.y()(point, pointIndex),5562color: color(series,series.seriesIndex)5563});5564});55655566var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));5567interactiveLayer.tooltip5568.position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})5569.chartContainer(that.parentNode)5570.enabled(tooltips)5571.valueFormatter(function(d,i) {5572return yAxis.tickFormat()(d);5573})5574.data(5575{5576value: xValue,5577series: allData5578}5579)();55805581interactiveLayer.renderGuideLine(pointXLocation);55825583});55845585interactiveLayer.dispatch.on("elementMouseout",function(e) {5586dispatch.tooltipHide();5587lines.clearHighlights();5588});55895590dispatch.on('tooltipShow', function(e) {5591if (tooltips) showTooltip(e, that.parentNode);5592});559355945595dispatch.on('changeState', function(e) {55965597if (typeof e.disabled !== 'undefined') {5598data.forEach(function(series,i) {5599series.disabled = e.disabled[i];5600});56015602state.disabled = e.disabled;5603}56045605chart.update();5606});56075608//============================================================56095610});56115612return chart;5613}561456155616//============================================================5617// Event Handling/Dispatching (out of chart's scope)5618//------------------------------------------------------------56195620lines.dispatch.on('elementMouseover.tooltip', function(e) {5621e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];5622dispatch.tooltipShow(e);5623});56245625lines.dispatch.on('elementMouseout.tooltip', function(e) {5626dispatch.tooltipHide(e);5627});56285629dispatch.on('tooltipHide', function() {5630if (tooltips) nv.tooltip.cleanup();5631});56325633//============================================================563456355636//============================================================5637// Expose Public Variables5638//------------------------------------------------------------56395640// expose chart's sub-components5641chart.dispatch = dispatch;5642chart.lines = lines;5643chart.legend = legend;5644chart.xAxis = xAxis;5645chart.yAxis = yAxis;5646chart.interactiveLayer = interactiveLayer;56475648d3.rebind(chart, lines, 'defined', 'isArea', 'x', 'y', 'size', 'xScale', 'yScale', 'xDomain', 'yDomain', 'xRange', 'yRange'5649, 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'useVoronoi','id', 'interpolate');56505651chart.options = nv.utils.optionsFunc.bind(chart);56525653chart.margin = function(_) {5654if (!arguments.length) return margin;5655margin.top = typeof _.top != 'undefined' ? _.top : margin.top;5656margin.right = typeof _.right != 'undefined' ? _.right : margin.right;5657margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;5658margin.left = typeof _.left != 'undefined' ? _.left : margin.left;5659return chart;5660};56615662chart.width = function(_) {5663if (!arguments.length) return width;5664width = _;5665return chart;5666};56675668chart.height = function(_) {5669if (!arguments.length) return height;5670height = _;5671return chart;5672};56735674chart.color = function(_) {5675if (!arguments.length) return color;5676color = nv.utils.getColor(_);5677legend.color(color);5678return chart;5679};56805681chart.showLegend = function(_) {5682if (!arguments.length) return showLegend;5683showLegend = _;5684return chart;5685};56865687chart.showXAxis = function(_) {5688if (!arguments.length) return showXAxis;5689showXAxis = _;5690return chart;5691};56925693chart.showYAxis = function(_) {5694if (!arguments.length) return showYAxis;5695showYAxis = _;5696return chart;5697};56985699chart.rightAlignYAxis = function(_) {5700if(!arguments.length) return rightAlignYAxis;5701rightAlignYAxis = _;5702yAxis.orient( (_) ? 'right' : 'left');5703return chart;5704};57055706chart.useInteractiveGuideline = function(_) {5707if(!arguments.length) return useInteractiveGuideline;5708useInteractiveGuideline = _;5709if (_ === true) {5710chart.interactive(false);5711chart.useVoronoi(false);5712}5713return chart;5714};57155716chart.tooltips = function(_) {5717if (!arguments.length) return tooltips;5718tooltips = _;5719return chart;5720};57215722chart.tooltipContent = function(_) {5723if (!arguments.length) return tooltip;5724tooltip = _;5725return chart;5726};57275728chart.state = function(_) {5729if (!arguments.length) return state;5730state = _;5731return chart;5732};57335734chart.defaultState = function(_) {5735if (!arguments.length) return defaultState;5736defaultState = _;5737return chart;5738};57395740chart.noData = function(_) {5741if (!arguments.length) return noData;5742noData = _;5743return chart;5744};57455746chart.transitionDuration = function(_) {5747if (!arguments.length) return transitionDuration;5748transitionDuration = _;5749return chart;5750};57515752//============================================================575357545755return chart;5756}57575758nv.models.linePlusBarChart = function() {5759"use strict";5760//============================================================5761// Public Variables with Default Settings5762//------------------------------------------------------------57635764var lines = nv.models.line()5765, bars = nv.models.historicalBar()5766, xAxis = nv.models.axis()5767, y1Axis = nv.models.axis()5768, y2Axis = nv.models.axis()5769, legend = nv.models.legend()5770;57715772var margin = {top: 30, right: 60, bottom: 50, left: 60}5773, width = null5774, height = null5775, getX = function(d) { return d.x }5776, getY = function(d) { return d.y }5777, color = nv.utils.defaultColor()5778, showLegend = true5779, tooltips = true5780, tooltip = function(key, x, y, e, graph) {5781return '<h3>' + key + '</h3>' +5782'<p>' + y + ' at ' + x + '</p>';5783}5784, x5785, y15786, y25787, state = {}5788, defaultState = null5789, noData = "No Data Available."5790, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')5791;57925793bars5794.padData(true)5795;5796lines5797.clipEdge(false)5798.padData(true)5799;5800xAxis5801.orient('bottom')5802.tickPadding(7)5803.highlightZero(false)5804;5805y1Axis5806.orient('left')5807;5808y2Axis5809.orient('right')5810;58115812//============================================================581358145815//============================================================5816// Private Variables5817//------------------------------------------------------------58185819var showTooltip = function(e, offsetElement) {5820var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),5821top = e.pos[1] + ( offsetElement.offsetTop || 0),5822x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),5823y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)),5824content = tooltip(e.series.key, x, y, e, chart);58255826nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);5827}5828;58295830//------------------------------------------------------------5831583258335834function chart(selection) {5835selection.each(function(data) {5836var container = d3.select(this),5837that = this;58385839var availableWidth = (width || parseInt(container.style('width')) || 960)5840- margin.left - margin.right,5841availableHeight = (height || parseInt(container.style('height')) || 400)5842- margin.top - margin.bottom;58435844chart.update = function() { container.transition().call(chart); };5845// chart.container = this;58465847//set state.disabled5848state.disabled = data.map(function(d) { return !!d.disabled });58495850if (!defaultState) {5851var key;5852defaultState = {};5853for (key in state) {5854if (state[key] instanceof Array)5855defaultState[key] = state[key].slice(0);5856else5857defaultState[key] = state[key];5858}5859}58605861//------------------------------------------------------------5862// Display No Data message if there's nothing to show.58635864if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {5865var noDataText = container.selectAll('.nv-noData').data([noData]);58665867noDataText.enter().append('text')5868.attr('class', 'nvd3 nv-noData')5869.attr('dy', '-.7em')5870.style('text-anchor', 'middle');58715872noDataText5873.attr('x', margin.left + availableWidth / 2)5874.attr('y', margin.top + availableHeight / 2)5875.text(function(d) { return d });58765877return chart;5878} else {5879container.selectAll('.nv-noData').remove();5880}58815882//------------------------------------------------------------588358845885//------------------------------------------------------------5886// Setup Scales58875888var dataBars = data.filter(function(d) { return !d.disabled && d.bar });5889var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #24058905891//x = xAxis.scale();5892x = dataLines.filter(function(d) { return !d.disabled; }).length && dataLines.filter(function(d) { return !d.disabled; })[0].values.length ? lines.xScale() : bars.xScale();5893//x = dataLines.filter(function(d) { return !d.disabled; }).length ? lines.xScale() : bars.xScale(); //old code before change above5894y1 = bars.yScale();5895y2 = lines.yScale();58965897//------------------------------------------------------------58985899//------------------------------------------------------------5900// Setup containers and skeleton of chart59015902var wrap = d3.select(this).selectAll('g.nv-wrap.nv-linePlusBar').data([data]);5903var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');5904var g = wrap.select('g');59055906gEnter.append('g').attr('class', 'nv-x nv-axis');5907gEnter.append('g').attr('class', 'nv-y1 nv-axis');5908gEnter.append('g').attr('class', 'nv-y2 nv-axis');5909gEnter.append('g').attr('class', 'nv-barsWrap');5910gEnter.append('g').attr('class', 'nv-linesWrap');5911gEnter.append('g').attr('class', 'nv-legendWrap');59125913//------------------------------------------------------------591459155916//------------------------------------------------------------5917// Legend59185919if (showLegend) {5920legend.width( availableWidth / 2 );59215922g.select('.nv-legendWrap')5923.datum(data.map(function(series) {5924series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;5925series.key = series.originalKey + (series.bar ? ' (left axis)' : ' (right axis)');5926return series;5927}))5928.call(legend);59295930if ( margin.top != legend.height()) {5931margin.top = legend.height();5932availableHeight = (height || parseInt(container.style('height')) || 400)5933- margin.top - margin.bottom;5934}59355936g.select('.nv-legendWrap')5937.attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')');5938}59395940//------------------------------------------------------------594159425943wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');594459455946//------------------------------------------------------------5947// Main Chart Component(s)594859495950lines5951.width(availableWidth)5952.height(availableHeight)5953.color(data.map(function(d,i) {5954return d.color || color(d, i);5955}).filter(function(d,i) { return !data[i].disabled && !data[i].bar }))59565957bars5958.width(availableWidth)5959.height(availableHeight)5960.color(data.map(function(d,i) {5961return d.color || color(d, i);5962}).filter(function(d,i) { return !data[i].disabled && data[i].bar }))5963596459655966var barsWrap = g.select('.nv-barsWrap')5967.datum(dataBars.length ? dataBars : [{values:[]}])59685969var linesWrap = g.select('.nv-linesWrap')5970.datum(dataLines[0] && !dataLines[0].disabled ? dataLines : [{values:[]}] );5971//.datum(!dataLines[0].disabled ? dataLines : [{values:dataLines[0].values.map(function(d) { return [d[0], null] }) }] );59725973d3.transition(barsWrap).call(bars);5974d3.transition(linesWrap).call(lines);59755976//------------------------------------------------------------597759785979//------------------------------------------------------------5980// Setup Axes59815982xAxis5983.scale(x)5984.ticks( availableWidth / 100 )5985.tickSize(-availableHeight, 0);59865987g.select('.nv-x.nv-axis')5988.attr('transform', 'translate(0,' + y1.range()[0] + ')');5989d3.transition(g.select('.nv-x.nv-axis'))5990.call(xAxis);599159925993y1Axis5994.scale(y1)5995.ticks( availableHeight / 36 )5996.tickSize(-availableWidth, 0);59975998d3.transition(g.select('.nv-y1.nv-axis'))5999.style('opacity', dataBars.length ? 1 : 0)6000.call(y1Axis);600160026003y2Axis6004.scale(y2)6005.ticks( availableHeight / 36 )6006.tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none60076008g.select('.nv-y2.nv-axis')6009.style('opacity', dataLines.length ? 1 : 0)6010.attr('transform', 'translate(' + availableWidth + ',0)');6011//.attr('transform', 'translate(' + x.range()[1] + ',0)');60126013d3.transition(g.select('.nv-y2.nv-axis'))6014.call(y2Axis);60156016//------------------------------------------------------------601760186019//============================================================6020// Event Handling/Dispatching (in chart's scope)6021//------------------------------------------------------------60226023legend.dispatch.on('stateChange', function(newState) {6024state = newState;6025dispatch.stateChange(state);6026chart.update();6027});60286029dispatch.on('tooltipShow', function(e) {6030if (tooltips) showTooltip(e, that.parentNode);6031});603260336034// Update chart from a state object passed to event handler6035dispatch.on('changeState', function(e) {60366037if (typeof e.disabled !== 'undefined') {6038data.forEach(function(series,i) {6039series.disabled = e.disabled[i];6040});60416042state.disabled = e.disabled;6043}60446045chart.update();6046});60476048//============================================================604960506051});60526053return chart;6054}605560566057//============================================================6058// Event Handling/Dispatching (out of chart's scope)6059//------------------------------------------------------------60606061lines.dispatch.on('elementMouseover.tooltip', function(e) {6062e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];6063dispatch.tooltipShow(e);6064});60656066lines.dispatch.on('elementMouseout.tooltip', function(e) {6067dispatch.tooltipHide(e);6068});60696070bars.dispatch.on('elementMouseover.tooltip', function(e) {6071e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];6072dispatch.tooltipShow(e);6073});60746075bars.dispatch.on('elementMouseout.tooltip', function(e) {6076dispatch.tooltipHide(e);6077});60786079dispatch.on('tooltipHide', function() {6080if (tooltips) nv.tooltip.cleanup();6081});60826083//============================================================608460856086//============================================================6087// Expose Public Variables6088//------------------------------------------------------------60896090// expose chart's sub-components6091chart.dispatch = dispatch;6092chart.legend = legend;6093chart.lines = lines;6094chart.bars = bars;6095chart.xAxis = xAxis;6096chart.y1Axis = y1Axis;6097chart.y2Axis = y2Axis;60986099d3.rebind(chart, lines, 'defined', 'size', 'clipVoronoi', 'interpolate');6100//TODO: consider rebinding x, y and some other stuff, and simply do soemthign lile bars.x(lines.x()), etc.6101//d3.rebind(chart, lines, 'x', 'y', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');61026103chart.options = nv.utils.optionsFunc.bind(chart);61046105chart.x = function(_) {6106if (!arguments.length) return getX;6107getX = _;6108lines.x(_);6109bars.x(_);6110return chart;6111};61126113chart.y = function(_) {6114if (!arguments.length) return getY;6115getY = _;6116lines.y(_);6117bars.y(_);6118return chart;6119};61206121chart.margin = function(_) {6122if (!arguments.length) return margin;6123margin.top = typeof _.top != 'undefined' ? _.top : margin.top;6124margin.right = typeof _.right != 'undefined' ? _.right : margin.right;6125margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;6126margin.left = typeof _.left != 'undefined' ? _.left : margin.left;6127return chart;6128};61296130chart.width = function(_) {6131if (!arguments.length) return width;6132width = _;6133return chart;6134};61356136chart.height = function(_) {6137if (!arguments.length) return height;6138height = _;6139return chart;6140};61416142chart.color = function(_) {6143if (!arguments.length) return color;6144color = nv.utils.getColor(_);6145legend.color(color);6146return chart;6147};61486149chart.showLegend = function(_) {6150if (!arguments.length) return showLegend;6151showLegend = _;6152return chart;6153};61546155chart.tooltips = function(_) {6156if (!arguments.length) return tooltips;6157tooltips = _;6158return chart;6159};61606161chart.tooltipContent = function(_) {6162if (!arguments.length) return tooltip;6163tooltip = _;6164return chart;6165};61666167chart.state = function(_) {6168if (!arguments.length) return state;6169state = _;6170return chart;6171};61726173chart.defaultState = function(_) {6174if (!arguments.length) return defaultState;6175defaultState = _;6176return chart;6177};61786179chart.noData = function(_) {6180if (!arguments.length) return noData;6181noData = _;6182return chart;6183};61846185//============================================================618661876188return chart;6189}6190nv.models.lineWithFocusChart = function() {6191"use strict";6192//============================================================6193// Public Variables with Default Settings6194//------------------------------------------------------------61956196var lines = nv.models.line()6197, lines2 = nv.models.line()6198, xAxis = nv.models.axis()6199, yAxis = nv.models.axis()6200, x2Axis = nv.models.axis()6201, y2Axis = nv.models.axis()6202, legend = nv.models.legend()6203, brush = d3.svg.brush()6204;62056206var margin = {top: 30, right: 30, bottom: 30, left: 60}6207, margin2 = {top: 0, right: 30, bottom: 20, left: 60}6208, color = nv.utils.defaultColor()6209, width = null6210, height = null6211, height2 = 1006212, x6213, y6214, x26215, y26216, showLegend = true6217, brushExtent = null6218, tooltips = true6219, tooltip = function(key, x, y, e, graph) {6220return '<h3>' + key + '</h3>' +6221'<p>' + y + ' at ' + x + '</p>'6222}6223, noData = "No Data Available."6224, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush')6225, transitionDuration = 2506226;62276228lines6229.clipEdge(true)6230;6231lines26232.interactive(false)6233;6234xAxis6235.orient('bottom')6236.tickPadding(5)6237;6238yAxis6239.orient('left')6240;6241x2Axis6242.orient('bottom')6243.tickPadding(5)6244;6245y2Axis6246.orient('left')6247;6248//============================================================624962506251//============================================================6252// Private Variables6253//------------------------------------------------------------62546255var showTooltip = function(e, offsetElement) {6256var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),6257top = e.pos[1] + ( offsetElement.offsetTop || 0),6258x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),6259y = yAxis.tickFormat()(lines.y()(e.point, e.pointIndex)),6260content = tooltip(e.series.key, x, y, e, chart);62616262nv.tooltip.show([left, top], content, null, null, offsetElement);6263};62646265//============================================================626662676268function chart(selection) {6269selection.each(function(data) {6270var container = d3.select(this),6271that = this;62726273var availableWidth = (width || parseInt(container.style('width')) || 960)6274- margin.left - margin.right,6275availableHeight1 = (height || parseInt(container.style('height')) || 400)6276- margin.top - margin.bottom - height2,6277availableHeight2 = height2 - margin2.top - margin2.bottom;62786279chart.update = function() { container.transition().duration(transitionDuration).call(chart) };6280chart.container = this;628162826283//------------------------------------------------------------6284// Display No Data message if there's nothing to show.62856286if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {6287var noDataText = container.selectAll('.nv-noData').data([noData]);62886289noDataText.enter().append('text')6290.attr('class', 'nvd3 nv-noData')6291.attr('dy', '-.7em')6292.style('text-anchor', 'middle');62936294noDataText6295.attr('x', margin.left + availableWidth / 2)6296.attr('y', margin.top + availableHeight1 / 2)6297.text(function(d) { return d });62986299return chart;6300} else {6301container.selectAll('.nv-noData').remove();6302}63036304//------------------------------------------------------------630563066307//------------------------------------------------------------6308// Setup Scales63096310x = lines.xScale();6311y = lines.yScale();6312x2 = lines2.xScale();6313y2 = lines2.yScale();63146315//------------------------------------------------------------631663176318//------------------------------------------------------------6319// Setup containers and skeleton of chart63206321var wrap = container.selectAll('g.nv-wrap.nv-lineWithFocusChart').data([data]);6322var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-lineWithFocusChart').append('g');6323var g = wrap.select('g');63246325gEnter.append('g').attr('class', 'nv-legendWrap');63266327var focusEnter = gEnter.append('g').attr('class', 'nv-focus');6328focusEnter.append('g').attr('class', 'nv-x nv-axis');6329focusEnter.append('g').attr('class', 'nv-y nv-axis');6330focusEnter.append('g').attr('class', 'nv-linesWrap');63316332var contextEnter = gEnter.append('g').attr('class', 'nv-context');6333contextEnter.append('g').attr('class', 'nv-x nv-axis');6334contextEnter.append('g').attr('class', 'nv-y nv-axis');6335contextEnter.append('g').attr('class', 'nv-linesWrap');6336contextEnter.append('g').attr('class', 'nv-brushBackground');6337contextEnter.append('g').attr('class', 'nv-x nv-brush');63386339//------------------------------------------------------------634063416342//------------------------------------------------------------6343// Legend63446345if (showLegend) {6346legend.width(availableWidth);63476348g.select('.nv-legendWrap')6349.datum(data)6350.call(legend);63516352if ( margin.top != legend.height()) {6353margin.top = legend.height();6354availableHeight1 = (height || parseInt(container.style('height')) || 400)6355- margin.top - margin.bottom - height2;6356}63576358g.select('.nv-legendWrap')6359.attr('transform', 'translate(0,' + (-margin.top) +')')6360}63616362//------------------------------------------------------------636363646365wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');636663676368//------------------------------------------------------------6369// Main Chart Component(s)63706371lines6372.width(availableWidth)6373.height(availableHeight1)6374.color(6375data6376.map(function(d,i) {6377return d.color || color(d, i);6378})6379.filter(function(d,i) {6380return !data[i].disabled;6381})6382);63836384lines26385.defined(lines.defined())6386.width(availableWidth)6387.height(availableHeight2)6388.color(6389data6390.map(function(d,i) {6391return d.color || color(d, i);6392})6393.filter(function(d,i) {6394return !data[i].disabled;6395})6396);63976398g.select('.nv-context')6399.attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')')64006401var contextLinesWrap = g.select('.nv-context .nv-linesWrap')6402.datum(data.filter(function(d) { return !d.disabled }))64036404d3.transition(contextLinesWrap).call(lines2);64056406//------------------------------------------------------------640764086409/*6410var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')6411.datum(data.filter(function(d) { return !d.disabled }))64126413d3.transition(focusLinesWrap).call(lines);6414*/641564166417//------------------------------------------------------------6418// Setup Main (Focus) Axes64196420xAxis6421.scale(x)6422.ticks( availableWidth / 100 )6423.tickSize(-availableHeight1, 0);64246425yAxis6426.scale(y)6427.ticks( availableHeight1 / 36 )6428.tickSize( -availableWidth, 0);64296430g.select('.nv-focus .nv-x.nv-axis')6431.attr('transform', 'translate(0,' + availableHeight1 + ')');64326433//------------------------------------------------------------643464356436//------------------------------------------------------------6437// Setup Brush64386439brush6440.x(x2)6441.on('brush', function() {6442//When brushing, turn off transitions because chart needs to change immediately.6443var oldTransition = chart.transitionDuration();6444chart.transitionDuration(0);6445onBrush();6446chart.transitionDuration(oldTransition);6447});64486449if (brushExtent) brush.extent(brushExtent);64506451var brushBG = g.select('.nv-brushBackground').selectAll('g')6452.data([brushExtent || brush.extent()])64536454var brushBGenter = brushBG.enter()6455.append('g');64566457brushBGenter.append('rect')6458.attr('class', 'left')6459.attr('x', 0)6460.attr('y', 0)6461.attr('height', availableHeight2);64626463brushBGenter.append('rect')6464.attr('class', 'right')6465.attr('x', 0)6466.attr('y', 0)6467.attr('height', availableHeight2);64686469var gBrush = g.select('.nv-x.nv-brush')6470.call(brush);6471gBrush.selectAll('rect')6472//.attr('y', -5)6473.attr('height', availableHeight2);6474gBrush.selectAll('.resize').append('path').attr('d', resizePath);64756476onBrush();64776478//------------------------------------------------------------647964806481//------------------------------------------------------------6482// Setup Secondary (Context) Axes64836484x2Axis6485.scale(x2)6486.ticks( availableWidth / 100 )6487.tickSize(-availableHeight2, 0);64886489g.select('.nv-context .nv-x.nv-axis')6490.attr('transform', 'translate(0,' + y2.range()[0] + ')');6491d3.transition(g.select('.nv-context .nv-x.nv-axis'))6492.call(x2Axis);649364946495y2Axis6496.scale(y2)6497.ticks( availableHeight2 / 36 )6498.tickSize( -availableWidth, 0);64996500d3.transition(g.select('.nv-context .nv-y.nv-axis'))6501.call(y2Axis);65026503g.select('.nv-context .nv-x.nv-axis')6504.attr('transform', 'translate(0,' + y2.range()[0] + ')');65056506//------------------------------------------------------------650765086509//============================================================6510// Event Handling/Dispatching (in chart's scope)6511//------------------------------------------------------------65126513legend.dispatch.on('stateChange', function(newState) {6514chart.update();6515});65166517dispatch.on('tooltipShow', function(e) {6518if (tooltips) showTooltip(e, that.parentNode);6519});65206521//============================================================652265236524//============================================================6525// Functions6526//------------------------------------------------------------65276528// Taken from crossfilter (http://square.github.com/crossfilter/)6529function resizePath(d) {6530var e = +(d == 'e'),6531x = e ? 1 : -1,6532y = availableHeight2 / 3;6533return 'M' + (.5 * x) + ',' + y6534+ 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)6535+ 'V' + (2 * y - 6)6536+ 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)6537+ 'Z'6538+ 'M' + (2.5 * x) + ',' + (y + 8)6539+ 'V' + (2 * y - 8)6540+ 'M' + (4.5 * x) + ',' + (y + 8)6541+ 'V' + (2 * y - 8);6542}654365446545function updateBrushBG() {6546if (!brush.empty()) brush.extent(brushExtent);6547brushBG6548.data([brush.empty() ? x2.domain() : brushExtent])6549.each(function(d,i) {6550var leftWidth = x2(d[0]) - x.range()[0],6551rightWidth = x.range()[1] - x2(d[1]);6552d3.select(this).select('.left')6553.attr('width', leftWidth < 0 ? 0 : leftWidth);65546555d3.select(this).select('.right')6556.attr('x', x2(d[1]))6557.attr('width', rightWidth < 0 ? 0 : rightWidth);6558});6559}656065616562function onBrush() {6563brushExtent = brush.empty() ? null : brush.extent();6564var extent = brush.empty() ? x2.domain() : brush.extent();65656566//The brush extent cannot be less than one. If it is, don't update the line chart.6567if (Math.abs(extent[0] - extent[1]) <= 1) {6568return;6569}65706571dispatch.brush({extent: extent, brush: brush});657265736574updateBrushBG();65756576// Update Main (Focus)6577var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')6578.datum(6579data6580.filter(function(d) { return !d.disabled })6581.map(function(d,i) {6582return {6583key: d.key,6584values: d.values.filter(function(d,i) {6585return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];6586})6587}6588})6589);6590focusLinesWrap.transition().duration(transitionDuration).call(lines);659165926593// Update Main (Focus) Axes6594g.select('.nv-focus .nv-x.nv-axis').transition().duration(transitionDuration)6595.call(xAxis);6596g.select('.nv-focus .nv-y.nv-axis').transition().duration(transitionDuration)6597.call(yAxis);6598}65996600//============================================================660166026603});66046605return chart;6606}660766086609//============================================================6610// Event Handling/Dispatching (out of chart's scope)6611//------------------------------------------------------------66126613lines.dispatch.on('elementMouseover.tooltip', function(e) {6614e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];6615dispatch.tooltipShow(e);6616});66176618lines.dispatch.on('elementMouseout.tooltip', function(e) {6619dispatch.tooltipHide(e);6620});66216622dispatch.on('tooltipHide', function() {6623if (tooltips) nv.tooltip.cleanup();6624});66256626//============================================================662766286629//============================================================6630// Expose Public Variables6631//------------------------------------------------------------66326633// expose chart's sub-components6634chart.dispatch = dispatch;6635chart.legend = legend;6636chart.lines = lines;6637chart.lines2 = lines2;6638chart.xAxis = xAxis;6639chart.yAxis = yAxis;6640chart.x2Axis = x2Axis;6641chart.y2Axis = y2Axis;66426643d3.rebind(chart, lines, 'defined', 'isArea', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');66446645chart.options = nv.utils.optionsFunc.bind(chart);66466647chart.x = function(_) {6648if (!arguments.length) return lines.x;6649lines.x(_);6650lines2.x(_);6651return chart;6652};66536654chart.y = function(_) {6655if (!arguments.length) return lines.y;6656lines.y(_);6657lines2.y(_);6658return chart;6659};66606661chart.margin = function(_) {6662if (!arguments.length) return margin;6663margin.top = typeof _.top != 'undefined' ? _.top : margin.top;6664margin.right = typeof _.right != 'undefined' ? _.right : margin.right;6665margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;6666margin.left = typeof _.left != 'undefined' ? _.left : margin.left;6667return chart;6668};66696670chart.margin2 = function(_) {6671if (!arguments.length) return margin2;6672margin2 = _;6673return chart;6674};66756676chart.width = function(_) {6677if (!arguments.length) return width;6678width = _;6679return chart;6680};66816682chart.height = function(_) {6683if (!arguments.length) return height;6684height = _;6685return chart;6686};66876688chart.height2 = function(_) {6689if (!arguments.length) return height2;6690height2 = _;6691return chart;6692};66936694chart.color = function(_) {6695if (!arguments.length) return color;6696color =nv.utils.getColor(_);6697legend.color(color);6698return chart;6699};67006701chart.showLegend = function(_) {6702if (!arguments.length) return showLegend;6703showLegend = _;6704return chart;6705};67066707chart.tooltips = function(_) {6708if (!arguments.length) return tooltips;6709tooltips = _;6710return chart;6711};67126713chart.tooltipContent = function(_) {6714if (!arguments.length) return tooltip;6715tooltip = _;6716return chart;6717};67186719chart.interpolate = function(_) {6720if (!arguments.length) return lines.interpolate();6721lines.interpolate(_);6722lines2.interpolate(_);6723return chart;6724};67256726chart.noData = function(_) {6727if (!arguments.length) return noData;6728noData = _;6729return chart;6730};67316732// Chart has multiple similar Axes, to prevent code duplication, probably need to link all axis functions manually like below6733chart.xTickFormat = function(_) {6734if (!arguments.length) return xAxis.tickFormat();6735xAxis.tickFormat(_);6736x2Axis.tickFormat(_);6737return chart;6738};67396740chart.yTickFormat = function(_) {6741if (!arguments.length) return yAxis.tickFormat();6742yAxis.tickFormat(_);6743y2Axis.tickFormat(_);6744return chart;6745};67466747chart.brushExtent = function(_) {6748if (!arguments.length) return brushExtent;6749brushExtent = _;6750return chart;6751};67526753chart.transitionDuration = function(_) {6754if (!arguments.length) return transitionDuration;6755transitionDuration = _;6756return chart;6757};67586759//============================================================676067616762return chart;6763}67646765nv.models.linePlusBarWithFocusChart = function() {6766"use strict";6767//============================================================6768// Public Variables with Default Settings6769//------------------------------------------------------------67706771var lines = nv.models.line()6772, lines2 = nv.models.line()6773, bars = nv.models.historicalBar()6774, bars2 = nv.models.historicalBar()6775, xAxis = nv.models.axis()6776, x2Axis = nv.models.axis()6777, y1Axis = nv.models.axis()6778, y2Axis = nv.models.axis()6779, y3Axis = nv.models.axis()6780, y4Axis = nv.models.axis()6781, legend = nv.models.legend()6782, brush = d3.svg.brush()6783;67846785var margin = {top: 30, right: 30, bottom: 30, left: 60}6786, margin2 = {top: 0, right: 30, bottom: 20, left: 60}6787, width = null6788, height = null6789, height2 = 1006790, getX = function(d) { return d.x }6791, getY = function(d) { return d.y }6792, color = nv.utils.defaultColor()6793, showLegend = true6794, extent6795, brushExtent = null6796, tooltips = true6797, tooltip = function(key, x, y, e, graph) {6798return '<h3>' + key + '</h3>' +6799'<p>' + y + ' at ' + x + '</p>';6800}6801, x6802, x26803, y16804, y26805, y36806, y46807, noData = "No Data Available."6808, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'brush')6809, transitionDuration = 06810;68116812lines6813.clipEdge(true)6814;6815lines26816.interactive(false)6817;6818xAxis6819.orient('bottom')6820.tickPadding(5)6821;6822y1Axis6823.orient('left')6824;6825y2Axis6826.orient('right')6827;6828x2Axis6829.orient('bottom')6830.tickPadding(5)6831;6832y3Axis6833.orient('left')6834;6835y4Axis6836.orient('right')6837;68386839//============================================================684068416842//============================================================6843// Private Variables6844//------------------------------------------------------------68456846var showTooltip = function(e, offsetElement) {6847if (extent) {6848e.pointIndex += Math.ceil(extent[0]);6849}6850var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),6851top = e.pos[1] + ( offsetElement.offsetTop || 0),6852x = xAxis.tickFormat()(lines.x()(e.point, e.pointIndex)),6853y = (e.series.bar ? y1Axis : y2Axis).tickFormat()(lines.y()(e.point, e.pointIndex)),6854content = tooltip(e.series.key, x, y, e, chart);68556856nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);6857};68586859//------------------------------------------------------------6860686168626863function chart(selection) {6864selection.each(function(data) {6865var container = d3.select(this),6866that = this;68676868var availableWidth = (width || parseInt(container.style('width')) || 960)6869- margin.left - margin.right,6870availableHeight1 = (height || parseInt(container.style('height')) || 400)6871- margin.top - margin.bottom - height2,6872availableHeight2 = height2 - margin2.top - margin2.bottom;68736874chart.update = function() { container.transition().duration(transitionDuration).call(chart); };6875chart.container = this;687668776878//------------------------------------------------------------6879// Display No Data message if there's nothing to show.68806881if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {6882var noDataText = container.selectAll('.nv-noData').data([noData]);68836884noDataText.enter().append('text')6885.attr('class', 'nvd3 nv-noData')6886.attr('dy', '-.7em')6887.style('text-anchor', 'middle');68886889noDataText6890.attr('x', margin.left + availableWidth / 2)6891.attr('y', margin.top + availableHeight1 / 2)6892.text(function(d) { return d });68936894return chart;6895} else {6896container.selectAll('.nv-noData').remove();6897}68986899//------------------------------------------------------------690069016902//------------------------------------------------------------6903// Setup Scales69046905var dataBars = data.filter(function(d) { return !d.disabled && d.bar });6906var dataLines = data.filter(function(d) { return !d.bar }); // removed the !d.disabled clause here to fix Issue #24069076908x = bars.xScale();6909x2 = x2Axis.scale();6910y1 = bars.yScale();6911y2 = lines.yScale();6912y3 = bars2.yScale();6913y4 = lines2.yScale();69146915var series1 = data6916.filter(function(d) { return !d.disabled && d.bar })6917.map(function(d) {6918return d.values.map(function(d,i) {6919return { x: getX(d,i), y: getY(d,i) }6920})6921});69226923var series2 = data6924.filter(function(d) { return !d.disabled && !d.bar })6925.map(function(d) {6926return d.values.map(function(d,i) {6927return { x: getX(d,i), y: getY(d,i) }6928})6929});69306931x .range([0, availableWidth]);69326933x2 .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))6934.range([0, availableWidth]);693569366937//------------------------------------------------------------693869396940//------------------------------------------------------------6941// Setup containers and skeleton of chart69426943var wrap = container.selectAll('g.nv-wrap.nv-linePlusBar').data([data]);6944var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-linePlusBar').append('g');6945var g = wrap.select('g');69466947gEnter.append('g').attr('class', 'nv-legendWrap');69486949var focusEnter = gEnter.append('g').attr('class', 'nv-focus');6950focusEnter.append('g').attr('class', 'nv-x nv-axis');6951focusEnter.append('g').attr('class', 'nv-y1 nv-axis');6952focusEnter.append('g').attr('class', 'nv-y2 nv-axis');6953focusEnter.append('g').attr('class', 'nv-barsWrap');6954focusEnter.append('g').attr('class', 'nv-linesWrap');69556956var contextEnter = gEnter.append('g').attr('class', 'nv-context');6957contextEnter.append('g').attr('class', 'nv-x nv-axis');6958contextEnter.append('g').attr('class', 'nv-y1 nv-axis');6959contextEnter.append('g').attr('class', 'nv-y2 nv-axis');6960contextEnter.append('g').attr('class', 'nv-barsWrap');6961contextEnter.append('g').attr('class', 'nv-linesWrap');6962contextEnter.append('g').attr('class', 'nv-brushBackground');6963contextEnter.append('g').attr('class', 'nv-x nv-brush');696469656966//------------------------------------------------------------696769686969//------------------------------------------------------------6970// Legend69716972if (showLegend) {6973legend.width( availableWidth / 2 );69746975g.select('.nv-legendWrap')6976.datum(data.map(function(series) {6977series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;6978series.key = series.originalKey + (series.bar ? ' (left axis)' : ' (right axis)');6979return series;6980}))6981.call(legend);69826983if ( margin.top != legend.height()) {6984margin.top = legend.height();6985availableHeight1 = (height || parseInt(container.style('height')) || 400)6986- margin.top - margin.bottom - height2;6987}69886989g.select('.nv-legendWrap')6990.attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')');6991}69926993//------------------------------------------------------------699469956996wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');699769986999//------------------------------------------------------------7000// Context Components70017002bars27003.width(availableWidth)7004.height(availableHeight2)7005.color(data.map(function(d,i) {7006return d.color || color(d, i);7007}).filter(function(d,i) { return !data[i].disabled && data[i].bar }));70087009lines27010.width(availableWidth)7011.height(availableHeight2)7012.color(data.map(function(d,i) {7013return d.color || color(d, i);7014}).filter(function(d,i) { return !data[i].disabled && !data[i].bar }));70157016var bars2Wrap = g.select('.nv-context .nv-barsWrap')7017.datum(dataBars.length ? dataBars : [{values:[]}]);70187019var lines2Wrap = g.select('.nv-context .nv-linesWrap')7020.datum(!dataLines[0].disabled ? dataLines : [{values:[]}]);70217022g.select('.nv-context')7023.attr('transform', 'translate(0,' + ( availableHeight1 + margin.bottom + margin2.top) + ')')70247025bars2Wrap.transition().call(bars2);7026lines2Wrap.transition().call(lines2);70277028//------------------------------------------------------------7029703070317032//------------------------------------------------------------7033// Setup Brush70347035brush7036.x(x2)7037.on('brush', onBrush);70387039if (brushExtent) brush.extent(brushExtent);70407041var brushBG = g.select('.nv-brushBackground').selectAll('g')7042.data([brushExtent || brush.extent()])70437044var brushBGenter = brushBG.enter()7045.append('g');70467047brushBGenter.append('rect')7048.attr('class', 'left')7049.attr('x', 0)7050.attr('y', 0)7051.attr('height', availableHeight2);70527053brushBGenter.append('rect')7054.attr('class', 'right')7055.attr('x', 0)7056.attr('y', 0)7057.attr('height', availableHeight2);70587059var gBrush = g.select('.nv-x.nv-brush')7060.call(brush);7061gBrush.selectAll('rect')7062//.attr('y', -5)7063.attr('height', availableHeight2);7064gBrush.selectAll('.resize').append('path').attr('d', resizePath);70657066//------------------------------------------------------------70677068//------------------------------------------------------------7069// Setup Secondary (Context) Axes70707071x2Axis7072.ticks( availableWidth / 100 )7073.tickSize(-availableHeight2, 0);70747075g.select('.nv-context .nv-x.nv-axis')7076.attr('transform', 'translate(0,' + y3.range()[0] + ')');7077g.select('.nv-context .nv-x.nv-axis').transition()7078.call(x2Axis);707970807081y3Axis7082.scale(y3)7083.ticks( availableHeight2 / 36 )7084.tickSize( -availableWidth, 0);70857086g.select('.nv-context .nv-y1.nv-axis')7087.style('opacity', dataBars.length ? 1 : 0)7088.attr('transform', 'translate(0,' + x2.range()[0] + ')');70897090g.select('.nv-context .nv-y1.nv-axis').transition()7091.call(y3Axis);709270937094y4Axis7095.scale(y4)7096.ticks( availableHeight2 / 36 )7097.tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none70987099g.select('.nv-context .nv-y2.nv-axis')7100.style('opacity', dataLines.length ? 1 : 0)7101.attr('transform', 'translate(' + x2.range()[1] + ',0)');71027103g.select('.nv-context .nv-y2.nv-axis').transition()7104.call(y4Axis);71057106//------------------------------------------------------------71077108//============================================================7109// Event Handling/Dispatching (in chart's scope)7110//------------------------------------------------------------71117112legend.dispatch.on('stateChange', function(newState) {7113chart.update();7114});71157116dispatch.on('tooltipShow', function(e) {7117if (tooltips) showTooltip(e, that.parentNode);7118});71197120//============================================================712171227123//============================================================7124// Functions7125//------------------------------------------------------------71267127// Taken from crossfilter (http://square.github.com/crossfilter/)7128function resizePath(d) {7129var e = +(d == 'e'),7130x = e ? 1 : -1,7131y = availableHeight2 / 3;7132return 'M' + (.5 * x) + ',' + y7133+ 'A6,6 0 0 ' + e + ' ' + (6.5 * x) + ',' + (y + 6)7134+ 'V' + (2 * y - 6)7135+ 'A6,6 0 0 ' + e + ' ' + (.5 * x) + ',' + (2 * y)7136+ 'Z'7137+ 'M' + (2.5 * x) + ',' + (y + 8)7138+ 'V' + (2 * y - 8)7139+ 'M' + (4.5 * x) + ',' + (y + 8)7140+ 'V' + (2 * y - 8);7141}714271437144function updateBrushBG() {7145if (!brush.empty()) brush.extent(brushExtent);7146brushBG7147.data([brush.empty() ? x2.domain() : brushExtent])7148.each(function(d,i) {7149var leftWidth = x2(d[0]) - x2.range()[0],7150rightWidth = x2.range()[1] - x2(d[1]);7151d3.select(this).select('.left')7152.attr('width', leftWidth < 0 ? 0 : leftWidth);71537154d3.select(this).select('.right')7155.attr('x', x2(d[1]))7156.attr('width', rightWidth < 0 ? 0 : rightWidth);7157});7158}715971607161function onBrush() {7162brushExtent = brush.empty() ? null : brush.extent();7163extent = brush.empty() ? x2.domain() : brush.extent();716471657166dispatch.brush({extent: extent, brush: brush});71677168updateBrushBG();716971707171//------------------------------------------------------------7172// Prepare Main (Focus) Bars and Lines71737174bars7175.width(availableWidth)7176.height(availableHeight1)7177.color(data.map(function(d,i) {7178return d.color || color(d, i);7179}).filter(function(d,i) { return !data[i].disabled && data[i].bar }));718071817182lines7183.width(availableWidth)7184.height(availableHeight1)7185.color(data.map(function(d,i) {7186return d.color || color(d, i);7187}).filter(function(d,i) { return !data[i].disabled && !data[i].bar }));71887189var focusBarsWrap = g.select('.nv-focus .nv-barsWrap')7190.datum(!dataBars.length ? [{values:[]}] :7191dataBars7192.map(function(d,i) {7193return {7194key: d.key,7195values: d.values.filter(function(d,i) {7196return bars.x()(d,i) >= extent[0] && bars.x()(d,i) <= extent[1];7197})7198}7199})7200);72017202var focusLinesWrap = g.select('.nv-focus .nv-linesWrap')7203.datum(dataLines[0].disabled ? [{values:[]}] :7204dataLines7205.map(function(d,i) {7206return {7207key: d.key,7208values: d.values.filter(function(d,i) {7209return lines.x()(d,i) >= extent[0] && lines.x()(d,i) <= extent[1];7210})7211}7212})7213);72147215//------------------------------------------------------------721672177218//------------------------------------------------------------7219// Update Main (Focus) X Axis72207221if (dataBars.length) {7222x = bars.xScale();7223} else {7224x = lines.xScale();7225}72267227xAxis7228.scale(x)7229.ticks( availableWidth / 100 )7230.tickSize(-availableHeight1, 0);72317232xAxis.domain([Math.ceil(extent[0]), Math.floor(extent[1])]);72337234g.select('.nv-x.nv-axis').transition().duration(transitionDuration)7235.call(xAxis);7236//------------------------------------------------------------723772387239//------------------------------------------------------------7240// Update Main (Focus) Bars and Lines72417242focusBarsWrap.transition().duration(transitionDuration).call(bars);7243focusLinesWrap.transition().duration(transitionDuration).call(lines);72447245//------------------------------------------------------------724672477248//------------------------------------------------------------7249// Setup and Update Main (Focus) Y Axes72507251g.select('.nv-focus .nv-x.nv-axis')7252.attr('transform', 'translate(0,' + y1.range()[0] + ')');725372547255y1Axis7256.scale(y1)7257.ticks( availableHeight1 / 36 )7258.tickSize(-availableWidth, 0);72597260g.select('.nv-focus .nv-y1.nv-axis')7261.style('opacity', dataBars.length ? 1 : 0);726272637264y2Axis7265.scale(y2)7266.ticks( availableHeight1 / 36 )7267.tickSize(dataBars.length ? 0 : -availableWidth, 0); // Show the y2 rules only if y1 has none72687269g.select('.nv-focus .nv-y2.nv-axis')7270.style('opacity', dataLines.length ? 1 : 0)7271.attr('transform', 'translate(' + x.range()[1] + ',0)');72727273g.select('.nv-focus .nv-y1.nv-axis').transition().duration(transitionDuration)7274.call(y1Axis);7275g.select('.nv-focus .nv-y2.nv-axis').transition().duration(transitionDuration)7276.call(y2Axis);7277}72787279//============================================================72807281onBrush();72827283});72847285return chart;7286}728772887289//============================================================7290// Event Handling/Dispatching (out of chart's scope)7291//------------------------------------------------------------72927293lines.dispatch.on('elementMouseover.tooltip', function(e) {7294e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];7295dispatch.tooltipShow(e);7296});72977298lines.dispatch.on('elementMouseout.tooltip', function(e) {7299dispatch.tooltipHide(e);7300});73017302bars.dispatch.on('elementMouseover.tooltip', function(e) {7303e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];7304dispatch.tooltipShow(e);7305});73067307bars.dispatch.on('elementMouseout.tooltip', function(e) {7308dispatch.tooltipHide(e);7309});73107311dispatch.on('tooltipHide', function() {7312if (tooltips) nv.tooltip.cleanup();7313});73147315//============================================================731673177318//============================================================7319// Expose Public Variables7320//------------------------------------------------------------73217322// expose chart's sub-components7323chart.dispatch = dispatch;7324chart.legend = legend;7325chart.lines = lines;7326chart.lines2 = lines2;7327chart.bars = bars;7328chart.bars2 = bars2;7329chart.xAxis = xAxis;7330chart.x2Axis = x2Axis;7331chart.y1Axis = y1Axis;7332chart.y2Axis = y2Axis;7333chart.y3Axis = y3Axis;7334chart.y4Axis = y4Axis;73357336d3.rebind(chart, lines, 'defined', 'size', 'clipVoronoi', 'interpolate');7337//TODO: consider rebinding x, y and some other stuff, and simply do soemthign lile bars.x(lines.x()), etc.7338//d3.rebind(chart, lines, 'x', 'y', 'size', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'interactive', 'clipEdge', 'clipVoronoi', 'id');73397340chart.options = nv.utils.optionsFunc.bind(chart);73417342chart.x = function(_) {7343if (!arguments.length) return getX;7344getX = _;7345lines.x(_);7346bars.x(_);7347return chart;7348};73497350chart.y = function(_) {7351if (!arguments.length) return getY;7352getY = _;7353lines.y(_);7354bars.y(_);7355return chart;7356};73577358chart.margin = function(_) {7359if (!arguments.length) return margin;7360margin.top = typeof _.top != 'undefined' ? _.top : margin.top;7361margin.right = typeof _.right != 'undefined' ? _.right : margin.right;7362margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;7363margin.left = typeof _.left != 'undefined' ? _.left : margin.left;7364return chart;7365};73667367chart.width = function(_) {7368if (!arguments.length) return width;7369width = _;7370return chart;7371};73727373chart.height = function(_) {7374if (!arguments.length) return height;7375height = _;7376return chart;7377};73787379chart.color = function(_) {7380if (!arguments.length) return color;7381color = nv.utils.getColor(_);7382legend.color(color);7383return chart;7384};73857386chart.showLegend = function(_) {7387if (!arguments.length) return showLegend;7388showLegend = _;7389return chart;7390};73917392chart.tooltips = function(_) {7393if (!arguments.length) return tooltips;7394tooltips = _;7395return chart;7396};73977398chart.tooltipContent = function(_) {7399if (!arguments.length) return tooltip;7400tooltip = _;7401return chart;7402};74037404chart.noData = function(_) {7405if (!arguments.length) return noData;7406noData = _;7407return chart;7408};74097410chart.brushExtent = function(_) {7411if (!arguments.length) return brushExtent;7412brushExtent = _;7413return chart;7414};741574167417//============================================================741874197420return chart;7421}74227423nv.models.multiBar = function() {7424"use strict";7425//============================================================7426// Public Variables with Default Settings7427//------------------------------------------------------------74287429var margin = {top: 0, right: 0, bottom: 0, left: 0}7430, width = 9607431, height = 5007432, x = d3.scale.ordinal()7433, y = d3.scale.linear()7434, id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one7435, getX = function(d) { return d.x }7436, getY = function(d) { return d.y }7437, forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove7438, clipEdge = true7439, stacked = false7440, color = nv.utils.defaultColor()7441, hideable = false7442, barColor = null // adding the ability to set the color for each rather than the whole group7443, disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled7444, delay = 12007445, xDomain7446, yDomain7447, xRange7448, yRange7449, groupSpacing = 0.17450, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')7451;74527453//============================================================745474557456//============================================================7457// Private Variables7458//------------------------------------------------------------74597460var x0, y0 //used to store previous scales7461;74627463//============================================================746474657466function chart(selection) {7467selection.each(function(data) {7468var availableWidth = width - margin.left - margin.right,7469availableHeight = height - margin.top - margin.bottom,7470container = d3.select(this);74717472if(hideable && data.length) hideable = [{7473values: data[0].values.map(function(d) {7474return {7475x: d.x,7476y: 0,7477series: d.series,7478size: 0.017479};}7480)}];74817482if (stacked)7483data = d3.layout.stack()7484.offset('zero')7485.values(function(d){ return d.values })7486.y(getY)7487(!data.length && hideable ? hideable : data);748874897490//add series index to each data point for reference7491data = data.map(function(series, i) {7492series.values = series.values.map(function(point) {7493point.series = i;7494return point;7495});7496return series;7497});749874997500//------------------------------------------------------------7501// HACK for negative value stacking7502if (stacked)7503data[0].values.map(function(d,i) {7504var posBase = 0, negBase = 0;7505data.map(function(d) {7506var f = d.values[i]7507f.size = Math.abs(f.y);7508if (f.y<0) {7509f.y1 = negBase;7510negBase = negBase - f.size;7511} else7512{7513f.y1 = f.size + posBase;7514posBase = posBase + f.size;7515}7516});7517});75187519//------------------------------------------------------------7520// Setup Scales75217522// remap and flatten the data for use in calculating the scales' domains7523var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate7524data.map(function(d) {7525return d.values.map(function(d,i) {7526return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 }7527})7528});75297530x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))7531.rangeBands(xRange || [0, availableWidth], groupSpacing);75327533//y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y1 : 0) }).concat(forceY)))7534y .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)))7535.range(yRange || [availableHeight, 0]);75367537// If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point7538if (x.domain()[0] === x.domain()[1])7539x.domain()[0] ?7540x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])7541: x.domain([-1,1]);75427543if (y.domain()[0] === y.domain()[1])7544y.domain()[0] ?7545y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])7546: y.domain([-1,1]);754775487549x0 = x0 || x;7550y0 = y0 || y;75517552//------------------------------------------------------------755375547555//------------------------------------------------------------7556// Setup containers and skeleton of chart75577558var wrap = container.selectAll('g.nv-wrap.nv-multibar').data([data]);7559var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibar');7560var defsEnter = wrapEnter.append('defs');7561var gEnter = wrapEnter.append('g');7562var g = wrap.select('g')75637564gEnter.append('g').attr('class', 'nv-groups');75657566wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');75677568//------------------------------------------------------------7569757075717572defsEnter.append('clipPath')7573.attr('id', 'nv-edge-clip-' + id)7574.append('rect');7575wrap.select('#nv-edge-clip-' + id + ' rect')7576.attr('width', availableWidth)7577.attr('height', availableHeight);75787579g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');7580758175827583var groups = wrap.select('.nv-groups').selectAll('.nv-group')7584.data(function(d) { return d }, function(d,i) { return i });7585groups.enter().append('g')7586.style('stroke-opacity', 1e-6)7587.style('fill-opacity', 1e-6);7588groups.exit()7589.transition()7590.selectAll('rect.nv-bar')7591.delay(function(d,i) {7592return i * delay/ data[0].values.length;7593})7594.attr('y', function(d) { return stacked ? y0(d.y0) : y0(0) })7595.attr('height', 0)7596.remove();7597groups7598.attr('class', function(d,i) { return 'nv-group nv-series-' + i })7599.classed('hover', function(d) { return d.hover })7600.style('fill', function(d,i){ return color(d, i) })7601.style('stroke', function(d,i){ return color(d, i) });7602groups7603.transition()7604.style('stroke-opacity', 1)7605.style('fill-opacity', .75);760676077608var bars = groups.selectAll('rect.nv-bar')7609.data(function(d) { return (hideable && !data.length) ? hideable.values : d.values });76107611bars.exit().remove();761276137614var barsEnter = bars.enter().append('rect')7615.attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})7616.attr('x', function(d,i,j) {7617return stacked ? 0 : (j * x.rangeBand() / data.length )7618})7619.attr('y', function(d) { return y0(stacked ? d.y0 : 0) })7620.attr('height', 0)7621.attr('width', x.rangeBand() / (stacked ? 1 : data.length) )7622.attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })7623;7624bars7625.style('fill', function(d,i,j){ return color(d, j, i); })7626.style('stroke', function(d,i,j){ return color(d, j, i); })7627.on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here7628d3.select(this).classed('hover', true);7629dispatch.elementMouseover({7630value: getY(d,i),7631point: d,7632series: data[d.series],7633pos: [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 shifted7634pointIndex: i,7635seriesIndex: d.series,7636e: d3.event7637});7638})7639.on('mouseout', function(d,i) {7640d3.select(this).classed('hover', false);7641dispatch.elementMouseout({7642value: getY(d,i),7643point: d,7644series: data[d.series],7645pointIndex: i,7646seriesIndex: d.series,7647e: d3.event7648});7649})7650.on('click', function(d,i) {7651dispatch.elementClick({7652value: getY(d,i),7653point: d,7654series: data[d.series],7655pos: [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 shifted7656pointIndex: i,7657seriesIndex: d.series,7658e: d3.event7659});7660d3.event.stopPropagation();7661})7662.on('dblclick', function(d,i) {7663dispatch.elementDblClick({7664value: getY(d,i),7665point: d,7666series: data[d.series],7667pos: [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 shifted7668pointIndex: i,7669seriesIndex: d.series,7670e: d3.event7671});7672d3.event.stopPropagation();7673});7674bars7675.attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})7676.transition()7677.attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',0)'; })76787679if (barColor) {7680if (!disabled) disabled = data.map(function() { return true });7681bars7682.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(); })7683.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(); });7684}768576867687if (stacked)7688bars.transition()7689.delay(function(d,i) {76907691return i * delay / data[0].values.length;7692})7693.attr('y', function(d,i) {76947695return y((stacked ? d.y1 : 0));7696})7697.attr('height', function(d,i) {7698return Math.max(Math.abs(y(d.y + (stacked ? d.y0 : 0)) - y((stacked ? d.y0 : 0))),1);7699})7700.attr('x', function(d,i) {7701return stacked ? 0 : (d.series * x.rangeBand() / data.length )7702})7703.attr('width', x.rangeBand() / (stacked ? 1 : data.length) );7704else7705bars.transition()7706.delay(function(d,i) {7707return i * delay/ data[0].values.length;7708})7709.attr('x', function(d,i) {7710return d.series * x.rangeBand() / data.length7711})7712.attr('width', x.rangeBand() / data.length)7713.attr('y', function(d,i) {7714return getY(d,i) < 0 ?7715y(0) :7716y(0) - y(getY(d,i)) < 1 ?7717y(0) - 1 :7718y(getY(d,i)) || 0;7719})7720.attr('height', function(d,i) {7721return Math.max(Math.abs(y(getY(d,i)) - y(0)),1) || 0;7722});7723772477257726//store old scales for use in transitions on update7727x0 = x.copy();7728y0 = y.copy();77297730});77317732return chart;7733}773477357736//============================================================7737// Expose Public Variables7738//------------------------------------------------------------77397740chart.dispatch = dispatch;77417742chart.options = nv.utils.optionsFunc.bind(chart);77437744chart.x = function(_) {7745if (!arguments.length) return getX;7746getX = _;7747return chart;7748};77497750chart.y = function(_) {7751if (!arguments.length) return getY;7752getY = _;7753return chart;7754};77557756chart.margin = function(_) {7757if (!arguments.length) return margin;7758margin.top = typeof _.top != 'undefined' ? _.top : margin.top;7759margin.right = typeof _.right != 'undefined' ? _.right : margin.right;7760margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;7761margin.left = typeof _.left != 'undefined' ? _.left : margin.left;7762return chart;7763};77647765chart.width = function(_) {7766if (!arguments.length) return width;7767width = _;7768return chart;7769};77707771chart.height = function(_) {7772if (!arguments.length) return height;7773height = _;7774return chart;7775};77767777chart.xScale = function(_) {7778if (!arguments.length) return x;7779x = _;7780return chart;7781};77827783chart.yScale = function(_) {7784if (!arguments.length) return y;7785y = _;7786return chart;7787};77887789chart.xDomain = function(_) {7790if (!arguments.length) return xDomain;7791xDomain = _;7792return chart;7793};77947795chart.yDomain = function(_) {7796if (!arguments.length) return yDomain;7797yDomain = _;7798return chart;7799};78007801chart.xRange = function(_) {7802if (!arguments.length) return xRange;7803xRange = _;7804return chart;7805};78067807chart.yRange = function(_) {7808if (!arguments.length) return yRange;7809yRange = _;7810return chart;7811};78127813chart.forceY = function(_) {7814if (!arguments.length) return forceY;7815forceY = _;7816return chart;7817};78187819chart.stacked = function(_) {7820if (!arguments.length) return stacked;7821stacked = _;7822return chart;7823};78247825chart.clipEdge = function(_) {7826if (!arguments.length) return clipEdge;7827clipEdge = _;7828return chart;7829};78307831chart.color = function(_) {7832if (!arguments.length) return color;7833color = nv.utils.getColor(_);7834return chart;7835};78367837chart.barColor = function(_) {7838if (!arguments.length) return barColor;7839barColor = nv.utils.getColor(_);7840return chart;7841};78427843chart.disabled = function(_) {7844if (!arguments.length) return disabled;7845disabled = _;7846return chart;7847};78487849chart.id = function(_) {7850if (!arguments.length) return id;7851id = _;7852return chart;7853};78547855chart.hideable = function(_) {7856if (!arguments.length) return hideable;7857hideable = _;7858return chart;7859};78607861chart.delay = function(_) {7862if (!arguments.length) return delay;7863delay = _;7864return chart;7865};78667867chart.groupSpacing = function(_) {7868if (!arguments.length) return groupSpacing;7869groupSpacing = _;7870return chart;7871};78727873//============================================================787478757876return chart;7877}78787879nv.models.multiBarChart = function() {7880"use strict";7881//============================================================7882// Public Variables with Default Settings7883//------------------------------------------------------------78847885var multibar = nv.models.multiBar()7886, xAxis = nv.models.axis()7887, yAxis = nv.models.axis()7888, legend = nv.models.legend()7889, controls = nv.models.legend()7890;78917892var margin = {top: 30, right: 20, bottom: 50, left: 60}7893, width = null7894, height = null7895, color = nv.utils.defaultColor()7896, showControls = true7897, showLegend = true7898, showXAxis = true7899, showYAxis = true7900, rightAlignYAxis = false7901, reduceXTicks = true // if false a tick will show for every data point7902, staggerLabels = false7903, rotateLabels = 07904, tooltips = true7905, tooltip = function(key, x, y, e, graph) {7906return '<h3>' + key + '</h3>' +7907'<p>' + y + ' on ' + x + '</p>'7908}7909, x //can be accessed via chart.xScale()7910, y //can be accessed via chart.yScale()7911, state = { stacked: false }7912, defaultState = null7913, noData = "No Data Available."7914, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')7915, controlWidth = function() { return showControls ? 180 : 0 }7916, transitionDuration = 2507917;79187919multibar7920.stacked(false)7921;7922xAxis7923.orient('bottom')7924.tickPadding(7)7925.highlightZero(true)7926.showMaxMin(false)7927.tickFormat(function(d) { return d })7928;7929yAxis7930.orient((rightAlignYAxis) ? 'right' : 'left')7931.tickFormat(d3.format(',.1f'))7932;79337934controls.updateState(false);7935//============================================================793679377938//============================================================7939// Private Variables7940//------------------------------------------------------------79417942var showTooltip = function(e, offsetElement) {7943var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),7944top = e.pos[1] + ( offsetElement.offsetTop || 0),7945x = xAxis.tickFormat()(multibar.x()(e.point, e.pointIndex)),7946y = yAxis.tickFormat()(multibar.y()(e.point, e.pointIndex)),7947content = tooltip(e.series.key, x, y, e, chart);79487949nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);7950};79517952//============================================================795379547955function chart(selection) {7956selection.each(function(data) {7957var container = d3.select(this),7958that = this;79597960var availableWidth = (width || parseInt(container.style('width')) || 960)7961- margin.left - margin.right,7962availableHeight = (height || parseInt(container.style('height')) || 400)7963- margin.top - margin.bottom;79647965chart.update = function() { container.transition().duration(transitionDuration).call(chart) };7966chart.container = this;79677968//set state.disabled7969state.disabled = data.map(function(d) { return !!d.disabled });79707971if (!defaultState) {7972var key;7973defaultState = {};7974for (key in state) {7975if (state[key] instanceof Array)7976defaultState[key] = state[key].slice(0);7977else7978defaultState[key] = state[key];7979}7980}7981//------------------------------------------------------------7982// Display noData message if there's nothing to show.79837984if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {7985var noDataText = container.selectAll('.nv-noData').data([noData]);79867987noDataText.enter().append('text')7988.attr('class', 'nvd3 nv-noData')7989.attr('dy', '-.7em')7990.style('text-anchor', 'middle');79917992noDataText7993.attr('x', margin.left + availableWidth / 2)7994.attr('y', margin.top + availableHeight / 2)7995.text(function(d) { return d });79967997return chart;7998} else {7999container.selectAll('.nv-noData').remove();8000}80018002//------------------------------------------------------------800380048005//------------------------------------------------------------8006// Setup Scales80078008x = multibar.xScale();8009y = multibar.yScale();80108011//------------------------------------------------------------801280138014//------------------------------------------------------------8015// Setup containers and skeleton of chart80168017var wrap = container.selectAll('g.nv-wrap.nv-multiBarWithLegend').data([data]);8018var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarWithLegend').append('g');8019var g = wrap.select('g');80208021gEnter.append('g').attr('class', 'nv-x nv-axis');8022gEnter.append('g').attr('class', 'nv-y nv-axis');8023gEnter.append('g').attr('class', 'nv-barsWrap');8024gEnter.append('g').attr('class', 'nv-legendWrap');8025gEnter.append('g').attr('class', 'nv-controlsWrap');80268027//------------------------------------------------------------802880298030//------------------------------------------------------------8031// Legend80328033if (showLegend) {8034legend.width(availableWidth - controlWidth());80358036if (multibar.barColor())8037data.forEach(function(series,i) {8038series.color = d3.rgb('#ccc').darker(i * 1.5).toString();8039})80408041g.select('.nv-legendWrap')8042.datum(data)8043.call(legend);80448045if ( margin.top != legend.height()) {8046margin.top = legend.height();8047availableHeight = (height || parseInt(container.style('height')) || 400)8048- margin.top - margin.bottom;8049}80508051g.select('.nv-legendWrap')8052.attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');8053}80548055//------------------------------------------------------------805680578058//------------------------------------------------------------8059// Controls80608061if (showControls) {8062var controlsData = [8063{ key: 'Grouped', disabled: multibar.stacked() },8064{ key: 'Stacked', disabled: !multibar.stacked() }8065];80668067controls.width(controlWidth()).color(['#444', '#444', '#444']);8068g.select('.nv-controlsWrap')8069.datum(controlsData)8070.attr('transform', 'translate(0,' + (-margin.top) +')')8071.call(controls);8072}80738074//------------------------------------------------------------807580768077wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');80788079if (rightAlignYAxis) {8080g.select(".nv-y.nv-axis")8081.attr("transform", "translate(" + availableWidth + ",0)");8082}80838084//------------------------------------------------------------8085// Main Chart Component(s)80868087multibar8088.disabled(data.map(function(series) { return series.disabled }))8089.width(availableWidth)8090.height(availableHeight)8091.color(data.map(function(d,i) {8092return d.color || color(d, i);8093}).filter(function(d,i) { return !data[i].disabled }))809480958096var barsWrap = g.select('.nv-barsWrap')8097.datum(data.filter(function(d) { return !d.disabled }))80988099barsWrap.transition().call(multibar);81008101//------------------------------------------------------------810281038104//------------------------------------------------------------8105// Setup Axes81068107if (showXAxis) {8108xAxis8109.scale(x)8110.ticks( availableWidth / 100 )8111.tickSize(-availableHeight, 0);81128113g.select('.nv-x.nv-axis')8114.attr('transform', 'translate(0,' + y.range()[0] + ')');8115g.select('.nv-x.nv-axis').transition()8116.call(xAxis);81178118var xTicks = g.select('.nv-x.nv-axis > g').selectAll('g');81198120xTicks8121.selectAll('line, text')8122.style('opacity', 1)81238124if (staggerLabels) {8125var getTranslate = function(x,y) {8126return "translate(" + x + "," + y + ")";8127};81288129var staggerUp = 5, staggerDown = 17; //pixels to stagger by8130// Issue #1408131xTicks8132.selectAll("text")8133.attr('transform', function(d,i,j) {8134return getTranslate(0, (j % 2 == 0 ? staggerUp : staggerDown));8135});81368137var totalInBetweenTicks = d3.selectAll(".nv-x.nv-axis .nv-wrap g g text")[0].length;8138g.selectAll(".nv-x.nv-axis .nv-axisMaxMin text")8139.attr("transform", function(d,i) {8140return getTranslate(0, (i === 0 || totalInBetweenTicks % 2 !== 0) ? staggerDown : staggerUp);8141});8142}81438144if (reduceXTicks)8145xTicks8146.filter(function(d,i) {8147return i % Math.ceil(data[0].values.length / (availableWidth / 100)) !== 0;8148})8149.selectAll('text, line')8150.style('opacity', 0);81518152if(rotateLabels)8153xTicks8154.selectAll('.tick text')8155.attr('transform', 'rotate(' + rotateLabels + ' 0,0)')8156.style('text-anchor', rotateLabels > 0 ? 'start' : 'end');81578158g.select('.nv-x.nv-axis').selectAll('g.nv-axisMaxMin text')8159.style('opacity', 1);8160}816181628163if (showYAxis) {8164yAxis8165.scale(y)8166.ticks( availableHeight / 36 )8167.tickSize( -availableWidth, 0);81688169g.select('.nv-y.nv-axis').transition()8170.call(yAxis);8171}817281738174//------------------------------------------------------------8175817681778178//============================================================8179// Event Handling/Dispatching (in chart's scope)8180//------------------------------------------------------------81818182legend.dispatch.on('stateChange', function(newState) {8183state = newState;8184dispatch.stateChange(state);8185chart.update();8186});81878188controls.dispatch.on('legendClick', function(d,i) {8189if (!d.disabled) return;8190controlsData = controlsData.map(function(s) {8191s.disabled = true;8192return s;8193});8194d.disabled = false;81958196switch (d.key) {8197case 'Grouped':8198multibar.stacked(false);8199break;8200case 'Stacked':8201multibar.stacked(true);8202break;8203}82048205state.stacked = multibar.stacked();8206dispatch.stateChange(state);82078208chart.update();8209});82108211dispatch.on('tooltipShow', function(e) {8212if (tooltips) showTooltip(e, that.parentNode)8213});82148215// Update chart from a state object passed to event handler8216dispatch.on('changeState', function(e) {82178218if (typeof e.disabled !== 'undefined') {8219data.forEach(function(series,i) {8220series.disabled = e.disabled[i];8221});82228223state.disabled = e.disabled;8224}82258226if (typeof e.stacked !== 'undefined') {8227multibar.stacked(e.stacked);8228state.stacked = e.stacked;8229}82308231chart.update();8232});82338234//============================================================823582368237});82388239return chart;8240}824182428243//============================================================8244// Event Handling/Dispatching (out of chart's scope)8245//------------------------------------------------------------82468247multibar.dispatch.on('elementMouseover.tooltip', function(e) {8248e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];8249dispatch.tooltipShow(e);8250});82518252multibar.dispatch.on('elementMouseout.tooltip', function(e) {8253dispatch.tooltipHide(e);8254});8255dispatch.on('tooltipHide', function() {8256if (tooltips) nv.tooltip.cleanup();8257});82588259//============================================================826082618262//============================================================8263// Expose Public Variables8264//------------------------------------------------------------82658266// expose chart's sub-components8267chart.dispatch = dispatch;8268chart.multibar = multibar;8269chart.legend = legend;8270chart.xAxis = xAxis;8271chart.yAxis = yAxis;82728273d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'clipEdge',8274'id', 'stacked', 'delay', 'barColor','groupSpacing');82758276chart.options = nv.utils.optionsFunc.bind(chart);82778278chart.margin = function(_) {8279if (!arguments.length) return margin;8280margin.top = typeof _.top != 'undefined' ? _.top : margin.top;8281margin.right = typeof _.right != 'undefined' ? _.right : margin.right;8282margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;8283margin.left = typeof _.left != 'undefined' ? _.left : margin.left;8284return chart;8285};82868287chart.width = function(_) {8288if (!arguments.length) return width;8289width = _;8290return chart;8291};82928293chart.height = function(_) {8294if (!arguments.length) return height;8295height = _;8296return chart;8297};82988299chart.color = function(_) {8300if (!arguments.length) return color;8301color = nv.utils.getColor(_);8302legend.color(color);8303return chart;8304};83058306chart.showControls = function(_) {8307if (!arguments.length) return showControls;8308showControls = _;8309return chart;8310};83118312chart.showLegend = function(_) {8313if (!arguments.length) return showLegend;8314showLegend = _;8315return chart;8316};83178318chart.showXAxis = function(_) {8319if (!arguments.length) return showXAxis;8320showXAxis = _;8321return chart;8322};83238324chart.showYAxis = function(_) {8325if (!arguments.length) return showYAxis;8326showYAxis = _;8327return chart;8328};83298330chart.rightAlignYAxis = function(_) {8331if(!arguments.length) return rightAlignYAxis;8332rightAlignYAxis = _;8333yAxis.orient( (_) ? 'right' : 'left');8334return chart;8335};83368337chart.reduceXTicks= function(_) {8338if (!arguments.length) return reduceXTicks;8339reduceXTicks = _;8340return chart;8341};83428343chart.rotateLabels = function(_) {8344if (!arguments.length) return rotateLabels;8345rotateLabels = _;8346return chart;8347}83488349chart.staggerLabels = function(_) {8350if (!arguments.length) return staggerLabels;8351staggerLabels = _;8352return chart;8353};83548355chart.tooltip = function(_) {8356if (!arguments.length) return tooltip;8357tooltip = _;8358return chart;8359};83608361chart.tooltips = function(_) {8362if (!arguments.length) return tooltips;8363tooltips = _;8364return chart;8365};83668367chart.tooltipContent = function(_) {8368if (!arguments.length) return tooltip;8369tooltip = _;8370return chart;8371};83728373chart.state = function(_) {8374if (!arguments.length) return state;8375state = _;8376return chart;8377};83788379chart.defaultState = function(_) {8380if (!arguments.length) return defaultState;8381defaultState = _;8382return chart;8383};83848385chart.noData = function(_) {8386if (!arguments.length) return noData;8387noData = _;8388return chart;8389};83908391chart.transitionDuration = function(_) {8392if (!arguments.length) return transitionDuration;8393transitionDuration = _;8394return chart;8395};83968397//============================================================839883998400return chart;8401}84028403nv.models.multiBarHorizontal = function() {8404"use strict";8405//============================================================8406// Public Variables with Default Settings8407//------------------------------------------------------------84088409var margin = {top: 0, right: 0, bottom: 0, left: 0}8410, width = 9608411, height = 5008412, id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one8413, x = d3.scale.ordinal()8414, y = d3.scale.linear()8415, getX = function(d) { return d.x }8416, getY = function(d) { return d.y }8417, forceY = [0] // 0 is forced by default.. this makes sense for the majority of bar graphs... user can always do chart.forceY([]) to remove8418, color = nv.utils.defaultColor()8419, barColor = null // adding the ability to set the color for each rather than the whole group8420, disabled // used in conjunction with barColor to communicate from multiBarHorizontalChart what series are disabled8421, stacked = false8422, showValues = false8423, valuePadding = 608424, valueFormat = d3.format(',.2f')8425, delay = 12008426, xDomain8427, yDomain8428, xRange8429, yRange8430, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')8431;84328433//============================================================843484358436//============================================================8437// Private Variables8438//------------------------------------------------------------84398440var x0, y0 //used to store previous scales8441;84428443//============================================================844484458446function chart(selection) {8447selection.each(function(data) {8448var availableWidth = width - margin.left - margin.right,8449availableHeight = height - margin.top - margin.bottom,8450container = d3.select(this);845184528453if (stacked)8454data = d3.layout.stack()8455.offset('zero')8456.values(function(d){ return d.values })8457.y(getY)8458(data);845984608461//add series index to each data point for reference8462data = data.map(function(series, i) {8463series.values = series.values.map(function(point) {8464point.series = i;8465return point;8466});8467return series;8468});8469847084718472//------------------------------------------------------------8473// HACK for negative value stacking8474if (stacked)8475data[0].values.map(function(d,i) {8476var posBase = 0, negBase = 0;8477data.map(function(d) {8478var f = d.values[i]8479f.size = Math.abs(f.y);8480if (f.y<0) {8481f.y1 = negBase - f.size;8482negBase = negBase - f.size;8483} else8484{8485f.y1 = posBase;8486posBase = posBase + f.size;8487}8488});8489});8490849184928493//------------------------------------------------------------8494// Setup Scales84958496// remap and flatten the data for use in calculating the scales' domains8497var seriesData = (xDomain && yDomain) ? [] : // if we know xDomain and yDomain, no need to calculate8498data.map(function(d) {8499return d.values.map(function(d,i) {8500return { x: getX(d,i), y: getY(d,i), y0: d.y0, y1: d.y1 }8501})8502});85038504x .domain(xDomain || d3.merge(seriesData).map(function(d) { return d.x }))8505.rangeBands(xRange || [0, availableHeight], .1);85068507//y .domain(yDomain || d3.extent(d3.merge(seriesData).map(function(d) { return d.y + (stacked ? d.y0 : 0) }).concat(forceY)))8508y .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)))85098510if (showValues && !stacked)8511y.range(yRange || [(y.domain()[0] < 0 ? valuePadding : 0), availableWidth - (y.domain()[1] > 0 ? valuePadding : 0) ]);8512else8513y.range(yRange || [0, availableWidth]);85148515x0 = x0 || x;8516y0 = y0 || d3.scale.linear().domain(y.domain()).range([y(0),y(0)]);85178518//------------------------------------------------------------851985208521//------------------------------------------------------------8522// Setup containers and skeleton of chart85238524var wrap = d3.select(this).selectAll('g.nv-wrap.nv-multibarHorizontal').data([data]);8525var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multibarHorizontal');8526var defsEnter = wrapEnter.append('defs');8527var gEnter = wrapEnter.append('g');8528var g = wrap.select('g');85298530gEnter.append('g').attr('class', 'nv-groups');85318532wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');85338534//------------------------------------------------------------8535853685378538var groups = wrap.select('.nv-groups').selectAll('.nv-group')8539.data(function(d) { return d }, function(d,i) { return i });8540groups.enter().append('g')8541.style('stroke-opacity', 1e-6)8542.style('fill-opacity', 1e-6);8543groups.exit().transition()8544.style('stroke-opacity', 1e-6)8545.style('fill-opacity', 1e-6)8546.remove();8547groups8548.attr('class', function(d,i) { return 'nv-group nv-series-' + i })8549.classed('hover', function(d) { return d.hover })8550.style('fill', function(d,i){ return color(d, i) })8551.style('stroke', function(d,i){ return color(d, i) });8552groups.transition()8553.style('stroke-opacity', 1)8554.style('fill-opacity', .75);855585568557var bars = groups.selectAll('g.nv-bar')8558.data(function(d) { return d.values });85598560bars.exit().remove();856185628563var barsEnter = bars.enter().append('g')8564.attr('transform', function(d,i,j) {8565return 'translate(' + y0(stacked ? d.y0 : 0) + ',' + (stacked ? 0 : (j * x.rangeBand() / data.length ) + x(getX(d,i))) + ')'8566});85678568barsEnter.append('rect')8569.attr('width', 0)8570.attr('height', x.rangeBand() / (stacked ? 1 : data.length) )85718572bars8573.on('mouseover', function(d,i) { //TODO: figure out why j works above, but not here8574d3.select(this).classed('hover', true);8575dispatch.elementMouseover({8576value: getY(d,i),8577point: d,8578series: data[d.series],8579pos: [ y(getY(d,i) + (stacked ? d.y0 : 0)), x(getX(d,i)) + (x.rangeBand() * (stacked ? data.length / 2 : d.series + .5) / data.length) ],8580pointIndex: i,8581seriesIndex: d.series,8582e: d3.event8583});8584})8585.on('mouseout', function(d,i) {8586d3.select(this).classed('hover', false);8587dispatch.elementMouseout({8588value: getY(d,i),8589point: d,8590series: data[d.series],8591pointIndex: i,8592seriesIndex: d.series,8593e: d3.event8594});8595})8596.on('click', function(d,i) {8597dispatch.elementClick({8598value: getY(d,i),8599point: d,8600series: data[d.series],8601pos: [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 shifted8602pointIndex: i,8603seriesIndex: d.series,8604e: d3.event8605});8606d3.event.stopPropagation();8607})8608.on('dblclick', function(d,i) {8609dispatch.elementDblClick({8610value: getY(d,i),8611point: d,8612series: data[d.series],8613pos: [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 shifted8614pointIndex: i,8615seriesIndex: d.series,8616e: d3.event8617});8618d3.event.stopPropagation();8619});862086218622barsEnter.append('text');86238624if (showValues && !stacked) {8625bars.select('text')8626.attr('text-anchor', function(d,i) { return getY(d,i) < 0 ? 'end' : 'start' })8627.attr('y', x.rangeBand() / (data.length * 2))8628.attr('dy', '.32em')8629.text(function(d,i) { return valueFormat(getY(d,i)) })8630bars.transition()8631.select('text')8632.attr('x', function(d,i) { return getY(d,i) < 0 ? -4 : y(getY(d,i)) - y(0) + 4 })8633} else {8634bars.selectAll('text').text('');8635}86368637bars8638.attr('class', function(d,i) { return getY(d,i) < 0 ? 'nv-bar negative' : 'nv-bar positive'})86398640if (barColor) {8641if (!disabled) disabled = data.map(function() { return true });8642bars8643.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(); })8644.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(); });8645}86468647if (stacked)8648bars.transition()8649.attr('transform', function(d,i) {8650return 'translate(' + y(d.y1) + ',' + x(getX(d,i)) + ')'8651})8652.select('rect')8653.attr('width', function(d,i) {8654return Math.abs(y(getY(d,i) + d.y0) - y(d.y0))8655})8656.attr('height', x.rangeBand() );8657else8658bars.transition()8659.attr('transform', function(d,i) {8660//TODO: stacked must be all positive or all negative, not both?8661return 'translate(' +8662(getY(d,i) < 0 ? y(getY(d,i)) : y(0))8663+ ',' +8664(d.series * x.rangeBand() / data.length8665+8666x(getX(d,i)) )8667+ ')'8668})8669.select('rect')8670.attr('height', x.rangeBand() / data.length )8671.attr('width', function(d,i) {8672return Math.max(Math.abs(y(getY(d,i)) - y(0)),1)8673});867486758676//store old scales for use in transitions on update8677x0 = x.copy();8678y0 = y.copy();86798680});86818682return chart;8683}868486858686//============================================================8687// Expose Public Variables8688//------------------------------------------------------------86898690chart.dispatch = dispatch;86918692chart.options = nv.utils.optionsFunc.bind(chart);86938694chart.x = function(_) {8695if (!arguments.length) return getX;8696getX = _;8697return chart;8698};86998700chart.y = function(_) {8701if (!arguments.length) return getY;8702getY = _;8703return chart;8704};87058706chart.margin = function(_) {8707if (!arguments.length) return margin;8708margin.top = typeof _.top != 'undefined' ? _.top : margin.top;8709margin.right = typeof _.right != 'undefined' ? _.right : margin.right;8710margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;8711margin.left = typeof _.left != 'undefined' ? _.left : margin.left;8712return chart;8713};87148715chart.width = function(_) {8716if (!arguments.length) return width;8717width = _;8718return chart;8719};87208721chart.height = function(_) {8722if (!arguments.length) return height;8723height = _;8724return chart;8725};87268727chart.xScale = function(_) {8728if (!arguments.length) return x;8729x = _;8730return chart;8731};87328733chart.yScale = function(_) {8734if (!arguments.length) return y;8735y = _;8736return chart;8737};87388739chart.xDomain = function(_) {8740if (!arguments.length) return xDomain;8741xDomain = _;8742return chart;8743};87448745chart.yDomain = function(_) {8746if (!arguments.length) return yDomain;8747yDomain = _;8748return chart;8749};87508751chart.xRange = function(_) {8752if (!arguments.length) return xRange;8753xRange = _;8754return chart;8755};87568757chart.yRange = function(_) {8758if (!arguments.length) return yRange;8759yRange = _;8760return chart;8761};87628763chart.forceY = function(_) {8764if (!arguments.length) return forceY;8765forceY = _;8766return chart;8767};87688769chart.stacked = function(_) {8770if (!arguments.length) return stacked;8771stacked = _;8772return chart;8773};87748775chart.color = function(_) {8776if (!arguments.length) return color;8777color = nv.utils.getColor(_);8778return chart;8779};87808781chart.barColor = function(_) {8782if (!arguments.length) return barColor;8783barColor = nv.utils.getColor(_);8784return chart;8785};87868787chart.disabled = function(_) {8788if (!arguments.length) return disabled;8789disabled = _;8790return chart;8791};87928793chart.id = function(_) {8794if (!arguments.length) return id;8795id = _;8796return chart;8797};87988799chart.delay = function(_) {8800if (!arguments.length) return delay;8801delay = _;8802return chart;8803};88048805chart.showValues = function(_) {8806if (!arguments.length) return showValues;8807showValues = _;8808return chart;8809};88108811chart.valueFormat= function(_) {8812if (!arguments.length) return valueFormat;8813valueFormat = _;8814return chart;8815};88168817chart.valuePadding = function(_) {8818if (!arguments.length) return valuePadding;8819valuePadding = _;8820return chart;8821};88228823//============================================================882488258826return chart;8827}88288829nv.models.multiBarHorizontalChart = function() {8830"use strict";8831//============================================================8832// Public Variables with Default Settings8833//------------------------------------------------------------88348835var multibar = nv.models.multiBarHorizontal()8836, xAxis = nv.models.axis()8837, yAxis = nv.models.axis()8838, legend = nv.models.legend().height(30)8839, controls = nv.models.legend().height(30)8840;88418842var margin = {top: 30, right: 20, bottom: 50, left: 60}8843, width = null8844, height = null8845, color = nv.utils.defaultColor()8846, showControls = true8847, showLegend = true8848, stacked = false8849, tooltips = true8850, tooltip = function(key, x, y, e, graph) {8851return '<h3>' + key + ' - ' + x + '</h3>' +8852'<p>' + y + '</p>'8853}8854, x //can be accessed via chart.xScale()8855, y //can be accessed via chart.yScale()8856, state = { stacked: stacked }8857, defaultState = null8858, noData = 'No Data Available.'8859, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')8860, controlWidth = function() { return showControls ? 180 : 0 }8861, transitionDuration = 2508862;88638864multibar8865.stacked(stacked)8866;8867xAxis8868.orient('left')8869.tickPadding(5)8870.highlightZero(false)8871.showMaxMin(false)8872.tickFormat(function(d) { return d })8873;8874yAxis8875.orient('bottom')8876.tickFormat(d3.format(',.1f'))8877;88788879controls.updateState(false);8880//============================================================888188828883//============================================================8884// Private Variables8885//------------------------------------------------------------88868887var showTooltip = function(e, offsetElement) {8888var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),8889top = e.pos[1] + ( offsetElement.offsetTop || 0),8890x = xAxis.tickFormat()(multibar.x()(e.point, e.pointIndex)),8891y = yAxis.tickFormat()(multibar.y()(e.point, e.pointIndex)),8892content = tooltip(e.series.key, x, y, e, chart);88938894nv.tooltip.show([left, top], content, e.value < 0 ? 'e' : 'w', null, offsetElement);8895};88968897//============================================================889888998900function chart(selection) {8901selection.each(function(data) {8902var container = d3.select(this),8903that = this;89048905var availableWidth = (width || parseInt(container.style('width')) || 960)8906- margin.left - margin.right,8907availableHeight = (height || parseInt(container.style('height')) || 400)8908- margin.top - margin.bottom;89098910chart.update = function() { container.transition().duration(transitionDuration).call(chart) };8911chart.container = this;89128913//set state.disabled8914state.disabled = data.map(function(d) { return !!d.disabled });89158916if (!defaultState) {8917var key;8918defaultState = {};8919for (key in state) {8920if (state[key] instanceof Array)8921defaultState[key] = state[key].slice(0);8922else8923defaultState[key] = state[key];8924}8925}89268927//------------------------------------------------------------8928// Display No Data message if there's nothing to show.89298930if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {8931var noDataText = container.selectAll('.nv-noData').data([noData]);89328933noDataText.enter().append('text')8934.attr('class', 'nvd3 nv-noData')8935.attr('dy', '-.7em')8936.style('text-anchor', 'middle');89378938noDataText8939.attr('x', margin.left + availableWidth / 2)8940.attr('y', margin.top + availableHeight / 2)8941.text(function(d) { return d });89428943return chart;8944} else {8945container.selectAll('.nv-noData').remove();8946}89478948//------------------------------------------------------------894989508951//------------------------------------------------------------8952// Setup Scales89538954x = multibar.xScale();8955y = multibar.yScale();89568957//------------------------------------------------------------895889598960//------------------------------------------------------------8961// Setup containers and skeleton of chart89628963var wrap = container.selectAll('g.nv-wrap.nv-multiBarHorizontalChart').data([data]);8964var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-multiBarHorizontalChart').append('g');8965var g = wrap.select('g');89668967gEnter.append('g').attr('class', 'nv-x nv-axis');8968gEnter.append('g').attr('class', 'nv-y nv-axis');8969gEnter.append('g').attr('class', 'nv-barsWrap');8970gEnter.append('g').attr('class', 'nv-legendWrap');8971gEnter.append('g').attr('class', 'nv-controlsWrap');89728973//------------------------------------------------------------897489758976//------------------------------------------------------------8977// Legend89788979if (showLegend) {8980legend.width(availableWidth - controlWidth());89818982if (multibar.barColor())8983data.forEach(function(series,i) {8984series.color = d3.rgb('#ccc').darker(i * 1.5).toString();8985})89868987g.select('.nv-legendWrap')8988.datum(data)8989.call(legend);89908991if ( margin.top != legend.height()) {8992margin.top = legend.height();8993availableHeight = (height || parseInt(container.style('height')) || 400)8994- margin.top - margin.bottom;8995}89968997g.select('.nv-legendWrap')8998.attr('transform', 'translate(' + controlWidth() + ',' + (-margin.top) +')');8999}90009001//------------------------------------------------------------900290039004//------------------------------------------------------------9005// Controls90069007if (showControls) {9008var controlsData = [9009{ key: 'Grouped', disabled: multibar.stacked() },9010{ key: 'Stacked', disabled: !multibar.stacked() }9011];90129013controls.width(controlWidth()).color(['#444', '#444', '#444']);9014g.select('.nv-controlsWrap')9015.datum(controlsData)9016.attr('transform', 'translate(0,' + (-margin.top) +')')9017.call(controls);9018}90199020//------------------------------------------------------------902190229023wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');902490259026//------------------------------------------------------------9027// Main Chart Component(s)90289029multibar9030.disabled(data.map(function(series) { return series.disabled }))9031.width(availableWidth)9032.height(availableHeight)9033.color(data.map(function(d,i) {9034return d.color || color(d, i);9035}).filter(function(d,i) { return !data[i].disabled }))903690379038var barsWrap = g.select('.nv-barsWrap')9039.datum(data.filter(function(d) { return !d.disabled }))90409041barsWrap.transition().call(multibar);90429043//------------------------------------------------------------904490459046//------------------------------------------------------------9047// Setup Axes90489049xAxis9050.scale(x)9051.ticks( availableHeight / 24 )9052.tickSize(-availableWidth, 0);90539054g.select('.nv-x.nv-axis').transition()9055.call(xAxis);90569057var xTicks = g.select('.nv-x.nv-axis').selectAll('g');90589059xTicks9060.selectAll('line, text')9061.style('opacity', 1)906290639064yAxis9065.scale(y)9066.ticks( availableWidth / 100 )9067.tickSize( -availableHeight, 0);90689069g.select('.nv-y.nv-axis')9070.attr('transform', 'translate(0,' + availableHeight + ')');9071g.select('.nv-y.nv-axis').transition()9072.call(yAxis);90739074//------------------------------------------------------------9075907690779078//============================================================9079// Event Handling/Dispatching (in chart's scope)9080//------------------------------------------------------------90819082legend.dispatch.on('stateChange', function(newState) {9083state = newState;9084dispatch.stateChange(state);9085chart.update();9086});90879088controls.dispatch.on('legendClick', function(d,i) {9089if (!d.disabled) return;9090controlsData = controlsData.map(function(s) {9091s.disabled = true;9092return s;9093});9094d.disabled = false;90959096switch (d.key) {9097case 'Grouped':9098multibar.stacked(false);9099break;9100case 'Stacked':9101multibar.stacked(true);9102break;9103}91049105state.stacked = multibar.stacked();9106dispatch.stateChange(state);91079108chart.update();9109});91109111dispatch.on('tooltipShow', function(e) {9112if (tooltips) showTooltip(e, that.parentNode);9113});91149115// Update chart from a state object passed to event handler9116dispatch.on('changeState', function(e) {91179118if (typeof e.disabled !== 'undefined') {9119data.forEach(function(series,i) {9120series.disabled = e.disabled[i];9121});91229123state.disabled = e.disabled;9124}91259126if (typeof e.stacked !== 'undefined') {9127multibar.stacked(e.stacked);9128state.stacked = e.stacked;9129}91309131selection.call(chart);9132});9133//============================================================913491359136});91379138return chart;9139}914091419142//============================================================9143// Event Handling/Dispatching (out of chart's scope)9144//------------------------------------------------------------91459146multibar.dispatch.on('elementMouseover.tooltip', function(e) {9147e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];9148dispatch.tooltipShow(e);9149});91509151multibar.dispatch.on('elementMouseout.tooltip', function(e) {9152dispatch.tooltipHide(e);9153});9154dispatch.on('tooltipHide', function() {9155if (tooltips) nv.tooltip.cleanup();9156});91579158//============================================================915991609161//============================================================9162// Expose Public Variables9163//------------------------------------------------------------91649165// expose chart's sub-components9166chart.dispatch = dispatch;9167chart.multibar = multibar;9168chart.legend = legend;9169chart.xAxis = xAxis;9170chart.yAxis = yAxis;91719172d3.rebind(chart, multibar, 'x', 'y', 'xDomain', 'yDomain', 'xRange', 'yRange', 'forceX', 'forceY', 'clipEdge', 'id', 'delay', 'showValues', 'valueFormat', 'stacked', 'barColor');91739174chart.options = nv.utils.optionsFunc.bind(chart);91759176chart.margin = function(_) {9177if (!arguments.length) return margin;9178margin.top = typeof _.top != 'undefined' ? _.top : margin.top;9179margin.right = typeof _.right != 'undefined' ? _.right : margin.right;9180margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;9181margin.left = typeof _.left != 'undefined' ? _.left : margin.left;9182return chart;9183};91849185chart.width = function(_) {9186if (!arguments.length) return width;9187width = _;9188return chart;9189};91909191chart.height = function(_) {9192if (!arguments.length) return height;9193height = _;9194return chart;9195};91969197chart.color = function(_) {9198if (!arguments.length) return color;9199color = nv.utils.getColor(_);9200legend.color(color);9201return chart;9202};92039204chart.showControls = function(_) {9205if (!arguments.length) return showControls;9206showControls = _;9207return chart;9208};92099210chart.showLegend = function(_) {9211if (!arguments.length) return showLegend;9212showLegend = _;9213return chart;9214};92159216chart.tooltip = function(_) {9217if (!arguments.length) return tooltip;9218tooltip = _;9219return chart;9220};92219222chart.tooltips = function(_) {9223if (!arguments.length) return tooltips;9224tooltips = _;9225return chart;9226};92279228chart.tooltipContent = function(_) {9229if (!arguments.length) return tooltip;9230tooltip = _;9231return chart;9232};92339234chart.state = function(_) {9235if (!arguments.length) return state;9236state = _;9237return chart;9238};92399240chart.defaultState = function(_) {9241if (!arguments.length) return defaultState;9242defaultState = _;9243return chart;9244};92459246chart.noData = function(_) {9247if (!arguments.length) return noData;9248noData = _;9249return chart;9250};92519252chart.transitionDuration = function(_) {9253if (!arguments.length) return transitionDuration;9254transitionDuration = _;9255return chart;9256};9257//============================================================925892599260return chart;9261}9262nv.models.multiChart = function() {9263"use strict";9264//============================================================9265// Public Variables with Default Settings9266//------------------------------------------------------------92679268var margin = {top: 30, right: 20, bottom: 50, left: 60},9269color = d3.scale.category20().range(),9270width = null,9271height = null,9272showLegend = true,9273tooltips = true,9274tooltip = function(key, x, y, e, graph) {9275return '<h3>' + key + '</h3>' +9276'<p>' + y + ' at ' + x + '</p>'9277},9278x,9279y,9280yDomain1,9281yDomain29282; //can be accessed via chart.lines.[x/y]Scale()92839284//============================================================9285// Private Variables9286//------------------------------------------------------------92879288var x = d3.scale.linear(),9289yScale1 = d3.scale.linear(),9290yScale2 = d3.scale.linear(),92919292lines1 = nv.models.line().yScale(yScale1),9293lines2 = nv.models.line().yScale(yScale2),92949295bars1 = nv.models.multiBar().stacked(false).yScale(yScale1),9296bars2 = nv.models.multiBar().stacked(false).yScale(yScale2),92979298stack1 = nv.models.stackedArea().yScale(yScale1),9299stack2 = nv.models.stackedArea().yScale(yScale2),93009301xAxis = nv.models.axis().scale(x).orient('bottom').tickPadding(5),9302yAxis1 = nv.models.axis().scale(yScale1).orient('left'),9303yAxis2 = nv.models.axis().scale(yScale2).orient('right'),93049305legend = nv.models.legend().height(30),9306dispatch = d3.dispatch('tooltipShow', 'tooltipHide');93079308var showTooltip = function(e, offsetElement) {9309var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),9310top = e.pos[1] + ( offsetElement.offsetTop || 0),9311x = xAxis.tickFormat()(lines1.x()(e.point, e.pointIndex)),9312y = ((e.series.yAxis == 2) ? yAxis2 : yAxis1).tickFormat()(lines1.y()(e.point, e.pointIndex)),9313content = tooltip(e.series.key, x, y, e, chart);93149315nv.tooltip.show([left, top], content, undefined, undefined, offsetElement.offsetParent);9316};93179318function chart(selection) {9319selection.each(function(data) {9320var container = d3.select(this),9321that = this;93229323chart.update = function() { container.transition().call(chart); };9324chart.container = this;93259326var availableWidth = (width || parseInt(container.style('width')) || 960)9327- margin.left - margin.right,9328availableHeight = (height || parseInt(container.style('height')) || 400)9329- margin.top - margin.bottom;93309331var dataLines1 = data.filter(function(d) {return !d.disabled && d.type == 'line' && d.yAxis == 1})9332var dataLines2 = data.filter(function(d) {return !d.disabled && d.type == 'line' && d.yAxis == 2})9333var dataBars1 = data.filter(function(d) {return !d.disabled && d.type == 'bar' && d.yAxis == 1})9334var dataBars2 = data.filter(function(d) {return !d.disabled && d.type == 'bar' && d.yAxis == 2})9335var dataStack1 = data.filter(function(d) {return !d.disabled && d.type == 'area' && d.yAxis == 1})9336var dataStack2 = data.filter(function(d) {return !d.disabled && d.type == 'area' && d.yAxis == 2})93379338var series1 = data.filter(function(d) {return !d.disabled && d.yAxis == 1})9339.map(function(d) {9340return d.values.map(function(d,i) {9341return { x: d.x, y: d.y }9342})9343})93449345var series2 = data.filter(function(d) {return !d.disabled && d.yAxis == 2})9346.map(function(d) {9347return d.values.map(function(d,i) {9348return { x: d.x, y: d.y }9349})9350})93519352x .domain(d3.extent(d3.merge(series1.concat(series2)), function(d) { return d.x } ))9353.range([0, availableWidth]);93549355var wrap = container.selectAll('g.wrap.multiChart').data([data]);9356var gEnter = wrap.enter().append('g').attr('class', 'wrap nvd3 multiChart').append('g');93579358gEnter.append('g').attr('class', 'x axis');9359gEnter.append('g').attr('class', 'y1 axis');9360gEnter.append('g').attr('class', 'y2 axis');9361gEnter.append('g').attr('class', 'lines1Wrap');9362gEnter.append('g').attr('class', 'lines2Wrap');9363gEnter.append('g').attr('class', 'bars1Wrap');9364gEnter.append('g').attr('class', 'bars2Wrap');9365gEnter.append('g').attr('class', 'stack1Wrap');9366gEnter.append('g').attr('class', 'stack2Wrap');9367gEnter.append('g').attr('class', 'legendWrap');93689369var g = wrap.select('g');93709371if (showLegend) {9372legend.width( availableWidth / 2 );93739374g.select('.legendWrap')9375.datum(data.map(function(series) {9376series.originalKey = series.originalKey === undefined ? series.key : series.originalKey;9377series.key = series.originalKey + (series.yAxis == 1 ? '' : ' (right axis)');9378return series;9379}))9380.call(legend);93819382if ( margin.top != legend.height()) {9383margin.top = legend.height();9384availableHeight = (height || parseInt(container.style('height')) || 400)9385- margin.top - margin.bottom;9386}93879388g.select('.legendWrap')9389.attr('transform', 'translate(' + ( availableWidth / 2 ) + ',' + (-margin.top) +')');9390}939193929393lines19394.width(availableWidth)9395.height(availableHeight)9396.interpolate("monotone")9397.color(data.map(function(d,i) {9398return d.color || color[i % color.length];9399}).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'line'}));94009401lines29402.width(availableWidth)9403.height(availableHeight)9404.interpolate("monotone")9405.color(data.map(function(d,i) {9406return d.color || color[i % color.length];9407}).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'line'}));94089409bars19410.width(availableWidth)9411.height(availableHeight)9412.color(data.map(function(d,i) {9413return d.color || color[i % color.length];9414}).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'bar'}));94159416bars29417.width(availableWidth)9418.height(availableHeight)9419.color(data.map(function(d,i) {9420return d.color || color[i % color.length];9421}).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'bar'}));94229423stack19424.width(availableWidth)9425.height(availableHeight)9426.color(data.map(function(d,i) {9427return d.color || color[i % color.length];9428}).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 1 && data[i].type == 'area'}));94299430stack29431.width(availableWidth)9432.height(availableHeight)9433.color(data.map(function(d,i) {9434return d.color || color[i % color.length];9435}).filter(function(d,i) { return !data[i].disabled && data[i].yAxis == 2 && data[i].type == 'area'}));94369437g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');943894399440var lines1Wrap = g.select('.lines1Wrap')9441.datum(dataLines1)9442var bars1Wrap = g.select('.bars1Wrap')9443.datum(dataBars1)9444var stack1Wrap = g.select('.stack1Wrap')9445.datum(dataStack1)94469447var lines2Wrap = g.select('.lines2Wrap')9448.datum(dataLines2)9449var bars2Wrap = g.select('.bars2Wrap')9450.datum(dataBars2)9451var stack2Wrap = g.select('.stack2Wrap')9452.datum(dataStack2)94539454var extraValue1 = dataStack1.length ? dataStack1.map(function(a){return a.values}).reduce(function(a,b){9455return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}})9456}).concat([{x:0, y:0}]) : []9457var extraValue2 = dataStack2.length ? dataStack2.map(function(a){return a.values}).reduce(function(a,b){9458return a.map(function(aVal,i){return {x: aVal.x, y: aVal.y + b[i].y}})9459}).concat([{x:0, y:0}]) : []94609461yScale1 .domain(yDomain1 || d3.extent(d3.merge(series1).concat(extraValue1), function(d) { return d.y } ))9462.range([0, availableHeight])94639464yScale2 .domain(yDomain2 || d3.extent(d3.merge(series2).concat(extraValue2), function(d) { return d.y } ))9465.range([0, availableHeight])94669467lines1.yDomain(yScale1.domain())9468bars1.yDomain(yScale1.domain())9469stack1.yDomain(yScale1.domain())94709471lines2.yDomain(yScale2.domain())9472bars2.yDomain(yScale2.domain())9473stack2.yDomain(yScale2.domain())94749475if(dataStack1.length){d3.transition(stack1Wrap).call(stack1);}9476if(dataStack2.length){d3.transition(stack2Wrap).call(stack2);}94779478if(dataBars1.length){d3.transition(bars1Wrap).call(bars1);}9479if(dataBars2.length){d3.transition(bars2Wrap).call(bars2);}94809481if(dataLines1.length){d3.transition(lines1Wrap).call(lines1);}9482if(dataLines2.length){d3.transition(lines2Wrap).call(lines2);}9483948494859486xAxis9487.ticks( availableWidth / 100 )9488.tickSize(-availableHeight, 0);94899490g.select('.x.axis')9491.attr('transform', 'translate(0,' + availableHeight + ')');9492d3.transition(g.select('.x.axis'))9493.call(xAxis);94949495yAxis19496.ticks( availableHeight / 36 )9497.tickSize( -availableWidth, 0);949894999500d3.transition(g.select('.y1.axis'))9501.call(yAxis1);95029503yAxis29504.ticks( availableHeight / 36 )9505.tickSize( -availableWidth, 0);95069507d3.transition(g.select('.y2.axis'))9508.call(yAxis2);95099510g.select('.y2.axis')9511.style('opacity', series2.length ? 1 : 0)9512.attr('transform', 'translate(' + x.range()[1] + ',0)');95139514legend.dispatch.on('stateChange', function(newState) {9515chart.update();9516});95179518dispatch.on('tooltipShow', function(e) {9519if (tooltips) showTooltip(e, that.parentNode);9520});95219522});95239524return chart;9525}952695279528//============================================================9529// Event Handling/Dispatching (out of chart's scope)9530//------------------------------------------------------------95319532lines1.dispatch.on('elementMouseover.tooltip', function(e) {9533e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];9534dispatch.tooltipShow(e);9535});95369537lines1.dispatch.on('elementMouseout.tooltip', function(e) {9538dispatch.tooltipHide(e);9539});95409541lines2.dispatch.on('elementMouseover.tooltip', function(e) {9542e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];9543dispatch.tooltipShow(e);9544});95459546lines2.dispatch.on('elementMouseout.tooltip', function(e) {9547dispatch.tooltipHide(e);9548});95499550bars1.dispatch.on('elementMouseover.tooltip', function(e) {9551e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];9552dispatch.tooltipShow(e);9553});95549555bars1.dispatch.on('elementMouseout.tooltip', function(e) {9556dispatch.tooltipHide(e);9557});95589559bars2.dispatch.on('elementMouseover.tooltip', function(e) {9560e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];9561dispatch.tooltipShow(e);9562});95639564bars2.dispatch.on('elementMouseout.tooltip', function(e) {9565dispatch.tooltipHide(e);9566});95679568stack1.dispatch.on('tooltipShow', function(e) {9569//disable tooltips when value ~= 09570//// TODO: consider removing points from voronoi that have 0 value instead of this hack9571if (!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 range9572setTimeout(function() { d3.selectAll('.point.hover').classed('hover', false) }, 0);9573return false;9574}95759576e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top],9577dispatch.tooltipShow(e);9578});95799580stack1.dispatch.on('tooltipHide', function(e) {9581dispatch.tooltipHide(e);9582});95839584stack2.dispatch.on('tooltipShow', function(e) {9585//disable tooltips when value ~= 09586//// TODO: consider removing points from voronoi that have 0 value instead of this hack9587if (!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 range9588setTimeout(function() { d3.selectAll('.point.hover').classed('hover', false) }, 0);9589return false;9590}95919592e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top],9593dispatch.tooltipShow(e);9594});95959596stack2.dispatch.on('tooltipHide', function(e) {9597dispatch.tooltipHide(e);9598});95999600lines1.dispatch.on('elementMouseover.tooltip', function(e) {9601e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];9602dispatch.tooltipShow(e);9603});96049605lines1.dispatch.on('elementMouseout.tooltip', function(e) {9606dispatch.tooltipHide(e);9607});96089609lines2.dispatch.on('elementMouseover.tooltip', function(e) {9610e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];9611dispatch.tooltipShow(e);9612});96139614lines2.dispatch.on('elementMouseout.tooltip', function(e) {9615dispatch.tooltipHide(e);9616});96179618dispatch.on('tooltipHide', function() {9619if (tooltips) nv.tooltip.cleanup();9620});9621962296239624//============================================================9625// Global getters and setters9626//------------------------------------------------------------96279628chart.dispatch = dispatch;9629chart.lines1 = lines1;9630chart.lines2 = lines2;9631chart.bars1 = bars1;9632chart.bars2 = bars2;9633chart.stack1 = stack1;9634chart.stack2 = stack2;9635chart.xAxis = xAxis;9636chart.yAxis1 = yAxis1;9637chart.yAxis2 = yAxis2;9638chart.options = nv.utils.optionsFunc.bind(chart);96399640chart.x = function(_) {9641if (!arguments.length) return getX;9642getX = _;9643lines1.x(_);9644bars1.x(_);9645return chart;9646};96479648chart.y = function(_) {9649if (!arguments.length) return getY;9650getY = _;9651lines1.y(_);9652bars1.y(_);9653return chart;9654};96559656chart.yDomain1 = function(_) {9657if (!arguments.length) return yDomain1;9658yDomain1 = _;9659return chart;9660};96619662chart.yDomain2 = function(_) {9663if (!arguments.length) return yDomain2;9664yDomain2 = _;9665return chart;9666};96679668chart.margin = function(_) {9669if (!arguments.length) return margin;9670margin = _;9671return chart;9672};96739674chart.width = function(_) {9675if (!arguments.length) return width;9676width = _;9677return chart;9678};96799680chart.height = function(_) {9681if (!arguments.length) return height;9682height = _;9683return chart;9684};96859686chart.color = function(_) {9687if (!arguments.length) return color;9688color = _;9689legend.color(_);9690return chart;9691};96929693chart.showLegend = function(_) {9694if (!arguments.length) return showLegend;9695showLegend = _;9696return chart;9697};96989699chart.tooltips = function(_) {9700if (!arguments.length) return tooltips;9701tooltips = _;9702return chart;9703};97049705chart.tooltipContent = function(_) {9706if (!arguments.length) return tooltip;9707tooltip = _;9708return chart;9709};97109711return chart;9712}971397149715nv.models.ohlcBar = function() {9716"use strict";9717//============================================================9718// Public Variables with Default Settings9719//------------------------------------------------------------97209721var margin = {top: 0, right: 0, bottom: 0, left: 0}9722, width = 9609723, height = 5009724, id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one9725, x = d3.scale.linear()9726, y = d3.scale.linear()9727, getX = function(d) { return d.x }9728, getY = function(d) { return d.y }9729, getOpen = function(d) { return d.open }9730, getClose = function(d) { return d.close }9731, getHigh = function(d) { return d.high }9732, getLow = function(d) { return d.low }9733, forceX = []9734, forceY = []9735, padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart9736, clipEdge = true9737, color = nv.utils.defaultColor()9738, xDomain9739, yDomain9740, xRange9741, yRange9742, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')9743;97449745//============================================================97469747//============================================================9748// Private Variables9749//------------------------------------------------------------97509751//TODO: store old scales for transitions97529753//============================================================975497559756function chart(selection) {9757selection.each(function(data) {9758var availableWidth = width - margin.left - margin.right,9759availableHeight = height - margin.top - margin.bottom,9760container = d3.select(this);976197629763//------------------------------------------------------------9764// Setup Scales97659766x .domain(xDomain || d3.extent(data[0].values.map(getX).concat(forceX) ));97679768if (padData)9769x.range(xRange || [availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);9770else9771x.range(xRange || [0, availableWidth]);97729773y .domain(yDomain || [9774d3.min(data[0].values.map(getLow).concat(forceY)),9775d3.max(data[0].values.map(getHigh).concat(forceY))9776])9777.range(yRange || [availableHeight, 0]);97789779// If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point9780if (x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]) singlePoint = true;9781if (x.domain()[0] === x.domain()[1])9782x.domain()[0] ?9783x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])9784: x.domain([-1,1]);97859786if (y.domain()[0] === y.domain()[1])9787y.domain()[0] ?9788y.domain([y.domain()[0] + y.domain()[0] * 0.01, y.domain()[1] - y.domain()[1] * 0.01])9789: y.domain([-1,1]);97909791//------------------------------------------------------------979297939794//------------------------------------------------------------9795// Setup containers and skeleton of chart97969797var wrap = d3.select(this).selectAll('g.nv-wrap.nv-ohlcBar').data([data[0].values]);9798var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-ohlcBar');9799var defsEnter = wrapEnter.append('defs');9800var gEnter = wrapEnter.append('g');9801var g = wrap.select('g');98029803gEnter.append('g').attr('class', 'nv-ticks');98049805wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');98069807//------------------------------------------------------------980898099810container9811.on('click', function(d,i) {9812dispatch.chartClick({9813data: d,9814index: i,9815pos: d3.event,9816id: id9817});9818});981998209821defsEnter.append('clipPath')9822.attr('id', 'nv-chart-clip-path-' + id)9823.append('rect');98249825wrap.select('#nv-chart-clip-path-' + id + ' rect')9826.attr('width', availableWidth)9827.attr('height', availableHeight);98289829g .attr('clip-path', clipEdge ? 'url(#nv-chart-clip-path-' + id + ')' : '');9830983198329833var ticks = wrap.select('.nv-ticks').selectAll('.nv-tick')9834.data(function(d) { return d });98359836ticks.exit().remove();983798389839var ticksEnter = ticks.enter().append('path')9840.attr('class', function(d,i,j) { return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i })9841.attr('d', function(d,i) {9842var w = (availableWidth / data[0].values.length) * .9;9843return 'm0,0l0,'9844+ (y(getOpen(d,i))9845- y(getHigh(d,i)))9846+ 'l'9847+ (-w/2)9848+ ',0l'9849+ (w/2)9850+ ',0l0,'9851+ (y(getLow(d,i)) - y(getOpen(d,i)))9852+ 'l0,'9853+ (y(getClose(d,i))9854- y(getLow(d,i)))9855+ 'l'9856+ (w/2)9857+ ',0l'9858+ (-w/2)9859+ ',0z';9860})9861.attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; })9862//.attr('fill', function(d,i) { return color[0]; })9863//.attr('stroke', function(d,i) { return color[0]; })9864//.attr('x', 0 )9865//.attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })9866//.attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) })9867.on('mouseover', function(d,i) {9868d3.select(this).classed('hover', true);9869dispatch.elementMouseover({9870point: d,9871series: data[0],9872pos: [x(getX(d,i)), y(getY(d,i))], // TODO: Figure out why the value appears to be shifted9873pointIndex: i,9874seriesIndex: 0,9875e: d3.event9876});98779878})9879.on('mouseout', function(d,i) {9880d3.select(this).classed('hover', false);9881dispatch.elementMouseout({9882point: d,9883series: data[0],9884pointIndex: i,9885seriesIndex: 0,9886e: d3.event9887});9888})9889.on('click', function(d,i) {9890dispatch.elementClick({9891//label: d[label],9892value: getY(d,i),9893data: d,9894index: i,9895pos: [x(getX(d,i)), y(getY(d,i))],9896e: d3.event,9897id: id9898});9899d3.event.stopPropagation();9900})9901.on('dblclick', function(d,i) {9902dispatch.elementDblClick({9903//label: d[label],9904value: getY(d,i),9905data: d,9906index: i,9907pos: [x(getX(d,i)), y(getY(d,i))],9908e: d3.event,9909id: id9910});9911d3.event.stopPropagation();9912});99139914ticks9915.attr('class', function(d,i,j) { return (getOpen(d,i) > getClose(d,i) ? 'nv-tick negative' : 'nv-tick positive') + ' nv-tick-' + j + '-' + i })9916d3.transition(ticks)9917.attr('transform', function(d,i) { return 'translate(' + x(getX(d,i)) + ',' + y(getHigh(d,i)) + ')'; })9918.attr('d', function(d,i) {9919var w = (availableWidth / data[0].values.length) * .9;9920return 'm0,0l0,'9921+ (y(getOpen(d,i))9922- y(getHigh(d,i)))9923+ 'l'9924+ (-w/2)9925+ ',0l'9926+ (w/2)9927+ ',0l0,'9928+ (y(getLow(d,i))9929- y(getOpen(d,i)))9930+ 'l0,'9931+ (y(getClose(d,i))9932- y(getLow(d,i)))9933+ 'l'9934+ (w/2)9935+ ',0l'9936+ (-w/2)9937+ ',0z';9938})9939//.attr('width', (availableWidth / data[0].values.length) * .9 )994099419942//d3.transition(ticks)9943//.attr('y', function(d,i) { return y(Math.max(0, getY(d,i))) })9944//.attr('height', function(d,i) { return Math.abs(y(getY(d,i)) - y(0)) });9945//.order(); // not sure if this makes any sense for this model99469947});99489949return chart;9950}995199529953//============================================================9954// Expose Public Variables9955//------------------------------------------------------------99569957chart.dispatch = dispatch;99589959chart.options = nv.utils.optionsFunc.bind(chart);99609961chart.x = function(_) {9962if (!arguments.length) return getX;9963getX = _;9964return chart;9965};99669967chart.y = function(_) {9968if (!arguments.length) return getY;9969getY = _;9970return chart;9971};99729973chart.open = function(_) {9974if (!arguments.length) return getOpen;9975getOpen = _;9976return chart;9977};99789979chart.close = function(_) {9980if (!arguments.length) return getClose;9981getClose = _;9982return chart;9983};99849985chart.high = function(_) {9986if (!arguments.length) return getHigh;9987getHigh = _;9988return chart;9989};99909991chart.low = function(_) {9992if (!arguments.length) return getLow;9993getLow = _;9994return chart;9995};99969997chart.margin = function(_) {9998if (!arguments.length) return margin;9999margin.top = typeof _.top != 'undefined' ? _.top : margin.top;10000margin.right = typeof _.right != 'undefined' ? _.right : margin.right;10001margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;10002margin.left = typeof _.left != 'undefined' ? _.left : margin.left;10003return chart;10004};1000510006chart.width = function(_) {10007if (!arguments.length) return width;10008width = _;10009return chart;10010};1001110012chart.height = function(_) {10013if (!arguments.length) return height;10014height = _;10015return chart;10016};1001710018chart.xScale = function(_) {10019if (!arguments.length) return x;10020x = _;10021return chart;10022};1002310024chart.yScale = function(_) {10025if (!arguments.length) return y;10026y = _;10027return chart;10028};1002910030chart.xDomain = function(_) {10031if (!arguments.length) return xDomain;10032xDomain = _;10033return chart;10034};1003510036chart.yDomain = function(_) {10037if (!arguments.length) return yDomain;10038yDomain = _;10039return chart;10040};1004110042chart.xRange = function(_) {10043if (!arguments.length) return xRange;10044xRange = _;10045return chart;10046};1004710048chart.yRange = function(_) {10049if (!arguments.length) return yRange;10050yRange = _;10051return chart;10052};1005310054chart.forceX = function(_) {10055if (!arguments.length) return forceX;10056forceX = _;10057return chart;10058};1005910060chart.forceY = function(_) {10061if (!arguments.length) return forceY;10062forceY = _;10063return chart;10064};1006510066chart.padData = function(_) {10067if (!arguments.length) return padData;10068padData = _;10069return chart;10070};1007110072chart.clipEdge = function(_) {10073if (!arguments.length) return clipEdge;10074clipEdge = _;10075return chart;10076};1007710078chart.color = function(_) {10079if (!arguments.length) return color;10080color = nv.utils.getColor(_);10081return chart;10082};1008310084chart.id = function(_) {10085if (!arguments.length) return id;10086id = _;10087return chart;10088};1008910090//============================================================100911009210093return chart;10094}10095nv.models.pie = function() {10096"use strict";10097//============================================================10098// Public Variables with Default Settings10099//------------------------------------------------------------1010010101var margin = {top: 0, right: 0, bottom: 0, left: 0}10102, width = 50010103, height = 50010104, getX = function(d) { return d.x }10105, getY = function(d) { return d.y }10106, getDescription = function(d) { return d.description }10107, id = Math.floor(Math.random() * 10000) //Create semi-unique ID in case user doesn't select one10108, color = nv.utils.defaultColor()10109, valueFormat = d3.format(',.2f')10110, showLabels = true10111, pieLabelsOutside = true10112, donutLabelsOutside = false10113, labelType = "key"10114, labelThreshold = .02 //if slice percentage is under this, don't show label10115, donut = false10116, labelSunbeamLayout = false10117, startAngle = false10118, endAngle = false10119, donutRatio = 0.510120, dispatch = d3.dispatch('chartClick', 'elementClick', 'elementDblClick', 'elementMouseover', 'elementMouseout')10121;1012210123//============================================================101241012510126function chart(selection) {10127selection.each(function(data) {10128var availableWidth = width - margin.left - margin.right,10129availableHeight = height - margin.top - margin.bottom,10130radius = Math.min(availableWidth, availableHeight) / 2,10131arcRadius = radius-(radius / 5),10132container = d3.select(this);101331013410135//------------------------------------------------------------10136// Setup containers and skeleton of chart1013710138//var wrap = container.selectAll('.nv-wrap.nv-pie').data([data]);10139var wrap = container.selectAll('.nv-wrap.nv-pie').data(data);10140var wrapEnter = wrap.enter().append('g').attr('class','nvd3 nv-wrap nv-pie nv-chart-' + id);10141var gEnter = wrapEnter.append('g');10142var g = wrap.select('g');1014310144gEnter.append('g').attr('class', 'nv-pie');1014510146wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');10147g.select('.nv-pie').attr('transform', 'translate(' + availableWidth / 2 + ',' + availableHeight / 2 + ')');1014810149//------------------------------------------------------------101501015110152container10153.on('click', function(d,i) {10154dispatch.chartClick({10155data: d,10156index: i,10157pos: d3.event,10158id: id10159});10160});101611016210163var arc = d3.svg.arc()10164.outerRadius(arcRadius);1016510166if (startAngle) arc.startAngle(startAngle)10167if (endAngle) arc.endAngle(endAngle);10168if (donut) arc.innerRadius(radius * donutRatio);1016910170// Setup the Pie chart and choose the data element10171var pie = d3.layout.pie()10172.sort(null)10173.value(function(d) { return d.disabled ? 0 : getY(d) });1017410175var slices = wrap.select('.nv-pie').selectAll('.nv-slice')10176.data(pie);1017710178slices.exit().remove();1017910180var ae = slices.enter().append('g')10181.attr('class', 'nv-slice')10182.on('mouseover', function(d,i){10183d3.select(this).classed('hover', true);10184dispatch.elementMouseover({10185label: getX(d.data),10186value: getY(d.data),10187point: d.data,10188pointIndex: i,10189pos: [d3.event.pageX, d3.event.pageY],10190id: id10191});10192})10193.on('mouseout', function(d,i){10194d3.select(this).classed('hover', false);10195dispatch.elementMouseout({10196label: getX(d.data),10197value: getY(d.data),10198point: d.data,10199index: i,10200id: id10201});10202})10203.on('click', function(d,i) {10204dispatch.elementClick({10205label: getX(d.data),10206value: getY(d.data),10207point: d.data,10208index: i,10209pos: d3.event,10210id: id10211});10212d3.event.stopPropagation();10213})10214.on('dblclick', function(d,i) {10215dispatch.elementDblClick({10216label: getX(d.data),10217value: getY(d.data),10218point: d.data,10219index: i,10220pos: d3.event,10221id: id10222});10223d3.event.stopPropagation();10224});1022510226slices10227.attr('fill', function(d,i) { return color(d, i); })10228.attr('stroke', function(d,i) { return color(d, i); });1022910230var paths = ae.append('path')10231.each(function(d) { this._current = d; });10232//.attr('d', arc);1023310234d3.transition(slices.select('path'))10235.attr('d', arc)10236.attrTween('d', arcTween);1023710238if (showLabels) {10239// This does the normal label10240var labelsArc = d3.svg.arc().innerRadius(0);1024110242if (pieLabelsOutside){ labelsArc = arc; }1024310244if (donutLabelsOutside) { labelsArc = d3.svg.arc().outerRadius(arc.outerRadius()); }1024510246ae.append("g").classed("nv-label", true)10247.each(function(d, i) {10248var group = d3.select(this);1024910250group10251.attr('transform', function(d) {10252if (labelSunbeamLayout) {10253d.outerRadius = arcRadius + 10; // Set Outer Coordinate10254d.innerRadius = arcRadius + 15; // Set Inner Coordinate10255var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);10256if ((d.startAngle+d.endAngle)/2 < Math.PI) {10257rotateAngle -= 90;10258} else {10259rotateAngle += 90;10260}10261return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')';10262} else {10263d.outerRadius = radius + 10; // Set Outer Coordinate10264d.innerRadius = radius + 15; // Set Inner Coordinate10265return 'translate(' + labelsArc.centroid(d) + ')'10266}10267});1026810269group.append('rect')10270.style('stroke', '#fff')10271.style('fill', '#fff')10272.attr("rx", 3)10273.attr("ry", 3);1027410275group.append('text')10276.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 aligned10277.style('fill', '#000')102781027910280});1028110282slices.select(".nv-label").transition()10283.attr('transform', function(d) {10284if (labelSunbeamLayout) {10285d.outerRadius = arcRadius + 10; // Set Outer Coordinate10286d.innerRadius = arcRadius + 15; // Set Inner Coordinate10287var rotateAngle = (d.startAngle + d.endAngle) / 2 * (180 / Math.PI);10288if ((d.startAngle+d.endAngle)/2 < Math.PI) {10289rotateAngle -= 90;10290} else {10291rotateAngle += 90;10292}10293return 'translate(' + labelsArc.centroid(d) + ') rotate(' + rotateAngle + ')';10294} else {10295d.outerRadius = radius + 10; // Set Outer Coordinate10296d.innerRadius = radius + 15; // Set Inner Coordinate10297return 'translate(' + labelsArc.centroid(d) + ')'10298}10299});1030010301slices.each(function(d, i) {10302var slice = d3.select(this);1030310304slice10305.select(".nv-label text")10306.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 aligned10307.text(function(d, i) {10308var percent = (d.endAngle - d.startAngle) / (2 * Math.PI);10309var labelTypes = {10310"key" : getX(d.data),10311"value": getY(d.data),10312"percent": d3.format('%')(percent)10313};10314return (d.value && percent > labelThreshold) ? labelTypes[labelType] : '';10315});1031610317var textBox = slice.select('text').node().getBBox();10318slice.select(".nv-label rect")10319.attr("width", textBox.width + 10)10320.attr("height", textBox.height + 10)10321.attr("transform", function() {10322return "translate(" + [textBox.x - 5, textBox.y - 5] + ")";10323});10324});10325}103261032710328// Computes the angle of an arc, converting from radians to degrees.10329function angle(d) {10330var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;10331return a > 90 ? a - 180 : a;10332}1033310334function arcTween(a) {10335a.endAngle = isNaN(a.endAngle) ? 0 : a.endAngle;10336a.startAngle = isNaN(a.startAngle) ? 0 : a.startAngle;10337if (!donut) a.innerRadius = 0;10338var i = d3.interpolate(this._current, a);10339this._current = i(0);10340return function(t) {10341return arc(i(t));10342};10343}1034410345function tweenPie(b) {10346b.innerRadius = 0;10347var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);10348return function(t) {10349return arc(i(t));10350};10351}1035210353});1035410355return chart;10356}103571035810359//============================================================10360// Expose Public Variables10361//------------------------------------------------------------1036210363chart.dispatch = dispatch;10364chart.options = nv.utils.optionsFunc.bind(chart);1036510366chart.margin = function(_) {10367if (!arguments.length) return margin;10368margin.top = typeof _.top != 'undefined' ? _.top : margin.top;10369margin.right = typeof _.right != 'undefined' ? _.right : margin.right;10370margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;10371margin.left = typeof _.left != 'undefined' ? _.left : margin.left;10372return chart;10373};1037410375chart.width = function(_) {10376if (!arguments.length) return width;10377width = _;10378return chart;10379};1038010381chart.height = function(_) {10382if (!arguments.length) return height;10383height = _;10384return chart;10385};1038610387chart.values = function(_) {10388nv.log("pie.values() is no longer supported.");10389return chart;10390};1039110392chart.x = function(_) {10393if (!arguments.length) return getX;10394getX = _;10395return chart;10396};1039710398chart.y = function(_) {10399if (!arguments.length) return getY;10400getY = d3.functor(_);10401return chart;10402};1040310404chart.description = function(_) {10405if (!arguments.length) return getDescription;10406getDescription = _;10407return chart;10408};1040910410chart.showLabels = function(_) {10411if (!arguments.length) return showLabels;10412showLabels = _;10413return chart;10414};1041510416chart.labelSunbeamLayout = function(_) {10417if (!arguments.length) return labelSunbeamLayout;10418labelSunbeamLayout = _;10419return chart;10420};1042110422chart.donutLabelsOutside = function(_) {10423if (!arguments.length) return donutLabelsOutside;10424donutLabelsOutside = _;10425return chart;10426};1042710428chart.pieLabelsOutside = function(_) {10429if (!arguments.length) return pieLabelsOutside;10430pieLabelsOutside = _;10431return chart;10432};1043310434chart.labelType = function(_) {10435if (!arguments.length) return labelType;10436labelType = _;10437labelType = labelType || "key";10438return chart;10439};1044010441chart.donut = function(_) {10442if (!arguments.length) return donut;10443donut = _;10444return chart;10445};1044610447chart.donutRatio = function(_) {10448if (!arguments.length) return donutRatio;10449donutRatio = _;10450return chart;10451};1045210453chart.startAngle = function(_) {10454if (!arguments.length) return startAngle;10455startAngle = _;10456return chart;10457};1045810459chart.endAngle = function(_) {10460if (!arguments.length) return endAngle;10461endAngle = _;10462return chart;10463};1046410465chart.id = function(_) {10466if (!arguments.length) return id;10467id = _;10468return chart;10469};1047010471chart.color = function(_) {10472if (!arguments.length) return color;10473color = nv.utils.getColor(_);10474return chart;10475};1047610477chart.valueFormat = function(_) {10478if (!arguments.length) return valueFormat;10479valueFormat = _;10480return chart;10481};1048210483chart.labelThreshold = function(_) {10484if (!arguments.length) return labelThreshold;10485labelThreshold = _;10486return chart;10487};10488//============================================================104891049010491return chart;10492}10493nv.models.pieChart = function() {10494"use strict";10495//============================================================10496// Public Variables with Default Settings10497//------------------------------------------------------------1049810499var pie = nv.models.pie()10500, legend = nv.models.legend()10501;1050210503var margin = {top: 30, right: 20, bottom: 20, left: 20}10504, width = null10505, height = null10506, showLegend = true10507, color = nv.utils.defaultColor()10508, tooltips = true10509, tooltip = function(key, y, e, graph) {10510return '<h3>' + key + '</h3>' +10511'<p>' + y + '</p>'10512}10513, state = {}10514, defaultState = null10515, noData = "No Data Available."10516, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')10517;1051810519//============================================================105201052110522//============================================================10523// Private Variables10524//------------------------------------------------------------1052510526var showTooltip = function(e, offsetElement) {10527var tooltipLabel = pie.description()(e.point) || pie.x()(e.point)10528var left = e.pos[0] + ( (offsetElement && offsetElement.offsetLeft) || 0 ),10529top = e.pos[1] + ( (offsetElement && offsetElement.offsetTop) || 0),10530y = pie.valueFormat()(pie.y()(e.point)),10531content = tooltip(tooltipLabel, y, e, chart);1053210533nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);10534};1053510536//============================================================105371053810539function chart(selection) {10540selection.each(function(data) {10541var container = d3.select(this),10542that = this;1054310544var availableWidth = (width || parseInt(container.style('width')) || 960)10545- margin.left - margin.right,10546availableHeight = (height || parseInt(container.style('height')) || 400)10547- margin.top - margin.bottom;1054810549chart.update = function() { container.transition().call(chart); };10550chart.container = this;1055110552//set state.disabled10553state.disabled = data.map(function(d) { return !!d.disabled });1055410555if (!defaultState) {10556var key;10557defaultState = {};10558for (key in state) {10559if (state[key] instanceof Array)10560defaultState[key] = state[key].slice(0);10561else10562defaultState[key] = state[key];10563}10564}1056510566//------------------------------------------------------------10567// Display No Data message if there's nothing to show.1056810569if (!data || !data.length) {10570var noDataText = container.selectAll('.nv-noData').data([noData]);1057110572noDataText.enter().append('text')10573.attr('class', 'nvd3 nv-noData')10574.attr('dy', '-.7em')10575.style('text-anchor', 'middle');1057610577noDataText10578.attr('x', margin.left + availableWidth / 2)10579.attr('y', margin.top + availableHeight / 2)10580.text(function(d) { return d });1058110582return chart;10583} else {10584container.selectAll('.nv-noData').remove();10585}1058610587//------------------------------------------------------------105881058910590//------------------------------------------------------------10591// Setup containers and skeleton of chart1059210593var wrap = container.selectAll('g.nv-wrap.nv-pieChart').data([data]);10594var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-pieChart').append('g');10595var g = wrap.select('g');1059610597gEnter.append('g').attr('class', 'nv-pieWrap');10598gEnter.append('g').attr('class', 'nv-legendWrap');1059910600//------------------------------------------------------------106011060210603//------------------------------------------------------------10604// Legend1060510606if (showLegend) {10607legend10608.width( availableWidth )10609.key(pie.x());1061010611wrap.select('.nv-legendWrap')10612.datum(data)10613.call(legend);1061410615if ( margin.top != legend.height()) {10616margin.top = legend.height();10617availableHeight = (height || parseInt(container.style('height')) || 400)10618- margin.top - margin.bottom;10619}1062010621wrap.select('.nv-legendWrap')10622.attr('transform', 'translate(0,' + (-margin.top) +')');10623}1062410625//------------------------------------------------------------106261062710628wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');106291063010631//------------------------------------------------------------10632// Main Chart Component(s)1063310634pie10635.width(availableWidth)10636.height(availableHeight);106371063810639var pieWrap = g.select('.nv-pieWrap')10640.datum([data]);1064110642d3.transition(pieWrap).call(pie);1064310644//------------------------------------------------------------106451064610647//============================================================10648// Event Handling/Dispatching (in chart's scope)10649//------------------------------------------------------------1065010651legend.dispatch.on('stateChange', function(newState) {10652state = newState;10653dispatch.stateChange(state);10654chart.update();10655});1065610657pie.dispatch.on('elementMouseout.tooltip', function(e) {10658dispatch.tooltipHide(e);10659});1066010661// Update chart from a state object passed to event handler10662dispatch.on('changeState', function(e) {1066310664if (typeof e.disabled !== 'undefined') {10665data.forEach(function(series,i) {10666series.disabled = e.disabled[i];10667});1066810669state.disabled = e.disabled;10670}1067110672chart.update();10673});1067410675//============================================================106761067710678});1067910680return chart;10681}1068210683//============================================================10684// Event Handling/Dispatching (out of chart's scope)10685//------------------------------------------------------------1068610687pie.dispatch.on('elementMouseover.tooltip', function(e) {10688e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];10689dispatch.tooltipShow(e);10690});1069110692dispatch.on('tooltipShow', function(e) {10693if (tooltips) showTooltip(e);10694});1069510696dispatch.on('tooltipHide', function() {10697if (tooltips) nv.tooltip.cleanup();10698});1069910700//============================================================107011070210703//============================================================10704// Expose Public Variables10705//------------------------------------------------------------1070610707// expose chart's sub-components10708chart.legend = legend;10709chart.dispatch = dispatch;10710chart.pie = pie;1071110712d3.rebind(chart, pie, 'valueFormat', 'values', 'x', 'y', 'description', 'id', 'showLabels', 'donutLabelsOutside', 'pieLabelsOutside', 'labelType', 'donut', 'donutRatio', 'labelThreshold');10713chart.options = nv.utils.optionsFunc.bind(chart);1071410715chart.margin = function(_) {10716if (!arguments.length) return margin;10717margin.top = typeof _.top != 'undefined' ? _.top : margin.top;10718margin.right = typeof _.right != 'undefined' ? _.right : margin.right;10719margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;10720margin.left = typeof _.left != 'undefined' ? _.left : margin.left;10721return chart;10722};1072310724chart.width = function(_) {10725if (!arguments.length) return width;10726width = _;10727return chart;10728};1072910730chart.height = function(_) {10731if (!arguments.length) return height;10732height = _;10733return chart;10734};1073510736chart.color = function(_) {10737if (!arguments.length) return color;10738color = nv.utils.getColor(_);10739legend.color(color);10740pie.color(color);10741return chart;10742};1074310744chart.showLegend = function(_) {10745if (!arguments.length) return showLegend;10746showLegend = _;10747return chart;10748};1074910750chart.tooltips = function(_) {10751if (!arguments.length) return tooltips;10752tooltips = _;10753return chart;10754};1075510756chart.tooltipContent = function(_) {10757if (!arguments.length) return tooltip;10758tooltip = _;10759return chart;10760};1076110762chart.state = function(_) {10763if (!arguments.length) return state;10764state = _;10765return chart;10766};1076710768chart.defaultState = function(_) {10769if (!arguments.length) return defaultState;10770defaultState = _;10771return chart;10772};1077310774chart.noData = function(_) {10775if (!arguments.length) return noData;10776noData = _;10777return chart;10778};1077910780//============================================================107811078210783return chart;10784}1078510786nv.models.scatter = function() {10787"use strict";10788//============================================================10789// Public Variables with Default Settings10790//------------------------------------------------------------1079110792var margin = {top: 0, right: 0, bottom: 0, left: 0}10793, width = 96010794, height = 50010795, color = nv.utils.defaultColor() // chooses color10796, id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't select one10797, x = d3.scale.linear()10798, y = d3.scale.linear()10799, z = d3.scale.linear() //linear because d3.svg.shape.size is treated as area10800, getX = function(d) { return d.x } // accessor to get the x value10801, getY = function(d) { return d.y } // accessor to get the y value10802, getSize = function(d) { return d.size || 1} // accessor to get the point size10803, getShape = function(d) { return d.shape || 'circle' } // accessor to get point shape10804, onlyCircles = true // Set to false to use shapes10805, forceX = [] // List of numbers to Force into the X scale (ie. 0, or a max / min, etc.)10806, forceY = [] // List of numbers to Force into the Y scale10807, forceSize = [] // List of numbers to Force into the Size scale10808, interactive = true // If true, plots a voronoi overlay for advanced point intersection10809, pointKey = null10810, pointActive = function(d) { return !d.notActive } // any points that return false will be filtered out10811, padData = false // If true, adds half a data points width to front and back, for lining up a line chart with a bar chart10812, padDataOuter = .1 //outerPadding to imitate ordinal scale outer padding10813, clipEdge = false // if true, masks points within x and y scale10814, clipVoronoi = true // if true, masks each point with a circle... can turn off to slightly increase performance10815, clipRadius = function() { return 25 } // function to get the radius for voronoi point clips10816, xDomain = null // Override x domain (skips the calculation from data)10817, yDomain = null // Override y domain10818, xRange = null // Override x range10819, yRange = null // Override y range10820, sizeDomain = null // Override point size domain10821, sizeRange = null10822, singlePoint = false10823, dispatch = d3.dispatch('elementClick', 'elementMouseover', 'elementMouseout')10824, useVoronoi = true10825;1082610827//============================================================108281082910830//============================================================10831// Private Variables10832//------------------------------------------------------------1083310834var x0, y0, z0 // used to store previous scales10835, timeoutID10836, needsUpdate = false // Flag for when the points are visually updating, but the interactive layer is behind, to disable tooltips10837;1083810839//============================================================108401084110842function chart(selection) {10843selection.each(function(data) {10844var availableWidth = width - margin.left - margin.right,10845availableHeight = height - margin.top - margin.bottom,10846container = d3.select(this);1084710848//add series index to each data point for reference10849data = data.map(function(series, i) {10850series.values = series.values.map(function(point) {10851point.series = i;10852return point;10853});10854return series;10855});1085610857//------------------------------------------------------------10858// Setup Scales1085910860// remap and flatten the data for use in calculating the scales' domains10861var 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 performance10862d3.merge(10863data.map(function(d) {10864return d.values.map(function(d,i) {10865return { x: getX(d,i), y: getY(d,i), size: getSize(d,i) }10866})10867})10868);1086910870x .domain(xDomain || d3.extent(seriesData.map(function(d) { return d.x; }).concat(forceX)))1087110872if (padData && data[0])10873x.range(xRange || [(availableWidth * padDataOuter + availableWidth) / (2 *data[0].values.length), availableWidth - availableWidth * (1 + padDataOuter) / (2 * data[0].values.length) ]);10874//x.range([availableWidth * .5 / data[0].values.length, availableWidth * (data[0].values.length - .5) / data[0].values.length ]);10875else10876x.range(xRange || [0, availableWidth]);1087710878y .domain(yDomain || d3.extent(seriesData.map(function(d) { return d.y }).concat(forceY)))10879.range(yRange || [availableHeight, 0]);1088010881z .domain(sizeDomain || d3.extent(seriesData.map(function(d) { return d.size }).concat(forceSize)))10882.range(sizeRange || [16, 256]);1088310884// If scale's domain don't have a range, slightly adjust to make one... so a chart can show a single data point10885if (x.domain()[0] === x.domain()[1] || y.domain()[0] === y.domain()[1]) singlePoint = true;10886if (x.domain()[0] === x.domain()[1])10887x.domain()[0] ?10888x.domain([x.domain()[0] - x.domain()[0] * 0.01, x.domain()[1] + x.domain()[1] * 0.01])10889: x.domain([-1,1]);1089010891if (y.domain()[0] === y.domain()[1])10892y.domain()[0] ?10893y.domain([y.domain()[0] - y.domain()[0] * 0.01, y.domain()[1] + y.domain()[1] * 0.01])10894: y.domain([-1,1]);1089510896if ( isNaN(x.domain()[0])) {10897x.domain([-1,1]);10898}1089910900if ( isNaN(y.domain()[0])) {10901y.domain([-1,1]);10902}109031090410905x0 = x0 || x;10906y0 = y0 || y;10907z0 = z0 || z;1090810909//------------------------------------------------------------109101091110912//------------------------------------------------------------10913// Setup containers and skeleton of chart1091410915var wrap = container.selectAll('g.nv-wrap.nv-scatter').data([data]);10916var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatter nv-chart-' + id + (singlePoint ? ' nv-single-point' : ''));10917var defsEnter = wrapEnter.append('defs');10918var gEnter = wrapEnter.append('g');10919var g = wrap.select('g');1092010921gEnter.append('g').attr('class', 'nv-groups');10922gEnter.append('g').attr('class', 'nv-point-paths');1092310924wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');1092510926//------------------------------------------------------------109271092810929defsEnter.append('clipPath')10930.attr('id', 'nv-edge-clip-' + id)10931.append('rect');1093210933wrap.select('#nv-edge-clip-' + id + ' rect')10934.attr('width', availableWidth)10935.attr('height', availableHeight);1093610937g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');109381093910940function updateInteractiveLayer() {1094110942if (!interactive) return false;1094310944var eventElements;1094510946var vertices = d3.merge(data.map(function(group, groupIndex) {10947return group.values10948.map(function(point, pointIndex) {10949// *Adding noise to make duplicates very unlikely10950// *Injecting series and point index for reference10951/* *Adding a 'jitter' to the points, because there's an issue in d3.geom.voronoi.10952*/10953var pX = getX(point,pointIndex);10954var pY = getY(point,pointIndex);1095510956return [x(pX)+ Math.random() * 1e-7,10957y(pY)+ Math.random() * 1e-7,10958groupIndex,10959pointIndex, point]; //temp hack to add noise untill I think of a better way so there are no duplicates10960})10961.filter(function(pointArray, pointIndex) {10962return pointActive(pointArray[4], pointIndex); // Issue #237.. move filter to after map, so pointIndex is correct!10963})10964})10965);10966109671096810969//inject series and point index for reference into voronoi10970if (useVoronoi === true) {1097110972if (clipVoronoi) {10973var pointClipsEnter = wrap.select('defs').selectAll('.nv-point-clips')10974.data([id])10975.enter();1097610977pointClipsEnter.append('clipPath')10978.attr('class', 'nv-point-clips')10979.attr('id', 'nv-points-clip-' + id);1098010981var pointClips = wrap.select('#nv-points-clip-' + id).selectAll('circle')10982.data(vertices);10983pointClips.enter().append('circle')10984.attr('r', clipRadius);10985pointClips.exit().remove();10986pointClips10987.attr('cx', function(d) { return d[0] })10988.attr('cy', function(d) { return d[1] });1098910990wrap.select('.nv-point-paths')10991.attr('clip-path', 'url(#nv-points-clip-' + id + ')');10992}109931099410995if(vertices.length) {10996// Issue #283 - Adding 2 dummy points to the voronoi b/c voronoi requires min 3 points to work10997vertices.push([x.range()[0] - 20, y.range()[0] - 20, null, null]);10998vertices.push([x.range()[1] + 20, y.range()[1] + 20, null, null]);10999vertices.push([x.range()[0] - 20, y.range()[0] + 20, null, null]);11000vertices.push([x.range()[1] + 20, y.range()[1] - 20, null, null]);11001}1100211003var bounds = d3.geom.polygon([11004[-10,-10],11005[-10,height + 10],11006[width + 10,height + 10],11007[width + 10,-10]11008]);1100911010var voronoi = d3.geom.voronoi(vertices).map(function(d, i) {11011return {11012'data': bounds.clip(d),11013'series': vertices[i][2],11014'point': vertices[i][3]11015}11016});110171101811019var pointPaths = wrap.select('.nv-point-paths').selectAll('path')11020.data(voronoi);11021pointPaths.enter().append('path')11022.attr('class', function(d,i) { return 'nv-path-'+i; });11023pointPaths.exit().remove();11024pointPaths11025.attr('d', function(d) {11026if (d.data.length === 0)11027return 'M 0 0'11028else11029return 'M' + d.data.join('L') + 'Z';11030});1103111032var mouseEventCallback = function(d,mDispatch) {11033if (needsUpdate) return 0;11034var series = data[d.series];11035if (typeof series === 'undefined') return;1103611037var point = series.values[d.point];1103811039mDispatch({11040point: point,11041series: series,11042pos: [x(getX(point, d.point)) + margin.left, y(getY(point, d.point)) + margin.top],11043seriesIndex: d.series,11044pointIndex: d.point11045});11046};1104711048pointPaths11049.on('click', function(d) {11050mouseEventCallback(d, dispatch.elementClick);11051})11052.on('mouseover', function(d) {11053mouseEventCallback(d, dispatch.elementMouseover);11054})11055.on('mouseout', function(d, i) {11056mouseEventCallback(d, dispatch.elementMouseout);11057});110581105911060} else {11061/*11062// bring data in form needed for click handlers11063var dataWithPoints = vertices.map(function(d, i) {11064return {11065'data': d,11066'series': vertices[i][2],11067'point': vertices[i][3]11068}11069});11070*/1107111072// add event handlers to points instead voronoi paths11073wrap.select('.nv-groups').selectAll('.nv-group')11074.selectAll('.nv-point')11075//.data(dataWithPoints)11076//.style('pointer-events', 'auto') // recativate events, disabled by css11077.on('click', function(d,i) {11078//nv.log('test', d, i);11079if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point11080var series = data[d.series],11081point = series.values[i];1108211083dispatch.elementClick({11084point: point,11085series: series,11086pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],11087seriesIndex: d.series,11088pointIndex: i11089});11090})11091.on('mouseover', function(d,i) {11092if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point11093var series = data[d.series],11094point = series.values[i];1109511096dispatch.elementMouseover({11097point: point,11098series: series,11099pos: [x(getX(point, i)) + margin.left, y(getY(point, i)) + margin.top],11100seriesIndex: d.series,11101pointIndex: i11102});11103})11104.on('mouseout', function(d,i) {11105if (needsUpdate || !data[d.series]) return 0; //check if this is a dummy point11106var series = data[d.series],11107point = series.values[i];1110811109dispatch.elementMouseout({11110point: point,11111series: series,11112seriesIndex: d.series,11113pointIndex: i11114});11115});11116}1111711118needsUpdate = false;11119}1112011121needsUpdate = true;1112211123var groups = wrap.select('.nv-groups').selectAll('.nv-group')11124.data(function(d) { return d }, function(d) { return d.key });11125groups.enter().append('g')11126.style('stroke-opacity', 1e-6)11127.style('fill-opacity', 1e-6);11128groups.exit()11129.remove();11130groups11131.attr('class', function(d,i) { return 'nv-group nv-series-' + i })11132.classed('hover', function(d) { return d.hover });11133groups11134.transition()11135.style('fill', function(d,i) { return color(d, i) })11136.style('stroke', function(d,i) { return color(d, i) })11137.style('stroke-opacity', 1)11138.style('fill-opacity', .5);111391114011141if (onlyCircles) {1114211143var points = groups.selectAll('circle.nv-point')11144.data(function(d) { return d.values }, pointKey);11145points.enter().append('circle')11146.style('fill', function (d,i) { return d.color })11147.style('stroke', function (d,i) { return d.color })11148.attr('cx', function(d,i) { return nv.utils.NaNtoZero(x0(getX(d,i))) })11149.attr('cy', function(d,i) { return nv.utils.NaNtoZero(y0(getY(d,i))) })11150.attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });11151points.exit().remove();11152groups.exit().selectAll('path.nv-point').transition()11153.attr('cx', function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })11154.attr('cy', function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })11155.remove();11156points.each(function(d,i) {11157d3.select(this)11158.classed('nv-point', true)11159.classed('nv-point-' + i, true)11160.classed('hover',false)11161;11162});11163points.transition()11164.attr('cx', function(d,i) { return nv.utils.NaNtoZero(x(getX(d,i))) })11165.attr('cy', function(d,i) { return nv.utils.NaNtoZero(y(getY(d,i))) })11166.attr('r', function(d,i) { return Math.sqrt(z(getSize(d,i))/Math.PI) });1116711168} else {1116911170var points = groups.selectAll('path.nv-point')11171.data(function(d) { return d.values });11172points.enter().append('path')11173.style('fill', function (d,i) { return d.color })11174.style('stroke', function (d,i) { return d.color })11175.attr('transform', function(d,i) {11176return 'translate(' + x0(getX(d,i)) + ',' + y0(getY(d,i)) + ')'11177})11178.attr('d',11179d3.svg.symbol()11180.type(getShape)11181.size(function(d,i) { return z(getSize(d,i)) })11182);11183points.exit().remove();11184groups.exit().selectAll('path.nv-point')11185.transition()11186.attr('transform', function(d,i) {11187return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'11188})11189.remove();11190points.each(function(d,i) {11191d3.select(this)11192.classed('nv-point', true)11193.classed('nv-point-' + i, true)11194.classed('hover',false)11195;11196});11197points.transition()11198.attr('transform', function(d,i) {11199//nv.log(d,i,getX(d,i), x(getX(d,i)));11200return 'translate(' + x(getX(d,i)) + ',' + y(getY(d,i)) + ')'11201})11202.attr('d',11203d3.svg.symbol()11204.type(getShape)11205.size(function(d,i) { return z(getSize(d,i)) })11206);11207}112081120911210// Delay updating the invisible interactive layer for smoother animation11211clearTimeout(timeoutID); // stop repeat calls to updateInteractiveLayer11212timeoutID = setTimeout(updateInteractiveLayer, 300);11213//updateInteractiveLayer();1121411215//store old scales for use in transitions on update11216x0 = x.copy();11217y0 = y.copy();11218z0 = z.copy();1121911220});1122111222return chart;11223}112241122511226//============================================================11227// Event Handling/Dispatching (out of chart's scope)11228//------------------------------------------------------------11229chart.clearHighlights = function() {11230//Remove the 'hover' class from all highlighted points.11231d3.selectAll(".nv-chart-" + id + " .nv-point.hover").classed("hover",false);11232};1123311234chart.highlightPoint = function(seriesIndex,pointIndex,isHoverOver) {11235d3.select(".nv-chart-" + id + " .nv-series-" + seriesIndex + " .nv-point-" + pointIndex)11236.classed("hover",isHoverOver);11237};112381123911240dispatch.on('elementMouseover.point', function(d) {11241if (interactive) chart.highlightPoint(d.seriesIndex,d.pointIndex,true);11242});1124311244dispatch.on('elementMouseout.point', function(d) {11245if (interactive) chart.highlightPoint(d.seriesIndex,d.pointIndex,false);11246});1124711248//============================================================112491125011251//============================================================11252// Expose Public Variables11253//------------------------------------------------------------1125411255chart.dispatch = dispatch;11256chart.options = nv.utils.optionsFunc.bind(chart);1125711258chart.x = function(_) {11259if (!arguments.length) return getX;11260getX = d3.functor(_);11261return chart;11262};1126311264chart.y = function(_) {11265if (!arguments.length) return getY;11266getY = d3.functor(_);11267return chart;11268};1126911270chart.size = function(_) {11271if (!arguments.length) return getSize;11272getSize = d3.functor(_);11273return chart;11274};1127511276chart.margin = function(_) {11277if (!arguments.length) return margin;11278margin.top = typeof _.top != 'undefined' ? _.top : margin.top;11279margin.right = typeof _.right != 'undefined' ? _.right : margin.right;11280margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;11281margin.left = typeof _.left != 'undefined' ? _.left : margin.left;11282return chart;11283};1128411285chart.width = function(_) {11286if (!arguments.length) return width;11287width = _;11288return chart;11289};1129011291chart.height = function(_) {11292if (!arguments.length) return height;11293height = _;11294return chart;11295};1129611297chart.xScale = function(_) {11298if (!arguments.length) return x;11299x = _;11300return chart;11301};1130211303chart.yScale = function(_) {11304if (!arguments.length) return y;11305y = _;11306return chart;11307};1130811309chart.zScale = function(_) {11310if (!arguments.length) return z;11311z = _;11312return chart;11313};1131411315chart.xDomain = function(_) {11316if (!arguments.length) return xDomain;11317xDomain = _;11318return chart;11319};1132011321chart.yDomain = function(_) {11322if (!arguments.length) return yDomain;11323yDomain = _;11324return chart;11325};1132611327chart.sizeDomain = function(_) {11328if (!arguments.length) return sizeDomain;11329sizeDomain = _;11330return chart;11331};1133211333chart.xRange = function(_) {11334if (!arguments.length) return xRange;11335xRange = _;11336return chart;11337};1133811339chart.yRange = function(_) {11340if (!arguments.length) return yRange;11341yRange = _;11342return chart;11343};1134411345chart.sizeRange = function(_) {11346if (!arguments.length) return sizeRange;11347sizeRange = _;11348return chart;11349};1135011351chart.forceX = function(_) {11352if (!arguments.length) return forceX;11353forceX = _;11354return chart;11355};1135611357chart.forceY = function(_) {11358if (!arguments.length) return forceY;11359forceY = _;11360return chart;11361};1136211363chart.forceSize = function(_) {11364if (!arguments.length) return forceSize;11365forceSize = _;11366return chart;11367};1136811369chart.interactive = function(_) {11370if (!arguments.length) return interactive;11371interactive = _;11372return chart;11373};1137411375chart.pointKey = function(_) {11376if (!arguments.length) return pointKey;11377pointKey = _;11378return chart;11379};1138011381chart.pointActive = function(_) {11382if (!arguments.length) return pointActive;11383pointActive = _;11384return chart;11385};1138611387chart.padData = function(_) {11388if (!arguments.length) return padData;11389padData = _;11390return chart;11391};1139211393chart.padDataOuter = function(_) {11394if (!arguments.length) return padDataOuter;11395padDataOuter = _;11396return chart;11397};1139811399chart.clipEdge = function(_) {11400if (!arguments.length) return clipEdge;11401clipEdge = _;11402return chart;11403};1140411405chart.clipVoronoi= function(_) {11406if (!arguments.length) return clipVoronoi;11407clipVoronoi = _;11408return chart;11409};1141011411chart.useVoronoi= function(_) {11412if (!arguments.length) return useVoronoi;11413useVoronoi = _;11414if (useVoronoi === false) {11415clipVoronoi = false;11416}11417return chart;11418};1141911420chart.clipRadius = function(_) {11421if (!arguments.length) return clipRadius;11422clipRadius = _;11423return chart;11424};1142511426chart.color = function(_) {11427if (!arguments.length) return color;11428color = nv.utils.getColor(_);11429return chart;11430};1143111432chart.shape = function(_) {11433if (!arguments.length) return getShape;11434getShape = _;11435return chart;11436};1143711438chart.onlyCircles = function(_) {11439if (!arguments.length) return onlyCircles;11440onlyCircles = _;11441return chart;11442};1144311444chart.id = function(_) {11445if (!arguments.length) return id;11446id = _;11447return chart;11448};1144911450chart.singlePoint = function(_) {11451if (!arguments.length) return singlePoint;11452singlePoint = _;11453return chart;11454};1145511456//============================================================114571145811459return chart;11460}11461nv.models.scatterChart = function() {11462"use strict";11463//============================================================11464// Public Variables with Default Settings11465//------------------------------------------------------------1146611467var scatter = nv.models.scatter()11468, xAxis = nv.models.axis()11469, yAxis = nv.models.axis()11470, legend = nv.models.legend()11471, controls = nv.models.legend()11472, distX = nv.models.distribution()11473, distY = nv.models.distribution()11474;1147511476var margin = {top: 30, right: 20, bottom: 50, left: 75}11477, width = null11478, height = null11479, color = nv.utils.defaultColor()11480, x = d3.fisheye ? d3.fisheye.scale(d3.scale.linear).distortion(0) : scatter.xScale()11481, y = d3.fisheye ? d3.fisheye.scale(d3.scale.linear).distortion(0) : scatter.yScale()11482, xPadding = 011483, yPadding = 011484, showDistX = false11485, showDistY = false11486, showLegend = true11487, showXAxis = true11488, showYAxis = true11489, rightAlignYAxis = false11490, showControls = !!d3.fisheye11491, fisheye = 011492, pauseFisheye = false11493, tooltips = true11494, tooltipX = function(key, x, y) { return '<strong>' + x + '</strong>' }11495, tooltipY = function(key, x, y) { return '<strong>' + y + '</strong>' }11496, tooltip = null11497, state = {}11498, defaultState = null11499, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')11500, noData = "No Data Available."11501, transitionDuration = 25011502;1150311504scatter11505.xScale(x)11506.yScale(y)11507;11508xAxis11509.orient('bottom')11510.tickPadding(10)11511;11512yAxis11513.orient((rightAlignYAxis) ? 'right' : 'left')11514.tickPadding(10)11515;11516distX11517.axis('x')11518;11519distY11520.axis('y')11521;1152211523controls.updateState(false);1152411525//============================================================115261152711528//============================================================11529// Private Variables11530//------------------------------------------------------------1153111532var x0, y0;1153311534var showTooltip = function(e, offsetElement) {11535//TODO: make tooltip style an option between single or dual on axes (maybe on all charts with axes?)1153611537var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),11538top = e.pos[1] + ( offsetElement.offsetTop || 0),11539leftX = e.pos[0] + ( offsetElement.offsetLeft || 0 ),11540topX = y.range()[0] + margin.top + ( offsetElement.offsetTop || 0),11541leftY = x.range()[0] + margin.left + ( offsetElement.offsetLeft || 0 ),11542topY = e.pos[1] + ( offsetElement.offsetTop || 0),11543xVal = xAxis.tickFormat()(scatter.x()(e.point, e.pointIndex)),11544yVal = yAxis.tickFormat()(scatter.y()(e.point, e.pointIndex));1154511546if( tooltipX != null )11547nv.tooltip.show([leftX, topX], tooltipX(e.series.key, xVal, yVal, e, chart), 'n', 1, offsetElement, 'x-nvtooltip');11548if( tooltipY != null )11549nv.tooltip.show([leftY, topY], tooltipY(e.series.key, xVal, yVal, e, chart), 'e', 1, offsetElement, 'y-nvtooltip');11550if( tooltip != null )11551nv.tooltip.show([left, top], tooltip(e.series.key, xVal, yVal, e, chart), e.value < 0 ? 'n' : 's', null, offsetElement);11552};1155311554var controlsData = [11555{ key: 'Magnify', disabled: true }11556];1155711558//============================================================115591156011561function chart(selection) {11562selection.each(function(data) {11563var container = d3.select(this),11564that = this;1156511566var availableWidth = (width || parseInt(container.style('width')) || 960)11567- margin.left - margin.right,11568availableHeight = (height || parseInt(container.style('height')) || 400)11569- margin.top - margin.bottom;1157011571chart.update = function() { container.transition().duration(transitionDuration).call(chart); };11572chart.container = this;1157311574//set state.disabled11575state.disabled = data.map(function(d) { return !!d.disabled });1157611577if (!defaultState) {11578var key;11579defaultState = {};11580for (key in state) {11581if (state[key] instanceof Array)11582defaultState[key] = state[key].slice(0);11583else11584defaultState[key] = state[key];11585}11586}1158711588//------------------------------------------------------------11589// Display noData message if there's nothing to show.1159011591if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {11592var noDataText = container.selectAll('.nv-noData').data([noData]);1159311594noDataText.enter().append('text')11595.attr('class', 'nvd3 nv-noData')11596.attr('dy', '-.7em')11597.style('text-anchor', 'middle');1159811599noDataText11600.attr('x', margin.left + availableWidth / 2)11601.attr('y', margin.top + availableHeight / 2)11602.text(function(d) { return d });1160311604return chart;11605} else {11606container.selectAll('.nv-noData').remove();11607}1160811609//------------------------------------------------------------116101161111612//------------------------------------------------------------11613// Setup Scales1161411615x0 = x0 || x;11616y0 = y0 || y;1161711618//------------------------------------------------------------116191162011621//------------------------------------------------------------11622// Setup containers and skeleton of chart1162311624var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]);11625var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id());11626var gEnter = wrapEnter.append('g');11627var g = wrap.select('g');1162811629// background for pointer events11630gEnter.append('rect').attr('class', 'nvd3 nv-background');1163111632gEnter.append('g').attr('class', 'nv-x nv-axis');11633gEnter.append('g').attr('class', 'nv-y nv-axis');11634gEnter.append('g').attr('class', 'nv-scatterWrap');11635gEnter.append('g').attr('class', 'nv-distWrap');11636gEnter.append('g').attr('class', 'nv-legendWrap');11637gEnter.append('g').attr('class', 'nv-controlsWrap');1163811639//------------------------------------------------------------116401164111642//------------------------------------------------------------11643// Legend1164411645if (showLegend) {11646var legendWidth = (showControls) ? availableWidth / 2 : availableWidth;11647legend.width(legendWidth);1164811649wrap.select('.nv-legendWrap')11650.datum(data)11651.call(legend);1165211653if ( margin.top != legend.height()) {11654margin.top = legend.height();11655availableHeight = (height || parseInt(container.style('height')) || 400)11656- margin.top - margin.bottom;11657}1165811659wrap.select('.nv-legendWrap')11660.attr('transform', 'translate(' + (availableWidth - legendWidth) + ',' + (-margin.top) +')');11661}1166211663//------------------------------------------------------------116641166511666//------------------------------------------------------------11667// Controls1166811669if (showControls) {11670controls.width(180).color(['#444']);11671g.select('.nv-controlsWrap')11672.datum(controlsData)11673.attr('transform', 'translate(0,' + (-margin.top) +')')11674.call(controls);11675}1167611677//------------------------------------------------------------116781167911680wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');1168111682if (rightAlignYAxis) {11683g.select(".nv-y.nv-axis")11684.attr("transform", "translate(" + availableWidth + ",0)");11685}1168611687//------------------------------------------------------------11688// Main Chart Component(s)1168911690scatter11691.width(availableWidth)11692.height(availableHeight)11693.color(data.map(function(d,i) {11694return d.color || color(d, i);11695}).filter(function(d,i) { return !data[i].disabled }));1169611697if (xPadding !== 0)11698scatter.xDomain(null);1169911700if (yPadding !== 0)11701scatter.yDomain(null);1170211703wrap.select('.nv-scatterWrap')11704.datum(data.filter(function(d) { return !d.disabled }))11705.call(scatter);1170611707//Adjust for x and y padding11708if (xPadding !== 0) {11709var xRange = x.domain()[1] - x.domain()[0];11710scatter.xDomain([x.domain()[0] - (xPadding * xRange), x.domain()[1] + (xPadding * xRange)]);11711}1171211713if (yPadding !== 0) {11714var yRange = y.domain()[1] - y.domain()[0];11715scatter.yDomain([y.domain()[0] - (yPadding * yRange), y.domain()[1] + (yPadding * yRange)]);11716}1171711718//Only need to update the scatter again if x/yPadding changed the domain.11719if (yPadding !== 0 || xPadding !== 0) {11720wrap.select('.nv-scatterWrap')11721.datum(data.filter(function(d) { return !d.disabled }))11722.call(scatter);11723}1172411725//------------------------------------------------------------117261172711728//------------------------------------------------------------11729// Setup Axes11730if (showXAxis) {11731xAxis11732.scale(x)11733.ticks( xAxis.ticks() && xAxis.ticks().length ? xAxis.ticks() : availableWidth / 100 )11734.tickSize( -availableHeight , 0);1173511736g.select('.nv-x.nv-axis')11737.attr('transform', 'translate(0,' + y.range()[0] + ')')11738.call(xAxis);1173911740}1174111742if (showYAxis) {11743yAxis11744.scale(y)11745.ticks( yAxis.ticks() && yAxis.ticks().length ? yAxis.ticks() : availableHeight / 36 )11746.tickSize( -availableWidth, 0);1174711748g.select('.nv-y.nv-axis')11749.call(yAxis);11750}117511175211753if (showDistX) {11754distX11755.getData(scatter.x())11756.scale(x)11757.width(availableWidth)11758.color(data.map(function(d,i) {11759return d.color || color(d, i);11760}).filter(function(d,i) { return !data[i].disabled }));11761gEnter.select('.nv-distWrap').append('g')11762.attr('class', 'nv-distributionX');11763g.select('.nv-distributionX')11764.attr('transform', 'translate(0,' + y.range()[0] + ')')11765.datum(data.filter(function(d) { return !d.disabled }))11766.call(distX);11767}1176811769if (showDistY) {11770distY11771.getData(scatter.y())11772.scale(y)11773.width(availableHeight)11774.color(data.map(function(d,i) {11775return d.color || color(d, i);11776}).filter(function(d,i) { return !data[i].disabled }));11777gEnter.select('.nv-distWrap').append('g')11778.attr('class', 'nv-distributionY');11779g.select('.nv-distributionY')11780.attr('transform',11781'translate(' + (rightAlignYAxis ? availableWidth : -distY.size() ) + ',0)')11782.datum(data.filter(function(d) { return !d.disabled }))11783.call(distY);11784}1178511786//------------------------------------------------------------1178711788117891179011791if (d3.fisheye) {11792g.select('.nv-background')11793.attr('width', availableWidth)11794.attr('height', availableHeight);1179511796g.select('.nv-background').on('mousemove', updateFisheye);11797g.select('.nv-background').on('click', function() { pauseFisheye = !pauseFisheye;});11798scatter.dispatch.on('elementClick.freezeFisheye', function() {11799pauseFisheye = !pauseFisheye;11800});11801}118021180311804function updateFisheye() {11805if (pauseFisheye) {11806g.select('.nv-point-paths').style('pointer-events', 'all');11807return false;11808}1180911810g.select('.nv-point-paths').style('pointer-events', 'none' );1181111812var mouse = d3.mouse(this);11813x.distortion(fisheye).focus(mouse[0]);11814y.distortion(fisheye).focus(mouse[1]);1181511816g.select('.nv-scatterWrap')11817.call(scatter);1181811819if (showXAxis)11820g.select('.nv-x.nv-axis').call(xAxis);1182111822if (showYAxis)11823g.select('.nv-y.nv-axis').call(yAxis);1182411825g.select('.nv-distributionX')11826.datum(data.filter(function(d) { return !d.disabled }))11827.call(distX);11828g.select('.nv-distributionY')11829.datum(data.filter(function(d) { return !d.disabled }))11830.call(distY);11831}11832118331183411835//============================================================11836// Event Handling/Dispatching (in chart's scope)11837//------------------------------------------------------------1183811839controls.dispatch.on('legendClick', function(d,i) {11840d.disabled = !d.disabled;1184111842fisheye = d.disabled ? 0 : 2.5;11843g.select('.nv-background') .style('pointer-events', d.disabled ? 'none' : 'all');11844g.select('.nv-point-paths').style('pointer-events', d.disabled ? 'all' : 'none' );1184511846if (d.disabled) {11847x.distortion(fisheye).focus(0);11848y.distortion(fisheye).focus(0);1184911850g.select('.nv-scatterWrap').call(scatter);11851g.select('.nv-x.nv-axis').call(xAxis);11852g.select('.nv-y.nv-axis').call(yAxis);11853} else {11854pauseFisheye = false;11855}1185611857chart.update();11858});1185911860legend.dispatch.on('stateChange', function(newState) {11861state.disabled = newState.disabled;11862dispatch.stateChange(state);11863chart.update();11864});1186511866scatter.dispatch.on('elementMouseover.tooltip', function(e) {11867d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-distx-' + e.pointIndex)11868.attr('y1', function(d,i) { return e.pos[1] - availableHeight;});11869d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-disty-' + e.pointIndex)11870.attr('x2', e.pos[0] + distX.size());1187111872e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];11873dispatch.tooltipShow(e);11874});1187511876dispatch.on('tooltipShow', function(e) {11877if (tooltips) showTooltip(e, that.parentNode);11878});1187911880// Update chart from a state object passed to event handler11881dispatch.on('changeState', function(e) {1188211883if (typeof e.disabled !== 'undefined') {11884data.forEach(function(series,i) {11885series.disabled = e.disabled[i];11886});1188711888state.disabled = e.disabled;11889}1189011891chart.update();11892});1189311894//============================================================118951189611897//store old scales for use in transitions on update11898x0 = x.copy();11899y0 = y.copy();119001190111902});1190311904return chart;11905}119061190711908//============================================================11909// Event Handling/Dispatching (out of chart's scope)11910//------------------------------------------------------------1191111912scatter.dispatch.on('elementMouseout.tooltip', function(e) {11913dispatch.tooltipHide(e);1191411915d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-distx-' + e.pointIndex)11916.attr('y1', 0);11917d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-disty-' + e.pointIndex)11918.attr('x2', distY.size());11919});11920dispatch.on('tooltipHide', function() {11921if (tooltips) nv.tooltip.cleanup();11922});1192311924//============================================================119251192611927//============================================================11928// Expose Public Variables11929//------------------------------------------------------------1193011931// expose chart's sub-components11932chart.dispatch = dispatch;11933chart.scatter = scatter;11934chart.legend = legend;11935chart.controls = controls;11936chart.xAxis = xAxis;11937chart.yAxis = yAxis;11938chart.distX = distX;11939chart.distY = distY;1194011941d3.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');11942chart.options = nv.utils.optionsFunc.bind(chart);1194311944chart.margin = function(_) {11945if (!arguments.length) return margin;11946margin.top = typeof _.top != 'undefined' ? _.top : margin.top;11947margin.right = typeof _.right != 'undefined' ? _.right : margin.right;11948margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;11949margin.left = typeof _.left != 'undefined' ? _.left : margin.left;11950return chart;11951};1195211953chart.width = function(_) {11954if (!arguments.length) return width;11955width = _;11956return chart;11957};1195811959chart.height = function(_) {11960if (!arguments.length) return height;11961height = _;11962return chart;11963};1196411965chart.color = function(_) {11966if (!arguments.length) return color;11967color = nv.utils.getColor(_);11968legend.color(color);11969distX.color(color);11970distY.color(color);11971return chart;11972};1197311974chart.showDistX = function(_) {11975if (!arguments.length) return showDistX;11976showDistX = _;11977return chart;11978};1197911980chart.showDistY = function(_) {11981if (!arguments.length) return showDistY;11982showDistY = _;11983return chart;11984};1198511986chart.showControls = function(_) {11987if (!arguments.length) return showControls;11988showControls = _;11989return chart;11990};1199111992chart.showLegend = function(_) {11993if (!arguments.length) return showLegend;11994showLegend = _;11995return chart;11996};1199711998chart.showXAxis = function(_) {11999if (!arguments.length) return showXAxis;12000showXAxis = _;12001return chart;12002};1200312004chart.showYAxis = function(_) {12005if (!arguments.length) return showYAxis;12006showYAxis = _;12007return chart;12008};1200912010chart.rightAlignYAxis = function(_) {12011if(!arguments.length) return rightAlignYAxis;12012rightAlignYAxis = _;12013yAxis.orient( (_) ? 'right' : 'left');12014return chart;12015};120161201712018chart.fisheye = function(_) {12019if (!arguments.length) return fisheye;12020fisheye = _;12021return chart;12022};1202312024chart.xPadding = function(_) {12025if (!arguments.length) return xPadding;12026xPadding = _;12027return chart;12028};1202912030chart.yPadding = function(_) {12031if (!arguments.length) return yPadding;12032yPadding = _;12033return chart;12034};1203512036chart.tooltips = function(_) {12037if (!arguments.length) return tooltips;12038tooltips = _;12039return chart;12040};1204112042chart.tooltipContent = function(_) {12043if (!arguments.length) return tooltip;12044tooltip = _;12045return chart;12046};1204712048chart.tooltipXContent = function(_) {12049if (!arguments.length) return tooltipX;12050tooltipX = _;12051return chart;12052};1205312054chart.tooltipYContent = function(_) {12055if (!arguments.length) return tooltipY;12056tooltipY = _;12057return chart;12058};1205912060chart.state = function(_) {12061if (!arguments.length) return state;12062state = _;12063return chart;12064};1206512066chart.defaultState = function(_) {12067if (!arguments.length) return defaultState;12068defaultState = _;12069return chart;12070};1207112072chart.noData = function(_) {12073if (!arguments.length) return noData;12074noData = _;12075return chart;12076};1207712078chart.transitionDuration = function(_) {12079if (!arguments.length) return transitionDuration;12080transitionDuration = _;12081return chart;12082};1208312084//============================================================120851208612087return chart;12088}1208912090nv.models.scatterPlusLineChart = function() {12091"use strict";12092//============================================================12093// Public Variables with Default Settings12094//------------------------------------------------------------1209512096var scatter = nv.models.scatter()12097, xAxis = nv.models.axis()12098, yAxis = nv.models.axis()12099, legend = nv.models.legend()12100, controls = nv.models.legend()12101, distX = nv.models.distribution()12102, distY = nv.models.distribution()12103;1210412105var margin = {top: 30, right: 20, bottom: 50, left: 75}12106, width = null12107, height = null12108, color = nv.utils.defaultColor()12109, x = d3.fisheye ? d3.fisheye.scale(d3.scale.linear).distortion(0) : scatter.xScale()12110, y = d3.fisheye ? d3.fisheye.scale(d3.scale.linear).distortion(0) : scatter.yScale()12111, showDistX = false12112, showDistY = false12113, showLegend = true12114, showXAxis = true12115, showYAxis = true12116, rightAlignYAxis = false12117, showControls = !!d3.fisheye12118, fisheye = 012119, pauseFisheye = false12120, tooltips = true12121, tooltipX = function(key, x, y) { return '<strong>' + x + '</strong>' }12122, tooltipY = function(key, x, y) { return '<strong>' + y + '</strong>' }12123, tooltip = function(key, x, y, date) { return '<h3>' + key + '</h3>'12124+ '<p>' + date + '</p>' }12125, state = {}12126, defaultState = null12127, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')12128, noData = "No Data Available."12129, transitionDuration = 25012130;1213112132scatter12133.xScale(x)12134.yScale(y)12135;12136xAxis12137.orient('bottom')12138.tickPadding(10)12139;12140yAxis12141.orient((rightAlignYAxis) ? 'right' : 'left')12142.tickPadding(10)12143;12144distX12145.axis('x')12146;12147distY12148.axis('y')12149;1215012151controls.updateState(false);12152//============================================================121531215412155//============================================================12156// Private Variables12157//------------------------------------------------------------1215812159var x0, y0;1216012161var showTooltip = function(e, offsetElement) {12162//TODO: make tooltip style an option between single or dual on axes (maybe on all charts with axes?)1216312164var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),12165top = e.pos[1] + ( offsetElement.offsetTop || 0),12166leftX = e.pos[0] + ( offsetElement.offsetLeft || 0 ),12167topX = y.range()[0] + margin.top + ( offsetElement.offsetTop || 0),12168leftY = x.range()[0] + margin.left + ( offsetElement.offsetLeft || 0 ),12169topY = e.pos[1] + ( offsetElement.offsetTop || 0),12170xVal = xAxis.tickFormat()(scatter.x()(e.point, e.pointIndex)),12171yVal = yAxis.tickFormat()(scatter.y()(e.point, e.pointIndex));1217212173if( tooltipX != null )12174nv.tooltip.show([leftX, topX], tooltipX(e.series.key, xVal, yVal, e, chart), 'n', 1, offsetElement, 'x-nvtooltip');12175if( tooltipY != null )12176nv.tooltip.show([leftY, topY], tooltipY(e.series.key, xVal, yVal, e, chart), 'e', 1, offsetElement, 'y-nvtooltip');12177if( tooltip != null )12178nv.tooltip.show([left, top], tooltip(e.series.key, xVal, yVal, e.point.tooltip, e, chart), e.value < 0 ? 'n' : 's', null, offsetElement);12179};1218012181var controlsData = [12182{ key: 'Magnify', disabled: true }12183];1218412185//============================================================121861218712188function chart(selection) {12189selection.each(function(data) {12190var container = d3.select(this),12191that = this;1219212193var availableWidth = (width || parseInt(container.style('width')) || 960)12194- margin.left - margin.right,12195availableHeight = (height || parseInt(container.style('height')) || 400)12196- margin.top - margin.bottom;1219712198chart.update = function() { container.transition().duration(transitionDuration).call(chart); };12199chart.container = this;1220012201//set state.disabled12202state.disabled = data.map(function(d) { return !!d.disabled });1220312204if (!defaultState) {12205var key;12206defaultState = {};12207for (key in state) {12208if (state[key] instanceof Array)12209defaultState[key] = state[key].slice(0);12210else12211defaultState[key] = state[key];12212}12213}1221412215//------------------------------------------------------------12216// Display noData message if there's nothing to show.1221712218if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {12219var noDataText = container.selectAll('.nv-noData').data([noData]);1222012221noDataText.enter().append('text')12222.attr('class', 'nvd3 nv-noData')12223.attr('dy', '-.7em')12224.style('text-anchor', 'middle');1222512226noDataText12227.attr('x', margin.left + availableWidth / 2)12228.attr('y', margin.top + availableHeight / 2)12229.text(function(d) { return d });1223012231return chart;12232} else {12233container.selectAll('.nv-noData').remove();12234}1223512236//------------------------------------------------------------122371223812239//------------------------------------------------------------12240// Setup Scales1224112242x = scatter.xScale();12243y = scatter.yScale();1224412245x0 = x0 || x;12246y0 = y0 || y;1224712248//------------------------------------------------------------122491225012251//------------------------------------------------------------12252// Setup containers and skeleton of chart1225312254var wrap = container.selectAll('g.nv-wrap.nv-scatterChart').data([data]);12255var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-scatterChart nv-chart-' + scatter.id());12256var gEnter = wrapEnter.append('g');12257var g = wrap.select('g')1225812259// background for pointer events12260gEnter.append('rect').attr('class', 'nvd3 nv-background').style("pointer-events","none");1226112262gEnter.append('g').attr('class', 'nv-x nv-axis');12263gEnter.append('g').attr('class', 'nv-y nv-axis');12264gEnter.append('g').attr('class', 'nv-scatterWrap');12265gEnter.append('g').attr('class', 'nv-regressionLinesWrap');12266gEnter.append('g').attr('class', 'nv-distWrap');12267gEnter.append('g').attr('class', 'nv-legendWrap');12268gEnter.append('g').attr('class', 'nv-controlsWrap');1226912270wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');1227112272if (rightAlignYAxis) {12273g.select(".nv-y.nv-axis")12274.attr("transform", "translate(" + availableWidth + ",0)");12275}1227612277//------------------------------------------------------------122781227912280//------------------------------------------------------------12281// Legend1228212283if (showLegend) {12284legend.width( availableWidth / 2 );1228512286wrap.select('.nv-legendWrap')12287.datum(data)12288.call(legend);1228912290if ( margin.top != legend.height()) {12291margin.top = legend.height();12292availableHeight = (height || parseInt(container.style('height')) || 400)12293- margin.top - margin.bottom;12294}1229512296wrap.select('.nv-legendWrap')12297.attr('transform', 'translate(' + (availableWidth / 2) + ',' + (-margin.top) +')');12298}1229912300//------------------------------------------------------------123011230212303//------------------------------------------------------------12304// Controls1230512306if (showControls) {12307controls.width(180).color(['#444']);12308g.select('.nv-controlsWrap')12309.datum(controlsData)12310.attr('transform', 'translate(0,' + (-margin.top) +')')12311.call(controls);12312}1231312314//------------------------------------------------------------123151231612317//------------------------------------------------------------12318// Main Chart Component(s)1231912320scatter12321.width(availableWidth)12322.height(availableHeight)12323.color(data.map(function(d,i) {12324return d.color || color(d, i);12325}).filter(function(d,i) { return !data[i].disabled }))1232612327wrap.select('.nv-scatterWrap')12328.datum(data.filter(function(d) { return !d.disabled }))12329.call(scatter);1233012331wrap.select('.nv-regressionLinesWrap')12332.attr('clip-path', 'url(#nv-edge-clip-' + scatter.id() + ')');1233312334var regWrap = wrap.select('.nv-regressionLinesWrap').selectAll('.nv-regLines')12335.data(function(d) {return d });1233612337regWrap.enter().append('g').attr('class', 'nv-regLines');1233812339var regLine = regWrap.selectAll('.nv-regLine').data(function(d){return [d]});12340var regLineEnter = regLine.enter()12341.append('line').attr('class', 'nv-regLine')12342.style('stroke-opacity', 0);1234312344regLine12345.transition()12346.attr('x1', x.range()[0])12347.attr('x2', x.range()[1])12348.attr('y1', function(d,i) {return y(x.domain()[0] * d.slope + d.intercept) })12349.attr('y2', function(d,i) { return y(x.domain()[1] * d.slope + d.intercept) })12350.style('stroke', function(d,i,j) { return color(d,j) })12351.style('stroke-opacity', function(d,i) {12352return (d.disabled || typeof d.slope === 'undefined' || typeof d.intercept === 'undefined') ? 0 : 112353});1235412355//------------------------------------------------------------123561235712358//------------------------------------------------------------12359// Setup Axes1236012361if (showXAxis) {12362xAxis12363.scale(x)12364.ticks( xAxis.ticks() ? xAxis.ticks() : availableWidth / 100 )12365.tickSize( -availableHeight , 0);1236612367g.select('.nv-x.nv-axis')12368.attr('transform', 'translate(0,' + y.range()[0] + ')')12369.call(xAxis);12370}1237112372if (showYAxis) {12373yAxis12374.scale(y)12375.ticks( yAxis.ticks() ? yAxis.ticks() : availableHeight / 36 )12376.tickSize( -availableWidth, 0);1237712378g.select('.nv-y.nv-axis')12379.call(yAxis);12380}123811238212383if (showDistX) {12384distX12385.getData(scatter.x())12386.scale(x)12387.width(availableWidth)12388.color(data.map(function(d,i) {12389return d.color || color(d, i);12390}).filter(function(d,i) { return !data[i].disabled }));12391gEnter.select('.nv-distWrap').append('g')12392.attr('class', 'nv-distributionX');12393g.select('.nv-distributionX')12394.attr('transform', 'translate(0,' + y.range()[0] + ')')12395.datum(data.filter(function(d) { return !d.disabled }))12396.call(distX);12397}1239812399if (showDistY) {12400distY12401.getData(scatter.y())12402.scale(y)12403.width(availableHeight)12404.color(data.map(function(d,i) {12405return d.color || color(d, i);12406}).filter(function(d,i) { return !data[i].disabled }));12407gEnter.select('.nv-distWrap').append('g')12408.attr('class', 'nv-distributionY');12409g.select('.nv-distributionY')12410.attr('transform', 'translate(' + (rightAlignYAxis ? availableWidth : -distY.size() ) + ',0)')12411.datum(data.filter(function(d) { return !d.disabled }))12412.call(distY);12413}1241412415//------------------------------------------------------------1241612417124181241912420if (d3.fisheye) {12421g.select('.nv-background')12422.attr('width', availableWidth)12423.attr('height', availableHeight)12424;1242512426g.select('.nv-background').on('mousemove', updateFisheye);12427g.select('.nv-background').on('click', function() { pauseFisheye = !pauseFisheye;});12428scatter.dispatch.on('elementClick.freezeFisheye', function() {12429pauseFisheye = !pauseFisheye;12430});12431}124321243312434function updateFisheye() {12435if (pauseFisheye) {12436g.select('.nv-point-paths').style('pointer-events', 'all');12437return false;12438}1243912440g.select('.nv-point-paths').style('pointer-events', 'none' );1244112442var mouse = d3.mouse(this);12443x.distortion(fisheye).focus(mouse[0]);12444y.distortion(fisheye).focus(mouse[1]);1244512446g.select('.nv-scatterWrap')12447.datum(data.filter(function(d) { return !d.disabled }))12448.call(scatter);1244912450if (showXAxis)12451g.select('.nv-x.nv-axis').call(xAxis);1245212453if (showYAxis)12454g.select('.nv-y.nv-axis').call(yAxis);1245512456g.select('.nv-distributionX')12457.datum(data.filter(function(d) { return !d.disabled }))12458.call(distX);12459g.select('.nv-distributionY')12460.datum(data.filter(function(d) { return !d.disabled }))12461.call(distY);12462}12463124641246512466//============================================================12467// Event Handling/Dispatching (in chart's scope)12468//------------------------------------------------------------1246912470controls.dispatch.on('legendClick', function(d,i) {12471d.disabled = !d.disabled;1247212473fisheye = d.disabled ? 0 : 2.5;12474g.select('.nv-background') .style('pointer-events', d.disabled ? 'none' : 'all');12475g.select('.nv-point-paths').style('pointer-events', d.disabled ? 'all' : 'none' );1247612477if (d.disabled) {12478x.distortion(fisheye).focus(0);12479y.distortion(fisheye).focus(0);1248012481g.select('.nv-scatterWrap').call(scatter);12482g.select('.nv-x.nv-axis').call(xAxis);12483g.select('.nv-y.nv-axis').call(yAxis);12484} else {12485pauseFisheye = false;12486}1248712488chart.update();12489});1249012491legend.dispatch.on('stateChange', function(newState) {12492state = newState;12493dispatch.stateChange(state);12494chart.update();12495});124961249712498scatter.dispatch.on('elementMouseover.tooltip', function(e) {12499d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-distx-' + e.pointIndex)12500.attr('y1', e.pos[1] - availableHeight);12501d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-disty-' + e.pointIndex)12502.attr('x2', e.pos[0] + distX.size());1250312504e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top];12505dispatch.tooltipShow(e);12506});1250712508dispatch.on('tooltipShow', function(e) {12509if (tooltips) showTooltip(e, that.parentNode);12510});1251112512// Update chart from a state object passed to event handler12513dispatch.on('changeState', function(e) {1251412515if (typeof e.disabled !== 'undefined') {12516data.forEach(function(series,i) {12517series.disabled = e.disabled[i];12518});1251912520state.disabled = e.disabled;12521}1252212523chart.update();12524});1252512526//============================================================125271252812529//store old scales for use in transitions on update12530x0 = x.copy();12531y0 = y.copy();125321253312534});1253512536return chart;12537}125381253912540//============================================================12541// Event Handling/Dispatching (out of chart's scope)12542//------------------------------------------------------------1254312544scatter.dispatch.on('elementMouseout.tooltip', function(e) {12545dispatch.tooltipHide(e);1254612547d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-distx-' + e.pointIndex)12548.attr('y1', 0);12549d3.select('.nv-chart-' + scatter.id() + ' .nv-series-' + e.seriesIndex + ' .nv-disty-' + e.pointIndex)12550.attr('x2', distY.size());12551});12552dispatch.on('tooltipHide', function() {12553if (tooltips) nv.tooltip.cleanup();12554});1255512556//============================================================125571255812559//============================================================12560// Expose Public Variables12561//------------------------------------------------------------1256212563// expose chart's sub-components12564chart.dispatch = dispatch;12565chart.scatter = scatter;12566chart.legend = legend;12567chart.controls = controls;12568chart.xAxis = xAxis;12569chart.yAxis = yAxis;12570chart.distX = distX;12571chart.distY = distY;1257212573d3.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');1257412575chart.options = nv.utils.optionsFunc.bind(chart);1257612577chart.margin = function(_) {12578if (!arguments.length) return margin;12579margin.top = typeof _.top != 'undefined' ? _.top : margin.top;12580margin.right = typeof _.right != 'undefined' ? _.right : margin.right;12581margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;12582margin.left = typeof _.left != 'undefined' ? _.left : margin.left;12583return chart;12584};1258512586chart.width = function(_) {12587if (!arguments.length) return width;12588width = _;12589return chart;12590};1259112592chart.height = function(_) {12593if (!arguments.length) return height;12594height = _;12595return chart;12596};1259712598chart.color = function(_) {12599if (!arguments.length) return color;12600color = nv.utils.getColor(_);12601legend.color(color);12602distX.color(color);12603distY.color(color);12604return chart;12605};1260612607chart.showDistX = function(_) {12608if (!arguments.length) return showDistX;12609showDistX = _;12610return chart;12611};1261212613chart.showDistY = function(_) {12614if (!arguments.length) return showDistY;12615showDistY = _;12616return chart;12617};1261812619chart.showControls = function(_) {12620if (!arguments.length) return showControls;12621showControls = _;12622return chart;12623};1262412625chart.showLegend = function(_) {12626if (!arguments.length) return showLegend;12627showLegend = _;12628return chart;12629};1263012631chart.showXAxis = function(_) {12632if (!arguments.length) return showXAxis;12633showXAxis = _;12634return chart;12635};1263612637chart.showYAxis = function(_) {12638if (!arguments.length) return showYAxis;12639showYAxis = _;12640return chart;12641};1264212643chart.rightAlignYAxis = function(_) {12644if(!arguments.length) return rightAlignYAxis;12645rightAlignYAxis = _;12646yAxis.orient( (_) ? 'right' : 'left');12647return chart;12648};1264912650chart.fisheye = function(_) {12651if (!arguments.length) return fisheye;12652fisheye = _;12653return chart;12654};1265512656chart.tooltips = function(_) {12657if (!arguments.length) return tooltips;12658tooltips = _;12659return chart;12660};1266112662chart.tooltipContent = function(_) {12663if (!arguments.length) return tooltip;12664tooltip = _;12665return chart;12666};1266712668chart.tooltipXContent = function(_) {12669if (!arguments.length) return tooltipX;12670tooltipX = _;12671return chart;12672};1267312674chart.tooltipYContent = function(_) {12675if (!arguments.length) return tooltipY;12676tooltipY = _;12677return chart;12678};1267912680chart.state = function(_) {12681if (!arguments.length) return state;12682state = _;12683return chart;12684};1268512686chart.defaultState = function(_) {12687if (!arguments.length) return defaultState;12688defaultState = _;12689return chart;12690};1269112692chart.noData = function(_) {12693if (!arguments.length) return noData;12694noData = _;12695return chart;12696};1269712698chart.transitionDuration = function(_) {12699if (!arguments.length) return transitionDuration;12700transitionDuration = _;12701return chart;12702};1270312704//============================================================127051270612707return chart;12708}1270912710nv.models.sparkline = function() {12711"use strict";12712//============================================================12713// Public Variables with Default Settings12714//------------------------------------------------------------1271512716var margin = {top: 2, right: 0, bottom: 2, left: 0}12717, width = 40012718, height = 3212719, animate = true12720, x = d3.scale.linear()12721, y = d3.scale.linear()12722, getX = function(d) { return d.x }12723, getY = function(d) { return d.y }12724, color = nv.utils.getColor(['#000'])12725, xDomain12726, yDomain12727, xRange12728, yRange12729;1273012731//============================================================127321273312734function chart(selection) {12735selection.each(function(data) {12736var availableWidth = width - margin.left - margin.right,12737availableHeight = height - margin.top - margin.bottom,12738container = d3.select(this);127391274012741//------------------------------------------------------------12742// Setup Scales1274312744x .domain(xDomain || d3.extent(data, getX ))12745.range(xRange || [0, availableWidth]);1274612747y .domain(yDomain || d3.extent(data, getY ))12748.range(yRange || [availableHeight, 0]);1274912750//------------------------------------------------------------127511275212753//------------------------------------------------------------12754// Setup containers and skeleton of chart1275512756var wrap = container.selectAll('g.nv-wrap.nv-sparkline').data([data]);12757var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparkline');12758var gEnter = wrapEnter.append('g');12759var g = wrap.select('g');1276012761wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')1276212763//------------------------------------------------------------127641276512766var paths = wrap.selectAll('path')12767.data(function(d) { return [d] });12768paths.enter().append('path');12769paths.exit().remove();12770paths12771.style('stroke', function(d,i) { return d.color || color(d, i) })12772.attr('d', d3.svg.line()12773.x(function(d,i) { return x(getX(d,i)) })12774.y(function(d,i) { return y(getY(d,i)) })12775);127761277712778// TODO: Add CURRENT data point (Need Min, Mac, Current / Most recent)12779var points = wrap.selectAll('circle.nv-point')12780.data(function(data) {12781var yValues = data.map(function(d, i) { return getY(d,i); });12782function pointIndex(index) {12783if (index != -1) {12784var result = data[index];12785result.pointIndex = index;12786return result;12787} else {12788return null;12789}12790}12791var maxPoint = pointIndex(yValues.lastIndexOf(y.domain()[1])),12792minPoint = pointIndex(yValues.indexOf(y.domain()[0])),12793currentPoint = pointIndex(yValues.length - 1);12794return [minPoint, maxPoint, currentPoint].filter(function (d) {return d != null;});12795});12796points.enter().append('circle');12797points.exit().remove();12798points12799.attr('cx', function(d,i) { return x(getX(d,d.pointIndex)) })12800.attr('cy', function(d,i) { return y(getY(d,d.pointIndex)) })12801.attr('r', 2)12802.attr('class', function(d,i) {12803return getX(d, d.pointIndex) == x.domain()[1] ? 'nv-point nv-currentValue' :12804getY(d, d.pointIndex) == y.domain()[0] ? 'nv-point nv-minValue' : 'nv-point nv-maxValue'12805});12806});1280712808return chart;12809}128101281112812//============================================================12813// Expose Public Variables12814//------------------------------------------------------------12815chart.options = nv.utils.optionsFunc.bind(chart);1281612817chart.margin = function(_) {12818if (!arguments.length) return margin;12819margin.top = typeof _.top != 'undefined' ? _.top : margin.top;12820margin.right = typeof _.right != 'undefined' ? _.right : margin.right;12821margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;12822margin.left = typeof _.left != 'undefined' ? _.left : margin.left;12823return chart;12824};1282512826chart.width = function(_) {12827if (!arguments.length) return width;12828width = _;12829return chart;12830};1283112832chart.height = function(_) {12833if (!arguments.length) return height;12834height = _;12835return chart;12836};1283712838chart.x = function(_) {12839if (!arguments.length) return getX;12840getX = d3.functor(_);12841return chart;12842};1284312844chart.y = function(_) {12845if (!arguments.length) return getY;12846getY = d3.functor(_);12847return chart;12848};1284912850chart.xScale = function(_) {12851if (!arguments.length) return x;12852x = _;12853return chart;12854};1285512856chart.yScale = function(_) {12857if (!arguments.length) return y;12858y = _;12859return chart;12860};1286112862chart.xDomain = function(_) {12863if (!arguments.length) return xDomain;12864xDomain = _;12865return chart;12866};1286712868chart.yDomain = function(_) {12869if (!arguments.length) return yDomain;12870yDomain = _;12871return chart;12872};1287312874chart.xRange = function(_) {12875if (!arguments.length) return xRange;12876xRange = _;12877return chart;12878};1287912880chart.yRange = function(_) {12881if (!arguments.length) return yRange;12882yRange = _;12883return chart;12884};1288512886chart.animate = function(_) {12887if (!arguments.length) return animate;12888animate = _;12889return chart;12890};1289112892chart.color = function(_) {12893if (!arguments.length) return color;12894color = nv.utils.getColor(_);12895return chart;12896};1289712898//============================================================128991290012901return chart;12902}1290312904nv.models.sparklinePlus = function() {12905"use strict";12906//============================================================12907// Public Variables with Default Settings12908//------------------------------------------------------------1290912910var sparkline = nv.models.sparkline();1291112912var margin = {top: 15, right: 100, bottom: 10, left: 50}12913, width = null12914, height = null12915, x12916, y12917, index = []12918, paused = false12919, xTickFormat = d3.format(',r')12920, yTickFormat = d3.format(',.2f')12921, showValue = true12922, alignValue = true12923, rightAlignValue = false12924, noData = "No Data Available."12925;1292612927//============================================================129281292912930function chart(selection) {12931selection.each(function(data) {12932var container = d3.select(this);1293312934var availableWidth = (width || parseInt(container.style('width')) || 960)12935- margin.left - margin.right,12936availableHeight = (height || parseInt(container.style('height')) || 400)12937- margin.top - margin.bottom;12938129391294012941chart.update = function() { chart(selection) };12942chart.container = this;129431294412945//------------------------------------------------------------12946// Display No Data message if there's nothing to show.1294712948if (!data || !data.length) {12949var noDataText = container.selectAll('.nv-noData').data([noData]);1295012951noDataText.enter().append('text')12952.attr('class', 'nvd3 nv-noData')12953.attr('dy', '-.7em')12954.style('text-anchor', 'middle');1295512956noDataText12957.attr('x', margin.left + availableWidth / 2)12958.attr('y', margin.top + availableHeight / 2)12959.text(function(d) { return d });1296012961return chart;12962} else {12963container.selectAll('.nv-noData').remove();12964}1296512966var currentValue = sparkline.y()(data[data.length-1], data.length-1);1296712968//------------------------------------------------------------12969129701297112972//------------------------------------------------------------12973// Setup Scales1297412975x = sparkline.xScale();12976y = sparkline.yScale();1297712978//------------------------------------------------------------129791298012981//------------------------------------------------------------12982// Setup containers and skeleton of chart1298312984var wrap = container.selectAll('g.nv-wrap.nv-sparklineplus').data([data]);12985var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-sparklineplus');12986var gEnter = wrapEnter.append('g');12987var g = wrap.select('g');1298812989gEnter.append('g').attr('class', 'nv-sparklineWrap');12990gEnter.append('g').attr('class', 'nv-valueWrap');12991gEnter.append('g').attr('class', 'nv-hoverArea');1299212993wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');1299412995//------------------------------------------------------------129961299712998//------------------------------------------------------------12999// Main Chart Component(s)1300013001var sparklineWrap = g.select('.nv-sparklineWrap');1300213003sparkline13004.width(availableWidth)13005.height(availableHeight);1300613007sparklineWrap13008.call(sparkline);1300913010//------------------------------------------------------------130111301213013var valueWrap = g.select('.nv-valueWrap');1301413015var value = valueWrap.selectAll('.nv-currentValue')13016.data([currentValue]);1301713018value.enter().append('text').attr('class', 'nv-currentValue')13019.attr('dx', rightAlignValue ? -8 : 8)13020.attr('dy', '.9em')13021.style('text-anchor', rightAlignValue ? 'end' : 'start');1302213023value13024.attr('x', availableWidth + (rightAlignValue ? margin.right : 0))13025.attr('y', alignValue ? function(d) { return y(d) } : 0)13026.style('fill', sparkline.color()(data[data.length-1], data.length-1))13027.text(yTickFormat(currentValue));13028130291303013031gEnter.select('.nv-hoverArea').append('rect')13032.on('mousemove', sparklineHover)13033.on('click', function() { paused = !paused })13034.on('mouseout', function() { index = []; updateValueLine(); });13035//.on('mouseout', function() { index = null; updateValueLine(); });1303613037g.select('.nv-hoverArea rect')13038.attr('transform', function(d) { return 'translate(' + -margin.left + ',' + -margin.top + ')' })13039.attr('width', availableWidth + margin.left + margin.right)13040.attr('height', availableHeight + margin.top);13041130421304313044function updateValueLine() { //index is currently global (within the chart), may or may not keep it that way13045if (paused) return;1304613047var hoverValue = g.selectAll('.nv-hoverValue').data(index)1304813049var hoverEnter = hoverValue.enter()13050.append('g').attr('class', 'nv-hoverValue')13051.style('stroke-opacity', 0)13052.style('fill-opacity', 0);1305313054hoverValue.exit()13055.transition().duration(250)13056.style('stroke-opacity', 0)13057.style('fill-opacity', 0)13058.remove();1305913060hoverValue13061.attr('transform', function(d) { return 'translate(' + x(sparkline.x()(data[d],d)) + ',0)' })13062.transition().duration(250)13063.style('stroke-opacity', 1)13064.style('fill-opacity', 1);1306513066if (!index.length) return;1306713068hoverEnter.append('line')13069.attr('x1', 0)13070.attr('y1', -margin.top)13071.attr('x2', 0)13072.attr('y2', availableHeight);130731307413075hoverEnter.append('text').attr('class', 'nv-xValue')13076.attr('x', -6)13077.attr('y', -margin.top)13078.attr('text-anchor', 'end')13079.attr('dy', '.9em')130801308113082g.select('.nv-hoverValue .nv-xValue')13083.text(xTickFormat(sparkline.x()(data[index[0]], index[0])));1308413085hoverEnter.append('text').attr('class', 'nv-yValue')13086.attr('x', 6)13087.attr('y', -margin.top)13088.attr('text-anchor', 'start')13089.attr('dy', '.9em')1309013091g.select('.nv-hoverValue .nv-yValue')13092.text(yTickFormat(sparkline.y()(data[index[0]], index[0])));1309313094}130951309613097function sparklineHover() {13098if (paused) return;1309913100var pos = d3.mouse(this)[0] - margin.left;1310113102function getClosestIndex(data, x) {13103var distance = Math.abs(sparkline.x()(data[0], 0) - x);13104var closestIndex = 0;13105for (var i = 0; i < data.length; i++){13106if (Math.abs(sparkline.x()(data[i], i) - x) < distance) {13107distance = Math.abs(sparkline.x()(data[i], i) - x);13108closestIndex = i;13109}13110}13111return closestIndex;13112}1311313114index = [getClosestIndex(data, Math.round(x.invert(pos)))];1311513116updateValueLine();13117}1311813119});1312013121return chart;13122}131231312413125//============================================================13126// Expose Public Variables13127//------------------------------------------------------------1312813129// expose chart's sub-components13130chart.sparkline = sparkline;1313113132d3.rebind(chart, sparkline, 'x', 'y', 'xScale', 'yScale', 'color');1313313134chart.options = nv.utils.optionsFunc.bind(chart);1313513136chart.margin = function(_) {13137if (!arguments.length) return margin;13138margin.top = typeof _.top != 'undefined' ? _.top : margin.top;13139margin.right = typeof _.right != 'undefined' ? _.right : margin.right;13140margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;13141margin.left = typeof _.left != 'undefined' ? _.left : margin.left;13142return chart;13143};1314413145chart.width = function(_) {13146if (!arguments.length) return width;13147width = _;13148return chart;13149};1315013151chart.height = function(_) {13152if (!arguments.length) return height;13153height = _;13154return chart;13155};1315613157chart.xTickFormat = function(_) {13158if (!arguments.length) return xTickFormat;13159xTickFormat = _;13160return chart;13161};1316213163chart.yTickFormat = function(_) {13164if (!arguments.length) return yTickFormat;13165yTickFormat = _;13166return chart;13167};1316813169chart.showValue = function(_) {13170if (!arguments.length) return showValue;13171showValue = _;13172return chart;13173};1317413175chart.alignValue = function(_) {13176if (!arguments.length) return alignValue;13177alignValue = _;13178return chart;13179};1318013181chart.rightAlignValue = function(_) {13182if (!arguments.length) return rightAlignValue;13183rightAlignValue = _;13184return chart;13185};1318613187chart.noData = function(_) {13188if (!arguments.length) return noData;13189noData = _;13190return chart;13191};1319213193//============================================================131941319513196return chart;13197}1319813199nv.models.stackedArea = function() {13200"use strict";13201//============================================================13202// Public Variables with Default Settings13203//------------------------------------------------------------1320413205var margin = {top: 0, right: 0, bottom: 0, left: 0}13206, width = 96013207, height = 50013208, color = nv.utils.defaultColor() // a function that computes the color13209, id = Math.floor(Math.random() * 100000) //Create semi-unique ID incase user doesn't selet one13210, getX = function(d) { return d.x } // accessor to get the x value from a data point13211, getY = function(d) { return d.y } // accessor to get the y value from a data point13212, style = 'stack'13213, offset = 'zero'13214, order = 'default'13215, interpolate = 'linear' // controls the line interpolation13216, clipEdge = false // if true, masks lines within x and y scale13217, x //can be accessed via chart.xScale()13218, y //can be accessed via chart.yScale()13219, scatter = nv.models.scatter()13220, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'areaClick', 'areaMouseover', 'areaMouseout')13221;1322213223scatter13224.size(2.2) // default size13225.sizeDomain([2.2,2.2]) // all the same size by default13226;1322713228/************************************13229* offset:13230* 'wiggle' (stream)13231* 'zero' (stacked)13232* 'expand' (normalize to 100%)13233* 'silhouette' (simple centered)13234*13235* order:13236* 'inside-out' (stream)13237* 'default' (input order)13238************************************/1323913240//============================================================132411324213243function chart(selection) {13244selection.each(function(data) {13245var availableWidth = width - margin.left - margin.right,13246availableHeight = height - margin.top - margin.bottom,13247container = d3.select(this);1324813249//------------------------------------------------------------13250// Setup Scales1325113252x = scatter.xScale();13253y = scatter.yScale();1325413255//------------------------------------------------------------132561325713258// Injecting point index into each point because d3.layout.stack().out does not give index13259data = data.map(function(aseries, i) {13260aseries.seriesIndex = i;13261aseries.values = aseries.values.map(function(d, j) {13262d.index = j;13263d.seriesIndex = i;13264return d;13265})13266return aseries;13267});1326813269var dataFiltered = data.filter(function(series) {13270return !series.disabled;13271});1327213273data = d3.layout.stack()13274.order(order)13275.offset(offset)13276.values(function(d) { return d.values }) //TODO: make values customizeable in EVERY model in this fashion13277.x(getX)13278.y(getY)13279.out(function(d, y0, y) {13280var yHeight = (getY(d) === 0) ? 0 : y;13281d.display = {13282y: yHeight,13283y0: y013284};13285})13286(dataFiltered);132871328813289//------------------------------------------------------------13290// Setup containers and skeleton of chart1329113292var wrap = container.selectAll('g.nv-wrap.nv-stackedarea').data([data]);13293var wrapEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedarea');13294var defsEnter = wrapEnter.append('defs');13295var gEnter = wrapEnter.append('g');13296var g = wrap.select('g');1329713298gEnter.append('g').attr('class', 'nv-areaWrap');13299gEnter.append('g').attr('class', 'nv-scatterWrap');1330013301wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');1330213303//------------------------------------------------------------133041330513306scatter13307.width(availableWidth)13308.height(availableHeight)13309.x(getX)13310.y(function(d) { return d.display.y + d.display.y0 })13311.forceY([0])13312.color(data.map(function(d,i) {13313return d.color || color(d, d.seriesIndex);13314}));133151331613317var scatterWrap = g.select('.nv-scatterWrap')13318.datum(data);1331913320scatterWrap.call(scatter);1332113322defsEnter.append('clipPath')13323.attr('id', 'nv-edge-clip-' + id)13324.append('rect');1332513326wrap.select('#nv-edge-clip-' + id + ' rect')13327.attr('width', availableWidth)13328.attr('height', availableHeight);1332913330g .attr('clip-path', clipEdge ? 'url(#nv-edge-clip-' + id + ')' : '');1333113332var area = d3.svg.area()13333.x(function(d,i) { return x(getX(d,i)) })13334.y0(function(d) {13335return y(d.display.y0)13336})13337.y1(function(d) {13338return y(d.display.y + d.display.y0)13339})13340.interpolate(interpolate);1334113342var zeroArea = d3.svg.area()13343.x(function(d,i) { return x(getX(d,i)) })13344.y0(function(d) { return y(d.display.y0) })13345.y1(function(d) { return y(d.display.y0) });133461334713348var path = g.select('.nv-areaWrap').selectAll('path.nv-area')13349.data(function(d) { return d });1335013351path.enter().append('path').attr('class', function(d,i) { return 'nv-area nv-area-' + i })13352.attr('d', function(d,i){13353return zeroArea(d.values, d.seriesIndex);13354})13355.on('mouseover', function(d,i) {13356d3.select(this).classed('hover', true);13357dispatch.areaMouseover({13358point: d,13359series: d.key,13360pos: [d3.event.pageX, d3.event.pageY],13361seriesIndex: i13362});13363})13364.on('mouseout', function(d,i) {13365d3.select(this).classed('hover', false);13366dispatch.areaMouseout({13367point: d,13368series: d.key,13369pos: [d3.event.pageX, d3.event.pageY],13370seriesIndex: i13371});13372})13373.on('click', function(d,i) {13374d3.select(this).classed('hover', false);13375dispatch.areaClick({13376point: d,13377series: d.key,13378pos: [d3.event.pageX, d3.event.pageY],13379seriesIndex: i13380});13381})13382path.exit().transition()13383.attr('d', function(d,i) { return zeroArea(d.values,i) })13384.remove();13385path13386.style('fill', function(d,i){13387return d.color || color(d, d.seriesIndex)13388})13389.style('stroke', function(d,i){ return d.color || color(d, d.seriesIndex) });13390path.transition()13391.attr('d', function(d,i) {13392return area(d.values,i)13393});13394133951339613397//============================================================13398// Event Handling/Dispatching (in chart's scope)13399//------------------------------------------------------------1340013401scatter.dispatch.on('elementMouseover.area', function(e) {13402g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', true);13403});13404scatter.dispatch.on('elementMouseout.area', function(e) {13405g.select('.nv-chart-' + id + ' .nv-area-' + e.seriesIndex).classed('hover', false);13406});1340713408//============================================================1340913410});134111341213413return chart;13414}134151341613417//============================================================13418// Event Handling/Dispatching (out of chart's scope)13419//------------------------------------------------------------1342013421scatter.dispatch.on('elementClick.area', function(e) {13422dispatch.areaClick(e);13423})13424scatter.dispatch.on('elementMouseover.tooltip', function(e) {13425e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top],13426dispatch.tooltipShow(e);13427});13428scatter.dispatch.on('elementMouseout.tooltip', function(e) {13429dispatch.tooltipHide(e);13430});1343113432//============================================================134331343413435//============================================================13436// Global getters and setters13437//------------------------------------------------------------1343813439chart.dispatch = dispatch;13440chart.scatter = scatter;1344113442d3.rebind(chart, scatter, 'interactive', 'size', 'xScale', 'yScale', 'zScale', 'xDomain', 'yDomain', 'xRange', 'yRange',13443'sizeDomain', 'forceX', 'forceY', 'forceSize', 'clipVoronoi', 'useVoronoi','clipRadius','highlightPoint','clearHighlights');1344413445chart.options = nv.utils.optionsFunc.bind(chart);1344613447chart.x = function(_) {13448if (!arguments.length) return getX;13449getX = d3.functor(_);13450return chart;13451};1345213453chart.y = function(_) {13454if (!arguments.length) return getY;13455getY = d3.functor(_);13456return chart;13457}1345813459chart.margin = function(_) {13460if (!arguments.length) return margin;13461margin.top = typeof _.top != 'undefined' ? _.top : margin.top;13462margin.right = typeof _.right != 'undefined' ? _.right : margin.right;13463margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;13464margin.left = typeof _.left != 'undefined' ? _.left : margin.left;13465return chart;13466};1346713468chart.width = function(_) {13469if (!arguments.length) return width;13470width = _;13471return chart;13472};1347313474chart.height = function(_) {13475if (!arguments.length) return height;13476height = _;13477return chart;13478};1347913480chart.clipEdge = function(_) {13481if (!arguments.length) return clipEdge;13482clipEdge = _;13483return chart;13484};1348513486chart.color = function(_) {13487if (!arguments.length) return color;13488color = nv.utils.getColor(_);13489return chart;13490};1349113492chart.offset = function(_) {13493if (!arguments.length) return offset;13494offset = _;13495return chart;13496};1349713498chart.order = function(_) {13499if (!arguments.length) return order;13500order = _;13501return chart;13502};1350313504//shortcut for offset + order13505chart.style = function(_) {13506if (!arguments.length) return style;13507style = _;1350813509switch (style) {13510case 'stack':13511chart.offset('zero');13512chart.order('default');13513break;13514case 'stream':13515chart.offset('wiggle');13516chart.order('inside-out');13517break;13518case 'stream-center':13519chart.offset('silhouette');13520chart.order('inside-out');13521break;13522case 'expand':13523chart.offset('expand');13524chart.order('default');13525break;13526}1352713528return chart;13529};1353013531chart.interpolate = function(_) {13532if (!arguments.length) return interpolate;13533interpolate = _;13534return chart;13535};13536//============================================================135371353813539return chart;13540}1354113542nv.models.stackedAreaChart = function() {13543"use strict";13544//============================================================13545// Public Variables with Default Settings13546//------------------------------------------------------------1354713548var stacked = nv.models.stackedArea()13549, xAxis = nv.models.axis()13550, yAxis = nv.models.axis()13551, legend = nv.models.legend()13552, controls = nv.models.legend()13553, interactiveLayer = nv.interactiveGuideline()13554;1355513556var margin = {top: 30, right: 25, bottom: 50, left: 60}13557, width = null13558, height = null13559, color = nv.utils.defaultColor() // a function that takes in d, i and returns color13560, showControls = true13561, showLegend = true13562, showXAxis = true13563, showYAxis = true13564, rightAlignYAxis = false13565, useInteractiveGuideline = false13566, tooltips = true13567, tooltip = function(key, x, y, e, graph) {13568return '<h3>' + key + '</h3>' +13569'<p>' + y + ' on ' + x + '</p>'13570}13571, x //can be accessed via chart.xScale()13572, y //can be accessed via chart.yScale()13573, yAxisTickFormat = d3.format(',.2f')13574, state = { style: stacked.style() }13575, defaultState = null13576, noData = 'No Data Available.'13577, dispatch = d3.dispatch('tooltipShow', 'tooltipHide', 'stateChange', 'changeState')13578, controlWidth = 25013579, cData = ['Stacked','Stream','Expanded']13580, transitionDuration = 25013581;1358213583xAxis13584.orient('bottom')13585.tickPadding(7)13586;13587yAxis13588.orient((rightAlignYAxis) ? 'right' : 'left')13589;1359013591controls.updateState(false);13592//============================================================135931359413595//============================================================13596// Private Variables13597//------------------------------------------------------------1359813599var showTooltip = function(e, offsetElement) {13600var left = e.pos[0] + ( offsetElement.offsetLeft || 0 ),13601top = e.pos[1] + ( offsetElement.offsetTop || 0),13602x = xAxis.tickFormat()(stacked.x()(e.point, e.pointIndex)),13603y = yAxis.tickFormat()(stacked.y()(e.point, e.pointIndex)),13604content = tooltip(e.series.key, x, y, e, chart);1360513606nv.tooltip.show([left, top], content, e.value < 0 ? 'n' : 's', null, offsetElement);13607};1360813609//============================================================136101361113612function chart(selection) {13613selection.each(function(data) {13614var container = d3.select(this),13615that = this;1361613617var availableWidth = (width || parseInt(container.style('width')) || 960)13618- margin.left - margin.right,13619availableHeight = (height || parseInt(container.style('height')) || 400)13620- margin.top - margin.bottom;1362113622chart.update = function() { container.transition().duration(transitionDuration).call(chart); };13623chart.container = this;1362413625//set state.disabled13626state.disabled = data.map(function(d) { return !!d.disabled });1362713628if (!defaultState) {13629var key;13630defaultState = {};13631for (key in state) {13632if (state[key] instanceof Array)13633defaultState[key] = state[key].slice(0);13634else13635defaultState[key] = state[key];13636}13637}1363813639//------------------------------------------------------------13640// Display No Data message if there's nothing to show.1364113642if (!data || !data.length || !data.filter(function(d) { return d.values.length }).length) {13643var noDataText = container.selectAll('.nv-noData').data([noData]);1364413645noDataText.enter().append('text')13646.attr('class', 'nvd3 nv-noData')13647.attr('dy', '-.7em')13648.style('text-anchor', 'middle');1364913650noDataText13651.attr('x', margin.left + availableWidth / 2)13652.attr('y', margin.top + availableHeight / 2)13653.text(function(d) { return d });1365413655return chart;13656} else {13657container.selectAll('.nv-noData').remove();13658}1365913660//------------------------------------------------------------136611366213663//------------------------------------------------------------13664// Setup Scales1366513666x = stacked.xScale();13667y = stacked.yScale();1366813669//------------------------------------------------------------136701367113672//------------------------------------------------------------13673// Setup containers and skeleton of chart1367413675var wrap = container.selectAll('g.nv-wrap.nv-stackedAreaChart').data([data]);13676var gEnter = wrap.enter().append('g').attr('class', 'nvd3 nv-wrap nv-stackedAreaChart').append('g');13677var g = wrap.select('g');1367813679gEnter.append("rect").style("opacity",0);13680gEnter.append('g').attr('class', 'nv-x nv-axis');13681gEnter.append('g').attr('class', 'nv-y nv-axis');13682gEnter.append('g').attr('class', 'nv-stackedWrap');13683gEnter.append('g').attr('class', 'nv-legendWrap');13684gEnter.append('g').attr('class', 'nv-controlsWrap');13685gEnter.append('g').attr('class', 'nv-interactive');1368613687g.select("rect").attr("width",availableWidth).attr("height",availableHeight);13688//------------------------------------------------------------13689// Legend1369013691if (showLegend) {13692var legendWidth = (showControls) ? availableWidth - controlWidth : availableWidth;13693legend13694.width(legendWidth);1369513696g.select('.nv-legendWrap')13697.datum(data)13698.call(legend);1369913700if ( margin.top != legend.height()) {13701margin.top = legend.height();13702availableHeight = (height || parseInt(container.style('height')) || 400)13703- margin.top - margin.bottom;13704}1370513706g.select('.nv-legendWrap')13707.attr('transform', 'translate(' + (availableWidth-legendWidth) + ',' + (-margin.top) +')');13708}1370913710//------------------------------------------------------------137111371213713//------------------------------------------------------------13714// Controls1371513716if (showControls) {13717var controlsData = [13718{ key: 'Stacked', disabled: stacked.offset() != 'zero' },13719{ key: 'Stream', disabled: stacked.offset() != 'wiggle' },13720{ key: 'Expanded', disabled: stacked.offset() != 'expand' }13721];1372213723controlWidth = (cData.length/3) * 260;1372413725controlsData = controlsData.filter(function(d) {13726return cData.indexOf(d.key) > -1;13727})1372813729controls13730.width( controlWidth )13731.color(['#444', '#444', '#444']);1373213733g.select('.nv-controlsWrap')13734.datum(controlsData)13735.call(controls);137361373713738if ( margin.top != Math.max(controls.height(), legend.height()) ) {13739margin.top = Math.max(controls.height(), legend.height());13740availableHeight = (height || parseInt(container.style('height')) || 400)13741- margin.top - margin.bottom;13742}137431374413745g.select('.nv-controlsWrap')13746.attr('transform', 'translate(0,' + (-margin.top) +')');13747}1374813749//------------------------------------------------------------137501375113752wrap.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');1375313754if (rightAlignYAxis) {13755g.select(".nv-y.nv-axis")13756.attr("transform", "translate(" + availableWidth + ",0)");13757}1375813759//------------------------------------------------------------13760// Main Chart Component(s)1376113762//------------------------------------------------------------13763//Set up interactive layer13764if (useInteractiveGuideline) {13765interactiveLayer13766.width(availableWidth)13767.height(availableHeight)13768.margin({left: margin.left, top: margin.top})13769.svgContainer(container)13770.xScale(x);13771wrap.select(".nv-interactive").call(interactiveLayer);13772}1377313774stacked13775.width(availableWidth)13776.height(availableHeight)1377713778var stackedWrap = g.select('.nv-stackedWrap')13779.datum(data);1378013781stackedWrap.transition().call(stacked);1378213783//------------------------------------------------------------137841378513786//------------------------------------------------------------13787// Setup Axes1378813789if (showXAxis) {13790xAxis13791.scale(x)13792.ticks( availableWidth / 100 )13793.tickSize( -availableHeight, 0);1379413795g.select('.nv-x.nv-axis')13796.attr('transform', 'translate(0,' + availableHeight + ')');1379713798g.select('.nv-x.nv-axis')13799.transition().duration(0)13800.call(xAxis);13801}1380213803if (showYAxis) {13804yAxis13805.scale(y)13806.ticks(stacked.offset() == 'wiggle' ? 0 : availableHeight / 36)13807.tickSize(-availableWidth, 0)13808.setTickFormat(stacked.offset() == 'expand' ? d3.format('%') : yAxisTickFormat);1380913810g.select('.nv-y.nv-axis')13811.transition().duration(0)13812.call(yAxis);13813}1381413815//------------------------------------------------------------138161381713818//============================================================13819// Event Handling/Dispatching (in chart's scope)13820//------------------------------------------------------------1382113822stacked.dispatch.on('areaClick.toggle', function(e) {13823if (data.filter(function(d) { return !d.disabled }).length === 1)13824data = data.map(function(d) {13825d.disabled = false;13826return d13827});13828else13829data = data.map(function(d,i) {13830d.disabled = (i != e.seriesIndex);13831return d13832});1383313834state.disabled = data.map(function(d) { return !!d.disabled });13835dispatch.stateChange(state);1383613837chart.update();13838});1383913840legend.dispatch.on('stateChange', function(newState) {13841state.disabled = newState.disabled;13842dispatch.stateChange(state);13843chart.update();13844});1384513846controls.dispatch.on('legendClick', function(d,i) {13847if (!d.disabled) return;1384813849controlsData = controlsData.map(function(s) {13850s.disabled = true;13851return s;13852});13853d.disabled = false;1385413855switch (d.key) {13856case 'Stacked':13857stacked.style('stack');13858break;13859case 'Stream':13860stacked.style('stream');13861break;13862case 'Expanded':13863stacked.style('expand');13864break;13865}1386613867state.style = stacked.style();13868dispatch.stateChange(state);1386913870chart.update();13871});138721387313874interactiveLayer.dispatch.on('elementMousemove', function(e) {13875stacked.clearHighlights();13876var singlePoint, pointIndex, pointXLocation, allData = [];13877data13878.filter(function(series, i) {13879series.seriesIndex = i;13880return !series.disabled;13881})13882.forEach(function(series,i) {13883pointIndex = nv.interactiveBisect(series.values, e.pointXValue, chart.x());13884stacked.highlightPoint(i, pointIndex, true);13885var point = series.values[pointIndex];13886if (typeof point === 'undefined') return;13887if (typeof singlePoint === 'undefined') singlePoint = point;13888if (typeof pointXLocation === 'undefined') pointXLocation = chart.xScale()(chart.x()(point,pointIndex));13889allData.push({13890key: series.key,13891value: chart.y()(point, pointIndex),13892color: color(series,series.seriesIndex)13893});13894});1389513896var xValue = xAxis.tickFormat()(chart.x()(singlePoint,pointIndex));13897interactiveLayer.tooltip13898.position({left: pointXLocation + margin.left, top: e.mouseY + margin.top})13899.chartContainer(that.parentNode)13900.enabled(tooltips)13901.valueFormatter(function(d,i) {13902return yAxis.tickFormat()(d);13903})13904.data(13905{13906value: xValue,13907series: allData13908}13909)();1391013911interactiveLayer.renderGuideLine(pointXLocation);1391213913});1391413915interactiveLayer.dispatch.on("elementMouseout",function(e) {13916dispatch.tooltipHide();13917stacked.clearHighlights();13918});139191392013921dispatch.on('tooltipShow', function(e) {13922if (tooltips) showTooltip(e, that.parentNode);13923});1392413925// Update chart from a state object passed to event handler13926dispatch.on('changeState', function(e) {1392713928if (typeof e.disabled !== 'undefined') {13929data.forEach(function(series,i) {13930series.disabled = e.disabled[i];13931});1393213933state.disabled = e.disabled;13934}1393513936if (typeof e.style !== 'undefined') {13937stacked.style(e.style);13938}1393913940chart.update();13941});1394213943});139441394513946return chart;13947}139481394913950//============================================================13951// Event Handling/Dispatching (out of chart's scope)13952//------------------------------------------------------------1395313954stacked.dispatch.on('tooltipShow', function(e) {13955//disable tooltips when value ~= 013956//// TODO: consider removing points from voronoi that have 0 value instead of this hack13957/*13958if (!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 range13959setTimeout(function() { d3.selectAll('.point.hover').classed('hover', false) }, 0);13960return false;13961}13962*/1396313964e.pos = [e.pos[0] + margin.left, e.pos[1] + margin.top],13965dispatch.tooltipShow(e);13966});1396713968stacked.dispatch.on('tooltipHide', function(e) {13969dispatch.tooltipHide(e);13970});1397113972dispatch.on('tooltipHide', function() {13973if (tooltips) nv.tooltip.cleanup();13974});1397513976//============================================================139771397813979//============================================================13980// Expose Public Variables13981//------------------------------------------------------------1398213983// expose chart's sub-components13984chart.dispatch = dispatch;13985chart.stacked = stacked;13986chart.legend = legend;13987chart.controls = controls;13988chart.xAxis = xAxis;13989chart.yAxis = yAxis;13990chart.interactiveLayer = interactiveLayer;1399113992d3.rebind(chart, stacked, 'x', 'y', 'size', 'xScale', 'yScale', 'xDomain', 'yDomain', 'xRange', 'yRange', 'sizeDomain', 'interactive', 'useVoronoi', 'offset', 'order', 'style', 'clipEdge', 'forceX', 'forceY', 'forceSize', 'interpolate');1399313994chart.options = nv.utils.optionsFunc.bind(chart);1399513996chart.margin = function(_) {13997if (!arguments.length) return margin;13998margin.top = typeof _.top != 'undefined' ? _.top : margin.top;13999margin.right = typeof _.right != 'undefined' ? _.right : margin.right;14000margin.bottom = typeof _.bottom != 'undefined' ? _.bottom : margin.bottom;14001margin.left = typeof _.left != 'undefined' ? _.left : margin.left;14002return chart;14003};1400414005chart.width = function(_) {14006if (!arguments.length) return width;14007width = _;14008return chart;14009};1401014011chart.height = function(_) {14012if (!arguments.length) return height;14013height = _;14014return chart;14015};1401614017chart.color = function(_) {14018if (!arguments.length) return color;14019color = nv.utils.getColor(_);14020legend.color(color);14021stacked.color(color);14022return chart;14023};1402414025chart.showControls = function(_) {14026if (!arguments.length) return showControls;14027showControls = _;14028return chart;14029};1403014031chart.showLegend = function(_) {14032if (!arguments.length) return showLegend;14033showLegend = _;14034return chart;14035};1403614037chart.showXAxis = function(_) {14038if (!arguments.length) return showXAxis;14039showXAxis = _;14040return chart;14041};1404214043chart.showYAxis = function(_) {14044if (!arguments.length) return showYAxis;14045showYAxis = _;14046return chart;14047};1404814049chart.rightAlignYAxis = function(_) {14050if(!arguments.length) return rightAlignYAxis;14051rightAlignYAxis = _;14052yAxis.orient( (_) ? 'right' : 'left');14053return chart;14054};1405514056chart.useInteractiveGuideline = function(_) {14057if(!arguments.length) return useInteractiveGuideline;14058useInteractiveGuideline = _;14059if (_ === true) {14060chart.interactive(false);14061chart.useVoronoi(false);14062}14063return chart;14064};1406514066chart.tooltip = function(_) {14067if (!arguments.length) return tooltip;14068tooltip = _;14069return chart;14070};1407114072chart.tooltips = function(_) {14073if (!arguments.length) return tooltips;14074tooltips = _;14075return chart;14076};1407714078chart.tooltipContent = function(_) {14079if (!arguments.length) return tooltip;14080tooltip = _;14081return chart;14082};1408314084chart.state = function(_) {14085if (!arguments.length) return state;14086state = _;14087return chart;14088};1408914090chart.defaultState = function(_) {14091if (!arguments.length) return defaultState;14092defaultState = _;14093return chart;14094};1409514096chart.noData = function(_) {14097if (!arguments.length) return noData;14098noData = _;14099return chart;14100};1410114102chart.transitionDuration = function(_) {14103if (!arguments.length) return transitionDuration;14104transitionDuration = _;14105return chart;14106};1410714108chart.controlsData = function(_) {14109if (!arguments.length) return cData;14110cData = _;14111return chart;14112};1411314114yAxis.setTickFormat = yAxis.tickFormat;1411514116yAxis.tickFormat = function(_) {14117if (!arguments.length) return yAxisTickFormat;14118yAxisTickFormat = _;14119return yAxis;14120};141211412214123//============================================================1412414125return chart;14126}14127})();1412814129