如何使用insertBefore和nextSibling方法交换现有子节点?

时间:2016-12-06 14:30:36

标签: javascript html

期望的结果: 考虑一下'Alpha Bravo Charlie Delta' 点击Alpha ='Bravo Alpha Charlie Delta' 点击Charlie ='Bravo Aplha Delta Charlie'

function myFunction(word) {
  var x = document.getElementById("Swap").checked;
  var y = document.getElementById("Delete").checked;
  var referenceNode = document.getElementById("word");


  if (x == true) {
    //referenceNode.parentNode.insertBefore(nextSibling);

  } else if (y == true) {
    word.parentNode.removeChild(word);
  } else {
    return false;
  }
}
<div id="container">
  <div id="word1" onClick="myFunction(this)">Alpha</div>
  <div id="word2" onClick="myFunction(this)">Bravo</div>
  <div id="word3" onClick="myFunction(this)">Charlie</div>
  <div id="word4" onClick="myFunction(this)">Delta</div>
</div>

<br>

<form>
  <input type="radio" name="selector" id="Delete" value="Delete" checked>
  <label for="Delete">Delete</label>
  <br>
  <input type="radio" name="selector" id="Swap" value="Swap">
  <label for="Swap">Swap</label>
  <br>
</form>

1 个答案:

答案 0 :(得分:4)

您的代码存在一些问题。

特别是,您不能只调用nextSibling,这是节点的属性。你必须这样称呼它:someNode.nextSibling

您还需要注意DOM中的所有内容都是一个节点,包括空白区域。因此,nextSibling通常会返回与每个TEXT_NODE之后的源代码中的回车符(空格)对应的div。相反,请使用nextElementSibling仅查找ELEMENT_NODE(不是TEXT_NODE)的下一个兄弟。详细了解节点类型 here

此外,insertBefore()方法有两个参数, newNode referenceNode 。详细了解 here

此外,您不应该使用内联HTML事件处理属性(不是您的实际问题,只是一种不好的做法)而且您不需要最后一个else分支。

见下面的工作示例。

// Get DOM reference to the Swap Radio Button
// Since there are only two radio buttons, we
// only need to get one of them. When we check
// it for checked later, if it isn't checked,
// we'll know that the other one is.
var x = document.getElementById("Swap");

// Get all the div elements into a node list
// based on the CSS class they all have:
var divs = document.querySelectorAll(".word");

// Loop through the node list and attach the click
// event handler to each. This replaces the inline
// HTML onClick event handlers you had before.
divs.forEach(function(div){
  div.addEventListener("click", myFunction);
});

// Click event handler
function myFunction() {  
  // Get the radio button that is checked by searching
  // using the CSS ":checked" pseudo-class that returns
  // elements that are currently in a checked state. 
  // In this example, you only have two radio buttons
  // and they are in a group making them mutually exclusive
  // since only one of them can be checked, querySelector 
  // will return the first element in the search node 
  // (document here) that matches the selector.
  var checked = document.querySelector(":checked");

  // See if that button is the Swap button
  if (x === checked) {
    
    // It is, now check to see if this clicked div
    // is NOT the last one. The JavaScript keyword
    // "this" refers to the "invocation context" 
    // object (the object responsible for triggering
    // this code. Since this is an event handler that
    // handles the click event of a DIV element, "this"
    // will refer to the DIV that was clicked. No need
    // to pass an object reference in. The test here
    // is just checking for the existence of a next
    // element sibling.
    if(this.nextElementSibling){
      // It's not the last div. Swap it with its next sibling:
      this.parentNode.insertBefore(this.nextElementSibling, this);
    }
  } else {
    // Delete was checked. Deleted the current div
    this.parentNode.removeChild(this);
  }     
}
<div id="container">
  <div class="word" id="word1">Alpha</div>
  <div class="word" id="word2">Bravo</div>
  <div class="word" id="word3">Charlie</div>
  <div class="word" id="word4">Delta</div>
</div>

<br>

<form>
  <input type="radio" name="selector" id="Delete" value="Delete" checked>
  <label for="Delete">Delete</label>
  <br>
  <input type="radio" name="selector" id="Swap" value="Swap">
  <label for="Swap">Swap</label>
  <br>
</form>