diff --git a/jquery.highchartTable.js b/jquery.highchartTable.js index 3c03126..3a54a47 100644 --- a/jquery.highchartTable.js +++ b/jquery.highchartTable.js @@ -1,494 +1,577 @@ ; (function($) { - $.fn.highchartTable = function() { - - var allowedGraphTypes = ['column', 'line', 'area', 'spline', 'pie']; - - var getCallable = function (table, attribute) { - var callback = $(table).data(attribute); - if (typeof callback != 'undefined') { - var infosCallback = callback.split('.'); - var callable = window[infosCallback[0]]; - for(var i = 1, infosCallbackLength = infosCallback.length; i < infosCallbackLength; i++) { - callable = callable[infosCallback[i]]; - } - return callable; - } - }; + $.fn.highchartTable = function() { - this.each(function() { - var table = $(this); - var $table = $(table); - var nbYaxis = 1; - - // Retrieve graph title from the table caption - var captions = $('caption', table); - var graphTitle = captions.length ? $(captions[0]).text() : ''; - - var graphContainer; - if ($table.data('graph-container-before') != 1) { - // Retrieve where the graph must be displayed from the graph-container attribute - var graphContainerSelector = $table.data('graph-container'); - if (!graphContainerSelector) { - throw "graph-container data attribute is mandatory"; - } + var allowedGraphTypes = ['column', 'line', 'area', 'spline', 'pie', 'bar', 'columnrange', 'bubble']; - if (graphContainerSelector[0] === '#' || graphContainerSelector.indexOf('..')===-1) { - // Absolute selector path - graphContainer = $(graphContainerSelector); - } else { - var referenceNode = table; - var currentGraphContainerSelector = graphContainerSelector; + var getCallable = function (table, attribute) { + var callback = $(table).data(attribute); + if (typeof callback != 'undefined') { + var infosCallback = callback.split('.'); + var callable = window[infosCallback[0]]; + for(var i = 1, infosCallbackLength = infosCallback.length; i < infosCallbackLength; i++) { + callable = callable[infosCallback[i]]; + } + return callable; + } + }; - while (currentGraphContainerSelector.indexOf('..')!==-1) { - currentGraphContainerSelector = currentGraphContainerSelector.replace(/^.. /, ''); - referenceNode = referenceNode.parent(); - } + this.each(function() { + var table = $(this); + var $table = $(table); + var nbYaxis = 1; + + // Retrieve graph title from the table caption + var captions = $('caption', table); + var graphTitle = captions.length ? $(captions[0]).text() : ''; + + var graphContainer; + if ($table.data('graph-container-before') != 1) { + // Retrieve where the graph must be displayed from the graph-container attribute + var graphContainerSelector = $table.data('graph-container'); + if (!graphContainerSelector) { + throw "graph-container data attribute is mandatory"; + } - graphContainer = $(currentGraphContainerSelector, referenceNode); - } - if (graphContainer.length !== 1) { - throw "graph-container is not available in this DOM or available multiple times"; - } - graphContainer = graphContainer[0]; - } else { - $table.before('
'); - graphContainer = $table.prev(); - graphContainer = graphContainer[0]; - } - - // Retrieve graph type from graph-type attribute - var globalGraphType = $table.data('graph-type'); - if (!globalGraphType) { - throw "graph-type data attribute is mandatory"; - } - if ($.inArray(globalGraphType, allowedGraphTypes) == -1) { - throw "graph-container data attribute must be one of " + allowedGraphTypes.join(', '); - } - - var stackingType = $table.data('graph-stacking'); - if (!stackingType) { - stackingType = 'normal'; - } - - var dataLabelsEnabled = $table.data('graph-datalabels-enabled'); - var isGraphInverted = $table.data('graph-inverted') == 1; - - // Retrieve series titles - var ths = $('thead th', table); - var columns = []; - var vlines = []; - var skippedColumns = 0; - var graphIsStacked = false; - ths.each(function(indexTh, th) { - var $th = $(th); - var columnScale = $th.data('graph-value-scale'); - - var serieGraphType = $th.data('graph-type'); - if($.inArray(serieGraphType, allowedGraphTypes) == -1) { - serieGraphType = globalGraphType; - } + if (graphContainerSelector[0] === '#' || graphContainerSelector.indexOf('..') === -1) { + // Absolute selector path + graphContainer = $(graphContainerSelector); + } else { + var referenceNode = table; + var currentGraphContainerSelector = graphContainerSelector; - var serieStackGroup = $th.data('graph-stack-group'); - if(serieStackGroup) { - graphIsStacked = true; - } + while (currentGraphContainerSelector.indexOf('..') !== -1) { + currentGraphContainerSelector = currentGraphContainerSelector.replace(/^.. /, ''); + referenceNode = referenceNode.parent(); + } - var serieDataLabelsEnabled = $th.data('graph-datalabels-enabled'); - if (typeof serieDataLabelsEnabled == 'undefined') { - serieDataLabelsEnabled = dataLabelsEnabled; - } + graphContainer = $(currentGraphContainerSelector, referenceNode); + } + if (graphContainer.length !== 1) { + throw "graph-container is not available in this DOM or available multiple times"; + } + graphContainer = graphContainer[0]; + } else { + $table.before('
'); + graphContainer = $table.prev(); + graphContainer = graphContainer[0]; + } - var yaxis = $th.data('graph-yaxis'); + // Retrieve graph type from graph-type attribute + var globalGraphType = $table.data('graph-type'); + if (!globalGraphType) { + throw "graph-type data attribute is mandatory"; + } + if ($.inArray(globalGraphType, allowedGraphTypes) == -1) { + throw "graph-container data attribute must be one of " + allowedGraphTypes.join(', '); + } - if (typeof yaxis != 'undefined' && yaxis == '1') { - nbYaxis = 2; - } + var stackingType = $table.data('graph-stacking'); + if (!stackingType) { - var isColumnSkipped = $th.data('graph-skip') == 1; - if (isColumnSkipped) - { - skippedColumns = skippedColumns + 1; - } + stackingType = 'normal'; + } - var thGraphConfig = { - libelle: $th.text(), - skip: isColumnSkipped, - indexTd: indexTh - skippedColumns - 1, - color: $th.data('graph-color'), - visible: !$th.data('graph-hidden'), - yAxis: typeof yaxis != 'undefined' ? yaxis : 0, - dashStyle: $th.data('graph-dash-style') || 'solid', - dataLabelsEnabled: serieDataLabelsEnabled == 1, - dataLabelsColor: $th.data('graph-datalabels-color') || $table.data('graph-datalabels-color') + var dataLabelsEnabled = $table.data('graph-datalabels-enabled'); + var isGraphInverted = $table.data('graph-inverted') == 1; - }; + // Retrieve series titles + var ths = $('thead th', table); + var columns = []; + var vlines = []; + var skippedColumns = 0; + var graphIsStacked = false; - var vlinex = $th.data('graph-vline-x'); - if (typeof vlinex == 'undefined') { - thGraphConfig.scale = typeof columnScale != 'undefined' ? parseFloat(columnScale) : 1; - thGraphConfig.graphType = serieGraphType == 'column' && isGraphInverted ? 'bar' : serieGraphType; - thGraphConfig.stack = serieStackGroup; - thGraphConfig.unit = $th.data('graph-unit'); - columns[indexTh] = thGraphConfig; - } else { - thGraphConfig.x = vlinex; - thGraphConfig.height = $th.data('graph-vline-height'); - thGraphConfig.name = $th.data('graph-vline-name'); - vlines[indexTh] = thGraphConfig; - } - }); - - var series = []; - $(columns).each(function(indexColumn, column) { - if(indexColumn!=0 && !column.skip) { - - var serieConfig = { - name: column.libelle + (column.unit ? ' (' + column.unit + ')' : ''), - data: [], - type: column.graphType, - stack: column.stack, - color: column.color, - visible: column.visible, - yAxis: column.yAxis, - dashStyle: column.dashStyle, - marker: { - enabled: false - }, - dataLabels: { - enabled: column.dataLabelsEnabled, - color: column.dataLabelsColor, - align: $table.data('graph-datalabels-align') || (globalGraphType == 'column' && isGraphInverted == 1 ? undefined : 'center') - } - }; - - if(column.dataLabelsEnabled) { - var callableSerieDataLabelsFormatter = getCallable(table, 'graph-datalabels-formatter'); - if (callableSerieDataLabelsFormatter) { - serieConfig.dataLabels.formatter = function () { - return callableSerieDataLabelsFormatter(this.y); - }; - } - } - series.push(serieConfig); - } - }); - - $(vlines).each(function(indexColumn, vline) { - if (typeof vline != 'undefined' && !vline.skip) { - series.push({ - name: vline.libelle, - data: [{x: vline.x, y:0, name: vline.name}, {x:vline.x, y:vline.height, name: vline.name}], - type: 'spline', - color: vline.color, - visible: vline.visible, - marker: { - enabled: false - } - }); - } - }); - - var xValues = []; - var callablePoint = getCallable(table, 'graph-point-callback'); - var isGraphDatetime = $table.data('graph-xaxis-type') == 'datetime'; - - var rows = $('tbody:first tr', table); - rows.each(function(indexRow, row) { - if (!!$(row).data('graph-skip')) { - return; - } + ths.each(function (indexTh, th) { + var $th = $(th); + var columnScale = $th.data('graph-value-scale'); - var tds = $('td', row); - tds.each(function(indexTd, td) { - var cellValue; - var column = columns[indexTd]; - - if (column.skip) { - return; - } - var $td = $(td); - if (indexTd==0) { - cellValue = $td.text(); - xValues.push(cellValue); - } else { - var rawCellValue = $td.text(); - var serie = series[column.indexTd]; - - if (rawCellValue.length==0) { - if (!isGraphDatetime) { - serie.data.push(null); - } - } else { - var cleanedCellValue = rawCellValue.replace(/\s/g, '').replace(/,/, '.'); - cellValue = Math.round(parseFloat(cleanedCellValue) * column.scale * 100) / 100; + var serieGraphType = $th.data('graph-type'); + if ($.inArray(serieGraphType, allowedGraphTypes) == -1) { + serieGraphType = globalGraphType; + } + + var serieStackGroup = $th.data('graph-stack-group'); + if (serieStackGroup) { + graphIsStacked = true; + } + + var serieDataLabelsEnabled = $th.data('graph-datalabels-enabled'); + if (typeof serieDataLabelsEnabled == 'undefined') { + serieDataLabelsEnabled = dataLabelsEnabled; + } + + var yaxis = $th.data('graph-yaxis'); - var dataGraphX = $td.data('graph-x'); - if (isGraphDatetime) { - dataGraphX = $('td', $(row)).first().text(); - var date = parseDate(dataGraphX); - dataGraphX = date.getTime() - date.getTimezoneOffset()*60*1000; + if (typeof yaxis != 'undefined' && yaxis == '1') { + nbYaxis = 2; } - var tdGraphName = $td.data('graph-name'); - var serieDataItem = { - name: typeof tdGraphName != 'undefined' ? tdGraphName : rawCellValue, - y: cellValue, - x: dataGraphX //undefined if no x defined in table + var isColumnSkipped = $th.data('graph-skip') == 1; + if (isColumnSkipped) { + skippedColumns = skippedColumns + 1; + } + + var thGraphConfig = { + libelle: $th.text(), + skip: isColumnSkipped, + indexTd: indexTh - skippedColumns - 1, + color: $th.data('graph-color'), + visible: !$th.data('graph-hidden'), + yAxis: typeof yaxis != 'undefined' ? yaxis : 0, + dashStyle: $th.data('graph-dash-style') || 'solid', + dataLabelsEnabled: serieDataLabelsEnabled == 1, + dataLabelsColor: $th.data('graph-datalabels-color') || $table.data('graph-datalabels-color') || "#000000" + }; - if (callablePoint) { - serieDataItem.events = { - click: function () { - return callablePoint(this); - } - }; + var vlinex = $th.data('graph-vline-x'); + if (typeof vlinex == 'undefined') { + thGraphConfig.scale = typeof columnScale != 'undefined' ? parseFloat(columnScale) : 1; + thGraphConfig.graphType = serieGraphType == 'column' && isGraphInverted ? 'bar' : serieGraphType; + thGraphConfig.stack = serieStackGroup; + thGraphConfig.unit = $th.data('graph-unit'); + columns[indexTh] = thGraphConfig; + } else { + thGraphConfig.x = vlinex; + thGraphConfig.height = $th.data('graph-vline-height'); + thGraphConfig.name = $th.data('graph-vline-name'); + vlines[indexTh] = thGraphConfig; + } + }); + + var series = []; + $(columns).each(function (indexColumn, column) { + if (indexColumn != 0 && !column.skip) { + + var serieConfig = { + name: column.libelle + (column.unit ? ' (' + column.unit + ')' : ''), + data: [], + type: column.graphType, + stack: column.stack, + color: column.color, + visible: column.visible, + yAxis: column.yAxis, + dashStyle: column.dashStyle, + marker: { + enabled: false + }, + dataLabels: { + enabled: (globalGraphType === 'bubble') ? true : column.dataLabelsEnabled, + color: column.dataLabelsColor, + align: $table.data('graph-datalabels-align') || (globalGraphType == 'column' && isGraphInverted == 1 ? undefined : 'center') + } + }; + + if (column.dataLabelsEnabled) { + var callableSerieDataLabelsFormatter = getCallable(table, 'graph-datalabels-formatter'); + if (callableSerieDataLabelsFormatter) { + serieConfig.dataLabels.formatter = function () { + return callableSerieDataLabelsFormatter(this.y); + }; + } + } + series.push(serieConfig); + } + }); + + $(vlines).each(function (indexColumn, vline) { + if (typeof vline != 'undefined' && !vline.skip) { + series.push({ + name: vline.libelle, + data: [{ + x: vline.x, + y: 0, + name: vline.name + }, {x: vline.x, y: vline.height, name: vline.name}], + type: 'spline', + color: vline.color, + visible: vline.visible, + marker: { + enabled: false + } + }); } + }); - if (column.graphType === 'pie') { - if ($td.data('graph-item-highlight')) { - serieDataItem.sliced = 1; - } + var xValues = []; + var callablePoint = getCallable(table, 'graph-point-callback'); + var isGraphDatetime = $table.data('graph-xaxis-type') == 'datetime'; + + var rows = $('tbody:first tr', table); + rows.each(function (indexRow, row) { + if (!!$(row).data('graph-skip')) { + return; } - var tdGraphItemColor = $td.data('graph-item-color'); - if (typeof tdGraphItemColor != 'undefined') { - serieDataItem.color = tdGraphItemColor; + var tds = $('td', row); + tds.each(function (indexTd, td) { + var cellValue; + var column = columns[indexTd]; + + if (column.skip) { + return; + } + + var $td = $(td); + if (indexTd == 0) { + cellValue = $td.text(); + xValues.push(cellValue); + } else { + var rawCellValue = $td.text(); + var serie = series[column.indexTd]; + + if (rawCellValue.length == 0) { + if (!isGraphDatetime) { + serie.data.push(null); + } + } else { + var cleanedCellValue = rawCellValue.replace(/\s/g, '').replace(/,/, '.'); + cellValue = Math.round(parseFloat(cleanedCellValue) * column.scale * 100) / 100; + + var dataGraphX = $td.data('graph-x'); + + if (isGraphDatetime) { + dataGraphX = $('td', $(row)).first().text(); + var date = parseDate(dataGraphX); + dataGraphX = date.getTime() - date.getTimezoneOffset() * 60 * 1000; + } + + var tdGraphName = $td.data('graph-name'); + + if (column.graphType === 'columnrange') { + var cleanedCellValueX = $td.next().text().replace(/\s/g, '').replace(/,/, '.'); + cellValueX = Math.round(parseFloat(cleanedCellValueX) * column.scale * 100) / 100; + var serieDataItem = [ cellValue, cellValueX]; + } + else if (column.graphType === 'bubble') { + var cleanedCellValueX = $td.next().text().replace(/\s/g, '').replace(/,/, '.'); + var cleanedCellValueY = $td.next().next().text().replace(/\s/g, '').replace(/,/, '.'); + var cleanedCellValueZ = $td.next().next().next().text().replace(/\s/g, '').replace(/,/, '.'); + + var cellValueX = Math.round(parseFloat(cleanedCellValueX) * column.scale * 100) / 100; + var cellValueY = Math.round(parseFloat(cleanedCellValueY) * column.scale * 100) / 100; + var cellValueZ = Math.round(parseFloat(cleanedCellValueZ) * column.scale * 100) / 100; + + var serieDataItem = { + fullName: $td.prev().text(), + dotInfo: $td.text(), + x: cellValueX, + y: cellValueY, + z: cellValueZ, + }; + } else { + var serieDataItem = { + name: typeof tdGraphName != 'undefined' ? tdGraphName : rawCellValue, + y: cellValue, + x: dataGraphX //undefined if no x defined in table + }; + } + + if (callablePoint) { + serieDataItem.events = { + click: function () { + return callablePoint(this); + } + }; + } + + if (column.graphType === 'pie') { + if ($td.data('graph-item-highlight')) { + serieDataItem.sliced = 1; + } + } + + var tdGraphItemColor = $td.data('graph-item-color'); + if (typeof tdGraphItemColor != 'undefined') { + serieDataItem.color = tdGraphItemColor; + } + + serie.data.push(serieDataItem); + } + } + }); + + }); + var yAxisConfig = []; + var yAxisNum; + for (yAxisNum = 1; yAxisNum <= nbYaxis; yAxisNum++) { + if (series[yAxisNum-1] && $table.data('graph-dual-axes')){ + var titleText = series[yAxisNum-1].name; + } else { + var titleText = null; } - serie.data.push(serieDataItem); - } - } - }); + var yAxisConfigCurrentAxis = { + title: { + text: typeof $table.data('graph-yaxis-' + yAxisNum + '-title-text') != 'undefined' ? $table.data('graph-yaxis-' + yAxisNum + '-title-text') : titleText + }, + max: typeof $table.data('graph-yaxis-' + yAxisNum + '-max') != 'undefined' ? $table.data('graph-yaxis-' + yAxisNum + '-max') : null, + min: typeof $table.data('graph-yaxis-' + yAxisNum + '-min') != 'undefined' ? $table.data('graph-yaxis-' + yAxisNum + '-min') : null, + reversed: $table.data('graph-yaxis-' + yAxisNum + '-reversed') == '1', + opposite: $table.data('graph-yaxis-' + yAxisNum + '-opposite') == '1', + tickInterval: $table.data('graph-yaxis-' + yAxisNum + '-tick-interval') || null, + labels: { + rotation: $table.data('graph-yaxis-' + yAxisNum + '-rotation') || 0 + }, + startOnTick: $table.data('graph-yaxis-' + yAxisNum + '-start-on-tick') !== "0", + endOnTick: $table.data('graph-yaxis-' + yAxisNum + '-end-on-tick') !== "0", + stackLabels: { + enabled: $table.data('graph-yaxis-' + yAxisNum + '-stacklabels-enabled') == '1' + }, + gridLineInterpolation: $table.data('graph-yaxis-' + yAxisNum + '-grid-line-interpolation') || null, + }; - }); - - var yAxisConfig = []; - var yAxisNum; - for (yAxisNum=1 ; yAxisNum <= nbYaxis ; yAxisNum++) { - var yAxisConfigCurrentAxis = { - title: { - text: typeof $table.data('graph-yaxis-'+yAxisNum+'-title-text') != 'undefined' ? $table.data('graph-yaxis-'+yAxisNum+'-title-text') : null - }, - max: typeof $table.data('graph-yaxis-'+yAxisNum+'-max') != 'undefined' ? $table.data('graph-yaxis-'+yAxisNum+'-max') : null, - min: typeof $table.data('graph-yaxis-'+yAxisNum+'-min') != 'undefined' ? $table.data('graph-yaxis-'+yAxisNum+'-min') : null, - reversed: $table.data('graph-yaxis-'+yAxisNum+'-reversed') == '1', - opposite: $table.data('graph-yaxis-'+yAxisNum+'-opposite') == '1', - tickInterval: $table.data('graph-yaxis-'+yAxisNum+'-tick-interval') || null, - labels: { - rotation: $table.data('graph-yaxis-'+yAxisNum+'-rotation') || 0 - }, - startOnTick: $table.data('graph-yaxis-'+yAxisNum+'-start-on-tick') !== "0", - endOnTick: $table.data('graph-yaxis-'+yAxisNum+'-end-on-tick') !== "0", - stackLabels : { - enabled: $table.data('graph-yaxis-'+yAxisNum+'-stacklabels-enabled') == '1' - }, - gridLineInterpolation: $table.data('graph-yaxis-'+yAxisNum+'-grid-line-interpolation') || null - }; + var callableYAxisFormatter = getCallable(table, 'graph-yaxis-' + yAxisNum + '-formatter-callback'); + if (callableYAxisFormatter) { + yAxisConfigCurrentAxis.labels.formatter = function () { + return callableYAxisFormatter(this.value); + }; + } - var callableYAxisFormatter = getCallable(table, 'graph-yaxis-'+yAxisNum+'-formatter-callback'); - if (callableYAxisFormatter) { - yAxisConfigCurrentAxis.labels.formatter = function () { - return callableYAxisFormatter(this.value); - }; - } + yAxisConfig.push(yAxisConfigCurrentAxis); + } + //The Bubble graph needs an object instead of an array to work, so we overwrite the previous settings from above + if (globalGraphType === 'bubble') { + //Disable legend and datalabels on this type of graph + $table.data('graph-legend-disabled', true); + + var yAxisConfig = { + plotLines: [{ + color: 'black', + dashStyle: 'dot', + width: (globalGraphType === 'bubble') ? 2 : null, + value: (globalGraphType === 'bubble') ? $table.data('graph-yaxis-value') : null, + label: { + align: 'right', + style: { + fontStyle: 'italic' + }, + text: columns[2].libelle || null, + x: -10, + + }, + zIndex: 3 + }] + } - yAxisConfig.push(yAxisConfigCurrentAxis); - } - - var defaultColors = [ - '#4572A7', - '#AA4643', - '#89A54E', - '#80699B', - '#3D96AE', - '#DB843D', - '#92A8CD', - '#A47D7C', - '#B5CA92' - ]; - var colors = []; - - var themeColors = typeof Highcharts.theme != 'undefined' && typeof Highcharts.theme.colors != 'undefined' ? Highcharts.theme.colors : []; - var lineShadow = $table.data('graph-line-shadow'); - var lineWidth = $table.data('graph-line-width') || 2; - - var nbOfColors = Math.max(defaultColors.length, themeColors.length); - for(var i=0; i < nbOfColors; i++) { - var dataname = 'graph-color-' + (i+1); - colors.push(typeof $table.data(dataname) != 'undefined' ? $table.data(dataname) : typeof themeColors[i] != 'undefined' ? themeColors[i] : defaultColors[i]); - } - - var marginTop = $table.data('graph-margin-top'); - var marginRight = $table.data('graph-margin-right'); - var marginBottom = $table.data('graph-margin-bottom'); - var marginLeft = $table.data('graph-margin-left'); - - var xAxisLabelsEnabled = $table.data('graph-xaxis-labels-enabled'); - - var xAxisLabelStyle = {}; - var xAxisLabelFontSize = $table.data('graph-xaxis-labels-font-size'); - - if (typeof xAxisLabelFontSize != 'undefined') - { - xAxisLabelStyle.fontSize = xAxisLabelFontSize; - } - - var highChartConfig = { - colors: colors, - chart: { - renderTo: graphContainer, - inverted: isGraphInverted, - marginTop: typeof marginTop != 'undefined' ? marginTop : null, - marginRight: typeof marginRight != 'undefined' ? marginRight : null, - marginBottom: typeof marginBottom != 'undefined' ? marginBottom : null, - marginLeft: typeof marginLeft != 'undefined' ? marginLeft : null, - spacingTop: $table.data('graph-spacing-top') || 10, - height: $table.data('graph-height') || null, - zoomType: $table.data('graph-zoom-type') || null, - polar: $table.data('graph-polar') || null - }, - title: { - text: graphTitle - }, - subtitle: { - text: $table.data('graph-subtitle-text') || '' - }, - legend: { - enabled: $table.data('graph-legend-disabled') != '1', - layout: $table.data('graph-legend-layout') || 'horizontal', - symbolWidth: $table.data('graph-legend-width') || 30, - x: $table.data('graph-legend-x') || 15, - y: $table.data('graph-legend-y') || 0 - }, - xAxis: { - categories: ($table.data('graph-xaxis-type') != 'datetime') ? xValues : undefined, - type: ($table.data('graph-xaxis-type') == 'datetime') ? 'datetime' : undefined, - reversed: $table.data('graph-xaxis-reversed') == '1', - opposite: $table.data('graph-xaxis-opposite') == '1', - showLastLabel: typeof $table.data('graph-xaxis-show-last-label') != 'undefined' ? $table.data('graph-xaxis-show-last-label') : true, - tickInterval: $table.data('graph-xaxis-tick-interval') || null, - dateTimeLabelFormats: { //by default, we display the day and month on the datetime graphs - second: '%e. %b', - minute: '%e. %b', - hour: '%e. %b', - day: '%e. %b', - week: '%e. %b', - month: '%e. %b', - year: '%e. %b' - }, - labels: - { - rotation: $table.data('graph-xaxis-rotation') || 0, - align: $table.data('graph-xaxis-align') || 'center', - enabled: typeof xAxisLabelsEnabled != 'undefined' ? xAxisLabelsEnabled : true, - style: xAxisLabelStyle - }, - startOnTick: $table.data('graph-xaxis-start-on-tick'), - endOnTick: $table.data('graph-xaxis-end-on-tick'), - min: getXAxisMinMax(table, 'min'), - max: getXAxisMinMax(table, 'max'), - alternateGridColor: $table.data('graph-xaxis-alternateGridColor') || null, - title: { - text: $table.data('graph-xaxis-title-text') || null - }, - gridLineWidth: $table.data('graph-xaxis-gridLine-width') || 0, - gridLineDashStyle: $table.data('graph-xaxis-gridLine-style') || 'ShortDot', - tickmarkPlacement: $table.data('graph-xaxis-tickmark-placement') || 'between', - lineWidth: $table.data('graph-xaxis-line-width') || 0 - }, - yAxis: yAxisConfig, - tooltip: { - formatter: function() { - if ($table.data('graph-xaxis-type') == 'datetime') { - return ''+ this.series.name +'
'+ Highcharts.dateFormat('%e. %b', this.x) +' : '+ this.y; - } else { - var xValue = typeof xValues[this.point.x] != 'undefined' ? xValues[this.point.x] : this.point.x; - if (globalGraphType === 'pie') { - return '' + this.series.name + '
' + xValue + ' : ' + this.point.y; + } + + var tooltipConfig = { + formatter: function () { + if ($table.data('graph-xaxis-type') == 'datetime') { + return '' + this.series.name + '
' + Highcharts.dateFormat('%e. %b', this.x) + ' : ' + this.y; + } else { + var xValue = typeof xValues[this.point.x] != 'undefined' ? xValues[this.point.x] : this.point.x; + if (stackingType === 'percent') { + return xValue + ' : ' + Math.round(this.point.percentage) + '%
'; + } + if (globalGraphType === 'pie') { + + return '' + this.series.name + '
' + xValue + ' : ' + this.point.y; + } + if (globalGraphType === 'columnrange') { + return '' + xValue + '
' + this.series.name + ' : ' + this.point.low + ' - ' + this.point.high; + } + if (globalGraphType === 'bubble') { + + var yValue = typeof xValues[this.point.y] != 'undefined' ? xValues[this.point.y] : this.point.y; + var zValue = typeof xValues[this.point.z] != 'undefined' ? xValues[this.point.z] : this.point.z; + return '' + this.point.fullName + '
' + + columns[2].libelle + ':' + xValue + '
' + + columns[3].libelle + ':' + yValue + '
' + + columns[4].libelle + ':' + zValue; + } + + + return '' + this.series.name + '
' + xValue + ' : ' + this.point.name; + } } - return '' + this.series.name + '
' + xValue + ' : ' + this.point.name; - } + }; + + + var defaultColors = [ + '#4572A7', + '#AA4643', + '#89A54E', + '#80699B', + '#3D96AE', + '#DB843D', + '#92A8CD', + '#A47D7C', + '#B5CA92' + ]; + var colors = []; + + var themeColors = typeof Highcharts.theme != 'undefined' && typeof Highcharts.theme.colors != 'undefined' ? Highcharts.theme.colors : []; + var lineShadow = $table.data('graph-line-shadow'); + var lineWidth = $table.data('graph-line-width') || 2; + + var nbOfColors = Math.max(defaultColors.length, themeColors.length); + for (var i = 0; i < nbOfColors; i++) { + var dataname = 'graph-color-' + (i + 1); + colors.push(typeof $table.data(dataname) != 'undefined' ? $table.data(dataname) : typeof themeColors[i] != 'undefined' ? themeColors[i] : defaultColors[i]); } - }, - credits: { - enabled: false - }, - plotOptions: { - line: { - dataLabels: { - enabled: true - }, - lineWidth: lineWidth - }, - area: { - lineWidth: lineWidth, - shadow: typeof lineShadow != 'undefined' ? lineShadow : true, - fillOpacity: $table.data('graph-area-fillOpacity') || 0.75 - }, - pie: { - allowPointSelect: true, - dataLabels: { - enabled: true - }, - showInLegend: $table.data('graph-pie-show-in-legend') == '1', - size: '80%' - }, - series: { - animation: false, - stickyTracking : false, - stacking: graphIsStacked ? stackingType : null, - groupPadding: $table.data('graph-group-padding') || 0 - } - }, - series: series, - exporting: { - filename: graphTitle.replace(/ /g, '_'), - buttons: { - exportButton: { - menuItems: null, - onclick: function() { - this.exportChart(); + + var marginTop = $table.data('graph-margin-top'); + var marginRight = $table.data('graph-margin-right'); + var marginBottom = $table.data('graph-margin-bottom'); + var marginLeft = $table.data('graph-margin-left'); + + var xAxisLabelsEnabled = $table.data('graph-xaxis-labels-enabled'); + + var xAxisLabelStyle = {}; + var xAxisLabelFontSize = $table.data('graph-xaxis-labels-font-size'); + + if (typeof xAxisLabelFontSize != 'undefined') { + xAxisLabelStyle.fontSize = xAxisLabelFontSize; + } + + var highChartConfig = { + colors: colors, + chart: { + renderTo: graphContainer, + inverted: isGraphInverted, + marginTop: typeof marginTop != 'undefined' ? marginTop : null, + marginRight: typeof marginRight != 'undefined' ? marginRight : null, + marginBottom: typeof marginBottom != 'undefined' ? marginBottom : null, + marginLeft: typeof marginLeft != 'undefined' ? marginLeft : null, + spacingTop: $table.data('graph-spacing-top') || 10, + height: $table.data('graph-height') || null, + zoomType: $table.data('graph-zoom-type') || null, + polar: $table.data('graph-polar') || null + }, + title: { + text: graphTitle + }, + subtitle: { + text: $table.data('graph-subtitle-text') || '' + }, + legend: { + enabled: $table.data('graph-legend-disabled') != '1', + layout: $table.data('graph-legend-layout') || 'horizontal', + symbolWidth: $table.data('graph-legend-width') || 30, + x: $table.data('graph-legend-x') || 15, + y: $table.data('graph-legend-y') || 0 + }, + xAxis: { + categories: ($table.data('graph-xaxis-type') != 'datetime') ? xValues : undefined, + type: ($table.data('graph-xaxis-type') == 'datetime') ? 'datetime' : undefined, + reversed: $table.data('graph-xaxis-reversed') == '1', + opposite: $table.data('graph-xaxis-opposite') == '1', + showLastLabel: typeof $table.data('graph-xaxis-show-last-label') != 'undefined' ? $table.data('graph-xaxis-show-last-label') : true, + tickInterval: $table.data('graph-xaxis-tick-interval') || null, + dateTimeLabelFormats: { //by default, we display the day and month on the datetime graphs + second: '%e. %b', + minute: '%e. %b', + hour: '%e. %b', + day: '%e. %b', + week: '%e. %b', + month: '%e. %b', + year: '%e. %b' + }, + labels: { + rotation: $table.data('graph-xaxis-rotation') || 0, + align: $table.data('graph-xaxis-align') || 'center', + enabled: typeof xAxisLabelsEnabled != 'undefined' ? xAxisLabelsEnabled : true, + style: xAxisLabelStyle + }, + plotLines: [{ + color: 'black', + dashStyle: 'dot', + width: (globalGraphType === 'bubble') ? 2 : null, + value: (globalGraphType === 'bubble') ? $table.data('graph-xaxis-value') : null, + label: { + align: 'middle', + rotation: 0, + y: 10, + style: { + fontStyle: 'italic' + }, + text: ($table.data('graph-type') == 'bubble') ? columns[3].libelle : null, + }, + zIndex: 3 + }], + startOnTick: $table.data('graph-xaxis-start-on-tick'), + endOnTick: $table.data('graph-xaxis-end-on-tick'), + min: getXAxisMinMax(table, 'min'), + max: getXAxisMinMax(table, 'max'), + alternateGridColor: $table.data('graph-xaxis-alternateGridColor') || null, + title: { + text: $table.data('graph-xaxis-title-text') || null + }, + gridLineWidth: $table.data('graph-xaxis-gridLine-width') || 0, + gridLineDashStyle: $table.data('graph-xaxis-gridLine-style') || 'ShortDot', + tickmarkPlacement: $table.data('graph-xaxis-tickmark-placement') || 'between', + lineWidth: $table.data('graph-xaxis-line-width') || 0 + }, + yAxis: yAxisConfig, + tooltip: tooltipConfig, + credits: { + enabled: false + }, + plotOptions: { + area: { + stacking: graphIsStacked, + }, + series: { + dataLabels: { + enabled: (globalGraphType === 'bubble') ? true : null, + format: (globalGraphType === 'bubble') ? '{point.dotInfo}' : null, + } + } + }, + series: series, + + exporting: { + filename: graphTitle.replace(/ /g, '_'), + buttons: { + exportButton: { + menuItems: null, + onclick: function () { + this.exportChart(); + } + } + } } - } + + }; + + $table.trigger('highchartTable.beforeRender', highChartConfig); + new Highcharts.Chart(highChartConfig); + + }); + //for fluent api + return this; + + }; + + var getXAxisMinMax = function(table, minOrMax) { + var value = $(table).data('graph-xaxis-'+minOrMax); + if (typeof value != 'undefined') { + if ($(table).data('graph-xaxis-type') == 'datetime') { + var date = parseDate(value); + return date.getTime() - date.getTimezoneOffset()*60*1000; } - } - }; - - $table.trigger('highchartTable.beforeRender', highChartConfig); - new Highcharts.Chart(highChartConfig); - - }); - //for fluent api - return this; - }; - - var getXAxisMinMax = function(table, minOrMax) { - var value = $(table).data('graph-xaxis-'+minOrMax); - if (typeof value != 'undefined') { - if ($(table).data('graph-xaxis-type') == 'datetime') { - var date = parseDate(value); - return date.getTime() - date.getTimezoneOffset()*60*1000; - } - return value; - } - return null; - }; - - var parseDate = function(datetime) { - var calculatedateInfos = datetime.split(' '); - var dateDayInfos = calculatedateInfos[0].split('-'); - var min = null; - var hour = null; - // If hour and minute are available in the datetime string - if(calculatedateInfos[1]) { - var dateHourInfos = calculatedateInfos[1].split(':'); - min = parseInt(dateHourInfos[0], 10); - hour = parseInt(dateHourInfos[1], 10); - } - return new Date(parseInt(dateDayInfos[0], 10), parseInt(dateDayInfos[1], 10)-1, parseInt(dateDayInfos[2], 10), min, hour); - }; - -})(jQuery); + return value; + } + return null; + }; + + var parseDate = function(datetime) { + var calculatedateInfos = datetime.split(' '); + var dateDayInfos = calculatedateInfos[0].split('-'); + var min = null; + var hour = null; + // If hour and minute are available in the datetime string + if(calculatedateInfos[1]) { + var dateHourInfos = calculatedateInfos[1].split(':'); + min = parseInt(dateHourInfos[0], 10); + hour = parseInt(dateHourInfos[1], 10); + } + return new Date(parseInt(dateDayInfos[0], 10), parseInt(dateDayInfos[1], 10)-1, parseInt(dateDayInfos[2], 10), min, hour); + }; + +})(jQuery); \ No newline at end of file