是否有原生 jQuery 函数可以切换元素?

发布于 2024-07-16 06:27:35 字数 145 浏览 7 评论 0原文

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

如果可能的话,我希望用一行来完成此操作。

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

Can I easily swap two elements with jQuery?

I'm looking to do this with one line if possible.

I have a select element and I have two buttons to move up or down the options, and I already have the selected and the destination selectors in place, I do it with an if, but I was wondering if there is an easier way.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(22

等数载,海棠开 2024-07-23 06:27:36

看看 jQuery 插件“Swapable”

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

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

take a look at jQuery plugin "Swapable"

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

it's built on "Sortable" and looks like sortable (drag-n-drop, placeholder, etc.) but only swap two elements: dragged and dropped. All other elements are not affected and stay on their current position.

挥剑断情 2024-07-23 06:27:36

这是基于@lotif的答案逻辑的答案,但更概括一些

如果您在元素实际移动之后/之前附加/前置

=> 无需克隆

=> events keep

有两种情况可能发生

  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>

This is an answer based on @lotif's answer logic, but bit more generalized

If you append/prepend after/before the elements are actually moved

=> no clonning needed

=> events kept

There are two cases that can happen

  1. One target has something " .prev() ious" => we can put the other target .after() that.
  2. One target is the first child of it's .parent() => we can .prepend() the other target to parent.

The CODE

This code could be done even shorter, but I kept it this way for readability. Note that prestoring parents (if needed) and previous elements is mandatory.

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

});

...feel free to wrap the inner code in a function :)

Example fiddle has extra click events attached to demonstrate event preservation...

Example fiddle: https://jsfiddle.net/ewroodqa/

...will work for various cases - even one such as:

<div>
  <div id="one">ONE</div>
</div>
<div>Something in the middle</div>
<div>
  <div></div>
  <div id="two">TWO</div>
</div>
从﹋此江山别 2024-07-23 06:27:36

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

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

If you're wanting to swap two items selected in the jQuery object, you can use this method

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

遮了一弯 2024-07-23 06:27:36

我想要一个不使用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对象一起使用

I wanted a solution witch does not use clone() as it has side effect with attached events, here is what I ended up to do

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;
};

it must not be used with jQuery objects containing more than one DOM element

錯遇了你 2024-07-23 06:27:36

如果每个元素有多个副本,则自然需要在循环中执行某些操作。 我最近就有这样的情况。 我需要切换的两个重复元素有类和容器 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"));
});

If you have multiple copies of each element you need to do something in a loop naturally. I had this situation recently. The two repeating elements I needed to switch had classes and a container div as so:

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

The following code allowed me to iterate through everything and reverse...

$( ".container " ).each(function() {
  $(this).children(".item2").after($(this).children(".item1"));
});
糖果控 2024-07-23 06:27:36

我已经用这个片段完成了

// 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();

I have done it with this snippet

// 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();
苍白女子 2024-07-23 06:27:36

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

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

是在 obj2 之前插入 obj1 ,

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

反之亦然。

因此,如果 obj1 在 obj3 之后,而 obj2 在 obj4 之后,并且如果您想更改 obj1 和 obj2 的位置,您将像这样执行

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

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

I did a table for changing order of obj in database used .after() .before(), so this is from what i have experiment.

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

Is insert obj1 before obj2 and

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

do the vice versa.

So if obj1 is after obj3 and obj2 after of obj4, and if you want to change place obj1 and obj2 you will do it like

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

This should do it
BTW you can use .prev() and .next() to find obj3 and obj4 if you didn't have some kind of index for it already.

梨涡少年 2024-07-23 06:27:36
$('.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();
    });
};

感谢 Yannick Guinnesshttps://jsfiddle.net /ARTsinn/TVjnr/

$('.five').swap('.two');

Create a jQuery function like this

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

Thanks to Yannick Guinness at https://jsfiddle.net/ARTsinn/TVjnr/

等待我真够勒 2024-07-23 06:27:36

如果nodeA和nodeB是兄弟节点,就像同一个中的两个,您可以只使用$(trA).insertAfter($ (trB))$(trA).insertBefore($(trB)) 交换它们,它对我有用。 并且之前不需要调用 $(trA).remove() ,否则需要重新绑定 $(trA) 上的一些点击事件

if nodeA and nodeB are siblings, likes two <tr> in the same <tbody>, you can just use $(trA).insertAfter($(trB)) or $(trA).insertBefore($(trB)) to swap them, it works for me. and you don't need to call $(trA).remove() before, else you need to re-bind some click events on $(trA)

请你别敷衍 2024-07-23 06:27:36

目前任何主流浏览器都不需要使用 jquery 来交换元素。 原生 dom 方法,insertAdjacentElement 可以实现这一点,无论它们位于何处:

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

No need to use jquery for any major browser to swap elements at the moment. Native dom method, insertAdjacentElement does the trick no matter how they are located:

var el1 = $("el1");
var el2 = $("el2");
el1[0].insertAdjacentElement("afterend", el2[0]);
忆依然 2024-07-23 06:27:36

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

The best option is to clone them with clone() method.

乜一 2024-07-23 06:27:36

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

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

结果应该是

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

jquery:

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

我希望它有帮助!

I think you can do it very simple. For example let's say you have next structure:
...

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

and the result should be

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

jquery:

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

I hope it helps!

掩于岁月 2024-07-23 06:27:35

这是一种仅使用 jQuery 解决此问题的有趣方法(如果两个元素彼此相邻):

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

或者

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

Here's an interesting way to solve this using only jQuery (if the 2 elements are next to each other):

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

or

$("#element1").after($("#element2"));
梦中楼上月下 2024-07-23 06:27:35

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

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

Paulo's right, but I'm not sure why he's cloning the elements concerned. This isn't really necessary and will lose any references or event listeners associated with the elements and their descendants.

Here's a non-cloning version using plain DOM methods (since jQuery doesn't really have any special functions to make this particular operation easier):

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);
}
一个人的旅程 2024-07-23 06:27:35

不,没有,但您可以创建一个:

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 个元素时,这才有效,否则可能会产生奇怪的结果。

No, there isn't, but you could whip one up:

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);
    });
};

Usage:

$(selector1).swapWith(selector2);

Note this only works if the selectors only match 1 element each, otherwise it could give weird results.

后eg是否自 2024-07-23 06:27:35

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

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

There are a lot of edge cases to this problem, which are not handled by the accepted answer or bobince's answer. Other solutions that involve cloning are on the right track, but cloning is expensive and unnecessary. We're tempted to clone, because of the age-old problem of how to swap two variables, in which one of the steps is to assign one of the variables to a temporary variable. The assignment, (cloning), in this case is not needed. Here is a jQuery-based solution:

function swap(a, b) {
    a = $(a); b = $(b);
    var tmp = $('<span>').hide();
    a.before(tmp);
    b.before(a);
    tmp.replaceWith(b);
};
闻呓 2024-07-23 06:27:35

jQuery .before 方法可用于通过添加临时的第三个元素作为书签来交换元素 - 在移动内容时将临时 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);

DEMO: https://jsfiddle.net/7t1hz94y/

The jQuery .before method can be used to swap elements by adding a temporary 3rd element as a bookmark - make a temporary DOM element as a placeholder while you move things around. .

$.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. put the temporary div temp before this

  2. move this before that

  3. move that before temp

3b) remove temp

Then use it like this

$(selectorA).swapWith(selectorB);

DEMO: https://jsfiddle.net/7t1hz94y/

铁憨憨 2024-07-23 06:27:35

你不需要两个克隆,一个就可以了。 根据 Paolo Bergantino 的回答,我们的答案是:

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

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

You shouldn't need two clones, one will do. Taking Paolo Bergantino answer we have:

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

Should be quicker. Passing in the smaller of the two elements should also speed things up.

墟烟 2024-07-23 06:27:35

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

I used a technique like this before. I use it for the connector list on 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');
凝望流年 2024-07-23 06:27:35

我创建了一个函数,允许您向上或向下移动多个选定的选项

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

。 依赖性:

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

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

swapWith(element.next() 或
元素.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);
}

I've made a function which allows you to move multiple selected options up or down

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

Dependencies:

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

First it checks whether the first/last selected option is able to move up/down.
Then it loops through all the elements and calls

swapWith(element.next() or
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);
}
揽清风入怀 2024-07-23 06:27:35

另一个没有克隆的元素:

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

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

然后 insert

; before 和 after 的 remove 仅当您无法确保之前始终有一个元素时才需要(在我的情况下是这样)

an other one without cloning:

I have an actual and a nominal element to swap:

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

then insert <div> before and the remove afterwards are only needed, if you cant ensure, that there is always an element befor (in my case it is)

江湖正好 2024-07-23 06:27:35

这是我在父元素内上下移动多个子元素的解决方案。
非常适合在列表框中移动选定的选项(<选择多个>

向上移动:

$(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"));
});

This is my solution to move multiple children elements up and down inside the parent element.
Works well for moving selected options in listbox (<select multiple></select>)

Move up:

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

Move down:

$($(parent).find("childrenSelector").get().reverse()).each((idx, child) => {
    $(opt).insertAfter($(child).next().not("childrenSelector"));
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文