The functionality of clicking on Google Visualization table chart to return row/column values is malfunctioning on Mozilla browser

I'm facing an issue with the code below that seems to behave differently in Chrome and Mozilla browsers.

In Chrome, when a cell is clicked, the code successfully returns the row / column clicked. However, in Mozilla, clicking a cell does not trigger any action.

I suspect the problem lies in this particular section of the code, but I'm unable to pinpoint the exact cause.

var selection = table.getChart().getSelection();
if (selection.length === 0)
  return;

var e = event || window.event;
var cell = e.target; //get selected cell

I came across a similar issue in a post from a few years back. The code snippet provided worked well in Chrome but failed to function in Mozilla, where clicking did not produce any result.

https://stackoverflow.com/questions/20165281/google-chart-getselection-doesnt-have-column-property/33445620#33445620

Here's the complete program. Any suggestions on resolving the Chrome vs Mozilla inconsistency?

Appreciate your help as always!

google.charts.load('current', {
  'packages': ['corechart', 'table', 'gauge', 'controls', 'charteditor']
});

renderChart_onPageLoad();

function renderChart_onPageLoad() {
  google.charts.setOnLoadCallback(function() {
    drawTable();
  }); //END setOnLoadCallback
} //END function renderChart_onEvent

function drawTable() {
  var jsonArray = jsonDataArray_1to1(json);

  //Modify header row to include id and label
  jsonArray = arrayHeaderRow_id_label_date(jsonArray);
  console.log('jsonArray'); console.log(jsonArray);

  var data = google.visualization.arrayToDataTable(jsonArray, false); // 'false' means that the first row contains labels, not data.
  //console.log('data');
  //console.log(data);

  var dashboard = new google.visualization.Dashboard(document.getElementById('div_dashboard'));

  var categoryPicker1 = new google.visualization.ControlWrapper({
    'controlType': 'CategoryFilter',
    'containerId': 'div_categoryPicker1',
    'matchType': 'any',
    'options': {
      'filterColumnIndex': 0, //Column used in control
      'ui': {
        //'label': 'Actual State:',
        //'labelSeparator': ':',
        'labelStacking': 'vertical',
        'selectedValuesLayout': 'belowWrapping',
        'allowTyping': false,
        'allowMultiple': false,
        'allowNone': true
      }
    }
  });

  var table = new google.visualization.ChartWrapper({
    chartType: 'Table',
    containerId: 'div_table',
    options: {
      allowHtml: true
    }
  });

  dashboard.bind([categoryPicker1], [table]);
  dashboard.draw(data);

  google.visualization.events.addListener(table, 'select', function() {

    //ORIGINAL from older post https://stackoverflow.com/a/33445620
    var selection = table.getChart().getSelection();
    if (selection.length === 0)
      return;

    var e = event || window.event;
    var cell = e.target; //get selected cell

    document.getElementById('output1').innerHTML = "Row: " + selection[0].row + " Column: " + cell.cellIndex;

    //NEW additional requirements

    var tableDataView = table.getDataTable();

    var selectedRow = selection[0].row;
    var selectedCol = cell.cellIndex;

    document.getElementById('output2').innerHTML = "selectedRow: " + selectedRow + " selectedCol: " + selectedCol;

    var colID = tableDataView.getColumnId(selectedCol);
    var colLabel = tableDataView.getColumnLabel(selectedCol);

    document.getElementById('output3').innerHTML = "colID: " + colID + " colLabel: " + colLabel;

  });
}

//Library

function jsonDataArray_1to1(json) {
  //DYNAMIC JSON ARRAY

  var dataArray_cln = [];

  //A. The desired table requires the fixed columns of ..... to ..... these are directly taken from the JSON.
  var dataArray_keys = Object.keys(json[0]);

  dataArray_cln.push(dataArray_keys);

  //Add rows 1 to json.length with null values
  var dataArray_rows = json.length;
  var dataArray_cols = dataArray_keys.length;

  for (i = 0; i < dataArray_rows; i++) {
    dataArray_cln.push(Array(dataArray_cols).fill(null));
  }

  //Update array from json data
  for (i = 0; i < dataArray_rows; i++) {
    //[i + 1] because row 0 is the header, push begins with row 1
    //dataArray_cln[row][col]

    //Content in row "i" is positioned into dataArray_cln[row][col] incrementing "j" to pull each key name from dataArray_keys
    for (var j = 0; j < dataArray_keys.length; j++) {
      eval('dataArray_cln[i + 1][' + j + '] = json[i].' + dataArray_keys[j]);
    }
  }

  //console.log(dataArray_cln);
  return dataArray_cln;
}

function arrayHeaderRow_id_label_date(arr) {
  for (var i = 0; i < arr[0].length; i++) {
    var valueOrig = arr[0][i];
    var valueNew;
    switch (true) {
      case valueOrig === 'wd':
        valueNew = JSON.parse('{"id":"' + valueOrig + '", "label":"' + valueOrig + '", "type": "date"}');
        break;
      default:
        valueNew = JSON.parse('{"id":"' + valueOrig + '", "label": "' + valueOrig + '"}');
    }
    arr[0][i] = valueNew;
  }
  return arr;
}
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id='div_dashboard'>
  <div id='div_categoryPicker1'></div>
  <div id='div_table'></div>
</div>

<div id="output1"></div><br/>
<div id="output2"></div><br/>
<div id="output3"></div><br/>

<script>
  var json = [{
      "division": "GS",
      "m1": 100.000000,
      "m2": 100.000000,
      "m3": null,
      "m4": null,
      "m5": null,
      "m6": null,
      "m7": null,
      "m8": null,
      "m9": null,
      "m10": null,
      "m11": null,
      "m12": null,
    },
    {
      "division": "GS",
      "m1": 100.000000,
      "m2": 90.000000,
      "m3": null,
      "m4": null,
      "m5": null,
      "m6": null,
      "m7": null,
      "m8": null,
      "m9": null,
      "m10": null,
      "m11": null,
      "m12": null,
    },
    {
      "division": "PS",
      "m1": null,
      "m2": null,
      "m3": 100.000000,
      "m4": null,
      "m5": 100.000000,
      "m6": 100.000000,
      "m7": 75.000000,
      "m8": null,
      "m9": null,
      "m10": null,
      "m11": null,
      "m12": null,
    },
    {
      "division": "PS",
      "m1": null,
      "m2": null,
      "m3": 100.000000,
      "m4": 100.000000,
      "m5": 100.000000,
      "m6": 100.000000,
      "m7": 80.000000,
      "m8": null,
      "m9": null,
      "m10": null,
      "m11": null,
      "m12": null,
    }
  ];

</script>

Answer №1

Google's table chart generates a standard HTML <table>.

Instead of relying on Google's 'select' event,
we can attach a regular 'click' event to the table's <td> elements.

Wait for the table chart's 'ready' event to trigger.
Then, set up a click handler for the cells.

To retrieve the column index --> cell.cellIndex
and for the row index --> cell.closest('tr').rowIndex

google.visualization.events.addListener(table, 'ready', function() {
  var container = document.getElementById(table.getContainerId());
  Array.prototype.forEach.call(container.getElementsByTagName('TD'), function(cell) {
    cell.addEventListener('click', selectCell);
  });

  function selectCell(sender) {
    var cell = sender.target;
    var row = cell.closest('tr');
    document.getElementById('output1').innerHTML = "Row: " + (row.rowIndex - 1) + " Column: " + cell.cellIndex;

    //NEW additional requirements

    var tableDataView = table.getDataTable();

    var selectedRow = row.rowIndex - 1;  // adjusting for header row (-1)
    var selectedCol = cell.cellIndex;

    document.getElementById('output2').innerHTML = "selectedRow: " + selectedRow + " selectedCol: " + selectedCol;

    var colID = tableDataView.getColumnId(selectedCol);
    var colLabel = tableDataView.getColumnLabel(selectedCol);

    document.getElementById('output3').innerHTML = "colID: " + colID + " colLabel: " + colLabel;
  }

});

Check out the functional example below...

google.charts.load('current', {
  'packages': ['corechart', 'table', 'gauge', 'controls', 'charteditor']
});

renderChart_onPageLoad();

function renderChart_onPageLoad() {
  google.charts.setOnLoadCallback(function() {
    drawTable();
  }); //END setOnLoadCallback
} //END function renderChart_onEvent

// Other JS functions and event handlers...

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Create a new division directly underneath the bootstrap column

Imagine having a bootstrap table like this: https://i.sstatic.net/kXHiP.jpg Now, if you want to click on a column and open a div with more details below it, is it achievable with CSS or JavaScript? https://i.sstatic.net/HIfkK.jpg I tried using the Metr ...

Module Ionic not found

When I attempt to run the command "ionic info", an error is displayed: [ERROR] Error loading @ionic/react package.json: Error: Cannot find module '@ionic/react/package' Below is the output of my ionic info: C:\Users\MyPC>ionic i ...

Changing HTML dynamically does not trigger the ng-click event within ng-bind-html

I have developed a custom directive that can display messages along with rendering HTML content that may contain Angular attributes like buttons, anchor tags with ng-click attribute, and more. index.html: <ir-error-panel status="status"></ir-err ...

Postman grants me the cookie, yet Chrome doesn't seem to deliver it

As I attempt to set a cookie named auth, containing the user's ID signed with JWT, I am puzzled by not seeing the auth cookie in Chrome when visiting http://localhost:5000/. Instead, I only observe these two cookies; https://i.sstatic.net/p0Foo.p ...

Issue with Moment.js incorrectly formatting date fields to a day prior to the expected date

Currently, I am attempting to resolve a small issue in my code related to a tiny bug. In my React component, I have set an initial state as follows: const initialFormData = Object.freeze({ date: Moment(new Date()).format('YYYY-MM-DD'), pr ...

Issue with starting React app using the "npm start" command

Upon the installation of a React App, I encountered a error message after executing the command "npm start" Cannot destructure property compile of 'undefined' or 'null'. npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! <a href=" ...

When a textarea contains a new line, it will automatically add an additional row and expand the size of the textarea

Developed a form with the functionality to move placeholders in a textarea upwards when clicked. The goal is to increment the height of the textarea by 1 row for every line break. However, I am uncertain about what to include in the if statement of my Ja ...

Trouble with retrieving data from localStorage

On my webpage, I have set up multiple input fields where users can enter data. When they click a button, the data from these inputs is stored inside <span>...</span> elements (the intention being that the text remains visible in these <span& ...

Issue with the navbar toggler not displaying the list items

When the screen is minimized, the toggle button appears. However, clicking it does not reveal the contents of the navbar on a small screen. I have tried loading jQuery before the bootstrap JS file as suggested by many, but it still doesn't work. Can s ...

Tips for creating JSON using AngularJs to store tabular information

I successfully created an HTML page using AngularJS. <form name="target" ng-submit="createAllKeywordsJSON(codeMasterList)"><!-- createAllKeywordsJSON() --> <input type="submit" value="Save" class="myButton" name="submit" style="margin: ...

What is the best way to create a new object in a Vue component with optimal efficiency?

Currently, I am working on initializing a map that would be utilized in my calculatePrice function. calculatePrice(key) { let prices = new Map({ 0: 17, 1: 19, 2: 24, 3: 27, 4: 30, 5: 46, 6: 50 ...

Attempting to transfer information between components via a shared service

Currently, I am utilizing a service to transfer data between components. The code snippet for my component is as follows: constructor(private psService: ProjectShipmentService, private pdComp: ProjectDetailsComponent) { } ngOnInit() { this.psSe ...

Creating an HTML table using an array of objects

I'm currently working on creating a function that will generate an HTML table from an array of objects. The array provided below is what I need to convert into a table. let units = [ { 'code': 'COMP2110', &apos ...

Tips for transferring large data without a page redirect using jQuery's post method:

Seeking advice on how to send large data via jQuery POST without redirecting the page. I'm working on a mobile chat project where communication between user app and server is done using JSON. The issue arises when dealing with big data as the jsonGet ...

Center a grid of cards on the page while keeping them aligned to the left

I have a grid of cards that I need to align in the center of the page and left within the grid, adjusting responsively to different screen sizes. For example, if there are 10 cards and only 4 can fit on a row due to screen size constraints, the first two ...

What is the proper way to activate speech recognition on electron?

I have a chatbot application running on Electron, and I am in need of implementing speech-to-text functionality. I initially tried using window.SpeechRecognition and window.webkitSpeechRecognition, but it seems like Chrome does not support speech recogniti ...

Please enter a numerical value into the input field in a JavaScript form

<script> function loop() { var input = document.getElementById('inputId').value; for (var i = 0; i < input; i++) { var result = document.getElementById('outputDiv').innerHTML ...

Enhance the v-autocomplete dropdown with a personalized touch by adding a custom

Currently utilizing the v-autocomplete component from Vuetify, and I am interested in incorporating a custom element into its dropdown menu. You can see the specific part I want to add highlighted with a red arrow in this screenshot: This is the current s ...

The parameter label is being detected as having an any type, as specified in the Binding element 'label'

Currently, I am referencing an example code snippet from react-hook-form. However, upon implementation, I encounter the following error: (parameter) label: any Binding element 'label' implicitly has an 'any' type.ts(7031) The example c ...

Node.js and Express: Delegate routes to different endpoints for handling by the Single Page Application, instead of just the root route

I have my node.js/Express server configured to host my Vue.js single page application from the root URL path (localhost:3333) within the public folder. When navigating through my app, everything works smoothly thanks to the vue.js History API handling all ...