title: build a javascript callback function from php for chartjs
body: <p>I'm building a graph on a template using chartjs, works great but the labels are having rounding issues and could do with showing the currency symbol so i discovered i can use a callback function in the tooltip.</p>
  
  <p>Now I'm creating the javascript in an array using php and then using json_encode to construct the chart data, when I run the code the content is rendered but now the tooltip has vanished.</p>
  
  <p>A simplified version of the array building is as follows:</p>
  
  <pre><code>$dataSets             = array();
  
      $res                  = new stdClass();
      $res-&gt;label           = 'Client (paid)';
      $res-&gt;backgroundColor = $palette[0]-&gt;background_color;
      $res-&gt;stack           = 'Stack 0';
      $res-&gt;data            = array_values( $pi['client'] );
      $dataSets[0]          = $res;
  
      $title                = new stdClass();
      $title-&gt;display       = true;
      $title-&gt;text          = 'Invoices Breakdown';
  
      $callbacks            = new stdClass();
      $label                = new stdClass();
  
      $callbacks-&gt;label     = "
      function(tooltipItem, data) {
          var label = data.datasets[tooltipItem.datasetIndex].label || '';
  
          if (label) {
              label += ': £';
          }
          label += Math.round(tooltipItem.yLabel * 100) / 100;
          return label;
      }";
  
      $tooltips             = new stdClass();
      $tooltips-&gt;mode       = 'index';
      $tooltips-&gt;intersect  = false;
      $tooltips-&gt;callbacks  = $callbacks;
  
      $scales               = new stdClass();
  
      $xAxes                = array();
      $x                    = new stdClass();
      $x-&gt;stacked           = true;
      $xAxes[]              = $x;
      $scales-&gt;xAxes        = $xAxes;
  
      $yAxes                = array();
      $y                    = new stdClass();
      $y-&gt;stacked           = true;
      $yAxes[]              = $y;
      $scales-&gt;yAxes        = $yAxes;
  
      $ds                   = new stdClass();
      $ds-&gt;type             = 'bar';
  
      $data                 = new stdClass();
      $data-&gt;labels         = $months;
      $data-&gt;datasets       = $dataSets;
      $ds-&gt;data             = $data;
  
      $options              = new stdClass();
      $options-&gt;title       = $title;
      $options-&gt;tooltips    = $tooltips;
      $options-&gt;responsive  = true;
      $options-&gt;scales      = $scales;
      $ds-&gt;options          = $options;
  
      return $ds;
  </code></pre>
  
  <p>So as can be seen i insert the callback as a string (the working version didn't have the $callback object)</p>
  
  <p>My code that outputs this object is this:</p>
  
  <pre><code>$chart = json_encode( $dataset );
  $html .= '
      &lt;canvas id="invoiceChart" width="100" height="50"&gt;&lt;/canvas&gt;
      &lt;script&gt;
          var ctx = document.getElementById("invoiceChart").getContext("2d");    
          var invoiceChart = new Chart(ctx, ' . $chart . ')
      &lt;/script&gt;';
  </code></pre>
  
  <p>So how would i insert a callback function in this way?</p>
  
  <p>An example of the code rendered as $chart is:</p>
  
  <pre><code>&lt;script&gt;
          var ctx = document.getElementById("invoiceChart").getContext("2d");    
          var invoiceChart = new Chart(ctx, {"type":"bar","data":{"labels":["Sep","Oct","Nov","Dec","Jan","Feb"],"datasets":[{"label":"Client (paid)","backgroundColor":"#784187","stack":"Stack 0","data":[0,2,655,75,31.5,0]},{"label":"Client (auth)","backgroundColor":"#DDDDDD","stack":"Stack 0","data":[0,5.4,925,971.03,1227.703,402]},{"label":"Client (draft)","backgroundColor":"#003D51","stack":"Stack 0","data":[0,0,0,0,0,761.667]},{"label":"Contractor (paid)","backgroundColor":"#EA9A24","stack":"Stack 1","data":[0,166.505,9.99,0,81.93,0]},{"label":"Contractor (auth)","backgroundColor":"#E6194B","stack":"Stack 1","data":[0,0,261.451,0,2361.165,90.915]},{"label":"Contractor (draft)","backgroundColor":"#3CB44B","stack":"Stack 1","data":[0,5.4,0,0,239.71300000000002,252.77800000000002]}]},"options":{"title":{"display":true,"text":"Invoices Breakdown"},"tooltips":{"mode":"index","intersect":false,"callbacks":{"label":"\r\n    function(tooltipItem, data) {\r\n        var label = data.datasets[tooltipItem.datasetIndex].label || '';\r\n\r\n        if (label) {\r\n            label += ': \u00a3';\r\n        }\r\n        label += Math.round(tooltipItem.yLabel * 100) \/ 100;\r\n        return label;\r\n    }"}},"responsive":true,"scales":{"xAxes":[{"stacked":true}],"yAxes":[{"stacked":true}]}}})
      &lt;/script&gt;
  </code></pre>
  
  <p>As you can see (unsurprisingly) the callback function is surrounded by quotes (well it is a string right)</p>
  
  <p>So how can I do this correctly?</p>
  
  <p><a href="https://www.chartjs.org/docs/2.7.3/configuration/tooltip.html#label-callback" rel="nofollow noreferrer">https://www.chartjs.org/docs/2.7.3/configuration/tooltip.html#label-callback</a></p>
  
  <p>edit: just thought I can probably use a place holder and a search and replace but is there another solution?</p>
  
  <p>thanks</p>