183

我可以用 jQuery 轻松交换两个元素吗?

如果可能的话,我希望用一条线来做到这一点。

我有一个选择元素,我有两个按钮可以向上或向下移动选项,而且我已经有了选定的和目标选择器,我用 if 来做,但我想知道是否有更简单的方法。

4

22 回答 22

247

我发现了一种仅使用 jQuery 来解决此问题的有趣方法:

$("#element1").before($("#element2"));

或者

$("#element1").after($("#element2"));

:)

于 2011-12-26T18:19:44.743 回答
79

Paulo 是对的,但我不确定他为什么要克隆相关元素。这并不是真正必要的,并且会丢失与元素及其后代关联的任何引用或事件侦听器。

这是一个使用普通 DOM 方法的非克隆版本(因为 jQuery 并没有任何特殊功能可以使这个特定操作更容易):

function swapNodes(a, b) {
    var aparent = a.parentNode;
    var asibling = a.nextSibling === b ? a : a.nextSibling;
    b.parentNode.insertBefore(a, b);
    aparent.insertBefore(b, asibling);
}
于 2009-03-30T18:25:45.167 回答
73

不,没有,但你可以抽出一个:

jQuery.fn.swapWith = function(to) {
    return this.each(function() {
        var copy_to = $(to).clone(true);
        var copy_from = $(this).clone(true);
        $(to).replaceWith(copy_from);
        $(this).replaceWith(copy_to);
    });
};

用法:

$(selector1).swapWith(selector2);

请注意,这仅在选择器每个仅匹配 1 个元素时才有效,否则可能会产生奇怪的结果。

于 2009-03-30T18:13:14.870 回答
46

这个问题有很多边缘情况,接受的答案或 bobince 的答案没有处理这些情况。其他涉及克隆的解决方案都在正确的轨道上,但克隆既昂贵又不必要。我们很想克隆,因为如何交换两个变量的古老问题,其中一个步骤是将变量之一分配给临时变量。在这种情况下,不需要分配(克隆)。这是一个基于 jQuery 的解决方案:

function swap(a, b) {
    a = $(a); b = $(b);
    var tmp = $('<span>').hide();
    a.before(tmp);
    b.before(a);
    tmp.replaceWith(b);
};
于 2013-09-26T16:39:02.350 回答
25

jQuery.before方法可用于通过添加临时 3rd 元素作为书签来交换元素 - 在移动内容时将临时 DOM 元素作为占位符。.

$.fn.swapWith = function(that) {
  var $this = this;
  var $that = $(that);
  
  // create temporary placeholder
  var $temp = $("<div>");
  
  // 3-step swap
  $this.before($temp);
  $that.before($this);
  $temp.before($that).remove();
        
  return $this;
}
  1. 将临时 div 放在temp前面this

  2. 前移this_that

  3. 前移that_temp

3b) 移除temp

然后像这样使用它

$(selectorA).swapWith(selectorB);

演示:https ://jsfiddle.net/7t1hz94y/

于 2016-07-21T21:59:05.057 回答
11

你不应该需要两个克隆,一个就可以了。以 Paolo Bergantino 的回答我们有:

jQuery.fn.swapWith = function(to) {
    return this.each(function() {
        var copy_to = $(to).clone(true);
        $(to).replaceWith(this);
        $(this).replaceWith(copy_to);
    });
};

应该更快。传入两个元素中较小的一个也应该加快速度。

于 2010-02-04T16:44:42.497 回答
8

我以前用过这样的技术。我将它用于http://mybackupbox.com上的连接器列表

// clone element1 and put the clone before element2
$('element1').clone().before('element2').end();

// replace the original element1 with element2
// leaving the element1 clone in it's place
$('element1').replaceWith('element2');
于 2012-02-26T06:00:32.847 回答
3

我制作了一个功能,允许您向上或向下移动多个选定的选项

$('#your_select_box').move_selected_options('down');
$('#your_select_boxt').move_selected_options('up');

依赖项:

$.fn.reverse = [].reverse;
function swapWith() (Paolo Bergantino)

首先它检查第一个/最后一个选择的选项是否能够向上/向下移动。然后它遍历所有元素并调用

swapWith(element.next() 或 element.prev())

jQuery.fn.move_selected_options = function(up_or_down) {
  if(up_or_down == 'up'){
      var first_can_move_up = $("#" + this.attr('id') + ' option:selected:first').prev().size();
      if(first_can_move_up){
          $.each($("#" + this.attr('id') + ' option:selected'), function(index, option){
              $(option).swapWith($(option).prev());
          });
      }
  } else {
      var last_can_move_down = $("#" + this.attr('id') + ' option:selected:last').next().size();
      if(last_can_move_down){
        $.each($("#" + this.attr('id') + ' option:selected').reverse(), function(index, option){
            $(option).swapWith($(option).next());
        });
      }
  }
  return $(this);
}
于 2011-01-27T14:34:49.483 回答
3

另一个没有克隆的:

我有一个实际元素和一个名义元素要交换:

            $nominal.before('<div />')
            $nb=$nominal.prev()
            $nominal.insertAfter($actual)
            $actual.insertAfter($nb)
            $nb.remove()

theninsert <div> beforeremovelater 只需要,如果你不能确保,总是有一个元素之前(在我的情况下是)

于 2014-09-14T17:10:27.053 回答
3

这是我在父元素内上下移动多个子元素的解决方案。适用于在列表框中移动选定的选项 ( <select multiple></select>)

提升:

$(parent).find("childrenSelector").each((idx, child) => {
    $(child).insertBefore($(child).prev().not("childrenSelector"));
});

下移:

$($(parent).find("childrenSelector").get().reverse()).each((idx, child) => {
    $(opt).insertAfter($(child).next().not("childrenSelector"));
});
于 2018-03-16T15:15:49.560 回答
2

看看 jQuery 插件“Swapable”

http://code.google.com/p/jquery-swapable/

它建立在“可排序”的基础上,看起来像可排序的(拖放、占位符等),但只交换两个元素:拖放。所有其他元素不受影响并保持在当前位置。

于 2010-07-03T21:42:55.357 回答
2

这是基于@lotif的答案逻辑的答案,但更笼统

如果您在元素实际移动
之后/之前附加/前置=> 不需要克隆
=> 保留事件

有两种情况可能发生

  1. 一个目标有一些“ .prev()ious”=>我们可以把另一个目标放在.after()那个地方。
  2. 一个目标是它的第一个孩子.parent()=> 我们可以.prepend()将另一个目标作为父母。

编码

这段代码可以做得更短,但为了便于阅读,我保持这种方式。请注意,预先存储父母(如果需要)和以前的元素是强制性的。

$(function(){
  var $one = $("#one");
  var $two = $("#two");
  
  var $onePrev = $one.prev(); 
  if( $onePrev.length < 1 ) var $oneParent = $one.parent();

  var $twoPrev = $two.prev();
  if( $twoPrev.length < 1 ) var $twoParent = $two.parent();
  
  if( $onePrev.length > 0 ) $onePrev.after( $two );
    else $oneParent.prepend( $two );
    
  if( $twoPrev.length > 0 ) $twoPrev.after( $one );
    else $twoParent.prepend( $one );

});

...随意将内部代码包装在一个函数中:)

示例小提琴附加了额外的点击事件以演示事件保存...
示例小提琴: https ://jsfiddle.net/ewroodqa/

...适用于各种情况 - 甚至是以下情况:

<div>
  <div id="one">ONE</div>
</div>
<div>Something in the middle</div>
<div>
  <div></div>
  <div id="two">TWO</div>
</div>
于 2016-05-05T00:18:09.090 回答
1

如果你想交换 jQuery 对象中选择的两个项目,你可以使用这个方法

http://www.vertstudios.com/blog/swap-jquery-plugin/

于 2010-09-12T09:04:13.367 回答
1

我想要一个不使用 clone() 的解决方案,因为它对附加事件有副作用,这就是我最终要做的

jQuery.fn.swapWith = function(target) {
    if (target.prev().is(this)) {
        target.insertBefore(this);
        return;
    }
    if (target.next().is(this)) {
        target.insertAfter(this);
        return
    }

    var this_to, this_to_obj,
        target_to, target_to_obj;

    if (target.prev().length == 0) {
        this_to = 'before';
        this_to_obj = target.next();
    }
    else {
        this_to = 'after';
        this_to_obj = target.prev();
    }
    if (jQuery(this).prev().length == 0) {
        target_to = 'before';
        target_to_obj = jQuery(this).next();
    }
    else {
        target_to = 'after';
        target_to_obj = jQuery(this).prev();
    }

    if (target_to == 'after') {
        target.insertAfter(target_to_obj);
    }
    else {
        target.insertBefore(target_to_obj);
    }
    if (this_to == 'after') {
        jQuery(this).insertAfter(this_to_obj);
    }
    else {
        jQuery(this).insertBefore(this_to_obj);
    }

    return this;
};

它不能与包含多个 DOM 元素的 jQuery 对象一起使用

于 2013-09-15T09:52:13.793 回答
1

如果每个元素都有多个副本,则自然需要循环执行某些操作。我最近有这种情况。我需要切换的两个重复元素具有类和容器 div,如下所示:

<div class="container">
  <span class="item1">xxx</span>
  <span class="item2">yyy</span>
</div> 
and repeat...

以下代码允许我遍历所有内容并反转...

$( ".container " ).each(function() {
  $(this).children(".item2").after($(this).children(".item1"));
});
于 2015-02-16T17:19:30.667 回答
1

我已经用这个片段完成了

// Create comments
var t1 = $('<!-- -->');
var t2 = $('<!-- -->');
// Position comments next to elements
$(ui.draggable).before(t1);
$(this).before(t2);
// Move elements
t1.after($(this));
t2.after($(ui.draggable));
// Remove comments
t1.remove();
t2.remove();
于 2015-03-14T10:03:08.307 回答
1

我做了一个表格,用于更改数据库中使用的 .after() .before() 中的 obj 顺序,所以这是我的实验。

$(obj1).after($(obj2))

是在 obj2 之前插入 obj1 并且

$(obj1).before($(obj2)) 

反之亦然。

因此,如果 obj1 在 obj3 之后,而 obj2 在 obj4 之后,并且如果你想改变 obj1 和 obj2 的位置,你会这样做

$(obj1).before($(obj4))
$(obj2).before($(obj3))

这应该这样做顺便说一句,如果您还没有某种索引,您可以使用 .prev() 和 .next() 来查找 obj3 和 obj4 。

于 2016-11-11T03:31:43.287 回答
1
$('.five').swap('.two');

像这样创建一个 jQuery 函数

$.fn.swap = function (elem) 
{
    elem = elem.jquery ? elem : $(elem);
    return this.each(function () 
    {
        $('<span></span>').insertBefore(this).before(elem.before(this)).remove();
    });
};

感谢https://jsfiddle.net/ARTsinn/TVjnr/Yannick Guinness

于 2020-04-14T16:49:01.460 回答
0

如果 nodeA 和 nodeB 是兄弟姐妹,喜欢两个<tr>在同一个<tbody>,你可以使用$(trA).insertAfter($(trB))$(trA).insertBefore($(trB))交换它们,它适用于我。而且你之前不需要调用$(trA).remove(),否则你需要重新绑定一些点击事件$(trA)

于 2017-08-26T03:36:42.853 回答
0

目前无需为任何主流浏览器使用 jquery 来交换元素。原生 dom 方法,insertAdjacentElement无论它们位于何处,都可以解决问题:

var el1 = $("el1");
var el2 = $("el2");
el1[0].insertAdjacentElement("afterend", el2[0]);
于 2020-08-29T11:50:39.403 回答
-2

最好的选择是使用 clone() 方法克隆它们。

于 2009-03-30T19:03:08.650 回答
-2

我认为你可以很简单地做到这一点。例如,假设您有下一个结构: ...

<div id="first">...</div>
<div id="second">...</div>

结果应该是

<div id="second">...</div>
<div id="first">...</div>

jQuery:

$('#second').after($('#first'));

我希望它有帮助!

于 2013-02-10T17:11:28.540 回答