3

I use jQuery and I use the following JS function to load and reload / redraw the Google Chart Calendar.

It works, however, it also removes the border from the selected item. I want to reload the calendar data, while keeping the currently selected item selected.

enter image description here

Any ideas?

function refreshCalendar( rows)
{
    //if( calendar != 0 )
    {
        calendar = new google.visualization.Calendar(document.getElementById('calendar_basic'))

        google.visualization.events.addListener(calendar, 'select', calendarSelectHandler);

        calendarData = new google.visualization.DataTable();
        calendarData.addColumn({ type: 'date', id: 'Date' });
        calendarData.addColumn({ type: 'number', id: 'Logs' });
        calendarData.addRows( rows );

        calendarOptions = {
            title: "Logs",
            height: 175,
            colorAxis: {minValue: 0,  colors: ['#FFFFFF', '#FF0000']},
            calendar: {
              focusedCellColor: {
                background: '#00FF00',
                stroke: '#004400',
                strokeOpacity: 1,
                strokeWidth: 2,
              },
              cellColor: {
                stroke: '#76a7fa',
                strokeOpacity: 0.5,
                strokeWidth: 1,
              }
            }
        };

        calendar.draw(calendarData, calendarOptions);
    }
}
Z0q
  • 1,689
  • 3
  • 28
  • 57

2 Answers2

2

Normally, you would use chart.getSelection and chart.setSelection.

Get selection on 'select' event
Set selection on 'ready' event

getSelection works fine, but setSelection doesn't work with the Calendar chart.
No error is thrown, but nothing is selected.
I tried versions '41' thru 'current'...

To demonstrate, the following example uses both a Calendar chart and a Column chart.
Make a selection on both charts, then click "Redraw Chart".
The selection for the Column chart remains but not on the Calendar.

google.charts.load('current', {
  callback: drawChart,
  packages: ['calendar', 'corechart']
});

function drawChart() {
  var selectionCal;
  var selectionCol;

  var calendar = new google.visualization.Calendar(document.getElementById('calendar'))
  google.visualization.events.addListener(calendar, 'select', function () {
    selectionCal = calendar.getSelection();
  });
  google.visualization.events.addListener(calendar, 'ready', function () {
    if (selectionCal) {
      calendar.setSelection(selectionCal);
    }
  });

  var column = new google.visualization.ColumnChart(document.getElementById('column'))
  google.visualization.events.addListener(column, 'select', function () {
    selectionCol = column.getSelection();
  });
  google.visualization.events.addListener(column, 'ready', function () {
    if (selectionCol) {
      column.setSelection(selectionCol);
    }
  });

  document.getElementById('test_button').addEventListener('click', function () {
    calendar.draw(calendarData, calendarOptions);
    column.draw(calendarData, {});
  }, false);

  var calendarData = new google.visualization.DataTable();
  calendarData.addColumn({ type: 'date', id: 'Date' });
  calendarData.addColumn({ type: 'number', id: 'Logs' });
  calendarData.addRows([
    [ new Date(2012, 3, 13), 37032 ],
    [ new Date(2012, 3, 14), 38024 ],
    [ new Date(2012, 3, 15), 38024 ],
    [ new Date(2012, 3, 16), 38108 ],
    [ new Date(2012, 3, 17), 38229 ],
  ]);

  var calendarOptions = {
      title: "Logs",
      height: 175,
      colorAxis: {minValue: 0,  colors: ['#FFFFFF', '#FF0000']},
      calendar: {
        focusedCellColor: {
          background: '#00FF00',
          stroke: '#004400',
          strokeOpacity: 1,
          strokeWidth: 2,
        },
        cellColor: {
          stroke: '#76a7fa',
          strokeOpacity: 0.5,
          strokeWidth: 1,
        }
      }
  };

  calendar.draw(calendarData, calendarOptions);
  column.draw(calendarData, {});
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="calendar"></div>
<div id="column"></div>
<input type="button" id="test_button" value="Redraw Chart" />
WhiteHat
  • 59,912
  • 7
  • 51
  • 133
  • So you're proving that it is not possible for calendars? – Z0q Mar 24 '16 at 13:58
  • 2
    that is correct, only other way would be to modify the SVG once the chart's ready event has fired / try to place your own marker – WhiteHat Mar 24 '16 at 16:11
  • I've also ran into this problem when trying to clear the selected cell with chart.setSelection(); [doesn't work] – h0dges Nov 15 '16 at 15:24
0

I can also confirm that the setSelection() method doesn't change anything on the UI for the calendar chart.

So I looked up what happens after selecting a day in the chart with the mouse. Then I implemented a simple DOM manipulation logic which does the same. You can use that logic as a replacement of the setSelection() use case. (It is just a quick prototype, but I hope it helps you, too).

For a litte demo I adjusted @WhiteHat snippet / the selected day survives now the refresh action (doesn't work with charts which needs to display more than one year!):

google.charts.load('current', {
  callback: drawChart,
  packages: ['calendar', 'corechart']
});

function drawChart() {
  var selectionCal;
  var selectionDate;
  var selectionCol;

  var calendar = new google.visualization.Calendar(document.getElementById('calendar'))
  google.visualization.events.addListener(calendar, 'select', function () {
    selectionCal = calendar.getSelection();
    selectionDate = new Date(selectionCal[0].date);
  });
  google.visualization.events.addListener(calendar, 'ready', function () {
    if (selectionDate) {
      // google calendar setSelection BUG :/
      // https://stackoverflow.com/a/36093217/810944
      // do it manually
      var doy = selectionDate.getDOY();
      markDayInChart(doy);
    }
  });

  var column = new google.visualization.ColumnChart(document.getElementById('column'))
  google.visualization.events.addListener(column, 'select', function () {
    selectionCol = column.getSelection();
  });
  google.visualization.events.addListener(column, 'ready', function () {
    if (selectionCol) {
      column.setSelection(selectionCol);
    }
  });

  document.getElementById('test_button').addEventListener('click', function () {
    calendar.draw(calendarData, calendarOptions);
    column.draw(calendarData, {});
  }, false);

  var calendarData = new google.visualization.DataTable();
  calendarData.addColumn({ type: 'date', id: 'Date' });
  calendarData.addColumn({ type: 'number', id: 'Logs' });
  calendarData.addRows([
    [ new Date(2012, 3, 13), 37032 ],
    [ new Date(2012, 3, 14), 38024 ],
    [ new Date(2012, 3, 15), 38024 ],
    [ new Date(2012, 3, 16), 38108 ],
    [ new Date(2012, 3, 17), 38229 ],
  ]);

  var calendarOptions = {
      title: "Logs",
      height: 175,
      colorAxis: {minValue: 0,  colors: ['#FFFFFF', '#FF0000']},
      calendar: {
        focusedCellColor: {
          background: '#00FF00',
          stroke: '#004400',
          strokeOpacity: 1,
          strokeWidth: 2,
        },
        cellColor: {
          stroke: '#76a7fa',
          strokeOpacity: 0.5,
          strokeWidth: 1,
        }
      }
  };

  calendar.draw(calendarData, calendarOptions);
  column.draw(calendarData, {});
}

function markDayInChart(dayOfYear) {
    // clones the logic for clicking / selecting a day via mouse
    // keep in mind to clean up the adjusted and added `rect`-elements if you do not use full page reloads!
    // doesn't work with charts which needs to display more than one year!
    var days_all_svg_group = $('#calendar svg').children('g')[1];
    var days_marked_svg_group = $('#calendar svg').children('g')[4];
    var day_svg_rect = $('rect:nth-of-type('+dayOfYear+')',$(days_all_svg_group));

    // hide the original rect
    $(day_svg_rect).css('display: none;');

    // add a cloned rect with a different stroke
    var day_marked_svg_rect = $(day_svg_rect).clone();
    $(day_marked_svg_rect).attr({stroke: '#000000', 'stroke-width': 2});
    $(day_marked_svg_rect).attr('stroke-opacity', null);
    $(days_marked_svg_group).append(day_marked_svg_rect);
  }

  // https://stackoverflow.com/a/26426761/810944
  Date.prototype.isLeapYear = function() {
    var year = this.getFullYear();
    if((year & 3) != 0) return false;
    return ((year % 100) != 0 || (year % 400) == 0);
  };

  // Get Day of Year
  Date.prototype.getDOY = function() {
      var dayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
      var mn = this.getMonth();
      var dn = this.getDate();
      var dayOfYear = dayCount[mn] + dn;
      if(mn > 1 && this.isLeapYear()) dayOfYear++;
      return dayOfYear;
  };
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="calendar"></div>
<div id="column"></div>
<input type="button" id="test_button" value="Redraw Chart" />
Community
  • 1
  • 1
einsA
  • 797
  • 1
  • 7
  • 19