1/******************************************************************************
2 *
3 * jquery.graphTable2-0.1.js
4 * by rebecca murphey
5 * http://blog.rebeccamurphey.com
6 * rmurphey gmail com
7 * License: GPL
8 * 17 December 2007
9 *
10 * table2Plot.js
11 * by tom cafferty
12 * http://www.glocalfocal.com
13 * tcafferty glocalfocal com
14 * License: GPL
15 * 03 December 2011
16 *
17 * requires:
18 *
19 *   - jquery.js (http://jquery.com) -- tested with 1.4.2
20 *   - jquery.jqplot (https://bitbucket.org/cleonello/jqplot/wiki/Home)
21 *
22 * usage:
23 *
24 *   jQuery('#myTable').tablePlot(graphTableOptionsObject,jplotOptionsObject);
25 *
26 *   - both arguments are optional; defaults will work in most cases
27 *     but you'll need to include {series: 'columns'} if your data is
28 *     in columns.
29 *   - for details on tablePlot options and defaults, see below.
30 *   - for details on jqlot options and defaults, see
31 *     http://www.jqplot.com/
32 *
33 * notes:
34 *
35 *   - this isn't going to work well with tables that use rowspan or colspan
36 *   - make sure to use the transform args to transform your cell contents into
37 *     something flot can understand -- especially important if your cells
38 *     contain currency or dates
39 *
40 ******************************************************************************/
41
42(function($) {
43
44 jQuery.fn.tablePlot = function(graphArgs_,plotArgs_) {
45
46    var args = {
47      /*
48       * options for reading the table -- defaults will work in most cases except
49       * you'll want to override the default args.series if your series are in columns
50       *
51       * note that anywhere the word "index" is used, the count starts from 0 at
52       * the top left of the table
53       *
54       */
55      series: 'rows', // are the series in rows or columns?
56      labels: 0, // index of the cell in the series row/column that contains the label for the series
57      xaxis: 0, // index of the row/column (whatever args.series is) that contains the x values
58      firstSeries: 1, // index of the row/column containing the first series
59      lastSeries: null, // index of the row/column containing the last series; will use the last cell in the row/col if not set
60      dataStart: 1, // index of the first cell in the series containing data
61      dataEnd: null, // index of the last cell in the series containing data; will use the last cell in the row/col if not set
62
63      /* graph size and position */
64      position: 'after', // before the table, after the table, or replace the table
65      width: null, // set to null to use the width of the table
66      height: null, // set to null to use the height of the table
67      min: 0, // defaults to minimum y value in the table
68      max: 0, // defaults to maximum y value in the table
69
70      /* data transformation before plotting */
71      dataTransform: null, // function to run on cell contents before passing to flot; string -> string
72      labelTransform: null, // function to run on cell contents before passing to flot; string -> string
73      xaxisTransform: null // function to run on cell contents before passing to flot; string -> string
74    }
75
76    // override defaults with user args
77    $.extend(true,args,graphArgs_);
78
79    /* default to last cell in the row/col for
80     * lastSeries and dataEnd if they haven't been set yet */
81
82    // index of the row/column containing the last series
83    if (! args.lastSeries) {
84      args.lastSeries = (args.series == 'columns') ?
85        $('tr',$(this)).eq(args.labels).find('th,td').length - 1 :
86        $('tr',$(this)).length - 1;
87    }
88
89    // index of the last cell in the series containing data
90    if (! args.dataEnd) {
91      args.dataEnd = (args.series == 'rows') ?
92        $('tr',$(this)).eq(args.firstSeries).find('th,td').length - 1:
93        $('tr',$(this)).length - 1;
94    }
95
96    return $(this).each(function() {
97      // use local min/max for y of each graph, based on initial args
98      var $table = $(this);
99
100      // make sure the table is a table!
101      if (! $table.is('table')) { return; }
102
103      // if no height and width have been set, then set
104      // width and height based on the width and height of the table
105      if (! args.width) { args.width = $table.width(); }
106      if (! args.height) { args.height = $table.height(); }
107
108      var min = args.min;
109      var max = args.max;
110      var $rows = $('tr',$table);
111      var line1 = new Array();
112      var line2 = new Array(args.lastSeries+1);
113      for (i=1; i <args.lastSeries+1; i++) {
114          line2[i]=new Array();
115      }
116      var line3 = new Array(args.lastSeries);
117      for (i=0; i <args.lastSeries; i++) {
118          line3[i]=new Array();
119      }
120      var ticks = new Array();
121      var yVal  = new Array();
122
123      ind = 1;
124      switch (args.series) {
125
126        case 'rows':
127          var $xaxisRow = $rows.eq(args.xaxis);
128
129          // iterate over each of the rows in the series
130          for (i=args.firstSeries;i<=args.lastSeries;i++) {
131            dataIndex = i-args.firstSeries;
132            line1[dataIndex] = new Array();
133
134            $dataRow = $('tr',$table).eq(i);
135
136            // get the label for the whole row
137            var label = $('th,td',$dataRow).eq(args.labels).text();
138
139            if (args.labelTransform) { label = args.labelTransform(label); }
140
141            for (j=args.dataStart;j<=args.dataEnd;j++) {
142              var x = $('th,td',$xaxisRow).eq(j).text();
143              var y = $('th,td',$dataRow).eq(j).text();
144
145              if (args.dataTransform) { y = args.dataTransform(y); }
146              if (args.xaxisTransform) { x = args.xaxisTransform(x); }
147
148              if (args.orient == 'vertical') {
149                if (plotArgs_.stackSeries) {
150                   line2[i][j-1] = parseInt(y, 10);
151                   ind=ind+1;
152                } else
153                   line1[dataIndex][line1[dataIndex].length] = [x, y];
154              } else {
155                yVal[line1[dataIndex].length] = x;
156                line1[dataIndex][line1[dataIndex].length] = [y, j];
157              }
158            }
159          }
160          break;
161
162        case 'columns':
163          // iterate over each of the columns in the series
164          var $labelRow = $rows.eq(args.labels);
165
166          for (j=args.firstSeries;j<=args.lastSeries;j++) { // j designates the column
167            dataIndex = j-args.firstSeries;
168            line1[dataIndex] = new Array();
169
170            var label = $labelRow.find('th,td').eq(j).text();
171            if (args.labelTransform) { label = args.labelTransform(label); }
172
173            for (i=args.dataStart;i<=args.dataEnd;i++) { // i designates the row
174              $cell = $rows.eq(i).find('th,td').eq(j);
175              var y = $cell.text();
176              var x = $rows.eq(i).find('th,td').eq(args.xaxis).text();
177
178              if (args.dataTransform) { y = args.dataTransform(y); }
179              if (args.xaxisTransform) { x = args.xaxisTransform(x); }
180
181              if (args.orient == 'vertical') {
182                if (plotArgs_.stackSeries) {
183                   line2[j][i-1] = parseInt(y, 10);
184                   ind=ind+1;
185                   if (i > 0) ticks[i-1]=x;
186                } else
187                    line1[dataIndex][line1[dataIndex].length] = [x, y];
188              } else {
189                if (plotArgs_.stackSeries) {
190                   line2[j][i-1] = parseInt(y, 10);
191                   ind=ind+1;
192                } else {
193                    yVal[line1[dataIndex].length] = x;
194                    line1[dataIndex][line1[dataIndex].length] = [y, i];
195                }
196              }
197            }
198          }
199          break;
200      }
201
202      var divid = 'chartdiv_' + args.id;
203      var divstr = '<div id="'+divid+'" style="width:'+args.width+'px; height:'+args.height+'px;" class="plot-graph"></div>';
204      if (args.placement) {
205          $div = $("#"+args.placement);
206      } else
207      switch (args.position) {
208        case 'after':
209          $div = $table.after(divstr).next('div');
210          break;
211
212        case 'replace':
213          $div = $table.after(divstr).next('div');
214          $table.remove();
215          break;
216
217        default:
218          $div = $table.before(divstr).prev('div');
219          break;
220      }
221      var plotArgs;
222      if (args.orient == 'vertical')
223         if (plotArgs_.stackSeries)
224           var plotArgs = {axes: {xaxis: {renderer: jQuery.jqplot.CategoryAxisRenderer, tickOptions: {angle: -30}, ticks: ticks}}};
225         else
226           var plotArgs = plotArgs_;
227      else
228           var plotArgs = plotArgs_;
229      jQuery.extend(true,plotArgs,plotArgs_);
230
231     if (plotArgs_.stackSeries) {
232         for (i=1; i<=args.lastSeries; i++)
233             line3[i-1] = line2[i];
234         plot1 = jQuery.jqplot(divid, line3, plotArgs);
235     }
236     else
237       plot1 = jQuery.jqplot(divid, line1, plotArgs);
238    });
239  };
240
241})(jQuery);
242