]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Rough Tooltips for 'single' hoverMode
authorTanner Linsley <tannerlinsley@gmail.com>
Tue, 12 May 2015 18:55:48 +0000 (12:55 -0600)
committerTanner Linsley <tannerlinsley@gmail.com>
Tue, 12 May 2015 18:55:48 +0000 (12:55 -0600)
samples/bar.html
src/Chart.Bar.js
src/Chart.Core.js

index d1bf880c67af345068924f3df00be2e6e1425bb7..0ddfd27408ee51eac652935c8d38575d96c7ef0b 100644 (file)
     var barChartData = {
         labels: ["January", "February", "March", "April", "May", "June", "July"],
         datasets: [{
+            label: 'Dataset 1',
             backgroundColor: "rgba(220,220,220,0.5)",
             data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
         }, {
+            label: 'Dataset 2',
             backgroundColor: "rgba(151,187,205,0.5)",
             data: [randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor(), randomScalingFactor()]
         }]
@@ -34,7 +36,7 @@
         var ctx = document.getElementById("canvas").getContext("2d");
         window.myBar = new Chart(ctx).Bar(barChartData, {
             responsive: true,
-            hoverMode: 'bar',
+            hoverMode: 'single',
             scaleBeginAtZero: false,
         });
     }
index a681bdfa2124236f068b149e4ff19ab2d0d72473..01872dde7b725b2cf7463b53f2b8374341b1137c 100644 (file)
                //Number - Spacing between data sets within X values
                barDatasetSpacing : 1,
 
-               //String - Hover mode for events
-               hoverMode : 'bars', // 'bar', 'dataset'
+               //String / Boolean - Hover mode for events.
+               hoverMode : 'single', // 'label', 'dataset', 'false'
 
                //Function - Custom hover handler
                onHover : null,
 
                //Function - Custom hover handler
-               hoverDuration : 400,
+               hoverAnimationDuration : 400,
 
                //String - A legend template
                legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].backgroundColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>"
 
                        this.ScaleClass = Chart.Scale.extend({
                                offsetGridLines : true,
-                               calculateBarX : function(datasetCount, datasetIndex, barIndex){
+                               calculateBarX : function(datasetCount, datasetIndex, elementIndex){
                                        //Reusable method for calculating the xPosition of a given bar based on datasetIndex & width of the bar
                                        var xWidth = this.calculateBaseWidth(),
-                                               xAbsolute = this.calculateX(barIndex) - (xWidth/2),
+                                               xAbsolute = this.calculateX(elementIndex) - (xWidth/2),
                                                barWidth = this.calculateBarWidth(datasetCount);
 
                                        return xAbsolute + (barWidth * datasetIndex) + (datasetIndex * options.barDatasetSpacing) + barWidth/2;
                },
                onHover: function(e){
 
-                       var active;
+
+                       // If exiting chart
                        if(e.type == 'mouseout'){
                                return false;
                        }
-                       if(this.options.hoverMode == 'bar'){
-                               active = this.getBarAtEvent(e);
-                       }
-                       else if(this.options.hoverMode == 'bars'){}
+
+                       var active = function(){
+                               switch(this.options.hoverMode){
+                                       case 'single':
+                                               return this.getBarAtEvent(e);
+                                       case 'label':
+                                               return this.getBarsAtEvent(e);
+                                       case 'dataset':
+                                               return this.getDatasetAtEvent(e);
+                                       default:
+                                               return e;
+                               }
+                       }.call(this);
 
 
-                       // Remove styling for last active
+                       // Remove styling for last active (even if it may still be active)
                        if(this.lastActive){
-                               if(this.options.hoverMode == 'bar'){
-                                       this.lastActive.rectangle.backgroundColor = this.data.datasets[this.lastActive.datasetIndex].backgroundColor;
-                                       this.lastActive.rectangle.borderColor = this.data.datasets[this.lastActive.datasetIndex].borderColor;
-                                       this.lastActive.rectangle.borderWidth = 0;
+                               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;
+                                               break;
+                                       case 'label':
+                                               break;
+                                       case 'dataset':
+                                               break;
+                                       default:
+                                               // do nothing
                                }
-                               else if(this.options.hoverMode == 'bars'){}
                        }
 
-                       // Custom Hover actions
+                       // On Hover hook
                        if(this.options.onHover){
                                this.options.onHover.call(this, active);
                        }
-                       else if(active){
-                               // or default hover action
-                               if(this.options.hoverMode == 'bar'){
-                                       active.rectangle.backgroundColor = this.data.datasets[active.datasetIndex].hoverBackgroundColor || Color(active.rectangle.backgroundColor).saturate(0.5).darken(0.25).rgbString();
-                                       active.rectangle.borderColor = this.data.datasets[active.datasetIndex].hoverBorderColor || Color(active.rectangle.borderColor).saturate(0.5).darken(0.25).rgbString();
+                       
+                       // Built in hover actions
+                       if(active && this.options.hoverMode){
+                               switch(this.options.hoverMode){
+                                       case 'single':
+                                               active.element.backgroundColor = this.data.datasets[active.datasetIndex].hoverBackgroundColor || helpers.color(active.element.backgroundColor).saturate(0.5).darken(0.25).rgbString();
+                                               active.element.borderColor = this.data.datasets[active.datasetIndex].hoverBorderColor || helpers.color(active.element.borderColor).saturate(0.5).darken(0.25).rgbString();
+                                               break;
+                                       case 'label':
+                                               break;
+                                       case 'dataset':
+                                               break;
+                                       default:
+                                               // do nothing
                                }
-                               else if(this.options.hoverMode == 'bars'){}
-
                        }
 
+                       // Only animate for major events
                        if(!this.animating){
                                // If entering
                                if(!this.lastActive && active){
-                                       this.render(false, this.options.hoverDuration);
+                                       this.render(false, this.options.hoverAnimationDuration);
                                }
 
-                               // If different bar
-                               if(this.lastActive && active && this.lastActive.rectangle !== active.rectangle){
-                                       this.render(false, this.options.hoverDuration);
+                               // If different element
+                               if(this.lastActive && active && this.lastActive.element !== active.element){
+                                       this.render(false, this.options.hoverAnimationDuration);
                                }
 
                                // if Leaving
                                if (this.lastActive && !active){
-                                       this.render(false, this.options.hoverDuration);
+                                       this.render(false, this.options.hoverAnimationDuration);
                                }
                        }
 
+                       // Remember Last Active
                        this.lastActive = active;
 
                        if (this.options.showTooltips){
-                               this.showTooltip(active);
+                               this.showTooltip(active, this.options.hoverMode);
                        }
                },
                // Calculate the base point for the bar.
                        var barsArray = [],
                                eventPosition = helpers.getRelativePosition(e),
                                datasetIterator = function(dataset){
-                                       barsArray.push(dataset.metaData[barIndex]);
+                                       barsArray.push(dataset.metaData[elementIndex]);
                                },
-                               barIndex;
+                               elementIndex;
 
                        for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; datasetIndex++) {
-                               for (barIndex = 0; barIndex < this.data.datasets[datasetIndex].metaData.length; barIndex++) {
-                                       if (this.data.datasets[datasetIndex].metaData[barIndex].inRange(eventPosition.x,eventPosition.y)){
+                               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;
                                        }
                        var eventPosition = helpers.getRelativePosition(e);
                        
                        for (var datasetIndex = 0; datasetIndex < this.data.datasets.length; ++datasetIndex) {
-                               for (var barIndex = 0; barIndex < this.data.datasets[datasetIndex].metaData.length; ++barIndex) {
-                                       if (this.data.datasets[datasetIndex].metaData[barIndex].inRange(eventPosition.x, eventPosition.y)) {
+                               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 = {
-                                                       rectangle : this.data.datasets[datasetIndex].metaData[barIndex],
+                                                       element : this.data.datasets[datasetIndex].metaData[elementIndex],
                                                        datasetIndex : datasetIndex,
-                                                       barIndex : barIndex,
+                                                       elementIndex : elementIndex,
                                                };
                                                return bar;
                                        }
index 8a476551b0acec260e49f952d935d5597460cb21..49e03ffc599ec6d3f32d963248dfa7a27270d2b8 100755 (executable)
                        ctx.lineTo(x, y + radius);
                        ctx.quadraticCurveTo(x, y, x + radius, y);
                        ctx.closePath();
+               },
+               color = helpers.color = function(color){
+                       if(!window.Color){
+                               console.log('Color.js not found!');
+                               return color;
+                       }
+                       return window.Color(color);
+               },
+               isArray = helpers.isArray = function(obj){
+                       if (!Array.isArray) {
+                               return Object.prototype.toString.call(arg) === '[object Array]';
+                       }
+                       return Array.isArray(obj);
                };
 
-
        //Store a reference to each instance - allowing us to globally resize chart instances on window resize.
        //Destroy method on the chart will remove the instance of the chart from this reference.
        Chart.instances = {};
 
                        delete Chart.instances[this.id];
                },
-               showTooltip : function(ChartElements, forceRedraw){
-                       // Only redraw the chart if we've actually changed what we're hovering on.
-                       if (typeof this.activeElements === 'undefined') this.activeElements = [];
-
-                       var isChanged = (function(Elements){
-                               var changed = false;
+               showTooltip : function(elements, hoverMode){
 
-                               if (Elements.length !== this.activeElements.length){
-                                       changed = true;
-                                       return changed;
+                       // Hide if no elements
+                       if(!elements){
+                               if(this.options.customTooltips){
+                                       this.options.customTooltips(false);
+                               }
+                               if(!this.animating){    
+                                       this.render(false, this.options.hoverAnimationDuration);
                                }
-
-                               each(Elements, function(element, index){
-                                       if (element !== this.activeElements[index]){
-                                               changed = true;
-                                       }
-                               }, this);
-                               return changed;
-                       }).call(this, ChartElements);
-
-                       if (!isChanged && !forceRedraw){
                                return;
                        }
-                       else{
-                               this.activeElements = ChartElements;
-                       }
-                       this.draw();
-                       if(this.options.customTooltips){
-                               this.options.customTooltips(false);
-                       }
-                       if (ChartElements.length > 0){
-                               // If we have multiple datasets, show a MultiTooltip for all of the data points at that index
-                               if (this.data.datasets && this.data.datasets.length > 1) {
+
+                       switch(hoverMode){
+                               case 'single':
+                                       var tooltipPosition = elements.element.tooltipPosition();
+                                       new Chart.Tooltip({
+                                               x: Math.round(tooltipPosition.x),
+                                               y: Math.round(tooltipPosition.y),
+                                               xPadding: this.options.tooltipXPadding,
+                                               yPadding: this.options.tooltipYPadding,
+                                               backgroundColor: this.options.tooltipBackgroundColor,
+                                               textColor: this.options.tooltipFontColor,
+                                               fontFamily: this.options.tooltipFontFamily,
+                                               fontStyle: this.options.tooltipFontStyle,
+                                               fontSize: this.options.tooltipFontSize,
+                                               caretHeight: this.options.tooltipCaretSize,
+                                               cornerRadius: this.options.tooltipCornerRadius,
+                                               text: template(this.options.tooltipTemplate, elements.element),
+                                               chart: this.chart,
+                                               custom: this.options.customTooltips
+                                       }).draw();
+                                       break;
+                               case 'label':
                                        var dataArray,
                                                dataIndex;
 
                                        for (var i = this.data.datasets.length - 1; i >= 0; i--) {
                                                dataArray = this.data.datasets[i].metaData;
-                                               dataIndex = indexOf(dataArray, ChartElements[0]);
+                                               dataIndex = indexOf(dataArray, elements[0]);
                                                if (dataIndex !== -1){
                                                        break;
                                                }
                                                labels: tooltipLabels,
                                                legendColors: tooltipColors,
                                                legendColorBackground : this.options.multiTooltipKeyBackground,
-                                               title: ChartElements[0].label,
+                                               title: elements[0].label,
                                                chart: this.chart,
                                                ctx: this.chart.ctx,
                                                custom: this.options.customTooltips
                                        }).draw();
-
-                               } else {
-                                       each(ChartElements, function(Element) {
-                                               var tooltipPosition = Element.tooltipPosition();
-                                               new Chart.Tooltip({
-                                                       x: Math.round(tooltipPosition.x),
-                                                       y: Math.round(tooltipPosition.y),
-                                                       xPadding: this.options.tooltipXPadding,
-                                                       yPadding: this.options.tooltipYPadding,
-                                                       backgroundColor: this.options.tooltipBackgroundColor,
-                                                       textColor: this.options.tooltipFontColor,
-                                                       fontFamily: this.options.tooltipFontFamily,
-                                                       fontStyle: this.options.tooltipFontStyle,
-                                                       fontSize: this.options.tooltipFontSize,
-                                                       caretHeight: this.options.tooltipCaretSize,
-                                                       cornerRadius: this.options.tooltipCornerRadius,
-                                                       text: template(this.options.tooltipTemplate, Element),
-                                                       chart: this.chart,
-                                                       custom: this.options.customTooltips
-                                               }).draw();
-                                       }, this);
-                               }
+                                       break;
+                               case 'dataset':
+                                       break;
+                               default:
                        }
+
                        return this;
                },
                toBase64Image : function(){
                                        // Color transitions if possible
                                        if(typeof value === 'string'){
                                                try{    
-                                                       var color = Color(this._start[key]).mix(Color(this[key]), ease);
+                                                       var color = helpers.color(this._start[key]).mix(helpers.color(this[key]), ease);
                                                        this._vm[key] = color.rgbString();
                                                } catch(err){
                                                        this._vm[key] = value;
                        {
                                return (chartX >= this.x - this.width / 2 && chartX <= this.x + this.width / 2) && (chartY >= this.base && chartY <= this.y);
                        }
-               }
+               },
+               tooltipPosition : function(){
+                       if (this.y < this.base){
+                               return {
+                                       x : this.x,
+                                       y : this.y
+                               };
+                       }
+                       else{
+                               return {
+                                       x : this.x,
+                                       y : this.base
+                               };
+                       }
+               },
        });
 
        Chart.Animation = Chart.Element.extend({