Modifying the placement of Legends with D3.js

I managed to create a bar chart using dimple.js and now I am attempting to add legends using d3.js. Although I have successfully added the legends, the legend text is overlapping and I need a way to wrap the text if it exceeds the space allocated for each legend. Additionally, I would like to display only two legends in a row but due to limited space, the third legend is currently hidden. My goal is to bring the third legend down to the second row.

http://jsfiddle.net/keshav_1007/qgn9gaec/3/ - you can view my fiddle here

var yMax = 1.2;
var svg1 = dimple.newSvg("body", 360, 360);
var dataChart = [{
    "Brand": "Aaaaaaaaaaaaaaaaaaaaaa",
        "Day": "Mon",
        "SalesVolume": 10
}, {
    "Brand": "Bbbbbbbbbbbbbbbbbbbb",
        "Day": "Mon",
        "SalesVolume": 20
},
                {
    "Brand": "Ccccccccccccccccc",
        "Day": "Mon",
        "SalesVolume": 20
}];
var myChart = new dimple.chart(svg1, dataChart);
myChart.setBounds(120, 10, 200, 200)
var dummy = ['aaaaaaaaaaaaaaaaaa','bbbbbbbbbbbbbbb','c'];
var x = myChart.addCategoryAxis("x", "Day");
var y = myChart.addPctAxis("y", "SalesVolume");
y.overrideMax = yMax;
y.addOrderRule("SalesVolume");
var s = myChart.addSeries("Brand", dimple.plot.bar);
s.barGap = 0.7;
var horz = 0;
var legendRectSize = 18; 
var legendSpacing = 4;
var legend = svg1.selectAll('.legend')  
          .data(dataChart)  
          .enter()
          .append('g') 
          .attr('class', 'legend') 
          .attr('transform', function(d, i) { 
            var height = legendRectSize + legendSpacing;
            var offset =  120;
            horz = horz + offset;
            var vert = i * height - offset;
            return 'translate('+horz+',260)';
          });
            legend.append('rect')
          .attr('width', legendRectSize)
          .attr('height', legendRectSize)
          .style('fill', '#333333')
          .style('stroke', '#333333');
        legend.append('text') 
          .attr('x', legendRectSize + legendSpacing)
          .attr('y', legendRectSize - legendSpacing)
          .text(function(d,i) {
            console.log(dataChart[i].Brand);
                             return dataChart[i].Brand; });
myChart.draw();

Thank you for your assistance.

Answer №1

This illustration can guide you. I have fragmented lengthy texts into segments of a fixed length (in this case, 10) and determined the x and y coordinates for every third legend.

var yMax = 1.2;
var svg1 = dimple.newSvg("body", 360, 860);
var dataChart = [{
    "Brand": "Aaaaaaaaaaaaaaaaaaaaaa",
        "Day": "Mon",
        "SalesVolume": 10
}, {
    "Brand": "Bbbbbbbbbbbbbbbbbbbb",
        "Day": "Mon",
        "SalesVolume": 20
},
                {
    "Brand": "Ccccccccccccccccc",
        "Day": "Mon",
        "SalesVolume": 20
}];
var myChart = new dimple.chart(svg1, dataChart);
myChart.setBounds(120, 10, 200, 200)
var dummy = ['aaaaaaaaaaaaaaaaaa','bbbbbbbbbbbbbbb','c'];
var x = myChart.addCategoryAxis("x", "Day");
var y = myChart.addPctAxis("y", "SalesVolume");
y.overrideMax = yMax;
y.addOrderRule("SalesVolume");
var s = myChart.addSeries("Brand", dimple.plot.bar);
s.barGap = 0.7;
var horz = 0;
var legendRectSize = 18; 
var legendSpacing = 4;
var vert = 260;
var legend = svg1.selectAll('.legend')  
          .data(dataChart)  
          .enter()
          .append('g') 
          .attr('class', 'legend') 
          .attr('transform', function(d, i) { 
              var height = legendRectSize + legendSpacing;
              var offset =  120;
              horz = horz + offset;
              if((i+1)%3 == 0){
                 vert += 100;
                 horz = 0 + offset;
              }
              return 'translate('+horz+','+vert+')';
          });

     legend.append('rect')
          .attr('width', legendRectSize)
          .attr('height', legendRectSize)
          .style('fill', '#333333')
          .style('stroke', '#333333');

     legend.each(function(d,i){        
          var cLegend = d3.select(this);
          // 10 is the fixed length based on which the long texts are spliced.
          var texts = d.Brand.match(/.{1,10}/g);
          texts.forEach(function(text, i){
              cLegend.append('text') 
              .attr('x', legendRectSize + legendSpacing)
                .attr('y', legendRectSize - legendSpacing+(i*25))
                  .text(text);
           });
     });

      myChart.draw();
<script src="http://dimplejs.org/dist/dimple.v1.1.5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

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 a combination of JQuery, HTML, and CSS, create a unique set of random colors for each box simultaneously

Seeking assistance in individually changing the color of each square element that is generated one at a time in a row of five, with an id="square" tag. When I click the clickMe() function, I want each square to randomly change color. However, currently onl ...

Unable to get Highlight.js to format echoed text from PHP

I'm utilizing PHP to echo text onto my page through an AJAX call in my HTML. I want Highlight.js to highlight the syntax within this text, but it doesn't seem to be working. When I directly include this code in my HTML: <pre> <code ...

Exploration of jsTree capabilities

I am currently exploring the jsTree plugin API and I'm struggling to grasp where exactly the API functions like set_theme, show_dots, etc. should be applied. On this page, I noticed that some functions are preceded by jQuery, while others are precede ...

Using NextJS to fetch data from an API after a form submission

Struggling with integrating an API call in my NextJS application, specifically when submitting a form. I keep encountering a random error upon submission, Error: Search(...): Nothing was returned from render. This usually means a return statement is missin ...

Exploring the potential of for loops and promises in verifying text across multiple elements

Currently, I am engaged in developing a function that is responsible for extracting the text of elements post utilizing a filter feature. Upon inspecting the displayed text output, it appears that the elements are being retrieved successfully; nonetheless, ...

Retrieving URL from AJAX Request in Express JS

Currently, I am in the process of developing an Express App and encountering a challenge regarding the storage of the user's URL from which their AJAX request originated. In simpler terms, when a website, such as www.example.com, sends an HTTP request ...

Utilizing MutationObserver in JavaScript for Streamlined Code Execution

One of my functions utilizes a MutationObserver to track attribute changes in a specified element and logs them to the console. Below is an example where I pass 'card' elements in a foreach loop: track_attr_changes(element); The parameter ' ...

Error: Call stack size limit reached in Template Literal Type

I encountered an error that says: ERROR in RangeError: Maximum call stack size exceeded at getResolvedBaseConstraint (/project/node_modules/typescript/lib/typescript.js:53262:43) at getBaseConstraintOfType (/project/node_modules/typescript/lib/type ...

Incorporating server-side rendered components into a Vue.js parent component

I have a server-side rendered page that includes information about "orders" and a root Vue object initialized as the "parent object." Is it feasible to assign the rendered HTML orders as children of that parent Vue object? Vue.js is known for its dynamic ...

Unraveling JSON syntax appears to be an ins

My main challenge is not rotating a DIV, but rather JSON parsing. I need to retrieve the correct attribute value from the variable rotateAttrSet, based on the browser type. I am able to do var rotateAttr = rSET.FF;, however, I am unable to do var rotateAt ...

Basics of refactoring with Jquery and JavaScript

As someone who is still learning JavaScript/JQuery, I am trying to figure out how to refactor this code into a reusable method or function. $.getJSON('@Url.Action("GetLabNames", "Micro")', null, function(j) { var options = ''; ...

JavaScript - Extract specific subvalue from object by using a key string

The issue I am currently encountering in my project involves a complex result object structure, as shown below: results = { a : { b : { c : value1 }}, d : value2, e : { f : value3 } } I am looking for a dynamic solution to retrieve a specific va ...

The chart JS label callback requires a specified type declaration

Currently, I am in the process of updating an old Angular platform to a newer version. One requirement is that everything must have its type declaration. I encountered a problem with the label callback showing this error: The error message reads: "Type &a ...

"Exploring the mechanics of this code: delving into the Buffer()

On a particular website, there is a task where you can solve puzzles and then compare your solution with others. I came across one solution that seems very concise and I'm having trouble understanding it. The task involves determining whether two cel ...

How can I use PHP to send the $_POST array via ajax?

I am faced with a situation where I have multiple input fields named Change[xxx]. In the traditional way, when an update button is clicked, data is sent and the database gets updated. But how do I pass this Change[xxx] data using Ajax without relying on jQ ...

How can I programmatically trigger a change event for a dropdown in Vue.js?

I am looking to trigger a dropdown change event within a Vue.js method. <select id="idDropdown" v-model="Result.Value" v-on:change.prevent="changeSelection($event, 'somevalue')"> How can I call the above `cha ...

Guide on sending a JSONP POST request using jQuery and setting the contentType

I'm struggling to figure out how to make a jsonp POST request with the correct content type of 'application/json'. Initially, I was able to send the POST request to the server using the jQuery.ajax method: jQuery.ajax({ type: ...

Tips on enabling the search bar to accept input and navigate to a new page

Currently, I am working on implementing a search box that redirects the user to a specific page based on their input. However, no matter what I try, it seems that when an input is provided, nothing happens. Here is the code I have been working with: <! ...

What is the best way to display the complete text or wrap a menu item in an Angular Material menu?

Is it possible to display the full text of a menu item instead of automatically converting it to ellipses or breaking the word? I've tried various CSS methods without success. Any suggestions? https://i.stack.imgur.com/3l7gE.png #html code <mat-m ...

Having difficulty showcasing the JSON data within the dropdown list within an HTML table

In my HTML table, I have 4 rows with Order ID and Product Comments columns disabled. Users can enter data in other columns and submit it. Upon submission, I receive a JSON object which I iterate through and display in the table. I am facing two challenges ...