Incorporating a Link to a RowLabel on a Google Chart Timeline

I have been working diligently on constructing a timeline for our team's Project Roadmap.

Everything is set up quite nicely: I've successfully embedded the Timeline into our Google Site and it seems to be functioning well with all the components added thus far.

My next objective is to incorporate a link on the RowLabel that will redirect me to another page within the Google Site. While I've come across some solutions for adding a listener and linking to a specific row item, my focus lies in attaching the link directly to the RowLabel itself, rather than the BarLabel.

For reference, here's an example of the current timeline implemented on the Google Site: https://sites.google.com/view/timeline-testing/home

What I aim to achieve is depicted in this Timeline Concept image: Timeline Concept

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

<script type="text/javascript">
  google.charts.load("current", {packages:["timeline"]});
  google.charts.setOnLoadCallback(drawChart);
  function drawChart() {

    var container = document.getElementById('roadmap');
    var chart = new google.visualization.Timeline(container);
    var dataTable = new google.visualization.DataTable();
    dataTable.addColumn({ type: 'string', id: 'Category' });
    dataTable.addColumn({ type: 'string', id: 'Project' });
    dataTable.addColumn({ type: 'string', role: 'tooltip', 'p': {'html': true} });
    dataTable.addColumn({ type: 'string', id: 'style', role: 'style' });
    dataTable.addColumn({ type: 'date', id: 'Start' });
    dataTable.addColumn({ type: 'date', id: 'End' });
    
    dataTable.addRows([

      [ 'Category 1', 'Project 1', 
      '<p style="padding:5px"><b>Overall Project:</b> Program X <br><b>Description:</b> Test 
      description for Project 1 <hr> <b> Start:</b> 2020/4/1 <br> <b> End:</b> 2020/8/15</p>', 
      '#2B8000', new Date(2020, 3, 13), new Date(2020, 6, 13)],
      
      [ 'Category 1', 'Project 2',  
      '<p style="padding:5px"><b>Overall Project:</b> Program X <br><b>Description:</b> Test 
      description for Project 2 <hr> <b>Start:</b> 2020/4/1 <br> <b>End:</b> 2020/8/15</p>', 
      '#2B8000', new Date(2020, 4, 22), new Date(2020, 6, 24)],

      // Additional rows...

    ]);

     // More code for customization options and functionalities
   }
</script>

// Some additional styling rules

// div containing roadmap visualization 
<div id="roadmap" style="height: 100%;"></div>

I am currently trying to configure the selector to detect when a RowLabel is clicked. There's uncertainty regarding where to store the link information within the DataTable. Should it be stored as another Data Column? The attempts at adding an extra Data Column like this have resulted in errors: dataTable.addColumn({ type: 'string', id: 'link' });

// Further elaboration on data structure...

Any guidance or assistance on this matter would be greatly appreciated!

Thank you,

UPDATE

Here is the status of the code: Styling of the rowLabel works fine, but the click event does not trigger on the Google Site Embed. To view the test on Google Site, visit this link: https://sites.google.com/view/timeline-testing/home

// Latest code snippet showcasing enhancements and modifications // Implementation of needed functionality and event handling

Answer №1

Perhaps, in this scenario, the 'select' event may not be the most suitable solution.

Alternatively, we could attach event listeners to the row labels during the 'ready' event.

In the options, we assign a distinct color to the row labels.

timeline: {
  rowLabelStyle: {
    color: '#3399cc'
  }
}

We can utilize this unique color to apply additional CSS styles.

#roadmap text[fill="#3399cc"] {
  cursor: pointer;
  text-decoration: underline;
}

Subsequently, use this distinctive color to identify the chart elements and add the click event listener.

function readyHandler() {
  var labels = container.getElementsByTagName('text');
  Array.prototype.forEach.call(labels, function(label) {
    if (label.getAttribute('fill') === options.timeline.rowLabelStyle.color) {
      label.addEventListener('click', clickHandler);
    }
  });
}

To save the link in the data table,
we can employ object notation for the initial column.
We provide the value (v:) and the link as a property (p:).

{v: 'Category 1', p: {link: 'https://www.google.com'}}

Then, utilize the getProperty method to retrieve the link from the data table within our click handler.

Initially, ascertain the content of the clicked label,
and utilize the data table method getFilteredRows to pinpoint the clicked row label.

function clickHandler(sender) {
  var rowLabel = sender.target.textContent;
  var dataRows = dataTable.getFilteredRows([{
    column: 0,
    value: rowLabel
  }]);
  if (dataRows.length > 0) {
    var link = dataTable.getProperty(dataRows[0], 0, 'link');
    window.open(link, '_blank');
  }
}

Refer to the following functioning snippet...

google.charts.load('current', {
  packages:['timeline']
}).then(function () {
  var container = document.getElementById('roadmap');
  var chart = new google.visualization.Timeline(container);
  var dataTable = new google.visualization.DataTable();
  dataTable.addColumn({type: 'string', id: 'Category'});
  dataTable.addColumn({type: 'string', id: 'Project'});
  dataTable.addColumn({type: 'string', role: 'tooltip', 'p': {'html': true}});
  dataTable.addColumn({type: 'string', id: 'style', role: 'style'});
  dataTable.addColumn({type: 'date', id: 'Start'});
  dataTable.addColumn({type: 'date', id: 'End'});

  dataTable.addRows([
    [{v: 'Category 1', p: {link: 'https://www.google.com'}}, 'Project 1', 'test', '#2B8000', new Date(2020, 3, 13), new Date(2020, 6, 13)],
    [{v: 'Category 1', p: {link: 'https://www.google.com'}}, 'Project 2', 'test', '#2B8000', new Date(2020, 4, 22), new Date(2020, 6, 24)],
    // Other rows...
  ]);

  var options = {
    height: (dataTable.getNumberOfRows() * 42) + 42,
    tooltip: {isHtml: true},
    legend: 'none',
    timeline: {
      rowLabelStyle: {
        color: '#3399cc'
      }
    }
  };

  function readyHandler() {
    var labels = container.getElementsByTagName('text');
    Array.prototype.forEach.call(labels, function(label) {
      if (label.getAttribute('fill') === options.timeline.rowLabelStyle.color) {
        label.addEventListener('click', clickHandler);
        label.setAttribute('style', 'cursor: pointer; text-decoration: underline;');
      }
    });
  }

  // Function declaration of clickHandler...

  google.visualization.events.addListener(chart, 'ready', readyHandler);
  chart.draw(dataTable, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="roadmap"></div>

Note: The chart will convert all colors in the options to lowercase.
(#3399cc) <-- Ensure using a lowercase option for the color,
otherwise, the ready handler may fail to locate the text elements...

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

Axios and fetch returned distinct status codes when querying the same external endpoint

I am attempting to make a request to the following endpoint: https://9gag.com/v1/group-posts/group/default/type/trending in order to retrieve 9gag posts data. Everything works smoothly when I use postman and chrome, however, when I attempted to make the r ...

Introduction to Ajax communication using node.js

Currently, I am attempting to create a basic node.js server that takes in a request for a string, selects one randomly from an array, and returns the chosen string. However, I am encountering some challenges along the way. Here's what my front end lo ...

Overlapping Flexbox elements causing stacking issues

My attempt to create a gallery layout with two larger blocks amidst smaller blocks is not functioning correctly. The large block is overlapping the two smaller blocks below it. Is there a way to prevent block overlapping using CSS? I have searched Stack O ...

The width of the tables is unpredictable and cannot be constrained

Currently, I am tasked with creating an email newsletter template for a client. Unfortunately, due to the constraints of email design, I am unable to use CSS and must rely on tables instead. Despite clearly defining the width of each cell, I am encounter ...

Using JavaScript to insert a value through AJAX

I'm currently working on a website that displays the value of a .TXT file, and here is the progress I've made so far: <script> $(document).ready(function() { $("#responsecontainer").load("info.txt"); var refreshId = setInterval(function( ...

Guide for extracting the first matching group with regex in node.js

Extracting a specific value from a string in a text file can be tricky. In the example below, the goal is to get the value of valuetext: <CONFIG_entry name="Konfiguration:Allgemeine Einstellungen:CMS-Server:Port" valuetext="15000" value="15000" adr="CL ...

How to sort Firebase real-time database by the child node with the highest number of

I am working on a database feature that allows users to 'like' comments on posts. Is there a way for me to sort the comments based on the number of likes they have? Although I am aware of using .orderByChild(), my issue lies in not having a sep ...

Toggle draggable grid in jQuery

Imagine I have a grid set up using the following code: $( "#dragIt" ).draggable({ grid: [ 15, 15 ] }); Now, there is a checkbox located below the div. Is there a way for me to switch the grid on and off by toggling the checkbox? I've searched the of ...

Is it possible in HTML to create an "intelligent" overflow effect where text is truncated and replaced with an ellipsis "..." followed by a link to view the full content?

I have a <div> that has a limited size, and I am looking for a way to display multiline text in it. If the text exceeds the available space, I would like to add "..." at the end along with a link to view the full content on another page. Is there a ...

What steps can I take to avoid Vue.js overriding jQuery bindings within components?

After incorporating vue.js into an existing project and attaching the vue instance to the body tag with an ID of "app," everything seemed to be running smoothly. jQuery and Vue.js were cooperating well together. However, as soon as I started creating compo ...

Link commitments and ornament an entity

I'm struggling to grasp the concept of promises, specifically in chaining them and enhancing an object with data fetched from various endpoints. For instance: In my node-express application, I have the following code //controller.js export const ge ...

The bytea data retrieved from Postgres does not match the original data I inserted

I have successfully integrated a React front end with a PostgreSQL back end using Express. I encountered an issue when handling byte arrays (Uint8Array) for files uploaded from the front end into the database. The file, which is 779 bytes in size, gets sto ...

Activate the date-picker view when the custom button is clicked

Utilizing this library for date-picker functionality has been quite beneficial. I am currently working on a feature that involves opening the date-picker upon clicking a custom button. The default input is functioning properly. <input name="pickerFromD ...

Guide on using jQuery to automatically scroll to the HTML container related to a clicked letter

I am in the process of finalizing my wiki page and I wish to add a specific function. My goal is that when a user clicks on a letter in the alphabet bar, the browser will smoothly scroll to the corresponding letter within the wiki column. However, I am en ...

Looking for guidance and bug assistance in HTML and JS, possibly involving PHP and MySQL. Can anyone offer advice?

I'm attempting to create an auto-complete feature for a forum (similar to the tags below) that will function within LimeSurvey. I am fairly new to this, so please provide explanations as if you were explaining it to a 5-year-old :) My objectives are: ...

How to Ensure the Final Column in an Angular Bootstrap Row Occupies the Remaining Available Space

Within my Angular5 application, there is a container component used to display a row with multiple components arranged in n columns, as shown below: <div class="row mx-5 my-5 h-75 w-80"> <div class="col-md-4 col-lg-4 m-0 p-0" *ngIf="advanc ...

Troubleshooting Bootstrap 4 Button Alignment on the Right

I am a newcomer to Bootstrap 4 and I am in the process of creating a straightforward page with it. Within my navigation bar, I have successfully added a logo and company name on the left side. However, I am encountering difficulty in placing two buttons on ...

JQuery Tic Tac Toe Duel: Face Off Against Your Friend in a Thr

Looking for some advice here. I'm new to game development and currently working on a 2 Player Tic Tac Toe game. I need help with implementing the game functionality. Any suggestions? I want to disable the "div" once a player clicks on it, but I' ...

What is the best way to retrieve information from a database using JSON with PHP, JQUERY, and

Trying to retrieve data from a MySQL database and pass it to a JavaScript file has been quite a challenge. Despite searching extensively online, the examples I found didn't work in my specific scenario. .html file <!DOCTYPE html PUBLIC '-//W ...

Ways to modify a link tag based on a specific browser width

Looking for a solution to optimize the drop-down sign in box code that gets appended to a hamburger menu when the mobile width media query is called. Can we refactor this to switch the drop-down sign in box to just an anchor tag (<a href="signin">< ...