| |
| nv.utils.windowSize = function() { |
| // Sane defaults |
| var size = {width: 640, height: 480}; |
| |
| // Earlier IE uses Doc.body |
| if (document.body && document.body.offsetWidth) { |
| size.width = document.body.offsetWidth; |
| size.height = document.body.offsetHeight; |
| } |
| |
| // IE can use depending on mode it is in |
| if (document.compatMode=='CSS1Compat' && |
| document.documentElement && |
| document.documentElement.offsetWidth ) { |
| size.width = document.documentElement.offsetWidth; |
| size.height = document.documentElement.offsetHeight; |
| } |
| |
| // Most recent browsers use |
| if (window.innerWidth && window.innerHeight) { |
| size.width = window.innerWidth; |
| size.height = window.innerHeight; |
| } |
| return (size); |
| }; |
| |
| |
| |
| // Easy way to bind multiple functions to window.onresize |
| // TODO: give a way to remove a function after its bound, other than removing all of them |
| nv.utils.windowResize = function(fun){ |
| if (fun === undefined) return; |
| var oldresize = window.onresize; |
| |
| window.onresize = function(e) { |
| if (typeof oldresize == 'function') oldresize(e); |
| fun(e); |
| } |
| } |
| |
| // Backwards compatible way to implement more d3-like coloring of graphs. |
| // If passed an array, wrap it in a function which implements the old default |
| // behavior |
| nv.utils.getColor = function(color) { |
| if (!arguments.length) return nv.utils.defaultColor(); //if you pass in nothing, get default colors back |
| |
| if( Object.prototype.toString.call( color ) === '[object Array]' ) |
| return function(d, i) { return d.color || color[i % color.length]; }; |
| else |
| return color; |
| //can't really help it if someone passes rubbish as color |
| } |
| |
| // Default color chooser uses the index of an object as before. |
| nv.utils.defaultColor = function() { |
| var colors = d3.scale.category20().range(); |
| return function(d, i) { return d.color || colors[i % colors.length] }; |
| } |
| |
| |
| // Returns a color function that takes the result of 'getKey' for each series and |
| // looks for a corresponding color from the dictionary, |
| nv.utils.customTheme = function(dictionary, getKey, defaultColors) { |
| getKey = getKey || function(series) { return series.key }; // use default series.key if getKey is undefined |
| defaultColors = defaultColors || d3.scale.category20().range(); //default color function |
| |
| var defIndex = defaultColors.length; //current default color (going in reverse) |
| |
| return function(series, index) { |
| var key = getKey(series); |
| |
| if (!defIndex) defIndex = defaultColors.length; //used all the default colors, start over |
| |
| if (typeof dictionary[key] !== "undefined") |
| return (typeof dictionary[key] === "function") ? dictionary[key]() : dictionary[key]; |
| else |
| return defaultColors[--defIndex]; // no match in dictionary, use default color |
| } |
| } |
| |
| |
| |
| // From the PJAX example on d3js.org, while this is not really directly needed |
| // it's a very cool method for doing pjax, I may expand upon it a little bit, |
| // open to suggestions on anything that may be useful |
| nv.utils.pjax = function(links, content) { |
| d3.selectAll(links).on("click", function() { |
| history.pushState(this.href, this.textContent, this.href); |
| load(this.href); |
| d3.event.preventDefault(); |
| }); |
| |
| function load(href) { |
| d3.html(href, function(fragment) { |
| var target = d3.select(content).node(); |
| target.parentNode.replaceChild(d3.select(fragment).select(content).node(), target); |
| nv.utils.pjax(links, content); |
| }); |
| } |
| |
| d3.select(window).on("popstate", function() { |
| if (d3.event.state) load(d3.event.state); |
| }); |
| } |
| |
| /* For situations where we want to approximate the width in pixels for an SVG:text element. |
| Most common instance is when the element is in a display:none; container. |
| Forumla is : text.length * font-size * constant_factor |
| */ |
| nv.utils.calcApproxTextWidth = function (svgTextElem) { |
| if (typeof svgTextElem.style === 'function' |
| && typeof svgTextElem.text === 'function') { |
| var fontSize = parseInt(svgTextElem.style("font-size").replace("px","")); |
| var textLength = svgTextElem.text().length; |
| |
| return textLength * fontSize * 0.5; |
| } |
| return 0; |
| }; |
| |
| /* Numbers that are undefined, null or NaN, convert them to zeros. |
| */ |
| nv.utils.NaNtoZero = function(n) { |
| if (typeof n !== 'number' |
| || isNaN(n) |
| || n === null |
| || n === Infinity) return 0; |
| |
| return n; |
| }; |
| |
| /* |
| Snippet of code you can insert into each nv.models.* to give you the ability to |
| do things like: |
| chart.options({ |
| showXAxis: true, |
| tooltips: true |
| }); |
| |
| To enable in the chart: |
| chart.options = nv.utils.optionsFunc.bind(chart); |
| */ |
| nv.utils.optionsFunc = function(args) { |
| if (args) { |
| d3.map(args).forEach((function(key,value) { |
| if (typeof this[key] === "function") { |
| this[key](value); |
| } |
| }).bind(this)); |
| } |
| return this; |
| }; |