/* FILE ARCHIVED ON 8:22:52 Sep 15, 2012 AND RETRIEVED FROM THE AN OPENWAYBACK INSTANCE ON 17:26:20 Jul 14, 2024. JAVASCRIPT APPENDED BY OPENWAYBACK, COPYRIGHT INTERNET ARCHIVE. ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. SECTION 108(a)(3)). */ var leafHandlerLoaded = void 0; var rootHandlerLoaded = void 0; $(document).ready(function(){ /* SD 2012-03-13 The dropdowns had an onchange event * that redirected the page to selected value. If you hit * the browser back button the page went back to the original * page, except for the dropdown that stayed the same. This * was because the browser caches the form values; particularly IE. * In order to avoid caching of the form elements we shall.. * 1. remove the onchange attributes on the dropdown * 2. transfer the onchange to a JQuery onchange event * 3. When an onchange is triggered, capture the new selected value * 4. Revert the dropdowns to the original values, then * 5. redirect the page to the newly selected values. * This is an ugly solution. It could have been put in the * meta tags in the original html files. */ if($('select[name="Drop1"]').length > 0) { /* *SD 2012-03-13 The following 5 lines may not be necessary, but they do make the html valid-html. */ var dropdown = $('select[name="Drop1"]').html(); dropdown = dropdown.replace('SELECTED=""','selected="selected"'); dropdown = dropdown.replace('SELECTED','selected="selected"'); dropdown = dropdown.replace('selected=""','selected="selected"'); $('select[name="Drop1"]').html(dropdown); //Drop1 $('select[name="Drop1"]').removeAttr('onchange'); var originalSelection = $('select[name="Drop1"] option:selected').attr('value'); $('select[name="Drop1"]').change(function(){ var currentSelection = $(this).attr('value'); $('select[name="Drop1"]').find('option[value="'+originalSelection+'"]').attr('selected','selected'); window.location = currentSelection; return false; }); } //DropF if($('select[name="DropF"]').length > 0) { $('select[name="DropF"]').removeAttr('onchange'); var originalSelectionF = $('select[name="DropF"] option:selected').attr('value'); $('select[name="DropF"]').change(function(){ var currentSelectionF = $(this).attr('value'); $('select[name="DropF"]').find('option[value="'+originalSelectionF+'"]').attr('selected','selected'); window.location = currentSelectionF; return false; }); } }); (function(){ /** * EIA Highcharts Theme v1.1.4 2012-02-28 * * Created by Shivan Computers Corporation on behalf * of the U.S. Energy Information Administration: * Author : Ryan Lynch (Ryan.Lynch@eia.gov) **/ (function(){ /////////////////////// // Private Variables // /////////////////////// // Shortcuts var HC = Highcharts, Chart = HC.Chart, StockChart = HC.StockChart, extend = HC.extend, each = HC.each, map = HC.map, // For compatability with Highcharts and Highstocks, // splat is undefined in the former splat = HC.splat || function (obj) { if (!$.isArray(obj)) { obj = [obj]; } return obj; }, merge = HC.merge, max = Math.max, min = Math.min, pow = Math.pow, abs = Math.abs, doc = document, win = window, // Function for prototypal inheritence, from // https://webarchive.library.unt.edu/web/20120915082252/http://webreflection.blogspot.com/2010/02/javascript-override-patterns.html chain = (function () { // recycled empty callback // used to avoid constructors execution // while extending function proto() {} // chain function return function ($prototype) { // associate the object/prototype // to the __proto__.prototype proto.prototype = $prototype; // and create a chain return new proto; }; }()), isIE = navigator.userAgent.match(/MSIE/) != null, // References for caching default x and y axis options defaultYAxisOptions, defaultXAxisOptions, // Flag to determine if an axis redraw is needed axisLabelRedraw; // We extend Highcharts with the colors and logo enumerations // first so we can reference them later extend(HC, { /////////////////// // Theme Version // /////////////////// eia_theme_version : '1.1.3', /////////////////////// // Logo Enumerations // /////////////////////// logos:{ none : 0, eia : 1, reuters : 2 }, //////////////// // EIA Colors // //////////////// eia_blue : '#0096d7', //Blue eia_tan : '#bd732a', //Tan eia_green : '#5D9732', //Green eia_yellow : '#ffc702', //Yellow eia_red : '#a33340', //Red eia_brown : '#403203', //Brown eia_lt_blue : '#76d5ff', //Light Blue eia_lt_green : '#bed5ad', //Light Green eia_dk_red : '#410e14', //Dark Red eia_grey : '#666666', //Grey eia_dk_blue : '#003953', //Dark Blue eia_dk_green : '#2a4b11', //Dark Green eia_dk_grey : '#333333', //Dark Grey ///////////////////////////////// // EIA Plotlines and Plotbands // ///////////////////////////////// eia_projections_line: { color: '#888', dashStyle: 'Dash', width : 1, zIndex: 3 // value: {projection start time / category} }, eia_projections_label: { color: '#888', fontWeight: 'bold' }, // For use where the yAxis min is non-zero eia_zero_axis_line : { color: '#000', dashStyle: 'Solid', zIndex:1, width: 1, value : 0 } }); extend(HC, { /////////////// // EIA Theme // /////////////// eiaTheme : { chart: { animation:!isIE, // Turn of animation in IE to improve performance plotBackgroundColor: 'rgba(255, 255, 255, .1)', defaultSeriesType: 'line', spacingBottom:20, // Determies the logo displayed on the chart. See logo enumerations // above logo:HC.logos.eia, events:{ redraw:function(){ onRedraw.apply(this, arguments); } }, style: { fontFamily: 'Arial, Verdana, Helvetica, sans-serif' }, lineUpYAxisZeros : false, borderColor : '#ffffff' }, colors: [ HC.eia_blue, HC.eia_tan, HC.eia_green, HC.eia_yellow, HC.eia_red, HC.eia_brown, HC.eia_lt_blue, HC.eia_lt_green, HC.eia_dk_red, HC.eia_grey, HC.eia_dk_blue, HC.eia_dk_green, HC.eia_dk_grey ], title: { align: 'left', margin: 35, style: { color: 'black', fontSize: '16px', fontWeight: 'bold' } }, subtitle: { style: { color: '#333', fontSize: '12px' }, align: 'left', floating: true, y:40 }, credits: { style: { color: '#888', fontSize: '11px' }, text: 'Source: U.S. Energy Information Administration', href: 'https://webarchive.library.unt.edu/web/20120915082252/http://www.eia.gov', position: { align: 'left', verticalAlign: 'bottom', x:15 } }, labels: { style: { fontSize: '12px', color: '#333' } }, xAxis: { labels: { style: { color: 'black' } }, endOnTick: false, startOnTick: false, tickColor: '#000', lineColor: '#000', title: { style: { color: '#888', fontWeight: 'bold', fontSize: '12px' } }, dateTimeLabelFormats : { day: '%e. %b, %y', week: '%e. %b, %y', month: '%b \'%y', year: '%Y' } }, yAxis: { labels: { style: { color: '#333' // formatter : see preprocessChart::preprocessAxis() } }, lineColor: '#A0A0A0', minorTickInterval: null, tickColor: '#A0A0A0', //zero based axis is the EIA default. In the future, it would // be useful to preprocess the data and determine if the chart // contains negative values, and override this default when // neccesary. min: 0, tickWidth: 0, title: { align:'above', style: { color: '#888', fontWeight: 'bold', fontSize: '12px' } } }, tooltip: { backgroundColor: 'rgba(255, 255, 255, 0.75)', style: { fontSize: '12px', color: '#000000', padding: 5 }, formatter:function(){ // We wrap this in a function, because we haven't defined // the universal tooltip function yet return HC.universalTooltipFormatter.apply(this, arguments); } }, plotOptions: { series: { animation:!isIE, // Turn of animation in IE to improve performance tooltip:{ // Determines whether or not to display the name of the series // in the tooltip. As with all plot options, this can be // applied to the individual series as well. showName: true // The precision for rounding numbers in the tooltip. // precision:0 } }, line: { shadow:0, lineWidth: 2, borderWidth:0, dataLabels: { color: '#333' }, marker: { enabled: false, states: { hover: { enabled: true, radius: 5 } } } }, area: { borderWidth: 0, shadow: false, lineWidth: 0, marker: { enabled: false, states: { hover: { enabled: true, radius: 4 } } } }, spline: { marker: { lineColor: '#333' } }, column: { borderWidth: 0, shadow: false, lineWidth: 0 }, bar: { shadow: false }, pie: { allowPointSelect: true, shadow: false, dataLabels: { style: { fontSize: '12px', color: 'red' } } }, scatter: { marker: { radius: 3, symbol: 'circle', states: { hover: { enabled: true, lineColor: 'rgb(100,100,100)' } } }, states: { hover: { marker: { radius: 3, enabled: true } } } } }, legend: { floating: false, borderWidth: 1, borderColor: '#e4e4e4', backgroundColor: '#f1f1f1', borderRadius: 0, symbolPadding: 5, itemStyle: { textDecoration: 'none' }, itemHoverStyle: { color: '#189bd7', textDecoration: 'underline' }, itemHiddenStyle: { color: '#CCC' } }, exporting: { enableImages:true, buttons:{ exportButton:{ menuItems: [{ text: 'Download Image', onclick: function(){ this.exportChart( { url : '/global/scripts/jquery/highcharts/exporting-server/index.cfm' }, HC.generateEIAExportOptions.apply(this) ); } }, /* commented out due to problem incorporating images such as logos. The other formats bake it in. Added final null button { text: 'Download SVG', onclick: function(){ this.exportChart( {type: 'image/svg+xml'}, HC.generateEIAExportOptions.apply(this) ); } }, */ { text: 'Download PDF', onclick: function(){ this.exportChart( { url : '/global/scripts/jquery/highcharts/exporting-server/index.cfm', type: 'application/pdf' }, HC.generateEIAExportOptions.apply(this) ); } }, { text: 'Download Data', onclick: function(){ this.generateCSV() } }, null ] }, printButton:{ onclick:function(){ printChart.apply(this); } } } } }, // X Value Types Labels, and Zooms // These correspond to the indices of the label // and zoom arrays. They also give oridnality // to the various period types. yTypes : { mixed : 0, positive : 1 }, xTypes: { category:0, annual:1, quaterly:2, // Not currently implemented monthly:3, weekly:4, daily:5 }, // Labels used in the csv export csvXLabels: [ 'Category', 'Year', 'Quarter', 'Month', 'Week of', 'Day' ], // Labels used in the tooltip tooltipXLabels: [ '', 'Year', 'Quarter', 'Month', 'Week of', 'Day' ], // Max zooms for the various xTypes xMaxZooms : [ 1, // 1 Categories 126144E6, // 4 years 31536E6, // 1 Year 107136E5, // 4 months 24192E5, // 4 weeks 6048E5 // 1 Week ], // X Value Parser /** * Parses X Values based on the passed x value type **/ parseXValue : function(xType, xValue){ var ret; switch(xType) { case HC.xTypes.annual: ret = HC.dateFormat('%Y', xValue); break; case HC.xTypes.monthly: ret = HC.dateFormat('%b %Y', xValue); break; case HC.xTypes.weekly: ret = HC.dateFormat('%m/%e/%Y', xValue); break; case HC.xTypes.daily: ret = HC.dateFormat('%m/%e/%Y', xValue); break; default: ret = xValue; break; } return ret; }, // Universal Tooltip function /** * Returns tooltip strings for non-shared and shared tooltips. **/ universalTooltipFormatter : function(){ var ret = ''; if(this.point != void 0){ // shared == false var xString, yString, nameString, series = this.series, chart = this.series.chart, seriesOpts = series.options, tipOpts = seriesOpts.tooltip, chartOpts = chart.options isPie = chartOpts.chart.defaultSeriesType == 'pie', isDateTime = isPie ? false : chartOpts.xAxis.type == 'datetime'; seriesName = series.name, // If we haven't determined xTypes, then treat it as a category axis xType = series.options.xType, xLabel = isPie ? '' : series.xAxis.options.categoryTitle || series.xAxis.options.title.text || HC.tooltipXLabels[xType], yLabel = isPie ? '' : series.yAxis.options.title.text || ''; if(!isPie){ nameString = seriesName; xString = (xLabel.length > 0 ? xLabel + ' : ' : '') + HC.parseXValue(xType, // used by the seasonal analysis to display a different date in the tooltip this.point.options && this.point.options.tooltipX !== void 0 ? this.point.options.tooltipX : this.x ); yString = series.options.compare != null ? HC.numberFormat(this.point.change, tipOpts.precision || void 0) + ' ' + yLabel: HC.numberFormat(this.y, tipOpts.precision || void 0) + ' ' + yLabel; } else{ nameString = this.point.name; xString = xLabel; yString = this.y; } ret = (series.options.tooltip.showName ? '' + nameString + '
' : '') + xString + (xString != '' ? '
' : '') + yString; } else{ // shared == true var xString, yString = '', nameString, i, series, point, yLabel, seriesOpts, tipOpts points = this.points, chart = points[0].series.chart, isPie = chart.options.chart.defaultSeriesType == 'pie', isDateTime = isPie ? false : chart.options.xAxis.type == 'datetime', xType = chart.options.maxXType, xLabel = HC.tooltipXLabels[xType]; if(!isPie){ xString = (xLabel != '' ? xLabel + ' : ' : '') + HC.parseXValue(xType, this.x); ret += xString + '
'; for(i=0; i' + ' ' + yString; if(i < points.length) ret += '
' } } else{ for(i=0; i' + ' ' + yString; if(i < points.length) ret += '
' } } } return ret; }, /** * Currently, this function doesn't do anything. It is stubbed here for later * use. For example, we may want to change some font sizes to account for * different fonts on the exporting server. **/ generateEIAExportOptions : function(){ var chart = this, ret = {}; return ret; }, /** * Overrides the default number formatter so that a null value for decimals * returns the number formatted without rounding/truncation, and a null value * for number returns an empty string instead of 0.00. **/ numberFormat : function(number, decimals, decPoint, thousandsSep) { if(number !== null && number !== void 0 && !isNaN(number)){ var lang = HC.getOptions().lang, // https://webarchive.library.unt.edu/web/20120915082252/http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_number_format/ n = number, c = isNaN(decimals = Math.abs(decimals)) ? // Here is the difference with the highcharts implementation, we default to the number of // existing decimal places, they default to 2 when decimals is not defined. Number#toFixed // can only work with a maximum of 20 decimal places, so we check and min it. Math.min(n.toString().match(/\d+\.?(\d*)/)[1].length, 20) : decimals, d = decPoint === undefined ? lang.decimalPoint : decPoint, t = thousandsSep === undefined ? lang.thousandsSep : thousandsSep, s = n < 0 ? "-" : "", i = String(parseInt(n = Math.abs(+n || 0).toFixed(c))), j = i.length > 3 ? i.length % 3 : 0; return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : ""); } else return ''; }, /** * Alternate constructor for EIA Highcharts. This function inherits all the * properties and methods of the super Highcharts.Chart, and takes the same * arguments * * @param {Object} options : The Chart options * @param {Function} callback : Chart onload callback function **/ Chart : constructorGenerator(Chart, {}), /** * Alternate constructor for EIA Highstocks charts. This function inherits * all the properties and methods of the super Highcharts.StockChart, and * takes the same arguments * * @param {Object} options : The StockChart options * @param {Function} callback : StockChart onload callback function **/ StockChart : HC.StockChart ? constructorGenerator(StockChart, { xAxis:{ type : 'dateTime' } }) : void 0 }); function constructorGenerator(originalConstructor, forcedOptions){ var ret = function(options, callback){ var chart = this, forcedOptions = forcedOptions || {}; isPie = options.chart.defaultSeriesType != void 0 && options.chart.defaultSeriesType == 'pie'; ops = jQuery.extend(true, {}, HC.getOptions(), options); // preprocess xAxis options ops.xAxis = map(splat(ops.xAxis || {}), function (xAxisOptions) { return merge(defaultXAxisOptions, xAxisOptions, forcedOptions.xAxis || {}); }); // preprocess yAxisOptions ops.yAxis = map(splat(ops.yAxis || {}), function (yAxisOptions) { opposite = yAxisOptions.opposite; return merge(defaultYAxisOptions, yAxisOptions, forcedOptions.yAxis || {}); }); // Preprocess the options common to pie and non-pie charts preprocessLogoOptions(ops); preprocessContainers(ops); if(isPie) chart = processPieChart.call(chart, originalConstructor, ops, callback); else chart = processNonPieChart.call(chart, originalConstructor, ops, callback); return chart; } ret.prototype = chain(originalConstructor.prototype); return ret; } /////////////////////////////// // Reset and Title Functions // /////////////////////////////// extend(Chart.prototype, { /** * Resets the zoom for the chart. The code is the same as the callback * for the "Reset Zoom" control that appears on the chart when zoomed. **/ resetZoom: function(){ var chart = this, axes = chart.xAxis; each(axes, function (axis) { axis.setExtremes(null, null, false); }); }, /** * Resets the chart to contain only the original series that existed at * creation time. Set redraw to true to redraw the chart after adding * the series. **/ resetSeries: function(redraw){ var chart = this, i, s, remArr = []; if(redraw === void 0) redraw = true; chart.removeAllSeries(redraw); for(i=0; i]*>.*?<\s*\/\2\s*>|<\s*\/[^>]+>|[^<>\s]+|(<[^>]+>))/g; // We add an extra blank word to the array to ensure that the loop // one more time if the last word is on it's own line. words = text.match(rWords).concat(''); while(k < words.length){ k = lastBreak; tmpLine = ''; do{ if(e){ // We get the line height before adding the new word lineHeight = e.getBBox().height; e.destroy(); } word = words[k]; tmpLine += word + ' '; // Prerender the text e = renderer.text(tmpLine, -9999, -9999).css(style).add(); k++; if(word.match(/<\s*\/?\s*br\/?\s*>/)){ // END OF LINE words.splice(k-1, 1); break; } boxWidth = e.getBBox().width; } while(boxWidth < textWidth && k < words.length) // Where we have a realllly big word, or one word if(k - 1 == lastBreak){ // we get the line height here, because in // this case the above loop ran only once. lineHeight = e.element.offsetHeight; line = words[k-1]; lastBreak = k; } else{ // Join the words with spaces, then remove spaces around html tags to prevent // extra space from being rendered when they are split into seperate spans line = words.slice(lastBreak, k-1).join(' ') // For IE, Highcharts renders text as regular HTML text, so we want to // preserve the spaces. For SVG text, we want to elimate them, since // there will already be a space between tspan elements. if(!isIE) line = line.replace(/\s+\s+/g, '>'); lastBreak = k - 1; } // Push the line into the collection lines.push({ line : line, lineHeight : lineHeight }); // Clean up e.destroy(); e = null; } return lines; } }); Chart.prototype.callbacks.push(function(){ var oldSetTitle = this.setTitle; this.adjustTitleAlignment(true, true); /** * Overrides the setTitle function to account for spacing adjustments **/ this.setTitle = function(title, subtitle){ oldSetTitle.call(this, title, subtitle); if(title) this.options.title = merge(this.options.title, title); if(subtitle) this.options.subtitle = merge(this.options.subtitle, subtitle); this.adjustTitleAlignment(title, subtitle); }; }); ///////////////////// // Private Methods // ///////////////////// /** * Processes pie charts options to apply various styles and * initializes the chart object. **/ function processPieChart(chartConstructor, ops, callback){ var chart = this; // Wait, this function does nothing!! This may change // in the future... chart = chartConstructor.call(chart, ops, callback) || chart; return chart; } /** * Preprocess non-pie chart options to apply various styles * and initializes the chart object. **/ function processNonPieChart(chartConstructor, ops, callback) { var chart = this, renderTo = ops.chart.renderTo, container = typeof(renderTo) == "string" ? $('#' + renderTo) : $(renderTo), spacingTopAdjust = 0, titleAdjust = 0, i, xAndYTypes, assocAxis, chart, xAxis, yAxisOptions = $.isArray(ops.yAxis) ? ops.yAxis : [ops.yAxis], dummyChart = { options : ops, // Copy of Highcarts ChartCounter object counters : { wrapColor: function (length) { if (this.color >= length) { this.color = 0; } }, wrapSymbol: function (length) { if (this.symbol >= length) { this.symbol = 0; } }, color:0, symbol:0 }, series : [], // Added for compatibility with Highstocks Series.bindAxis method xAxis : [], yAxis : [] }, // create a sandbox and a renderer to prerender the axis // titles and chart title sandbox = $('
') .appendTo('body').css({position:'absolute',top:-9999}), sandboxRenderer = new HC.Renderer(sandbox[0], 0, 0); // For some reason this set of operations breaks the export routine // Have to look into this further at a later time. Besides, these // options don't really need to be processed for exported charts. if(!ops.chart.forExport){ // Initialize the series on the dummy chart // object and determine the series xTYpes if(ops.series) each(ops.series, function(seriesOps){ var serie = new HC.Series; // Series.init modifies the series options, so we // clone the series options with $.extend when // creating the fake series here serie.init(dummyChart, $.extend(true, {}, seriesOps)); dummyChart.series.push(serie); xAndYTypes = determineSeriesXAndYType.call(dummyChart, serie); seriesOps.xType = serie.options.xType = seriesOps.xType !== void 0 ? seriesOps.xType : xAndYTypes.xType; if(xAndYTypes.yType === HC.yTypes.mixed){ assocAxis = yAxisOptions[seriesOps.yAxis !== void 0 ? seriesOps.yAxis : 0]; // only set the min to null if the min in the options is zero or otherwise falsey assocAxis.min = assocAxis.min ? assocAxis.min : null; } }); // Determine the min and max xType ops.minXType = determineMaxMinXType.call(dummyChart, min); ops.maxXType = determineMaxMinXType.call(dummyChart, max); ops.chart.zoomType = ops.chart.zoomType !== void 0 ? ops.chart.zoomType : determineZoomType.call(dummyChart); // Set the max zoom to the maximum zoom for the // Minimum xType. So if there is annual and monthly // data, our max zoom will be the annual max zoom. xAxis = splat(ops.xAxis) xAxis[0].maxZoom = xAxis[0].maxZoom !== void 0 ? xAxis[0].maxZoom : HC.xMaxZooms[ops.minXType]; // Determine the appropriate zoom type } // Enable the crosshairs for shared tooltips ops.tooltip.crosshairs = ops.tooltip.shared; // Process the yAxis options for(i=0; i').css({ height:'auto', width:'auto' }).addClass('outerChartContainer'); printContainer = $('
').css({ height:'auto', width:'auto' }).addClass('printChartContainer'); // Set up the outer and print containers. We // add the outer container before the container // so that it will occupy it's index when we // remove it and add it to the outer continer. container.before(outerContainer); printContainer.appendTo(outerContainer); container.appendTo(printContainer); } options.chart.outerContainer = outerContainer[0]; options.chart.printContainer = printContainer[0]; options.chart.container = container[0]; } } /** * Preprocesses the options for vertical axis objects. This function * processes above axis titles, and applies the label formatter which * formats labels with consistent precision. Note that the formatter * will never decrease precision, because of the danger of an infinite * loop. Sometimes this results in excess precision in the final * lables if a higher precision was found on first render, or if the * chart has been resized. **/ function preprocessAxis(axisOptions, renderer){ var chart = this, opts = jQuery.extend( true, {}, defaultYAxisOptions, axisOptions ), titleOpts = opts.title, yAxisPrecision = 0, newYAxisPrecision = 0, titleSpan, originalAlign = titleOpts.originalAlign || titleOpts.align.toLowerCase(), spacingTopAdjust = 0; if(originalAlign == 'above'){ // return if the text is undefined, null, or empty if(titleOpts.text == void 0 || opts.text == ''){ // Set the align to middle so that we don't have // any rendering issues, since 'above' is not // actually a valid align jQuery.extend(true, axisOptions, { align:'middle', originalAlign:'middle' }); } else{ titleSpan = renderer.text( titleOpts.text, 0, 0 ).attr({ rotation:0 }) .css(titleOpts.style).add(); var titleBox = titleSpan.getBBox(); // Extend the axis options with the highcharts options // that will position the title above the axis if(titleOpts.align == 'above') jQuery.extend(true, axisOptions, { title:{ margin: -1 * titleBox.width, rotation: 0, align:'high', x:axisOptions.opposite ? titleBox.width : 0, y:-10 } }); spacingTopAdjust = titleBox.height; } } // Store the original align so we can shift the yAxis title // on export for above axis titles jQuery.extend(true, axisOptions, { title:{ originalAlign:originalAlign } }); if(!axisOptions.labels || !axisOptions.labels.formatter){ jQuery.extend(true, axisOptions, { labels:{ // This function has to be defined in preprocessAxis because it // needs to be applied to each axis, and because we store the // yAxisPrecision in a reference scoped to that closure. formatter : function() { var ret = this.value.toString(), decimalRegex = /\d+\.?(\d*)/; if(decimalRegex.test(ret)){ // Determine The number of numeric characters // after the decimal point. newYAxisPrecision= Math.max(this.value.toString() .match(decimalRegex)[1].length, newYAxisPrecision); // If we haven't defined a yAxisPrecision for this // axis, then lets do it here. if(yAxisPrecision === void 0) yAxisPrecision = newYAxisPrecision; // If this value has a greater precision than // the one we've previously recorded, set the // value on the chart and force a redraw. if(this.isLast){ if(newYAxisPrecision != yAxisPrecision){ yAxisPrecision = newYAxisPrecision; // Set the axisLabelRedraw flag so that the yAxis // will be redrawn on load or on redraw axisLabelRedraw = true; } newYAxisPrecision = 0; ret = HC.numberFormat(this.value, yAxisPrecision,'.',','); } // Otherwise, round and format the number else{ ret = HC.numberFormat(this.value, yAxisPrecision,'.',','); } } return ret; } } }); } return spacingTopAdjust; } function preprocessChartTitle(titleOps, renderer, chartWidth){ var spacingTopAdjust = 0, titleLines, titleBox; if(titleOps || titleOps.text){ titleLines = Chart.prototype.splitText(titleOps.text, titleOps.style, chartWidth, renderer); titleOps.text = $.map(titleLines, function(item){return item.line}).join('
'); if(titleLines.length > 1){ for(i=1; i Year, Week > Month, etc. **/ function determineMaxMinXType(checker){ var chart = this, i, s, maxType, xType ; for(i=0; i 1){ for(i = 0; i < chart.yAxis.length; i++){ axi = axis[i]; extremes = axi.getExtremes(); ratios[i] = { min : minimum = Math.abs(extremes.min), max : maximum = Math.abs(extremes.max), axisLength : axisLength = maximum + minimum, positiveRatio : Math.abs(maximum) / axisLength, negativeRatio : Math.abs(minimum) / axisLength }; } for(i = 0; i < ratios.length; i++){ var positiveRatio = ratios[i].positiveRatio; var negativeRatio = ratios[i].negativeRatio; var ratioDiff = Math.abs(positiveRatio - negativeRatio); if(!isNaN(positiveRatio) && !isNaN(negativeRatio)){ allPositive &= positiveRatio == 1; allNegative &= negativeRatio == 1; if(minimumRatioDiff === void 0 || ratioDiff < minimumRatioDiff){ minimumRatioDiff = ratioDiff; optimumRatios = { positiveRatio : positiveRatio, negativeRatio : negativeRatio } } } } if(minimumRatioDiff == 1 && (!allPositive && !allNegative)){ optimumRatios = { positiveRatio : 0.5, negativeRatio : 0.5 }; } for(i=0; i= 0 ; k--) if(cat < categories[k]) break; categories.splice(k+1, 0, cat); } else categories.push(cat); // Add it to the hash so we know we've processed it categoriesHash[cat] = 1; } } // "Constants" var chart = this, POST_URL = chart.options.exporting.csvOptions.postURL, OVERRIDE_URL = chart.options.exporting.csvOptions.overrideURL, //// CSV Characters NULL_STRING = '--', FIELD_DELIM_REGEXP = /,/g, RECORD_DELIM_REGEXP = /\n/g, //// Other REGEXP HTML_TAG_REGEXP = /<[\/\w]+>/g, FILE_CHAR_REGEXP = /[\?%\*:\|"\<\>\\,]/g, PER_REGEXP = /\//g, MULTI_SPACE_REGEXP = /\s+/g, // Variables i, j, k, cat, p, s, d, xTitle, propertiesHash, linkHeaders, csvArr, headers, record, dataHash, input1, input2, dataStart, xType, xAxisOps = splat(chart.options.xAxis)[0], keyHeaders firstTime = true, isDateTime = false, categories = [], dataHashes = {}, propertiesHashes = {}, categoriesHash = {}, hasSourceLink = false, hasSourceKey = false, chartTitle = 'chartData'; // If we have an override URL, then we change the window location and return if(OVERRIDE_URL) return window.location = OVERRIDE_URL; // See if we have a chart title, if so, use for the file name try{ if(chart.options.title.text !== void 0 && chart.options.title.text.length > 0) chartTitle = chart.options.title.text .replace(HTML_TAG_REGEXP, ' ') .replace(FILE_CHAR_REGEXP, '') .replace(PER_REGEXP, ' per ') .replace(MULTI_SPACE_REGEXP, ' '); if(chart.options.subtitle.text !== void 0 && chart.options.subtitle.text.length > 0) chartTitle += ' (' + chart.options.subtitle.text .replace(HTML_TAG_REGEXP, ' ') .replace(FILE_CHAR_REGEXP, '') .replace(PER_REGEXP, ' per ') .replace(MULTI_SPACE_REGEXP, ' ') + ')'; }catch(e){/*DO NOTHING*/} // See if we are dealing with a date time or a category axis try{ isDateTime = xAxisOps.type == 'datetime'; }catch(e){/*DO NOTHING*/} // See if we have an XAxis title, if so use for the date/category header try{ if( xAxisOps.title.text !== void 0 && xAxisOps.title.text.length > 0 ) xTitle = xAxisOps.title.text; }catch(e){/*DO NOTHING*/} // Loop through the chart series for(i=0; i pairs if(!chart.options.navigator){ dataHash = dataHashes[s.name] = {}; // Store the sourceKey and propertiesHashes[s.name] = { sourceKey : s.options.sourceKey, sourceLink : s.options.sourceLink }; // We use this flag later to determine if we should add a // row for source links in the csv file hasSourceLink |= typeof propertiesHashes[s.name].sourceLink != 'undefined'; hasSourceKey |= typeof propertiesHashes[s.name].sourceKey != 'undefined'; for(j=0; j= 0 ; k--) if(cat < categories[k]) break; categories.splice(k+1, 0, cat); } else categories.push(cat); // Add it to the hash so we know we've processed it categoriesHash[cat] = 1; } } } else if(!chart.options.navigator.enabled || s.name != 'Navigator'){ dataHash = dataHashes[s.name] = {}; if(s.type == 'pie'){ for(j=0; j