【问题标题】:Swap two horizontally aligned divs交换两个水平对齐的 div
【发布时间】:2012-11-26 11:36:52
【问题描述】:

我在一条水平线上有以下 DOM 元素:

  1. 包含一行文本的 div;即“你好世界”。此 div 的宽度与包含的文本相同。
  2. 交换两个 div 的按钮。
  3. 一个包含列表框的 div。此 div 的宽度与包含列表框的宽度相同。

使用floatposition:absolute 我可以将这些元素正确对齐在一行上。但是,当用户单击交换按钮时,div 应该交换位置。我不希望从 DOM 中删除 div 并将它们再次添加到彼此的位置。这是因为元素实际上是 Javascript 对象(更具体的说是 Google 闭包库组件),它们保存变量并附加了事件处理程序。是否可以使用 CSS 交换 div,而不为 div 分配静态宽度?

简化示例:

<div style="position:relative; height:60px;">
  <div style="float:left;">Our Team</div>
  <div style="float:left;"><button onclick="swap();">swap home/away</button></div>
  <div style="float:left;"><select><option>Opponent A</option><option>Opponent B</option></select></div>
</div>
<div style="clear:both;"></div>

当用户单击按钮时,第一个(我们的团队)和第三个(对手)div 应该在浏览器中进行视觉交换,最好不要从 DOM 中删除元素。

【问题讨论】:

  • 向我们展示你的代码,你是如何实现这些东西的…………
  • @ShailenderArora 我添加了 HTML 代码的简化版本。

标签: javascript html css google-closure-library


【解决方案1】:

我不希望从 DOM 中删除 div 并将它们再次添加到彼此的位置。这是因为元素实际上是 Javascript 对象(更具体地说是 Google 闭包库组件),它们包含变量并附加了事件处理程序。

最好的解决方案是移动 DOM 中的元素。这样做会保留现有的事件处理程序,这意味着您的代码应该仍然可以工作:

http://jsfiddle.net/thirtydot/LGGW2/

function swap() {
    var target1 = document.querySelector('#swapMe > :first-child');
    var target2 = document.querySelector('#swapMe > :last-child');

    var parent = target1.parentNode;
    parent.insertBefore(target1, null);
    parent.insertBefore(target2, parent.firstChild);
}​

我假设您已经有了对要交换的元素的引用,因此您可以将 document.querySelector 行替换为任何合适的行。

写完这个答案后,我搜索了一个更通用的“swap”函数,发现了这个,看起来不错:Swap 2 html elements and preserve event listeners on them

【讨论】:

  • 这确实是最好的解决方案。谢谢!
【解决方案2】:

在您的 HTML 中,两个 div 都相同 (style="float:left;"),没有 classid,因此您只能交换两个 div 的 HTML,即

function swap(e)
{
    e  = e || window.event, target = e.target || e.srcElement;
    var nEl=getElem(target.parentNode, 'next');
    var pEl=getElem(target.parentNode, 'prev');
    var pElHtml=pEl.innerHTML, nElHtml=nEl.innerHTML;
    pEl.innerHTML=nElHtml;
    nEl.innerHTML=pElHtml;
}

function getElem(elem, which) {
    if(which==='next') which='nextSibling';
    else if((which==='prev')) which='previousSibling'; 
    do{
        elem = elem[which];
    }
    while (elem && elem.nodeType != 1);
    return elem;        
}​

DEMO.

【讨论】:

  • 不幸的是,这样做会弄乱绑定事件。点击“我们的团队”,然后点击交换,然后再次点击“我们的团队”:jsfiddle.net/thirtydot/Wxp9j/1
  • @thirtydot,您完全正确,但我认为没有这样的事件,所以我这样回答,但再次感谢 +1。
【解决方案3】:

对于您的问题,我有一些解决方案。一两个与你的风格有关。如果我是你,我会删除内联样式(除非由 javascript 添加)并将相同的类添加到所有“浮动”元素。

对于更多更新的浏览器,这将完美地工作:

.floaters{
    display:inline-block;
}

但对于较旧的浏览器(ie5.5、6、7、8),您需要申请:

.floaters{
    display:inline;
    float:left;
    height:60px;/*set a default height*/
}

现在是swap(); 函数。我不确定你是如何应用它的,但我会通过更改它们的 innerHTML(); 来交换元素

function swap(){
    var ele1HTML = document.getElementById('ele1').innerHTML();
    var ele3HTML = document.getElementById('ele3').innerHTML();
    document.getElementById('ele1').innerHTML(ele3HTML);
    document.getElementById('ele3').innerHTML(ele1HTML);
}

但下面的代码将要求您将 ID 属性添加到您的 div。这是一个例子:

<div id="menu">
  <div id="ele1" class="floater">
      Our Team
  </div>
  <div id="ele2" class="floater">
      <button onclick="swap();">swap home/away</button>
  </div>
  <div id="ele3" class="floater">
      <select>
          <option>Opponent A</option>
          <option>Opponent B</option>
      </select>
  </div>
</div>
<div id="anotherDiv"></div>

但不要忘记重新应用您的样式:

#menu{
    position:relative;
    height:60px; /*not needed for the older browser as I've set the child elements to 60px;*/
}
#anotherDiv{
    clear:both;
}

【讨论】:

  • 所以你只想交换元素一次?或更改按钮内的 html?
  • @Beneto 每次用户单击按钮时,都会交换元素。元素本身,以及其中的元素不能从 DOM 中删除,因为有/可以附加到它们的事件处理程序。在客户端内存中,变量与这些 DOM 元素相关联。如果删除此类元素的 innerHTML,则必须在每个交换操作上重新分配这些变量和事件处理程序。另外,我不会在我的生产代码中使用内联样式,但在此处显示代码是一种更简洁的方式。
  • @Korneel 哦,是的,我没想到我只是在交换子元素,从没想过触发它们。
猜你喜欢
  • 1970-01-01
  • 2020-10-17
  • 1970-01-01
  • 1970-01-01
  • 2014-02-23
  • 2011-01-25
  • 2019-08-25
  • 2014-01-01
  • 2013-04-16
相关资源
最近更新 更多