From: Tanner Linsley Date: Tue, 12 May 2015 23:22:47 +0000 (-0600) Subject: Getting into 'label' hoverMode tooltips X-Git-Tag: v2.0-alpha~22 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4ef57315da7e74e16eb8a910f0b971179f08de51;p=thirdparty%2FChart.js.git Getting into 'label' hoverMode tooltips --- diff --git a/samples/bar.html b/samples/bar.html index 17afaf6af..b698faf8a 100644 --- a/samples/bar.html +++ b/samples/bar.html @@ -36,7 +36,7 @@ var ctx = document.getElementById("canvas").getContext("2d"); window.myBar = new Chart(ctx).Bar(barChartData, { responsive: true, - hoverMode: 'single', + hoverMode: 'label', scaleBeginAtZero: false, }); } diff --git a/src/Chart.Bar.js b/src/Chart.Bar.js index 386e305dc..c7dde124a 100644 --- a/src/Chart.Bar.js +++ b/src/Chart.Bar.js @@ -106,6 +106,8 @@ width : this.scale.calculateBarWidth(this.data.datasets.length), x: this.scale.calculateBarX(this.data.datasets.length, datasetIndex, index), y: this.calculateBarBase(), + _datasetIndex: datasetIndex, + _index: index, }); // Copy to view model bar.save(); @@ -114,6 +116,7 @@ // Create tooltip instance exclusively for this chart with some defaults. this.tooltip = new Chart.Tooltip({ _chart: this.chart, + _data: this.data, _options: this.options, opacity:0, xPadding: this.options.tooltipXPadding, @@ -144,6 +147,7 @@ return false; } + // Find Active Elements this.active = function(){ switch(this.options.hoverMode){ case 'single': @@ -157,14 +161,18 @@ } }.call(this); + // On Hover hook + if(this.options.onHover){ + this.options.onHover.call(this, this.active); + } // Remove styling for last active (even if it may still be active) if(this.lastActive){ switch(this.options.hoverMode){ case 'single': - this.lastActive.element.backgroundColor = this.data.datasets[this.lastActive.datasetIndex].backgroundColor; - this.lastActive.element.borderColor = this.data.datasets[this.lastActive.datasetIndex].borderColor; - this.lastActive.element.borderWidth = 0; + this.lastActive[0].backgroundColor = this.data.datasets[this.lastActive[0]._datasetIndex].backgroundColor; + this.lastActive[0].borderColor = this.data.datasets[this.lastActive[0]._datasetIndex].borderColor; + this.lastActive[0].borderWidth = 0; break; case 'label': break; @@ -174,18 +182,13 @@ // do nothing } } - - // On Hover hook - if(this.options.onHover){ - this.options.onHover.call(this, this.active); - } // Built in hover actions if(this.active && this.options.hoverMode){ switch(this.options.hoverMode){ case 'single': - this.active.element.backgroundColor = this.data.datasets[this.active.datasetIndex].hoverBackgroundColor || helpers.color(this.active.element.backgroundColor).saturate(0.5).darken(0.25).rgbString(); - this.active.element.borderColor = this.data.datasets[this.active.datasetIndex].hoverBorderColor || helpers.color(this.active.element.borderColor).saturate(0.5).darken(0.25).rgbString(); + this.active[0].backgroundColor = this.data.datasets[this.active[0]._datasetIndex].hoverBackgroundColor || helpers.color(this.active[0].backgroundColor).saturate(0.5).darken(0.25).rgbString(); + this.active[0].borderColor = this.data.datasets[this.active[0]._datasetIndex].hoverBorderColor || helpers.color(this.active[0].borderColor).saturate(0.5).darken(0.25).rgbString(); break; case 'label': break; @@ -200,22 +203,20 @@ // Built in Tooltips if(this.options.showTooltips){ - // The usual + // The usual updates this.tooltip.initialize(); - // Active Details + // Active if(this.active){ - var tooltipPosition = this.active.element.tooltipPosition(); helpers.extend(this.tooltip, { opacity: 1, - x: Math.round(tooltipPosition.x), - y: Math.round(tooltipPosition.y), - _active: this.active.element, + _active: this.active, }); - this.tooltip.updateContent(); + + this.tooltip.update(); } else{ - // Inactive Details + // Inactive helpers.extend(this.tooltip, { opacity: 0, _active: false, @@ -227,16 +228,31 @@ if(!this.animating){ // If entering if(!this.lastActive && this.active){ + console.log('entering'); this.render(false, this.options.hoverAnimationDuration); } + var changed = false; + + if (this.active.length !== this.lastActive.length){ + changed = true; + } + + helpers.each(this.active, function(element, index){ + if (element !== this.lastActive[index]){ + changed = true; + } + }, this); + // If different element - if(this.lastActive && this.active && this.lastActive.element !== this.active.element){ + if(this.lastActive && this.active && changed){ + console.log('changing'); this.render(false, this.options.hoverAnimationDuration); } // if Leaving if (this.lastActive && !this.active){ + console.log('leaving'); this.render(false, this.options.hoverAnimationDuration); } } @@ -279,6 +295,8 @@ borderColor : this.data.datasets[datasetIndex].borderColor, borderWidth : this.data.datasets[datasetIndex].borderWidth, backgroundColor : this.data.datasets[datasetIndex].backgroundColor, + _datasetIndex: datasetIndex, + _index: index, _start: undefined }); }, this); @@ -308,33 +326,28 @@ for (elementIndex = 0; elementIndex < this.data.datasets[datasetIndex].metaData.length; elementIndex++) { if (this.data.datasets[datasetIndex].metaData[elementIndex].inRange(eventPosition.x,eventPosition.y)){ helpers.each(this.data.datasets, datasetIterator); - return barsArray; } } } - return barsArray; + return barsArray.length ? barsArray : false; }, // Get the single bar that was clicked on // @return : An object containing the dataset index and bar index of the matching bar. Also contains the rectangle that was drawn getBarAtEvent : function(e) { - var bar; + var bar = []; var eventPosition = helpers.getRelativePosition(e); for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; ++datasetIndex) { for (var elementIndex = 0; elementIndex < this.data.datasets[datasetIndex].metaData.length; ++elementIndex) { if (this.data.datasets[datasetIndex].metaData[elementIndex].inRange(eventPosition.x, eventPosition.y)) { - bar = { - element : this.data.datasets[datasetIndex].metaData[elementIndex], - datasetIndex : datasetIndex, - elementIndex : elementIndex, - }; + bar.push(this.data.datasets[datasetIndex].metaData[elementIndex]); return bar; } } } - return bar; + return false; }, buildScale : function(labels){ var self = this; diff --git a/src/Chart.Core.js b/src/Chart.Core.js index db7d16da4..9f80f2fa6 100755 --- a/src/Chart.Core.js +++ b/src/Chart.Core.js @@ -1300,102 +1300,82 @@ }); Chart.Tooltip = Chart.Element.extend({ - updateContent: function(){ - + update: function(){ switch(this._options.hoverMode){ case 'single': helpers.extend(this, { - text: template(this._options.tooltipTemplate, this._active) + text: template(this._options.tooltipTemplate, this._active), + }); + var tooltipPosition = this._active[0].tooltipPosition(); + helpers.extend(this.tooltip, { + x: Math.round(tooltipPosition.x), + y: Math.round(tooltipPosition.y), }); return this; + case 'label': - } + var dataArray, + dataIndex; - return; + var tooltipLabels = [], + tooltipColors = []; + for (var i = this._data.datasets.length - 1; i >= 0; i--) { + dataArray = this._data.datasets[i].metaData; + dataIndex = indexOf(dataArray, this._active[0]); + if (dataIndex !== -1){ + break; + } + } - var dataArray, - dataIndex; + var medianPosition = (function(index) { + // Get all the points at that particular index + var elements = [], + dataCollection, + xPositions = [], + yPositions = [], + xMax, + yMax, + xMin, + yMin; + helpers.each(this._data.datasets, function(dataset){ + dataCollection = dataset.metaData; + if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){ + elements.push(dataCollection[dataIndex]); + } + }); - for (var i = this.data.datasets.length - 1; i >= 0; i--) { - dataArray = this.data.datasets[i].metaData; - dataIndex = indexOf(dataArray, this.active[0]); - if (dataIndex !== -1){ - break; - } - } - var tooltipLabels = [], - tooltipColors = [], - medianPosition = (function(index) { - - // Get all the points at that particular index - var Elements = [], - dataCollection, - xPositions = [], - yPositions = [], - xMax, - yMax, - xMin, - yMin; - helpers.each(this.data.datasets, function(dataset){ - dataCollection = dataset.metaData; - if (dataCollection[dataIndex] && dataCollection[dataIndex].hasValue()){ - Elements.push(dataCollection[dataIndex]); - } - }); + helpers.each(elements, function(element) { + xPositions.push(element._vm.x); + yPositions.push(element._vm.y); - helpers.each(Elements, function(element) { - xPositions.push(element.x); - yPositions.push(element.y); + //Include any colour information about the element + tooltipLabels.push(helpers.template(this._options.multiTooltipTemplate, element)); + tooltipColors.push({ + fill: element._vm.backgroundColor, + stroke: element._vm.borderColor + }); + }, this); - //Include any colour information about the element - tooltipLabels.push(helpers.template(this.multiTooltipTemplate, element)); - tooltipColors.push({ - fill: element._vm.backgroundColor || element.backgroundColor, - stroke: element._vm.borderColor || element.borderColor - }); + yMin = min(yPositions); + yMax = max(yPositions); - }, this); - - yMin = min(yPositions); - yMax = max(yPositions); - - xMin = min(xPositions); - xMax = max(xPositions); - - return { - x: (xMin > this.chart.width/2) ? xMin : xMax, - y: (yMin + yMax)/2 - }; - }).call(this, dataIndex); - - new Chart.MultiTooltip({ - x: medianPosition.x, - y: medianPosition.y, - xPadding: this.tooltipXPadding, - yPadding: this.tooltipYPadding, - xOffset: this.tooltipXOffset, - backgroundColor: this.tooltipBackgroundColor, - textColor: this.tooltipFontColor, - fontFamily: this.tooltipFontFamily, - fontStyle: this.tooltipFontStyle, - fontSize: this.tooltipFontSize, - titleTextColor: this.tooltipTitleFontColor, - titleFontFamily: this.tooltipTitleFontFamily, - titleFontStyle: this.tooltipTitleFontStyle, - titleFontSize: this.tooltipTitleFontSize, - cornerRadius: this.tooltipCornerRadius, - labels: tooltipLabels, - legendColors: tooltipColors, - legendColorBackground : this.multiTooltipKeyBackground, - title: this.data.datasets[0].label, - chart: this.chart, - ctx: this.chart.ctx, - custom: this.customTooltips - }).draw(); + xMin = min(xPositions); + xMax = max(xPositions); - return this; + return { + x: (xMin > this._chart.width/2) ? xMin : xMax, + y: (yMin + yMax)/2 + }; + }).call(this, dataIndex); + + helpers.extend(this, { + x: medianPosition.x, + y: medianPosition.y, + }); + return this; + } }, draw : function(){