Forum Discussion

DXC's avatar
DXC
Cloud Apps
01-16-2025
Solved

How to show 2 colors for 1 legend item?

I am building a bar chart show actual vs target number. And in my actual number, I am using a conditional color if it is over the target then show yellow if not show blue here.  After I added the co...
  • TriAnthony's avatar
    01-17-2025

    Hi DXC,

    Below is a script you can use to replace the grey box for the measure with conditional formatting with a two-tone box, one for each of the selected colors. If you need to reuse the script for another widget, make sure to update the line below with the correct measure name.

    const measureName = "Actual Sale"

    Example:

    Script:

     

    widget.on("ready", function(se, ev) {
    
      // Define the measure name
      const measureName = "Actual Sale";
    
      // Define a unique ID for the two-tone legend item
      const legendItemID = "two-tone-" + widget.oid + "-" + measureName.replace(/\s+/g, "") + "-legend-item";
    
      // Find the metadata of the measure
      const measureMetadata = widget.metadata.panels[1].items.find((item) => {
        if (item.jaql && item.jaql.title.indexOf(measureName) !== -1) {
          return true;
        }
      });
    
      // Define the gradient colors as variables
      const color1 = measureMetadata.format.color.conditions[0].color;
      const color2 = measureMetadata.format.color.conditions[1].color;
    
      // Find the text element for the measure
      const legendItemText = Array.from(element.get(0).querySelectorAll("text")).find(
        (textElement) => textElement.textContent.trim() === measureName
      );
    
      if (legendItemText) {
        // Locate the parent <g> group containing the text and rect
        const parentGroup = legendItemText.closest("g");
    
        if (parentGroup) {
          // Find the associated <rect> element
          const rectElement = parentGroup.querySelector("rect.highcharts-point");
    
          if (rectElement) {
            // Create a <defs> element for the gradient
            const defs = document.createElementNS("http://www.w3.org/2000/svg", "defs");
            const gradient = document.createElementNS("http://www.w3.org/2000/svg", "linearGradient");
            gradient.setAttribute("id", legendItemID);
            gradient.setAttribute("x1", "0%");
            gradient.setAttribute("y1", "0%");
            gradient.setAttribute("x2", "100%");
            gradient.setAttribute("y2", "0%");
    
            // Create gradient stops
            const stop1 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
            stop1.setAttribute("offset", "50%");
            stop1.setAttribute("style", `stop-color: ${color1}; stop-opacity: 1`);
    
            const stop2 = document.createElementNS("http://www.w3.org/2000/svg", "stop");
            stop2.setAttribute("offset", "50%");
            stop2.setAttribute("style", `stop-color: ${color2}; stop-opacity: 1`);
    
            // Append stops to the gradient
            gradient.appendChild(stop1);
            gradient.appendChild(stop2);
            defs.appendChild(gradient);
    
            // Insert the <defs> into the SVG root (if not already present)
            let svgRoot = rectElement.closest("svg");
            if (!svgRoot) {
              // Wrap the rect in a new SVG if one isn't present
              svgRoot = document.createElementNS("http://www.w3.org/2000/svg", "svg");
              svgRoot.setAttribute("width", "20");
              svgRoot.setAttribute("height", "20");
              rectElement.parentNode.replaceChild(svgRoot, rectElement);
              svgRoot.appendChild(rectElement);
            }
            svgRoot.insertBefore(defs, svgRoot.firstChild);
    
            // Apply the gradient to the rect
            rectElement.setAttribute("fill", `url(#${legendItemID})`);
          }
        }
      }
    
    });