<html>

<head>
  <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
</head>

<body itemscope itemtype="http://schema.org/Action">

  <section id="mdx_mainwrap" class="container-fluid">

    <div id="content">
      <div class="site-width">
        <div class="row">

          <section id="mdx_contentmainwrap">

            <section id="mdx_content" class="col-md-9 margin40">

              <article class="mdx_contentmain">
                <div class="content">

                  <div id="postMain" class="">
                    <script type="text/javascript">
                      google.charts.load("current", {
                        "packages": ["corechart", "controls"]
                      });
                      google.charts.setOnLoadCallback(drawDashboard);
                      var chartTable;

                      function drawDashboard() {
                        var dashboard = new google.visualization.Dashboard(
                          document.getElementById('dashboard_div'));
                        var slider = new google.visualization.ControlWrapper({
                          'controlType': 'NumberRangeFilter',
                          'containerId': 'slider_div',
                          'options': {
                            'filterColumnIndex': 6,
                            'minValue': 0,
                            'ui': {
                              'labelStacking': 'vertical',
                              'label': 'Filter Total Cost'
                            }
                          }
                        });
                        var categoryPicker = new google.visualization.ControlWrapper({
                          'controlType': 'CategoryFilter',
                          'containerId': 'categoryPicker_div',
                          'options': {
                            'filterColumnIndex': 1,
                            'ui': {
                              'labelStacking': 'vertical',
                              'label': '',
                              'allowTyping': false,
                              'allowMultiple': true,
                              'sortValues': false,
                              'caption': 'Select types...',
                            }
                          },
                          'state': {
                            'selectedValues': ['ES', 'MS', 'HS', 'Other']
                          }
                        });
                        var pie = new google.visualization.ChartWrapper({
                          'chartType': 'PieChart',
                          'containerId': 'piechart_div',
                          'options': {
                            'width': 300,
                            'height': 300,
                            'legend': 'none',
                            'chartArea': {
                              'left': 15,
                              'top': 15,
                              'right': 0,
                              'bottom': 20
                            },
                            'pieSliceText': 'label',
                            'backgroundColor': 'none'
                          },
                          'view': {
                            'columns': [0, 4]
                          }
                        });
                        chartTable = new google.visualization.ChartWrapper({
                          'chartType': 'Table',
                          'containerId': 'table_div',
                          'options': {
                            width: '100%',
                            height: '100%',
                            'view': {
                              columns: '[0,4,5]'
                            },
                            'frozenColumns': 1,
                            'allowHtml': true,
                            'cssClassNames': {
                              headerRow: 'chartHrow',
                              headerCell: 'chartHcell'
                            }
                          }
                        });
                        var data = google.visualization.arrayToDataTable([
                          ['Facility', 'Type', 'Hard Costs', 'Soft Costs', 'Escalation', 'Contigency', 'Total'],
                          ["Arovista ES", "ES", 15841494, 4277203, 5029674, 2514837, 27663209],
                          ["Brea Canyon HS", "HS", 2372719, 640634, 753338, 376669, 4143360],
                          ["Country Hills ES", "ES", 12490072, 3372320, 3965598, 1982799, 21810789],
                          ["Brea Junior High", "MS", 24843927, 6707860, 7887947, 3943973, 43383708],
                          ["Brea Olinda HS", "HS", 79205632, 21385521, 25147788, 12573894, 138312835],
                          ["Laurel ES", "ES", 12354669, 3335761, 3922607, 1961304, 21574340],
                          ["Mariposa ES", "ES", 12691499, 3426705, 4029551, 2014775, 22162529],
                          ["Olinda ES", "ES", 360141, 97238, 114345, 57172, 628897],
                          ["Fanning ES", "ES", 11554998, 311949, 3668712, 1834356, 20177915]
                        ]);
                        var columnsTable = new google.visualization.DataTable();
                        columnsTable.addColumn('number', 'colIndex');
                        columnsTable.addColumn('string', 'colLabel');
                        var initState = {
                          selectedValues: []
                        };
                        // put the columns into this data table (skip column 0<<and 1>>)
                        for (var i = 2; i < data.getNumberOfColumns(); i++) {
                          columnsTable.addRow([i, data.getColumnLabel(i)]);
                          // you can comment out this next line if you want
                          // to have a default selection other than the whole list
                          //initState.selectedValues.push(data.getColumnLabel(i));
                        }
                        // you can set individual columns to be the default columns
                        // (instead of populating via the loop above) like this:
                        initState.selectedValues.push(data.getColumnLabel(6));
                        var columnFilter = new google.visualization.ControlWrapper({
                          controlType: 'CategoryFilter',
                          containerId: 'colFilter_div',
                          dataTable: columnsTable,
                          options: {
                            filterColumnLabel: 'colLabel',
                            ui: {
                              labelStacking: 'vertical',
                              label: 'Cost Column to Visualize:',
                              allowTyping: false,
                              allowMultiple: false, // <<was true>>
                              allowNone: false,
                              sortValues: false, // <<added>>
                              selectedValuesLayout: 'belowStacked'
                            }
                          },
                          state: initState
                        });

                        function setChartView() {
                          var state = columnFilter.getState();
                          var row;
                          var view = {
                            columns: [0]
                          };
                          for (var i = 0; i < state.selectedValues.length; i++) {
                            row = columnsTable.getFilteredRows([{
                              column: 1,
                              value: state.selectedValues[i]
                            }])[0];
                            view.columns.push(columnsTable.getValue(row, 0));
                          }
                          // sort the indices into their original order
                          view.columns.sort(function(a, b) {
                            return (a - b);
                          });
                          pie.setView(view);
                          pie.draw();
                          // <<added these remaining lines to tie into slider control>>
                          var label = 'Filter by ' + state.selectedValues[0] + ' Cost:';
                          slider.setOption('ui', {
                            'labelStacking': 'vertical',
                            'label': label,
                            'format': {
                              pattern: '$###,###'
                            }
                          });
                          slider.setOption('filterColumnIndex', columnsTable.getValue(row, 0));
                          slider.draw();
                          for (var i = 0; i < 7; i++) { // manually update i=number to actual column count
                            data.setColumnProperty(i, 'className', 'chartHcell');
                          }
                          data.setColumnProperty(columnsTable.getValue(row, 0), 'className', 'chartHighlight');
                          //  data.setColumnProperty(columnsTable.getValue(row, 0), 'className', 'chartHighlight');
                        }
                        google.visualization.events.addListener(columnFilter, 'statechange', setChartView);
                        setChartView();
                        columnFilter.draw();
                        // end code for CategoryFilter column selector by Andrew Gallant
                        var usdFormatter = new google.visualization.NumberFormat({
                          pattern: '$###,###'
                        });
                        usdFormatter.format(data, 2);
                        usdFormatter.format(data, 3);
                        usdFormatter.format(data, 4);
                        usdFormatter.format(data, 5);
                        usdFormatter.format(data, 6);

                        function jumpToSite() {
                          // note that you have to insert "getChart()" 
                          // between chartTable and getSelection() in order
                          // to access the selection through the dashboard
                          var selection = chartTable.getChart().getSelection();
                          var message = '';
                          var view = chartTable.getDataTable();
                          for (var i = 0; i < selection.length; i++) {
                            var item = selection[i];
                            if (item.row != null && item.column != null) {} else if (item.row != null) {
                              // references view instead of data 
                              message = view.getFormattedValue(item.row, 0);
                            } else if (item.column != null) {
                              // references view instead of data
                              message = view.getFormattedValue(0, item.column);
                            }
                          }
                          var jump = "#" + message + "costs";
                          document.location.hash = jump;
                        }
                        // google.visualization.events.addListener(chartTable, 'select', jumpToSite);
                        dashboard.bind([slider, categoryPicker], [pie, chartTable]);
                        // added next two lines per Brian Nolan's bootstrap table row
                        google.visualization.events.addListener(chartTable, 'ready', calcTotal);
                        google.visualization.events.addOneTimeListener(chartTable, 'ready', addSortListener);
                        dashboard.draw(data);
                        // added this function per Brian Nolan's bootstrap table row
                        function addSortListener() {
                          google.visualization.events.addListener(chartTable.getChart(), 'sort', calcTotal);
                        }
                      }
                      //total the columns
                      function calcTotal() {
                        var filteredData = chartTable.getDataTable();
                        var columnIndicesToTotal = [2, 3, 4, 5, 6]; // which columns have sums
                        var totals = {}
                        for (var i = 0; i < columnIndicesToTotal.length; i++) {
                          var total = 0;
                          for (var row = 0; row < filteredData.getNumberOfRows(); row++) {
                            total += filteredData.getValue(row, columnIndicesToTotal[i]);
                          }
                          totals[columnIndicesToTotal[i]] = total;
                        }
                        displayTotals(filteredData, totals);
                      }

                      function displayTotals(filteredData, totals) {
                        var htmlString;
                        htmlString = '<tr class="google-visualization-table-tr-even chartHrow">';
                        htmlString += '<td class="google-visualization-table-td">Totals:</td>';
                        for (var col = 1; col < filteredData.getNumberOfColumns(); col++) {
                          if (totals[col]) {
                            var tempSum = '$' + totals[col].toLocaleString('en');
                            htmlString += '<td class="google-visualization-table-td google-visualization-table-td-number chartHcell">' + tempSum + '</td>';
                          } else {
                            htmlString += '<td class="google-visualization-table-td google-visualization-table-td-bool">&nbsp;</td>';
                          }
                        }
                        htmlString += '</tr>';
                        $('#table_div').find('table').append(htmlString);
                      };
                    </script>

                    <div id="dashboard_div">

                      <table width=100%>
                        <tr>
                          <td>
                            <div id="piechart_div" align="center"></div>
                            <div id="colFilter_div" align="center" style="padding: 1em"></div>

                          </td>
                          <td>
                            <div id="slider_div" width="100" align="center" style="padding: 1em"></div>
                            <div id="categoryPicker_div" align="center" style="padding: 1em"></div>

                          </td>
                        </tr>
                        <tr>
                          <td>
                          </td>

                        </tr>
                      </table>
                      <div id="table_div" width=100%></div>

                    </div>
                    <hr/>
                  </div>
                </div>
              </article>
            </section>
          </section>
        </div>
      </div>
    </div>
  </section>
  </div>
  <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
</body>

</html>

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.