Hiding the C3 tooltip after engaging with it

I'm currently expanding my knowledge on utilizing C3.js for creating charts, and one aspect I'm focusing on is enhancing the tooltip functionality. Typically, C3 tooltips only appear when you hover over data points as demonstrated in this example. These tooltips are not persistent and lack interactivity.

After discovering some code on Stack Overflow (link here) that incorporates a timeout and CSS modifications to make the tooltips persist and enable user interaction, I faced an issue with closing the tooltip once it appears. I wanted to implement a mechanism where the tooltip could be closed by clicking anywhere on the chart or the tooltip itself, or via a defined timeout. It's bothersome to have tooltips lingering on the chart indefinitely after their initial appearance.

You can view the implementation of this code on this JSFiddle.

I assumed there should be a function that I could call or override for handling the tooltip closure. I experimented with adding an onclick feature so that clicking on a data point triggers an action, but I struggled to achieve the desired outcome. To uncover how to incorporate onclick functionality, I referred to this resource.

data: {
  columns: [ ['data1', 40, 50, 60, 70, 80] ],
  types: { data1: 'bar'},
  onclick: function(e) { alert(e.value); }
}

The method through which the tooltip closure would be initiated isn't a crucial concern for me. Below is the code snippet from the JSFiddle exemplifying interactions with the tooltip and its persistence without automatic closure.

CSS:

.c3-tooltip-container {
    background-color: #ccc;
    border: solid 1px black;
    padding: 20px;
    pointer-events: auto !important;
}

JS:

var features = dates = defects = [
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10
];

var chart = c3.generate({
    data: {
        columns: [
            ['data1', 30000, 20000, 10000, 40000, 15000, 250000],
            ['data2', 100, 200, 100, 40, 150, 250]
        ],
    },
    tooltip: {
        position: function () {
            var position = c3.chart.internal.fn.tooltipPosition.apply(this, arguments);
            position.top = 0;
            return position;
        },
        contents: function (data, defaultTitleFormat, defaultValueFormat, color) {
            var $$ = this, config = $$.config,
            titleFormat = config.tooltip_format_title || defaultTitleFormat,
            nameFormat = config.tooltip_format_name || function (name) { return name; },
            valueFormat = config.tooltip_format_value || defaultValueFormat,
            text, i, title, value;
            text = "<div id='tooltip' class='d3-tip'>";
            title = dates[data[0].index];
            text += "<span class='info'><b><u>Date</u></b></span><br>";
            text += "<span class='info'>" + title + "</span><br>";
            text += "<span class='info'><b><u>Features</u> : </b> " + features[data[0].index] + "</span><br>";
            text += "<span class='info'><b><u>Enhancements</u> : </b> " + defects[data[0].index] + "</span><br>";
            text += "</div>";
            return text;
        }
    }
});

Answer №1

If you need to hide a tooltip either when:

  • you click on it
  • a certain timeout has passed

You will require the following:

  • A function to change the visibility of the tooltip
  • A function to handle the click action
  • A timer storage for controlling the timer stop/restart functionality

Here is an example implementation:

// Function to handle click action
window.action = function() {
    // Perform actions here
    // ...
    clearTimeout(timeout);
    hideTooltip();
}

// Timer storage
var timeout;

var chart = c3.generate({
    ...
    tooltip: {
        position: ...
        contents: function (...) {
            // Code to clear and restart timer
            clearTimeout(timeout);
            timeout = setTimeout(hideTooltip, 5000); // Tooltip will auto-hide after 5 seconds

            ...
            text = "<div id='tooltip' class='d3-tip' onclick='window.action()'>";
            ...
            return text;
        }
    }
});

// Disable default tooltip hiding behavior
c3.chart.internal.fn.hideTooltip = function (){};

// Custom function to hide the tooltip
var hideTooltip = function() {
    d3.select('.c3-tooltip-container').style('display', 'none');
}

For a demonstration, check out the updated fiddle here.

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

Using Angular 5 to access a variable within a component while iterating through a loop

I am currently in the process of transferring code from an AngularJS component to an Angular 5 component. Within my code, I have stored an array of objects in a variable called productlist. In my previous controller, I initialized another empty array nam ...

How to Access Data Attribute in React TypeScript on Click Event

Recently, I encountered a situation with my React component where I have a button with a click handler that utilizes the data-* attribute. In the past, with regular React, extracting the value from the data-* attribute was straightforward. However, as I am ...

I've encountered an issue when attempting to use innerHTML for DOM manipulation

I've been attempting to remove a specific list item <li> from the inner HTML by assigning them proper IDs. However, I'm encountering difficulties in deleting it. How can I delete these list items after clicking on the cross button? Feel fr ...

Utilizing $.when to merge AJAX requests and then passing the resulting data to a designated function

I am struggling with sending data between functions and using $.when in my JavaScript code. I have separate functions and AJAX calls that update content on the page, but they need to load together on page load. Despite trying various solutions to combine A ...

What is the best method for securely storing and managing refresh and access tokens within a node.js application?

Currently, I am working with next.js and I am looking for a way to persist an API refresh token without using a database in my application. What would be the recommended practice for storing this token securely so that it can be updated as needed? Storin ...

Prior to stacking the divs, separate the line within the div

In the process of creating a responsive navbar with Bootstrap, I encountered an issue. When resizing the window to a smaller size, the collapse icon shifts from the top right position below my "logo". Here is how the site appears on a regular screen: http ...

Preventing the addition of duplicate items to an array

My current challenge involves pushing containers into an array in my JavaScript code. However, once a container has been pushed, I want to prevent that same one from being pushed again. If you'd like to take a look at the JSfiddle where I'm work ...

The integration of AngularJS with Bootstrap 3 accordion seems to encounter issues when included through ng-view

Here's the issue: When using the accordion in a view loaded with the ng-view directive, the accordion title clicks stop working correctly. Check out this demo for an example However, when the accordion is used directly on the page without ng-view, i ...

Obtain information using AJAX calls with jQuery Flot

Having an issue with jQuery Flot that I need help resolving. PHP output (not in JSON format): [[1, 153], [2, 513], [3, 644]] ~~ [[1, 1553], [2, 1903], [3, 2680]] Here is the jQuery call: $.ajax({ url: 'xxx.php', success: function (dat ...

What is the best way to fill HTML tables using an ajax response?

This is a Laravel blade view/page that requires updating without the need to refresh the entire page. The blade.php code functions correctly and retrieves data from a MySQL database, but there seems to be an issue with the AJAX and JavaScript implementati ...

Making a POST request across domains without relying on any third-party frameworks

Is it possible to create a cross-domain request using vanilla JavaScript without relying on frameworks like jQuery? I am looking to send a JSON to a service on a different domain and receive the response using a callback function. Can this be done solely ...

Is there a way to merge two separate on click functions into one cohesive function?

I currently have two separate onclick functions as shown below. They are functioning properly but I am considering combining them for optimization purposes. Essentially, clicking on xx displays certain elements, hides others, and adds a class. Clicking o ...

What is the best approach: retrieving the tooltip text before hovering over with the Actions class, or after hovering over?

Apologies if this question has been asked before. I have looked through numerous answers on this platform, but I am still unable to retrieve the tool-tip text. I can see the title without using the Actions class to hover over and display the tool-tip. Ho ...

Exploring the use of Angular with tables: applying classes dynamically using ngClass and repeating items using

My table is generated from a Web Service JSON, each row has a button to mark it for deletion. When you click the button, a JS alert displays the ID of the row element, and I also need to add the 'danger' bootstrap class to the row. Now, I can cap ...

How can I use absolute positioning and scrolling with an Iframe?

One of the key elements of this website is the implementation of iframes, with only one displayed at a time. However, my current issue revolves around the inability to scroll within these iframes due to their absolute positioning. I have attempted variou ...

What is the best way to transform a string into an array?

After receiving an object from the http response, it looks something like this: {"[3, company1]":["role_user"], "[4, company2]":["role_admin"] } The key in the object is represented as an array. Is there a method in ...

What is causing my HTML wrapper to malfunction?

Below is the HTML code for my website: <div id="wrapper"> <div id="header"> <img src="images/MyBannerFinished.jpg" alt="Header" width="803" class="headerimage" /> </div> <!--- End Header ---> <div id="navbar"> <ul ...

Utilizing Angular to intercept AJAX requests, verifying internet connectivity before proceeding with sending the request

In my Angular (with Ionic) app, I have this code snippet: my_app.factory('connectivityInterceptorService', ['$q', '$rootScope', function ($q, $rootScope) { var connectivityInterceptorServiceFactory = {}; var _request ...

Using CSS to duplicate images in multiple repetitions horizontally

In the process of developing a UHD project that involves showcasing large images, I have encountered limitations with iOS and certain mobile browsers. While stationary browsers pose no issue, iOS only supports PNG images up to 5 megapixels in resolution, w ...

What is the best way to push a variable after employing the split function in JavaScript?

error: An unexpected TypeError occurred while trying to read property 'push'. The error was on this line: " this.name[i].push(arrayData[0]); " I'm confused because the console.log statement before that line shows "data is loaded:" alo ...