показать раскрывающийся список для определенного узла при нажатии стрелки вниз - PullRequest
0 голосов
/ 17 мая 2018

Я хочу показать имя узла вместе с такими действиями, как редактирование, удаление в выпадающем меню, например, материал.Я включил выпадающий значок в сторону каждого конечного узла, чтобы при щелчке на нем отображался раскрывающийся список, содержащий имя и редактирование этого конкретного узла, удалялся текст в списке, аналогичный функции раскрывающегося списка.Я не мог показать выпадающий список при нажатии на значок стрелки вниз.Как мне это сделать?

Этот код показывает стрелку вниз на каждой стороне имени конечного узла

node
  .append("foreignObject")
  .attr("width", "30")
  .attr("height", "30")
  .html(d => {
    if (d.parent && d.parent.parent) {
      return `<i class="dropdown-trigger material-icons" data-target=${d.data.name}>arrow_drop_down</i>
      <ul class="dropdown-content" id=${d.data.name}>
        <li>${d.data.name}</li>
        <li>delete</li>
      </ul>
                `;
    }
  })
  .attr("transform", d => {
    if (d.parent && d.parent.parent) {
      return pos === "left" ? "translate(-20,-5)" : "translate(10,-5)";
    }
  });

, но выпадающий элемент не отображается.

var data = {
  "name": "root@gmail.com",
  "children": [{
    "topic_id": 31572,
    "name": "Person Name 1",
    "children": [{
        "topic_id": 31573,
        "name": "Branch 4.1"
      }, {
        "topic_id": 31574,
        "name": "Branch 4.2"
      }, {
        "topic_id": 31575,
        "name": "Branch 4.2"
      },
      {
        "topic_id": 31576,
        "name": "Branch 4.2"
      }, {
        "topic_id": 31577,
        "name": "Branch 4.2"
      },
      {
        "topic_id": 31578,
        "name": "Branch 4.2"
      }
    ]
  }, {
    "topic_id": 32572,
    "name": "Person name 2",
    "children": [{
        "topic_id": 33572,
        "name": "Branch 4.1"
      }, {
        "topic_id": 34572,
        "name": "Branch 4.2"
      }, {
        "topic_id": 35572,
        "name": "Branch 4.2"
      },
      {
        "topic_id": 36572,
        "name": "Branch 4.2"
      }, {
        "topic_id": 37572,
        "name": "Branch 4.2"
      },
      {
        "topic_id": 38572,
        "name": "Branch 4.2"
      }
    ]
  }, {
    "topic_id": 41572,
    "name": "Person Name 3",
    "children": [{
        "topic_id": 51572,
        "name": "Branch 4.1"
      }, {
        "topic_id": 61572,
        "name": "Branch 4.2"
      }, {
        "topic_id": 71572,
        "name": "Branch 4.2"
      },
      {
        "topic_id": 81572,
        "name": "Branch 4.2"
      }, {
        "topic_id": 91572,
        "name": "Branch 4.2"
      },
      {
        "topic_id": 92572,
        "name": "Branch 4.2"
      }
    ]
  }, {
    "name": "Person Name 4",
    "children": [{
        "name": "Branch 4.1"
      }, {
        "name": "Branch 4.2"
      }, {
        "name": "Branch 4.2"
      },
      {
        "name": "Branch 4.2"
      }, {
        "name": "Branch 4.2"
      },
      {
        "name": "Branch 4.2"
      }
    ]
  }]
};


const LAST_CHILDREN_WIDTH = 13;
let flagForChildren = false;
let groups = [];
data.children.forEach(d => {
  let a = [];
  if (d.children.length > 0) {
    flagForChildren = true;
  }
  for (let i = 0; i < d.children.length; i += 2) {
    let b = d.children.slice(i, i + 2);
    if (b[0] && b[1]) {
      a.push(Object.assign(b[0], {
        children: [b[1]]
      }));
    } else {
      let child = b[0];
      if (i >= 6) {
        child = Object.assign(child, {
          children: [{
            name: "..."
          }]
        });
      }
      a.push(child);
    }
  }
  d.children = a;
  groups.push(d);
});

data.children = groups;
let split_index = Math.round(data.children.length / 2);
let rectangleHeight = 45;
let leftData = {
  name: data.name,
  children: JSON.parse(JSON.stringify(data.children.slice(0, split_index)))
};
let leftDataArray = [];
leftDataArray.push(leftData);

// Right data
let rightData = {
  name: data.name,
  children: JSON.parse(JSON.stringify(data.children.slice(split_index)))
};
// Create d3 hierarchies
let right = d3.hierarchy(rightData);
let left = d3.hierarchy(leftData);
// Render both trees
drawTree(right, "right");
drawTree(left, "left");

// draw single tree
function drawTree(root, pos) {
  let SWITCH_CONST = 1;
  if (pos === "left") {
    SWITCH_CONST = -1;
  }
  const margin = {
      top: 20,
      right: 120,
      bottom: 20,
      left: 120
    },
    width = window.innerWidth - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

  let svg = d3
    .select("svg")
    .attr("height", height + margin.top + margin.bottom)
    .attr("width", width + margin.right + margin.left)
    .attr('view-box', '0 0 ' + (width + margin.right) + ' ' + (height + margin.top + margin.bottom))
    .style("margin-top", "20px")
    .style("margin-left", "88px");

  const myTool = d3.select("body").append("div")
    .attr("class", "mytooltip")
    .style("opacity", "0")
    .style("display", "none");;


  // Shift the entire tree by half it's width
  let g = svg.append("g").attr("transform", "translate(" + width / 2 + ",0)");

  let deductWidthValue = flagForChildren ? 0 : width * 0.33;
  // Create new default tree layout
  let tree = d3
    .tree()
    // Set the size
    // Remember the tree is rotated
    // so the height is used as the width
    // and the width as the height
    .size([height - 50, SWITCH_CONST * (width - deductWidthValue) / 2])
    .separation((a, b) => a.parent === b.parent ? 4 : 4.25);

  tree(root);

  let nodes = root.descendants();
  let links = root.links();
  // Set both root nodes to be dead center vertically
  nodes[0].x = height / 2;

  // Create links
  let link = g
    .selectAll(".link")
    .data(links)
    .enter();

  link
    .append("line")
    .attr("class", function(d) {
      if (d.target.depth === 2) {
        return 'link'
      } else {
        return 'hard--link'
      }
    })
    .attr("x1", function(d) {
      if (
        d.target.depth === 3
      ) {
        return 0;
      }
      return d.source.y + 100 / 2; //d.source.y + 100/2
    })
    .attr("x2", function(d) {
      if (
        d.target.depth === 3
      ) {
        return 0;
      } else if (d.target.depth === 2) {
        return d.target.y;
      }
      return d.target.y + 100 / 2; //d.target.y + 100/2;
    })
    .attr("y1", function(d) {
      if (
        d.target.depth === 3
      ) {
        return 0;
      }
      return d.source.x + 50 / 2;
    })
    .attr("y2", function(d) {
      if (
        d.target.depth === 3
      ) {
        return 0;
      } else if (d.target.depth === 2) {
        return d.target.x + LAST_CHILDREN_WIDTH / 2;
      }
      return d.target.x + 50 / 2;
    });

  //Rectangle width

  let node = g
    .selectAll(".node")
    .data(nodes)
    .enter()
    .append("g")
    .on("mouseover", function(d) {})
    .attr("class", function(d) {
      return "node" + (d.children ? " node--internal" : " node--leaf");
    })
    .attr("transform", function(d) {
      if (d.parent && d.parent.parent) { // this is the leaf node
        if (d.parent.parent.parent) {
          return (
            "translate(" +
            d.parent.y +
            "," +
            (d.x + LAST_CHILDREN_WIDTH + 15) +
            ")"
          );
        }
        return "translate(" + d.y + "," + d.x + ")";
      }
      return "translate(" + d.y + "," + d.x + ")";
    });

  // topic rect
  node
    .append("rect")
    .attr("height", (d, i) => d.parent && d.parent.parent ? 15 : rectangleHeight)
    .attr("width", (d, i) => d.parent && d.parent.parent ? 15 : rectangleWidth(d))
    .attr("rx", (d, i) => d.parent && d.parent.parent ? 5 : 5)
    .attr("ry", (d, i) => d.parent && d.parent.parent ? 5 : 5)

  // topic edges
  node.append('line')
    .attr('x1', d => {
      if (d.depth === 2) {
        return 10
      }
    })
    .attr('x2', d => {
      if (d.depth === 2) {
        return 10
      }
    })
    .attr('y1', d => {
      if (d.depth === 2) {
        if (d.children) {
          return 0;
        }
        return 40;
      }
    })
    .attr('y2', d => {
      if (d.depth === 2) {
        return 40
      }
    })
    .attr('class', 'hard--link')

  // topic names
  node
    .append("text")
    .attr("dy", function(d, i) {
      return d.parent && d.parent.parent ? 10 : rectangleHeight / 2;
    })
    .attr("dx", function(d, i) {
      if (!(d.parent && d.parent.parent)) {
        return 12;
      } else {
        return 20;
      }
    })
    .style("fill", function(d, i) {
      return d.parent && d.parent.parent ? "Black" : "White";
    })
    .text(function(d) {
      let name = d.data.topic_name || d.data.name;
      return name.length > 12 ? `${name.substring(0, 12)}...` : name;
    })
    .style("text-anchor", function(d) {
      if (d.parent && d.parent.parent) {
        return pos === "left" && "end"
      }
    })
    .style("font-size", "12")
    .attr("transform", function(d) {
      if (d.parent && d.parent.parent) {
        return pos === "left" ? "translate(-30,0)" : "translate(5,0)"
      }
    })
  node
    .append("foreignObject")
    .attr("width", "30")
    .attr("height", "30")
    .html(d => {
      if (d.parent && d.parent.parent) {
        return `<i class="dropdown-trigger material-icons" data-target=${d.data.name}>arrow_drop_down</i>
          <ul class="dropdown-content" id=${d.data.topic_id}>
            <li class="topic-name-btn">${d.data.name}</li>
            <li class="action" id="action-delete">delete</li>
          </ul>
        `;
      }
    })
    .attr("transform", d => {
      if (d.parent && d.parent.parent) {
        return pos === "left" ? "translate(-20,-5)" : "translate(10,-5)";
      }
    }).on('click', showDropdown)

  function showDropdown(el) {
    const selectedDOMId = document.getElementById(el.data.topic_id);
    const show = el.data.topic_id && selectedDOMId.classList.toggle("show");
    if (show !== undefined) {
      console.log('selectedDOMId', selectedDOMId);
      selectedDOMId.style.left = (d3.event.pageX - 113) + "px"
      selectedDOMId.style.left = (d3.event.pageY - 50) + "px"
    }
  }

}

function rectangleWidth(d) {
  const MIN_WIDTH = 50;
  const MAX_WIDTH = 100;
  let dynamicLength = 6;
  if (d.data.topic_name) {
    dynamicLength = d.data.topic_name.length;
  } else if (d.data.name) {
    dynamicLength = d.data.name.length;
  }
  dynamicLength = dynamicLength < 3 ? MIN_WIDTH : MAX_WIDTH;
  return dynamicLength;
}
.show {
  display: block !important;
}

.dropdown-content {
  display: none;
  /* position: absolute; */
  background-color: #f1f1f1;
  padding: 0;
  margin-top: -25px;
  margin-left: 33px;
  min-width: 100px;
  overflow: auto;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
}

.dropdown-content li {
  list-style: none;
}

.dropdown-trigger {
  cursor: pointer;
}

li.topic-name-btn {
  background: #159c11;
  color: #fff;
  height: 25px;
  vertical-align: middle;
  padding-top: 5px;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.3/d3.min.js"></script>

</head>

<body>
  <svg className='spider-graph-svg'>
      </svg>
</body>

</html>

Как показать раскрывающийся список в конкретном узле, на котором стрелка вниз нажимается без использования jquery?

Обновлен код, но он еще не работает

Теперь я могу показать раскрывающийся список, но если я нажму на одну из тем, отобразится раскрывающийся список, и если снова, не закрывая этот раскрывающийся список, я нажмуна другом узле отображается раскрывающийся список для обоих узлов.Как закрыть другой предыдущий раскрывающийся список при нажатии на другой узел, чтобы отображался только текущий раскрывающийся список узлов?

1 Ответ

0 голосов
/ 18 мая 2018

вы можете добавить элемент HTML Select к вашему ForeignObject, что может быть достигнуто с помощью объединения данных D3, например

 var svg = d3.select("body").append("svg")
        .attr("width", 200)
        .attr("height", 100);
  
      var data = ["Node1"]
  
      var node = svg.selectAll(".node")
        .data(data)
        .enter()
        .append("g")
        .attr("transform", "translate(50,50)")
    
    node.append("circle")
        .attr("cx", 0)
        .attr("cy", 0)
        .attr("r", 10)
        .on("click", function(d){
  	         let div = d3.select(this.parentNode).select("div")
  	         let currentValue = div.style("display")
             let newValue = currentValue == "none" ? "block" : "none"
             div.style("display", newValue)
	     })

    var nodeSelect = node.append("foreignObject")
        .attr("width", 100)
        .attr("height", 100)
        .append("xhtml:body")
        .append("div")
            .append("select")
    
    nodeSelect.selectAll("option")
        .data(function(d){
              let options = [d,"delete","edit"]
          return options
            })
        .enter()
        .append("option")
        .attr("value", function(d){ return d })
        .text(function(d){ return d })
<!DOCTYPE html>
<html>
<head>
    <script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
</body>
</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...