Split highcharts legend items into separate lines

Currently, I am facing a challenge with a chart containing 10 series. Specifically, I would like to split the series legends into two rows - four in the first row and six in the second row. Despite my efforts to adjust legend.itemWidth and legend.width, I have not been successful in achieving this layout. Are there any known solutions to this issue, or perhaps a workaround that could be implemented? For better clarity, attached below is a screenshot depicting the desired arrangement.

https://i.sstatic.net/vPToV.png

Your assistance on this matter would be greatly appreciated.

Answer №1

You have the ability to utilize Highcharts' wrap method in order to design your own custom legend layout:

Highcharts.wrap(Highcharts.Legend.prototype, 'render', function(proceed) {
  proceed.apply(this, Array.prototype.slice.call(arguments, 1));

  var legend = this,
    legendWidth = legend.legendWidth,
    items = legend.allItems,
    firstLineWidth = 0,
    secondLineWidth = 0,
    firstStartPoint,
    secondStartPoint;

  Highcharts.each(items, function(item, i) {
    if (i < 4) {
      firstLineWidth += item.itemWidth;
    } else {
      secondLineWidth += item.itemWidth;
    }
  });

  firstStartPoint = (legendWidth - firstLineWidth) / 2;
  secondStartPoint = (legendWidth - secondLineWidth) / 2;

  Highcharts.each(items, function(item, i) {
    if (i < 4) {
      item.legendGroup.attr({
        translateX: firstStartPoint
      });
      firstStartPoint += item.itemWidth;
    } else {
      item.legendGroup.attr({
        translateX: secondStartPoint,
        translateY: 18
      });
      secondStartPoint += item.itemWidth;
    }
  });
});

Check out a live demonstration here: http://jsfiddle.net/BlackLabel/7he9btvg/

For more information, refer to the documentation: https://www.highcharts.com/docs/extending-highcharts/extending-highcharts

Answer №2

According to Sachi Tekina, creating a custom legend is the most effective way to achieve this goal. Highcharts legends are constructed in a way that does not allow them to be split into two lines as demonstrated in your example, whether it be through code options or CSS modifications (primarily due to their use of position: absolute, which can make adjustments quite cumbersome).

Here is an instance of a personalized legend I developed using a Highcharts demo: http://jsfiddle.net/brightmatrix/g0tfe12j/

To begin, construct your customized legend using checkboxes. Take note of the break tag used to shift some onto a second line.

<div align="center">
  <form id="test" name="test" method="post">
    <input type="checkbox" class="myCheckboxClass" name="myCheckbox" series="Tokyo" id="checkbox1" checked><label for="checkbox1">Tokyo</label>
    <input type="checkbox" class="myCheckboxClass" name="myCheckbox" series="New York" id="checkbox2" checked><label for="checkbox1">New York</label>
    <br />
    <input type="checkbox" class="myCheckboxClass" name="myCheckbox" series="Berlin" id="checkbox3" checked><label for="checkbox1">Berlin</label>
    <input type="checkbox" class="myCheckboxClass" name="myCheckbox" series="London" id="checkbox4" checked><label for="checkbox1">London</label>
  </form>
</div>

Subsequently, implement a function that activates whenever a checkbox is interacted with. This function will check the custom attribute in each checkbox ("series") and toggle the related series on or off within your chart:

// when a checkbox is clicked, trigger the function
$(".myCheckboxClass").on('click',function() {
        // get the value of "series", a custom attribute for the checkbox
        var seriesName = $(this).attr("series");
        // if that value matches a series, show or hide it in the chart
        for (i = 0; i < $("#container").highcharts().series.length; i++) {
            if ($("#container").highcharts().series[i].name == seriesName) {
                // if the checkbox is checked, show the dataset
                if ($(this).prop("checked")) {
                    $("#container").highcharts().series[i].show();
                // if the checkbox is unchecked, hide the dataset
                } else {
                    $("#container").highcharts().series[i].hide();
                }
            }
        }
});

Finally, style the custom legend to complement your chart design preferences.

I trust this information proves beneficial to you.

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

Clicking the button will close the active tab in Firefox

I need help with a webpage that has a popup. When the user clicks the OK button in the popup, I want the current tab to close. The OK button is an HTML input tag. I've tried various ways of using JavaScript's close method and searched online, but ...

The JQuery function assigning a value of 0 to the selectedIndex property is not functioning properly across all selected fields

<select name="wpcf-others" id="abc" class="myzebra-control myzebra-select"> <option value="wpcf-field123">General Work Jobs</option> <option value="wpcf-fields--1">Journalist/Editors Jobs</option> <option value="wpcf-4868b8 ...

What is the best approach for writing a concise Select statement that produces a data list?

Currently, I am working on a small web application using Express.js and SQLite for local use. However, I am facing an issue when trying to perform a full select query on a table. All my scripts are written in JScript in 'use-strict' mode. I am a ...

Placing an element on the page starting from the bottom and moving it towards the

Is there a way to display items on a page from bottom to top, similar to how messages are shown in a chat? Here's an example: .chart div { font: 10px sans-serif; background-color: steelblue; padding: 3px; margin: 1px; color: white; disp ...

Contrary to expectations, the middleware EJS fails to render JPG files at

I am currently working on a NodeJS server using EJS. The goal of this server is to render an HTML page that contains a line of text and a jpg file. However, I am encountering an issue with the jpg file not being loaded by the server. Even though I have sp ...

`Making adjustments to specific text on an HTML page prior to its presentation`

I am looking for a way to conceal specific text on any HTML page before it is shown. After some experimentation with Greasemonkey, I attempted the following approach: var html = document.body.innerHTML; html = html.replace( /some pattern/g, '???&apo ...

Modifying an object's attribute in React.js by toggling a checkbox

As I delve into learning React, I am constructing a straightforward todo list. Here's the object contained within my initialState: getInitialState:function(){ return { items: [ { text:"Buy Fish", ...

Idea fails to detect imports

I have been attempting to use Angular2 in IntelliJ IDEA IDE. Although my code is valid (I have tried compiling and executing it), the IDE keeps showing me this error: https://i.stack.imgur.com/w6wIj.jpg Is there a way to configure IntelliJ IDEA to hide t ...

Sending user credentials to a new page in JavaScript

My goal is to direct the user from one web page to another that requires a password for access. The user arrives on the initial page by scanning a barcode with a specific terminal, similar to a smartphone equipped with a customized barcode reader applicati ...

Converting a intricate hexadecimal code into an emoji is not possible

Is there a way to convert a hex code into an emoji without using surrogate pairs? For example, I want to turn the hex code U+1F64C into its corresponding emoji, without complications like using simple hex values like 2728 or more complex ones like 1F601. ...

Create basic HTML using the react.cloneElement method

When using React.cloneElement(), the first parameter always needs to be a react component that is passed as children in props. Is there a way to pass a simple HTML node as a child? Please see the example code below for clarification: Dialog.jsx (Common c ...

Refreshing data from firebase on each route change

I created an Angular service that retrieves items from Firebase using snapshotChanges and returns them. In my component, I subscribe to the data and store it in an array. I then display the data in cards using ngFor. However, whenever I navigate between p ...

Utilizing VueMq for personalized breakpoints and module inclusions

In my main app.js, I set and define breakpoints by importing the VueMq package. import VueMq from 'vue-mq'; Vue.use(VueMq, { breakpoints: { xsmall: 500, small: 768, medium: 1024, large: 1360, x ...

Issue with the side panel: unable to close it

There seems to be an issue with the close button on the sidebar—it's neither displaying nor functioning properly. The show sidebar feature works perfectly fine, but there is a problem with the closing function. Below is the HTML, CSS, and JavaScript ...

What is the best way to toggle the visibility of fields on a modal in a Ruby on Rails

I am working on an application that utilizes Rails 4.1 and Ruby 2.1.2. The show.html.erb view for the Assignment Model in this application is as follows: <h1><%= "#{'Source URL'}"%> <div class="source-url"><%= @assignment.so ...

Deliver a response to recipients through the "button" feature within the WhatsApp cloud API

I'm working on building a chatbot for my booking company. Here is an outline of my initial bot flow: const axios = require("axios").default; function initialize_bot(message, phone_number, access_token, sender, username) { if (message === ...

Can you use a lightbox to showcase multiple images while only displaying one image at a time to trigger them?

Currently, I am utilizing Lightbox in order to showcase photos. For example, I have divided the photos into two categories: "work" and "vacation". To implement this, I would follow this code snippet... <a href="images/image-1.jpg" rel="lightbox[work]"& ...

React maintains the state of just a single element within an array at a time

I'm faced with a roadblock while developing my covid19 application. The app should display a list of countries on the left side of the screen, allowing users to add any number of countries to the right side for more detailed covid data. I'm still ...

Node.js CallbackHandler: Simplifying event handling in JavaScript applications

I implemented the following function in a .js file to handle an asynchronous network connection: function requestWatsonDiscovery(queryString) { console.log('Query =', queryString); if (typeof queryString !== 'undefined') { ...

Select an alternative JavaScript file that performs the identical function

One of the features on my projects index page is a dropdown that triggers an AJAX call to the index action: def index @projects = sorted_projects # sort projects based on dropdown selection respond_to do |format| format.html format. ...