使用HTML输入更新数据值并更改数据数组

时间:2017-11-27 21:26:07

标签: javascript d3.js

我希望在单击形状时更新<div>中显示的形状标签,x位置和y位置值。 https://jsfiddle.net/NovasTaylor/q8cLhw9b/

用户编辑表单字段以根据需要更改值,然后单击“提交”将更改(如果有)写回JSON数组。

我在矩形的"click"事件中构建了表单,该事件也会触发不透明度以在页面顶部的<div>中显示表单:

.on("click", function(d){
  d3.select("#rectInfo").style("opacity", 1);

  var infoForm = d3.select("#rectInfo").append("form")
   .attr("id", "foo")
   .attr("action", "javascript:submitForm();")
   .attr("method", "post")
   .attr("class", "formEle");

显示按需工作。但是,我不知道如何将表单中的值推回到JSON数组。 submitForm()函数只清除div convent。

function submitForm(){
  d3.selectAll(".formEle").remove();
  d3.select("#rectInfo").style("opacity", 0);
}

如何将表单中的值恢复为JSON数组?

1 个答案:

答案 0 :(得分:3)

根据your comment,您不会将此信息发送到任何地方。因此,您不需要表格。

所以,只需将常规文本输入附加到该div ...

var div = d3.select("#rectInfo")

var labelText = div.append("p")
    .text("Label: ");

var labelInput = labelText.append("input")
    .attr("size", "15")
    .attr("type", "text")
    .attr("value", d.label);

var xPosText = div.append("p")
    .text("X pos: ");

var xPosInput = xPosText.append("input")
    .attr("size", "15")
    .attr("type", "text")
    .attr("value", d.x);

var yPosText = div.append("p")
    .text("Y pos: ");

var yPosInput = yPosText.append("input")
    .attr("size", "15")
    .attr("type", "text")
    .attr("value", d.y);

...并创建一个按钮,在“点击”时,获取输入的值并更改xylabel属性:

var button = div.append("button")
    .text("Submit/Hide")
    .on("click", function() {
        d3.select(self).attr("x", function(d) {
            return d.x = +xPosInput.node().value
        }).attr("y", function(d) {
            return d.y = +yPosInput.node().value
        });
        d3.select("#text" + i).text(function(d) {
                return "Label: " + (d.label = labelInput.node().value);
            })
            .attr("x", function(d) {
                return d.x = +xPosInput.node().value + 10
            }).attr("y", function(d) {
                return d.y = +yPosInput.node().value + 10
            });
    })

注意这种模式:

return d.x = +xPosInput.node().value

它做了两件事:

  1. 返回一个值(在本例中为+xPosInput.node().value);
  2. 它将该值分配给d.x,从而更改我们的数据。
  3. 此外,输入返回字符串,即使用户键入数字......这就是为什么在上面的示例中xPosInput.node().value之前存在一元加号运算符的原因。

    作为最后一点,我不是删除/重新附加元素的粉丝(我在谈论div)。你可以简单地更新它们。但是,正如我在其他答案中告诉你的那样,这是一个不同的问题,并且在S.O.我们试图在每个问题中只保留一个问题(所以,我在这个答案中没有处理它)。

    以下是包含这些更改的代码:

    var rectInfoActive = false;
    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()
      .append("g");
    
    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 self = this;
    
        if (rectInfoActive == true) {
          // clicked a node while previous info block displayed
          d3.selectAll("input").remove();
          d3.selectAll(".formEle").remove();
          d3.select("#rectInfo").selectAll("*").remove();
          d3.select("#rectInfo").style("opacity", 0);
        }
    
        d3.select("#rectInfo").style("opacity", 1);
    
        // Form displayed in /div becomes visible onclick of a rect.
        // submit button clears the form. No data update yet.
        var div = d3.select("#rectInfo")
    
        var labelText = div.append("p")
          .text("Label: ");
    
        var labelInput = labelText.append("input")
          .attr("size", "15")
          .attr("type", "text")
          .attr("value", d.label);
    
        var xPosText = div.append("p")
          .text("X pos: ");
    
        var xPosInput = xPosText.append("input")
          .attr("size", "15")
          .attr("type", "text")
          .attr("value", d.x);
    
        var yPosText = div.append("p")
          .text("Y pos: ");
    
        var yPosInput = yPosText.append("input")
          .attr("size", "15")
          .attr("type", "text")
          .attr("value", d.y);
    
        var button = div.append("button")
          .text("Submit/Hide")
          .on("click", function() {
            d3.select(self).attr("x", function(d) {
              return d.x = +xPosInput.node().value
            }).attr("y", function(d) {
              return d.y = +yPosInput.node().value
            });
            d3.select("#text" + i).text(function(d) {
                return "Label: " + (d.label = labelInput.node().value);
              })
              .attr("x", function(d) {
                return d.x = +xPosInput.node().value + 10
              }).attr("y", function(d) {
                return d.y = +yPosInput.node().value + 10
              });
    
            d3.select("#rectInfo").selectAll("*").remove();
            d3.select("#rectInfo").style("opacity", 0);
          })
    
        rectInfoActive = true;
    
    
    
      });
    // END OF FORM
    
    // Rectangle Label
    rects.append("text")
      .attr("id", function(d, i) {
        return "text" + 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
      });
    
    
    
    // Misc functions -------------------------------------------------------------
    // clearTheForm ----
    // Clear the form and input values. This will later become the Update function
    //  that will update changed values back into the JSON array.
    #rectInfo {
      background-color: white;
      position: relative;
      padding: 10px;
      width: 230px;
      height: 100px;
      border: 2px;
      outline: grey solid thin;
    }
    
    #rectInfo p {
      margin: 4px;
    }
    
    .formLabel {
      font-family: courier;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
    <!-- Click on a shape to see its label, x, y pos.
      Submit button clears the div (not working here in fiddle)
      but should be changed to instead call a fnt that updates the data with values changed in the form.
    -->
    
    <div id="rectInfo" style="opacity:0">
      <!-- Rect info will appear here -->
    </div>