<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://rt-wiki.bestpractical.com/index.php?action=history&amp;feed=atom&amp;title=HTML5Charts</id>
	<title>HTML5Charts - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://rt-wiki.bestpractical.com/index.php?action=history&amp;feed=atom&amp;title=HTML5Charts"/>
	<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=HTML5Charts&amp;action=history"/>
	<updated>2026-08-22T20:35:41Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.1</generator>
	<entry>
		<id>https://rt-wiki.bestpractical.com/index.php?title=HTML5Charts&amp;diff=1484&amp;oldid=prev</id>
		<title>Admin: 13 revisions imported</title>
		<link rel="alternate" type="text/html" href="https://rt-wiki.bestpractical.com/index.php?title=HTML5Charts&amp;diff=1484&amp;oldid=prev"/>
		<updated>2016-04-06T20:11:18Z</updated>

		<summary type="html">&lt;p&gt;13 revisions imported&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;This works in RT 4.0.6.      &lt;br /&gt;
The end result should look something like this:&lt;br /&gt;
&lt;br /&gt;
[[File:Bar.png|thumb|left|400px]][[File:Line.png|thumb|left|400px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:Pie.png|thumb|left|400px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is a bit hacky, ok, a lot, I&amp;#039;ll try to create a proper extension if/when I&amp;#039;ll have some time, meanwhile here&amp;#039;s how it&amp;#039;s done:&lt;br /&gt;
&lt;br /&gt;
First of all, you&amp;#039;ll need Chris Leonello&amp;#039;s excellent package jqplot. You can download it here:&lt;br /&gt;
&lt;br /&gt;
http://www.jqplot.com/deploy/download/jquery.jqplot.1.0.4r1120.zip&lt;br /&gt;
&lt;br /&gt;
This is the version I&amp;#039;m using, can&amp;#039;t guarantee for newer versions.&lt;br /&gt;
&lt;br /&gt;
Perhaps it&amp;#039;s a good idea to wander around his site and see what can be achieved with the library.&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
Ok, down to business.&lt;br /&gt;
* Unzip somewhere and copy to your /path/to/rt/local/html/NoAuth/js (create the folder if not there) the following files:&lt;br /&gt;
 excanvas.js, jquery.jqplot.js&lt;br /&gt;
from the &amp;quot;plugins&amp;quot; directory:&lt;br /&gt;
      jqplot.pieRenderer.js&lt;br /&gt;
      jqplot.barRenderer.js&lt;br /&gt;
      jqplot.categoryAxisRenderer.js&lt;br /&gt;
      jqplot.dateAxisRenderer.js&lt;br /&gt;
      jqplot.canvasAxisLabelRenderer.js&lt;br /&gt;
      jqplot.canvasAxisTickRenderer.js&lt;br /&gt;
      jqplot.canvasTextRenderer.js&lt;br /&gt;
      jqplot.cursor.js&lt;br /&gt;
      jqplot.pointLabels.js&lt;br /&gt;
If you plan to play with other plugins you can copy all the content of the &amp;quot;plugins&amp;quot; directory&lt;br /&gt;
&lt;br /&gt;
* Copy jquery.jqplot.min.css to /path/to/rt/local/html/NoAuth/css.&lt;br /&gt;
&lt;br /&gt;
* Go to /path/to/rt/local/html/NoAuth/js and create a file called charts.js with the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
function switchTypes(atLoad){&lt;br /&gt;
        var isSelected = atLoad ? &amp;#039;selected=&amp;quot;selected&amp;quot;&amp;#039;: &amp;#039;&amp;#039;;&lt;br /&gt;
        if (!jQuery(&amp;quot;#PrimaryGroupBy&amp;quot;).length){return};&lt;br /&gt;
        if (jQuery(&amp;quot;#PrimaryGroupBy&amp;quot;).val().match(/Hourly|Annually|Monthly|Daily/)){&lt;br /&gt;
                if (!jQuery(&amp;quot;#ChartStyle option[value=&amp;#039;line&amp;#039;]&amp;quot;).length){&lt;br /&gt;
                        jQuery(&amp;quot;#ChartStyle&amp;quot;).append(&amp;#039;&amp;lt;option &amp;#039;+ isSelected + &amp;#039; value=&amp;quot;line&amp;quot;&amp;gt;line&amp;lt;/option&amp;gt;&amp;#039;);&lt;br /&gt;
                }&lt;br /&gt;
        } else {&lt;br /&gt;
                jQuery(&amp;quot;#ChartStyle option[value=&amp;#039;line&amp;#039;]&amp;quot;).remove();&lt;br /&gt;
        };&lt;br /&gt;
    };&lt;br /&gt;
  function massageValues(vals, suffix){&lt;br /&gt;
        jQuery.each(vals, function(ind, val){&lt;br /&gt;
                if(val[0].match(/Not Set/i)){&lt;br /&gt;
                        delete vals[ind];&lt;br /&gt;
                        return;&lt;br /&gt;
                } else {&lt;br /&gt;
                        val[0] += suffix;&lt;br /&gt;
                }&lt;br /&gt;
                val[1] = Number(val[1]);&lt;br /&gt;
        });&lt;br /&gt;
  };&lt;br /&gt;
  function drawChart(divIndex, chartStyle, tk, vals, period ){&lt;br /&gt;
        var myDiv = &amp;quot;plot&amp;quot;+divIndex;&lt;br /&gt;
        jQuery(&amp;quot;#&amp;quot;+myDiv).width(3*screen.availWidth/4);&lt;br /&gt;
        jQuery.jqplot.config.enablePlugins = true;&lt;br /&gt;
       var plotOpts = {};&lt;br /&gt;
       if (chartStyle.match(/^bar/)) {&lt;br /&gt;
                plotOpts = jqPlotOpts.bar;&lt;br /&gt;
                plotOpts.axes.xaxis.ticks = tk;&lt;br /&gt;
                jQuery.each(vals, function(index, value){vals[index] = Number(value)});&lt;br /&gt;
        } else if (chartStyle == &amp;#039;pie&amp;#039;) {&lt;br /&gt;
                plotOpts = jqPlotOpts.pie;&lt;br /&gt;
                jQuery.each(vals, function(index, value){vals[index][1] = Number(value[1])});&lt;br /&gt;
        } else if (chartStyle.match(/^line/)){&lt;br /&gt;
                var suffix = &amp;quot;&amp;quot;;&lt;br /&gt;
                var format = &amp;quot;&amp;quot;;&lt;br /&gt;
                if (period.match(/Annually/)){&lt;br /&gt;
                        suffix = &amp;quot;-12-31 0:00AM&amp;quot;;&lt;br /&gt;
                        format = &amp;#039;%Y&amp;#039;;&lt;br /&gt;
                } else if (period.match(/Monthly/)){&lt;br /&gt;
                        suffix = &amp;quot;-01 0:00AM&amp;quot;&lt;br /&gt;
                        format = &amp;#039;%b %Y&amp;#039;;&lt;br /&gt;
                } else if (period.match(/Daily/)){&lt;br /&gt;
                        suffix = &amp;quot; 0:00AM&amp;quot;&lt;br /&gt;
                        format = &amp;#039;%#d %b %Y&amp;#039;;&lt;br /&gt;
                } else if (period.match(/Hourly/)){&lt;br /&gt;
                        suffix = &amp;quot;&amp;quot;&lt;br /&gt;
                }&lt;br /&gt;
                plotOpts = jqPlotOpts.line;&lt;br /&gt;
                plotOpts.axes.xaxis.tickOptions.formatString = format;&lt;br /&gt;
                massageValues(vals, suffix);&lt;br /&gt;
        }&lt;br /&gt;
        plotOpts.animate = !jQuery.jqplot.use_excanvas;&lt;br /&gt;
        var myPlot = jQuery.jqplot (myDiv, [vals], plotOpts);&lt;br /&gt;
&lt;br /&gt;
   };&lt;br /&gt;
 function setupCharts(o){&lt;br /&gt;
     jQuery.ajaxSetup( {cache: false });&lt;br /&gt;
     jQuery.each(o, function(key, configObj){&lt;br /&gt;
        jQuery.get(&amp;#039;/Helpers/LoadChart&amp;#039;,configObj,&lt;br /&gt;
                function(data){&lt;br /&gt;
                        drawChart(key, configObj[&amp;quot;ChartStyle&amp;quot;], data.ticks, data.vals, configObj[&amp;quot;PrimaryGroupBy&amp;quot;]);&lt;br /&gt;
                        var i = 0, total = 0;&lt;br /&gt;
                        for(i;i&amp;lt;data.ticks.length;i++){&lt;br /&gt;
                                var cls = i%2 ? &amp;#039;evenline&amp;#039; : &amp;#039;oddline&amp;#039;;&lt;br /&gt;
                                var value = typeof(data.vals[i]) == &amp;#039;number&amp;#039; ? data.vals[i] : data.vals[i][1];&lt;br /&gt;
                                total += value;&lt;br /&gt;
                                var line = &amp;#039;&amp;lt;tr class=&amp;quot;&amp;#039; + cls + &amp;#039;&amp;quot;&amp;gt;&amp;lt;td class=&amp;quot;label collection-as-table&amp;quot;&amp;gt;&amp;#039;+data.ticks[i]+&lt;br /&gt;
                                   &amp;#039;&amp;lt;/td&amp;gt;&amp;lt;td class=&amp;quot;value collection-as-table&amp;quot;&amp;gt;&amp;#039;+value+&amp;#039;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;#039;;&lt;br /&gt;
                                jQuery(&amp;#039;#Results&amp;#039;+key).append(line);&lt;br /&gt;
                        };&lt;br /&gt;
                        var lastcls = i%2 ? &amp;#039;evenline&amp;#039; : &amp;#039;oddline&amp;#039;;&lt;br /&gt;
                        var totline = &amp;#039;&amp;lt;tr class=&amp;quot;&amp;#039;+lastcls+&amp;#039;&amp;quot;&amp;gt;&amp;lt;td class=&amp;quot;label collection-as-table&amp;quot;&amp;gt;Total&amp;lt;/td&amp;gt;&amp;lt;td class=&amp;quot;value collection-as-table&amp;quot;&amp;gt;&amp;#039;+&lt;br /&gt;
                                total+&amp;#039;&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;&amp;#039;;&lt;br /&gt;
                        jQuery(&amp;#039;#Results&amp;#039;+key).append(totline);&lt;br /&gt;
         }&lt;br /&gt;
        );&lt;br /&gt;
        jQuery(&amp;#039;#Header&amp;#039;+key).html(configObj[&amp;quot;PrimaryGroupBy&amp;quot;]);&lt;br /&gt;
      }); //each chartObj&lt;br /&gt;
     jQuery.ajaxSetup( {cache: true });&lt;br /&gt;
        if (!jQuery(&amp;quot;#PrimaryGroupBy&amp;quot;).length ||&lt;br /&gt;
                jQuery(&amp;quot;#PrimaryGroupBy&amp;quot;).data(&amp;#039;events&amp;#039;) != null ){return};&lt;br /&gt;
        jQuery(&amp;quot;#PrimaryGroupBy&amp;quot;).change(function(){switchTypes(false)});&lt;br /&gt;
        switchTypes(true);&lt;br /&gt;
 };&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Then a file called config.charts.js, with the following content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
var jqPlotOpts = {&lt;br /&gt;
        line: {&lt;br /&gt;
              seriesDefaults: {&lt;br /&gt;
                         renderer: jQuery.jqplot.LineRenderer,&lt;br /&gt;
                         pointLabels: { show:  true },&lt;br /&gt;
                         rendererOptions: { animation: {speed: 3000}, smooth: true },&lt;br /&gt;
                },&lt;br /&gt;
              axes: {&lt;br /&gt;
                        xaxis: {&lt;br /&gt;
                                renderer: jQuery.jqplot.DateAxisRenderer,&lt;br /&gt;
                                tickOptions: { angle: -30 },&lt;br /&gt;
                                tickRenderer:jQuery.jqplot.CanvasAxisTickRenderer,&lt;br /&gt;
                                labelRenderer: jQuery.jqplot.CanvasAxisLabelRenderer&lt;br /&gt;
                        }&lt;br /&gt;
                },&lt;br /&gt;
              cursor: { show: true, zoom: true }&lt;br /&gt;
        },&lt;br /&gt;
        pie: {&lt;br /&gt;
              seriesDefaults: {&lt;br /&gt;
                         renderer: jQuery.jqplot.PieRenderer,&lt;br /&gt;
                         rendererOptions: {showDataLabels: true, dataLabels: &amp;#039;value&amp;#039;}&lt;br /&gt;
                },&lt;br /&gt;
              legend: { show: true, placement: &amp;#039;outsideGrid&amp;#039;},&lt;br /&gt;
             cursor: { show: false, zoom: false, dblClickReset: false }&lt;br /&gt;
        },&lt;br /&gt;
        bar: {&lt;br /&gt;
              seriesDefaults: {&lt;br /&gt;
                         renderer: jQuery.jqplot.BarRenderer,&lt;br /&gt;
                         pointLabels: { show: true },&lt;br /&gt;
                         rendererOptions: { varyBarColor: true, animation: {speed: 3000} }&lt;br /&gt;
                        },&lt;br /&gt;
              axes: {&lt;br /&gt;
                        xaxis: {&lt;br /&gt;
                                renderer: jQuery.jqplot.CategoryAxisRenderer,&lt;br /&gt;
                                tickOptions: { angle: -30 },&lt;br /&gt;
                                tickRenderer:jQuery.jqplot.CanvasAxisTickRenderer,&lt;br /&gt;
                                labelRenderer: jQuery.jqplot.CanvasAxisLabelRenderer&lt;br /&gt;
                        }&lt;br /&gt;
                 },&lt;br /&gt;
              cursor: { show: false, zoom: false, dblClickReset: false }&lt;br /&gt;
        }&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Now we need to patch jquery.jqplot.js(dont&amp;#039; ask, some problems with jQuery.noconflict). Create a file called patch_jqplot.txt with this content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@@ -11055,7 +11055,7 @@&lt;br /&gt;
 &lt;br /&gt;
 })(jQuery);  &lt;br /&gt;
 &lt;br /&gt;
-&lt;br /&gt;
+(function($){&lt;br /&gt;
     var backCompat = $.uiBackCompat !== false;&lt;br /&gt;
 &lt;br /&gt;
     $.jqplot.effects = {&lt;br /&gt;
@@ -11205,7 +11205,8 @@&lt;br /&gt;
         }&lt;br /&gt;
 &lt;br /&gt;
         // catch (effect, speed, ?)&lt;br /&gt;
-        if ( $.type( options ) === &amp;quot;number&amp;quot; || $.fx.speeds[ options ]) {&lt;br /&gt;
+        //if ( $.type( options ) === &amp;quot;number&amp;quot; || $.fx.speeds[ options ]) {&lt;br /&gt;
+        if ( typeof( options ) === &amp;quot;number&amp;quot; || $.fx.speeds[ options ]) {&lt;br /&gt;
             callback = speed;&lt;br /&gt;
             speed = options;&lt;br /&gt;
             options = {};&lt;br /&gt;
@@ -11377,5 +11378,5 @@&lt;br /&gt;
         });&lt;br /&gt;
 &lt;br /&gt;
     };&lt;br /&gt;
-&lt;br /&gt;
-&lt;br /&gt;
+ })(jQuery);&lt;br /&gt;
+ &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Then run:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 patch -u ./jquery.jqplot.js ./patch_jqplot.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Minify everything into a file called charts.min.js. If you have jsmin installed, you can use this bash code:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
for f in  &amp;quot;&lt;br /&gt;
     jquery.jqplot.js&lt;br /&gt;
      jqplot.pieRenderer.js&lt;br /&gt;
      jqplot.barRenderer.js&lt;br /&gt;
      jqplot.categoryAxisRenderer.js&lt;br /&gt;
      jqplot.dateAxisRenderer.js&lt;br /&gt;
      jqplot.canvasAxisLabelRenderer.js&lt;br /&gt;
      jqplot.canvasAxisTickRenderer.js&lt;br /&gt;
      jqplot.canvasTextRenderer.js&lt;br /&gt;
      jqplot.cursor.js&lt;br /&gt;
      excanvas.js&lt;br /&gt;
      jqplot.pointLabels.js&lt;br /&gt;
      config.charts.js&lt;br /&gt;
      charts.js&lt;br /&gt;
  &amp;quot;; do cat $f | /path/to/rt/bin/jsmin &amp;gt;&amp;gt; charts.min.js; done&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Or you might prefer to only concatenate them in order to simplify debugging in the browser. Make sure you use the filename charts.min.js as that&amp;#039;s the one loaded in the browser. The debugging is going to be a bit tricky as I&amp;#039;m loading this script dynamically. Sorry.&lt;br /&gt;
&lt;br /&gt;
* Create a copy of the Charts.html file in the ../local directory like that:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
cp /path/to/your/rt/share/html/Search/Chart.html /path/to/your/rt/local/html/Search/Chart.html&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Patch it. Create a file called patch_Chart_html.txt containing this:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
@@ -69,7 +69,6 @@&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 my $title = loc( &amp;quot;Search results grouped by [_1]&amp;quot;, $PrimaryGroupByLabel );&lt;br /&gt;
-&lt;br /&gt;
 my $saved_search = $m-&amp;gt;comp( &amp;#039;/Widgets/SavedSearch:new&amp;#039;,&lt;br /&gt;
     SearchType   =&amp;gt; &amp;#039;Chart&amp;#039;,&lt;br /&gt;
     SearchFields =&amp;gt; [qw(Query PrimaryGroupBy ChartStyle)] );&lt;br /&gt;
@@ -94,6 +93,7 @@&lt;br /&gt;
         SavedSearchLoad&lt;br /&gt;
         SavedSearchLoadButton&lt;br /&gt;
         SavedSearchOwner&lt;br /&gt;
+        ChartStyle &lt;br /&gt;
     );&lt;br /&gt;
 &lt;br /&gt;
     for(@session_fields) {&lt;br /&gt;
@@ -110,7 +110,6 @@&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
 }&lt;br /&gt;
-&lt;br /&gt;
 &amp;lt;/%init&amp;gt;&lt;br /&gt;
 &amp;lt;&amp;amp; /Elements/Header, Title =&amp;gt; $title &amp;amp;&amp;gt;&lt;br /&gt;
 &amp;lt;&amp;amp; /Elements/Tabs, QueryArgs =&amp;gt; \%query &amp;amp;&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Then patch Chart.html:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 patch -u /path/to/rt/local/html/Search/Chart.html patch_Chart_html.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Create a file /path/to/rt/local/html/Search/Elements/Chart and put this inside:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;%args&amp;gt;&lt;br /&gt;
$Query =&amp;gt; &amp;quot;id &amp;gt; 0&amp;quot;&lt;br /&gt;
$PrimaryGroupBy =&amp;gt; &amp;#039;Queue&amp;#039;&lt;br /&gt;
$ChartStyle =&amp;gt; &amp;#039;bars&amp;#039;&lt;br /&gt;
&amp;lt;/%args&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;%once&amp;gt;&lt;br /&gt;
my $ChartDivIndex = 0;&lt;br /&gt;
&amp;lt;/%once&amp;gt;&lt;br /&gt;
&amp;lt;script type=&amp;quot;text/javascript&amp;quot;&amp;gt;&lt;br /&gt;
 if(window.chartObj === undefined){&lt;br /&gt;
         window.chartObj = { &amp;lt;%$ChartDivIndex |n %&amp;gt; : {&lt;br /&gt;
                                                ChartStyle: &amp;lt;%$ChartStyle |n, j%&amp;gt;, PrimaryGroupBy:  &amp;lt;% $PrimaryGroupBy |n, j %&amp;gt;, Query: &amp;lt;% $Query |n, j %&amp;gt;&lt;br /&gt;
                        }&lt;br /&gt;
                     };  &lt;br /&gt;
        jQuery(document).ready(function(){&lt;br /&gt;
                        jQuery.getScript(&amp;#039;/NoAuth/js/charts.min.js&amp;#039;, function(){setupCharts(window.chartObj)});&lt;br /&gt;
                        jQuery(&amp;#039;&amp;lt;link&amp;gt;&amp;#039;).appendTo(&amp;#039;head&amp;#039;).attr({&lt;br /&gt;
                                rel: &amp;#039;stylesheet&amp;#039;,&lt;br /&gt;
                                type: &amp;#039;text/css&amp;#039;,&lt;br /&gt;
                                href: &amp;#039;/NoAuth/css/jquery.jqplot.min.css&amp;#039;&lt;br /&gt;
                        });&lt;br /&gt;
        });&lt;br /&gt;
 } else {&lt;br /&gt;
        window.chartObj[&amp;lt;%$ChartDivIndex |n %&amp;gt;] = {&lt;br /&gt;
                                                ChartStyle: &amp;lt;%$ChartStyle |n, j%&amp;gt;, PrimaryGroupBy:  &amp;lt;% $PrimaryGroupBy |n, j %&amp;gt;, Query: &amp;lt;% $Query |n, j %&amp;gt;&lt;br /&gt;
                        };&lt;br /&gt;
 };       &lt;br /&gt;
&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;chart-wrapper&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;span class=&amp;quot;chart image&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div id=&amp;lt;% &amp;quot;plot&amp;quot;.$ChartDivIndex |n %&amp;gt; style=&amp;quot;position:relative;height:auto;width:auto&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;table class=&amp;quot;collection-as-table chart&amp;quot; id =&amp;lt;% &amp;quot;Results&amp;quot;.$ChartDivIndex |n %&amp;gt;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;th class=&amp;quot;collection-as-table&amp;quot; id=&amp;lt;%&amp;quot;Header&amp;quot;.$ChartDivIndex |n %&amp;gt;&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;
&amp;lt;th class=&amp;quot;collection-as-table&amp;quot;&amp;gt;Tickets&amp;lt;/th&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
% $ChartDivIndex++;&lt;br /&gt;
&amp;lt;div class=&amp;quot;query&amp;quot;&amp;gt;&amp;lt;span class=&amp;quot;label&amp;quot;&amp;gt;&amp;lt;% loc(&amp;#039;Query&amp;#039;) %&amp;gt;:&amp;lt;/span&amp;gt;&amp;lt;span class=&amp;quot;value&amp;quot;&amp;gt;&amp;lt;% $Query %&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Create a file called /path/to/your/rt/local/html/Helpers/LoadChart with this content:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
% $r-&amp;gt;content_type(&amp;#039;application/json&amp;#039;);&lt;br /&gt;
&amp;lt;% $response |n %&amp;gt;&lt;br /&gt;
% $m-&amp;gt;abort;&lt;br /&gt;
&amp;lt;%args&amp;gt;&lt;br /&gt;
$Query =&amp;gt; &amp;quot;id &amp;gt; 0&amp;quot;&lt;br /&gt;
$PrimaryGroupBy =&amp;gt; &amp;#039;Queue&amp;#039;&lt;br /&gt;
$ChartStyle =&amp;gt; &amp;#039;bars&amp;#039;&lt;br /&gt;
&amp;lt;/%args&amp;gt;&lt;br /&gt;
&amp;lt;%init&amp;gt;&lt;br /&gt;
use JSON;&lt;br /&gt;
use RT::Report::Tickets;&lt;br /&gt;
$PrimaryGroupBy ||= &amp;#039;Queue&amp;#039;; # make sure PrimaryGroupBy is not undef&lt;br /&gt;
my $called_by = $m-&amp;gt;callers(1)-&amp;gt;name();&lt;br /&gt;
my $tix = RT::Report::Tickets-&amp;gt;new( $session{&amp;#039;CurrentUser&amp;#039;} );&lt;br /&gt;
my %AllowedGroupings = reverse $tix-&amp;gt;Groupings( Query =&amp;gt; $Query );&lt;br /&gt;
$PrimaryGroupBy = &amp;#039;Queue&amp;#039; unless exists $AllowedGroupings{$PrimaryGroupBy};&lt;br /&gt;
my ($count_name, $value_name) = $tix-&amp;gt;SetupGroupings(&lt;br /&gt;
    Query =&amp;gt; $Query, GroupBy =&amp;gt; $PrimaryGroupBy,&lt;br /&gt;
);&lt;br /&gt;
my %class = (&lt;br /&gt;
    Queue =&amp;gt; &amp;#039;RT::Queue&amp;#039;,&lt;br /&gt;
    Owner =&amp;gt; &amp;#039;RT::User&amp;#039;,&lt;br /&gt;
    Creator =&amp;gt; &amp;#039;RT::User&amp;#039;,&lt;br /&gt;
    LastUpdatedBy =&amp;gt; &amp;#039;RT::User&amp;#039;,&lt;br /&gt;
);&lt;br /&gt;
my $class = $class{ $PrimaryGroupBy };&lt;br /&gt;
&lt;br /&gt;
my (@keys, @values);&lt;br /&gt;
while ( my $entry = $tix-&amp;gt;Next ) {&lt;br /&gt;
    if ($class) {&lt;br /&gt;
        my $q = $class-&amp;gt;new( $session{&amp;#039;CurrentUser&amp;#039;} );&lt;br /&gt;
        $q-&amp;gt;Load( $entry-&amp;gt;LabelValue( $value_name ) );&lt;br /&gt;
        push @keys, $q-&amp;gt;Name;&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        push @keys, $entry-&amp;gt;LabelValue( $value_name );&lt;br /&gt;
    }&lt;br /&gt;
    $keys[-1] ||= loc(&amp;#039;(no value)&amp;#039;);&lt;br /&gt;
    push @values, $entry-&amp;gt;__Value( $count_name );&lt;br /&gt;
}&lt;br /&gt;
my %data;&lt;br /&gt;
my %loc_keys;&lt;br /&gt;
foreach my $key (@keys) { $data{$key} = shift @values; $loc_keys{$key} = loc($key); }&lt;br /&gt;
my @sorted_keys = map { $loc_keys{$_}} sort { $loc_keys{$a} cmp $loc_keys{$b} } keys %loc_keys;&lt;br /&gt;
my @sorted_values = map { $data{$_}} sort { $loc_keys{$a} cmp $loc_keys{$b} } keys %loc_keys;&lt;br /&gt;
my $query_string = $m-&amp;gt;comp(&amp;#039;/Elements/QueryString&amp;#039;, %ARGS);&lt;br /&gt;
&lt;br /&gt;
my ($i,$total);&lt;br /&gt;
my @ticks = @sorted_keys;&lt;br /&gt;
my @vals;&lt;br /&gt;
if ($ChartStyle =~ /^bar/) {&lt;br /&gt;
        @vals = @sorted_values;&lt;br /&gt;
} elsif ($ChartStyle  =~ /^pie|^line/) {&lt;br /&gt;
         @vals = map [$_, $data{$_}], @sorted_keys;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
my $response = to_json({ticks =&amp;gt; \@ticks, vals =&amp;gt; \@vals });&lt;br /&gt;
&amp;lt;/%init&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
This will be the endpoint of the ajax call that gets the chart data.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;So what&amp;#039;s happening then (very succinctly)?&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
I moved all the internal &amp;quot;execute the query and give us the results&amp;quot; logic from the ../Elements/Chart component to the ../Helpers/LoadChart component. Almost&amp;amp;nbsp;wholesale, not many changes, just made it return results as json.&lt;br /&gt;
&lt;br /&gt;
The Chart component now does the following:&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;- loads the script charts.min.js. I don&amp;#039;t want to use the normal @JSFiles path because it&amp;#039;s rather heavy, more than 300k and it&amp;#039;s only used for the &amp;quot;Chart&amp;quot; or &amp;quot;Dashboard&amp;quot; pages&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;- Once loaded, it executes the function SetupCharts. This in turn fires an ajax call to LoadCharts, draws the charts (via js function drawchart) and populates the result tables.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;- There&amp;#039;s some hacky logic in there to handle dashboards. If I have more than one chart per page I don&amp;#039;t want to load the scripts/create the document.ready() jQuery call more than once. I also need different names for the wrapper divs. I&amp;#039;m not particularly proud of this part, but it works.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;- There&amp;#039;s a nice side efect in dashboards: as the charts are now populated via ajax calls, this will happen in parallel (browser permitting).&lt;br /&gt;
&lt;br /&gt;
I added the new style &amp;quot;line&amp;quot;, available only for time related charts (CreatedMonthly....). If you pick this style you&amp;#039;ll be able to zoom into the chart by selecting an area. Double click to zoom back.&lt;br /&gt;
&lt;br /&gt;
No download as image at the moment I&amp;#039;m afraid, you&amp;#039;ll have to use some sniping tool in order to copy them.&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>