0

High everyone,

I am trying to get two things to happen. First, I want to create a custom tooltip for a columnrange-type series where the tooltip shows something like HIGH: 'this.point.high' and on a new line "LOW:" 'this.point.low'. Second, I would like these 'low' and 'high' values to populate a form field dynamically. For example, when a user drags the high value for the columnrange entry, I want this to dynamically update a number in the corresponding formfield that collects user input.

Here is a fiddle: https://jsfiddle.net/e9zqmy12/

Code:


<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/modules/export-data.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>
<script src="https://code.highcharts.com/modules/draggable-points.js"></script>

<figure class="highcharts-figure">
    <div id="container"></div>
    
 
</figure>



    


var myChart;

Highcharts.setOptions({
    plotOptions: {
        series: {
            animation: false
        }
    }
});

// draw chart
  myChart = Highcharts.chart('container', 
 {
    chart: {
      type: "line",
      events: {
            click: function (e) {
                // find the clicked values and the series
               var y = Math.round(e.yAxis[0].value),
                   x=12
                   series = this.series[3].data[12];
                series.update({x, y, color: 'blue'});
               
            },
            drag: function (e) {
                 var y = Math.round(e.yAxis[0].value),
                   x=12
                   series = this.series[3].data[12];
                series.update({x, y, color: 'blue'});
               
            }
        }
     
    },
    title: {
      text: "Forecasting History"
    },
    


    xAxis: {
      type: 'category',
      allowDecimals: true,
      title: {
        text: "Quarter"
      },
      

    plotBands: [{
    color: 'rgba(204,153,255,0.2)', // Color value
    from: 11.5, // Start of the plot band
    to: 12.5, // End of the plot band
    label: {
                    text: 'Forecast'
                }
   
    }]
    },
    yAxis: {
      title: {
        text: "Inflation (%)"
      },
      plotLines: [{
        value: 0,
        width: 2,
        color: '#aaa',
        zIndex: 10
      }]
    },
   tooltip: {
        style: {
            color: 'black',
            fontWeight: 'bold',
            fontSize: 13
        },
     positioner: function () {
            return { x: 80, y:0 };
        },
    shared: true,
    headerFormat: '',
    valueDecimals: 2,
    shadow: false,
    borderWidth: 2,
    borderColor: '#000000',
    shape: 'rect',
    backgroundColor: 'rgba(255,255,255,0.8)'
  },
 
    series: [
        
            {
              name: 'Inflation',
              data: [3.9,4.98,5.72,5.73,3.61,3.68,3.72,2.64,2.1,1.94,1.99,1.87,null],
              tooltip: {
              pointFormat: '{series.name}: <b>{point.y}%</b><br/>',
            },
            },{
               name: 'Central Bank Forecast',
               data: [2,3.47,4.2,4.62,4.51,3.079,3.13,3.15,2.43,2.17,1.7,2.17,null],
                tooltip: {
              pointFormat: '{series.name}: <b>{point.y}%</b><br/>',
            },
             },{
               name: 'Your Forecast',
               showInLegend: false,
               data: [null,null,null,null,null,null,null,null,null,null,null,null,2],
                  tooltip: {
              pointFormat: '{series.name}: <b>{point.y}%</b><br/>',
            },
               marker: {
               radius: 2.5,
               fillColor: 'red'
     
              },
             },{

                plotOptions: {
                    columnrange: {
                                dataLabels: {
                                    enabled: true,
                                   
                                }
                    }
                    
                    },
                
                    
               name: 'Forecast Range',
               color: 'rgba(255,0,0,.1)',
               type: 'columnrange',
               data: [[12,1,3]],
               tooltip: {
            
            pointFormatter: function() {
            
                console.log(this);
                return "LOW: "+this.point.low + " HIGH:" +this.point.high;
            }
        },
               
          
                 dragDrop: {
                 draggableY: true,
                 groupBy: 'GroupId',
                 dragMinY: -10,
                 dragMaxY: 10,
                 dragPrecisionY: .01,
                 liveRedraw: false
                    },
            }
            ], 
    });
   














1 Answers1

0

It seems that your code was almost good except this callback pointFormatter callback - notice that this calls for point already, so this.point refers to undefined, it should be:

  tooltip: {
    pointFormatter: function() {

      console.log(this);
      return "LOW: " + this.low + "  <br>HIGH:" + this.high;
    }
  },

Demo: https://jsfiddle.net/BlackLabel/vbo6j9em/

Sebastian Wędzel
  • 11,417
  • 1
  • 6
  • 16
  • Sebastian - Thanks! This fixed the tooltip issue. I have one other issue -- is it possible to take these values (this.low and this.high) and pass them to a variable so that (1) I can capture the data that a user inputs by dragging the low, high points on a chart (I already have the click/drag functionality) and also have these values automatically and dynamically populate a formfield? – FloppyDogEars Nov 27 '21 at 19:00
  • @FloppyDogEars take a look at this demo and analyze the logic nested in the render callback: https://jsfiddle.net/BlackLabel/f7hw84py/ – Sebastian Wędzel Nov 27 '21 at 20:17
  • Sebastian -- This looks like it is most of my answer. My extreme ignorance is a real barrier, though. I am trying to get the two values (low, high as you have them labeled) to show up as input in two corresponding form fields. I am using oTree. Formfields in oTree are based on django, I think (so I just include {{formfields}} etc.). I could also use raw HTML (so ). Either way, I haven't had any success getting these values to showup as input in a formfield. – FloppyDogEars Nov 28 '21 at 22:01
  • @FloppyDogEars something like is done here? https://jsfiddle.net/BlackLabel/3zwdsfq4/ – Sebastian Wędzel Nov 29 '21 at 08:16
  • Sebastian - That is exactly what I'd like to achieve! Alas, this solution ( though it works perfectly in the fiddle you linked) doesn't work in oTree and I have absolutely no idea why that is true. I am accepting your answer because it is clearly correct. There must be something weird about how oTree works that stops this from working. When I implement this in oTree, I still just get blank formfields. – FloppyDogEars Nov 29 '21 at 11:29
  • @FloppyDogEars I don't know oTree, so I am not able to help you - you should probably ask another question with oTree tag, like 'how to integrate oTree input with JS value'. Thanks for accepting! Good luck with your project. – Sebastian Wędzel Nov 29 '21 at 12:45