是否有一个原生的jQuery函数来切换元素?

时间:2009-03-30 17:57:08

标签: jquery swap javascript

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

如果可能,我希望用一行来做这件事。

我有一个选择元素,我有两个按钮可以向上或向下移动选项,我已经选择了目标选择器,我用if做了,但我想知道是否有更容易方式。

22 个答案:

答案 0 :(得分:219)

我找到了一种有趣的方法来解决这个问题,只使用jQuery:

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

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

:)

答案 1 :(得分:75)

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

这是一个使用普通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);
}

答案 2 :(得分:66)

不,没有,但你可以鞭打一个:

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个元素的情况,否则会产生奇怪的结果。

答案 3 :(得分:36)

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

function swap(a, b) {
    a = $(a); b = $(b);
    var tmp = $('<span>').hide();
    a.before(tmp);
    b.before(a);
    tmp.replaceWith(b);
};

答案 4 :(得分:15)

对于一般情况,这些答案中的许多答案都是错误的,如果它们实际上甚至工作,则其他答案会不必要地复杂化。 jQuery .before.after方法可以完成您想要做的大部分工作,但是您需要第三个元素,就像许多交换算法的工作方式一样。它很简单 - 当你移动东西时,将一个临时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.after($that).remove();

  return $this;
}

1)将临时div temp放在this

之前

2)在this

之前移动that

3)在that

之后移动temp

3b)删除temp

然后简单地

$(selectorA).swapWith(selectorB);

DEMO:http://codepen.io/anon/pen/akYajE

答案 5 :(得分: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);
    });
};

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

答案 6 :(得分:7)

之前我使用过这样的技术。我将它用于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');

答案 7 :(得分: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);
}

答案 8 :(得分:3)

另一个没有克隆的人:

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

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

然后只需要insert <div> beforeremove,如果你无法确保,总是有一个元素(在我的情况下是)

答案 9 :(得分:2)

看一下jQuery插件“Swapable”

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

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

答案 10 :(得分:2)

这是我在父元素中上下移动多个子元素的解决方案。 适用于在列表框中移动所选选项(<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"));
});

答案 11 :(得分:2)

这是一个基于 @lotif 的回答逻辑的答案,但有点概括

如果您在元素实际 移动之后/之前追加/前置
=&GT;不需要克隆
=&GT;事件保持

有两种情况可能发生

  1. 一个目标有“ .prev() ious”=&gt;我们可以将其他目标 .after()
  2. 一个目标是它的第一个孩子 .parent() =&gt;我们可以 .prepend() 将其他目标转为父母。
  3. 代码

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

    $(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>
    

答案 12 :(得分:1)

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

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

答案 13 :(得分: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/上的扬尼克·吉尼斯

答案 14 :(得分:1)

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

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

在obj2和

之前插入obj1
$(obj1).before($(obj2)) 

反之亦然。

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

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

这应该这样做 顺便说一下,你可以使用.prev()和.next()找到obj3和obj4,如果你已经没有某种索引了。

答案 15 :(得分: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();

答案 16 :(得分: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"));
});

答案 17 :(得分: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对象一起使用

答案 18 :(得分:0)

如果nodeA和nodeB是兄弟姐妹,喜欢同一<tr>中的两个<tbody>,您可以使用$(trA).insertAfter($(trB))$(trA).insertBefore($(trB))来交换它们,它适合我。并且您之前不需要致电$(trA).remove(),否则您需要重新绑定$(trA)上的某些点击事件

答案 19 :(得分:0)

目前无需在任何主要浏览器中使用jquery来交换元素。原生dom方法insertAdjacentElement可以解决问题,无论它们如何定位:

var el1 = $("el1");
var el2 = $("el2");
el1[0].insertAdjacentElement("afterend", el2[0]);

答案 20 :(得分:-2)

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

答案 21 :(得分:-2)

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

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

,结果应为

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

jquery的:

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

我希望它有所帮助!