在JS中交换父节点的两个子节点

问题描述 投票:0回答:1

我有一个由九个

div
组成的父 div,每个都有不同的背景图像。我的任务是,每当我单击除
div
之外的任何
targetDiv
时,div 就会被 DOM 中的
targetDiv
交换。所以,这是代码:

function swap(e) {
  let parent = document.getElementsByClassName('container')[0];
  swapDivsByBackground(parent, e.style.background);
}

function swapDivsByBackground(parent, bgImage1) {

  const children = Array.from(parent.children);
  const moveDiv = children.find(div =>
    div.style.background.includes(bgImage1)
  );
  if (!moveDiv)
    return;

  const moveIndex = children.indexOf(moveDiv);
  const targetIndex = children.indexOf(targetDiv);

  parent.removeChild(moveDiv);
  parent.removeChild(targetDiv);

  try {
    parent.insertBefore(moveDiv, children[moveIndex + 1] || null);
  } catch (e) {
    console.log(moveIndex + 1);
    console.log(children[moveIndex + 1]);
    console.log(e.message);
  }
  try {
    parent.insertBefore(targetDiv, children[targetIndex + 1] || null);
  } catch (e) {
    console.log(targetIndex + 1);
    console.log(children[targetIndex + 1]);
    console.log(e.message);
  }
}

我在这里严重面临一些问题。有时,没有交换,有时,我什至收到一条错误消息:

无法在“Node”上执行“insertBefore”:要在其之前插入新节点的节点不是该节点的子节点。

但与此同时,我还收到来自

console.log(moveIndex+1);
console.log(children[moveIndex+1]);
的控制台消息,显示了有效的 div 引用。但是,如果该节点不是子节点,那么为什么会显示这些消息?他们应该显示未定义。

javascript html dom-manipulation
1个回答
0
投票

我会这样做...

const parentDiv = document.querySelector('.container');

parentDiv.addEventListener('click', ({target:inDiv}) => 
  {
  if (!inDiv.matches('.container > div')) return;

  let targetDiv = parentDiv.querySelector('.targetDiv');

  if (!targetDiv)                inDiv.classList.add('targetDiv');
  else if (targetDiv===inDiv)    inDiv.classList.remove('targetDiv');
  else
    {                      // swapp
    if      (inDiv.nextElementSibling === targetDiv)  targetDiv.after(inDiv);  // they follow each other
    else if (targetDiv.nextElementSibling === inDiv)  targetDiv.before(inDiv);  // => 1 single mov needed
    else
      {
      let mov_A = { refelm: inDiv.nextElementSibling,     method:'before' }
        , mov_B = { refelm: targetDiv.nextElementSibling, method:'before' }
        ;
      if ( !mov_A.refelm )
        {
        mov_A.refelm = parentDiv;
        mov_A.method = 'append';
        }
      if ( !mov_B.refelm )
        {
        mov_B.refelm = parentDiv;
        mov_B.method = 'append';
        }
      mov_A.refelm[mov_A.method](targetDiv);
      mov_B.refelm[mov_B.method](inDiv);
      }
    }
  })
.container {
  font-size  : 12px;
  }
.container > div {
  margin     : .2em;
  width      : 6em;
  text-align : center;
  padding    : .2em;
  border     : 1px solid grey;
  cursor     : pointer;
  }
.container > div.targetDiv {
  outline  : .01em solid red;
  }
.container > div.b3 {background-color: #ffc0cb;}
.container > div.b6 {background-color: #c0fbff;}
.container > div.b9 {background-color: #dad757;}
<div class="container">
  <div>b1</div>
  <div>b2</div>
  <div class="b3">b3</div>
  <div>b4</div>
  <div>b5</div>
  <div class="b6">b6</div>
  <div>b7</div>
  <div>b8</div>
  <div class="b9">b9</div>
</div>

© www.soinside.com 2019 - 2024. All rights reserved.