Skip to content Skip to sidebar Skip to footer

Popup Form To Edit Shape Position And Label?

I want to click on a shape to edit its text label and x,y coordinates using a popup form that, when submitted, updates the data for that shape and the shape then moves to the new x

Solution 1:

In D3 it's quite simple to override the datum. Inside the listener where d is the first parameter, just do:

d.foo = bar;

In your example, let's use prompt to get the new values. This is just a demo to show you how to do it: you can easily change the ugly prompts for fancy popup divs.

So, inside the listener, we get the new values...

var newLabel = prompt("Please enter the new label: ");
var newX = prompt("Please enter the new x position: ");
var newY = prompt("Please enter the new y position: ");

... and use them to reposition the rectangles, overriding the datum at the same time:

d3.select(this)
    .attr("x", d.x = +newX)
    .attr("y", d.y = +newY);

The only problem is getting the labels. As you have to go up and down in the DOM, I suggest you to give them (unique) ids...

rects.append("text")
    .attr("id", function(d, i) {
        return"label" + i;
    })

... and them getting them:

d3.select(this.parentNode)
    .select("#label" + i)
    .text(newLabel)
    .attr("x", function(d) {
        return d.x + 10;
    })
    .attr("y", function(d) {
        return d.y + 10;
    });

Here is your code with those changes only:

var rectData = [{
  "label": "one",
  "x": 100,
  "y": 50,
  "height": 100,
  "width": 120,
  "color": "green"
}, {
  "label": "two",
  "x": 250,
  "y": 50,
  "height": 100,
  "width": 120,
  "color": "purple"
}, {
  "label": "three",
  "x": 400,
  "y": 50,
  "height": 100,
  "width": 120,
  "color": "red"
}];

var svg = d3.select("body").append("svg")
  .attr("width", 600)
  .attr("height", 200);

var rects = svg.selectAll("rect")
  .data(rectData)
  .enter();

rects.append("rect")
  .attr("x", function(d) {
    return d.x;
  })
  .attr("y", function(d) {
    return d.y;
  })
  .attr("height", function(d) {
    return d.height;
  })
  .attr("width", function(d) {
    return d.width;
  })
  .style("fill", function(d) {
    return d.color;
  })
  .on('mouseover', function(d) {
    var rectSelection = d3.select(this)
      .style({
        opacity: '0.5'
      })
  })
  .on('mouseout', function(d) {
    var rectSelection = d3.select(this)
      .style({
        opacity: '1'
      })
  })
  .on("click", function(d, i) {
    var newLabel = prompt("Please enter the new label: ")
    var newX = prompt("Please enter the new x position: ")
    var newY = prompt("Please enter the new y position: ")
    d3.select(this).attr("x", d.x = +newX).attr("y", d.y = +newY);
    d3.select(this.parentNode).select("#label" + i).text(newLabel).attr("x", function(d) {
        return d.x + 10;
      })
      .attr("y", function(d) {
        return d.y + 10;
      })
  });

// Rectangle Label
rects.append("text")
  .attr("id", function(d, i) {
    return"label" + i;
  })
  .style("fill", "black")
  .attr("dy", ".35em")
  .attr("x", function(d) {
    return d.x + 10;
  })
  .attr("y", function(d) {
    return d.y + 10;
  })
  .text(function(d) {
    return"Label: " + d.label
  });
<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Have in mind that this is a very, very simple demo: I'm neither checking the type of the input (string, integer, float...) nor their values.

PS: If you were using D3 v4 (that, with your code, requires no change at all!), you could avoid the new-positioned rectangle going behind the other ones with a simple selection.raise().

Post a Comment for "Popup Form To Edit Shape Position And Label?"