37

I'm wondering if it's posible to switch positions of two divs with jQuery.

I have two div like this

<div class="div1">STUFF ONE</div>
<div class="div2">STUFF TWO</div>

so if div2 has content (or contains more than just white spaces) it switches the order of div1 and div2

so this:

<div class="div1">STUFF ONE</div>
<div class="div2">STUFF TWO</div>

would become this:

<div class="div2">STUFF TWO</div>
<div class="div1">STUFF ONE</div>

But if it was this:

<div class="div1">STUFF ONE</div>
<div class="div2"></div>

or this:

<div class="div1">STUFF ONE</div>
<div class="div2">    </div>

it wouldn't do anything.

Also... if posible, if switched I would like to add a class to div1.

Any help with this will be very much appreciated.

UPDATE:

I forgot to add that I have to run this across multipul instanses on the same page.

Each instance is formated like this:

<div class="view-container"> 
  <div class="view-content"> 
   <div class="views-row">
     <div class="div1">STUFF ONE</div>
     <div class="div2">STUFF TWO</div>
   </div>
   <div class="views-row">
     <div class="div1">STUFF ONE</div>
     <div class="div2">STUFF TWO</div>
   </div>
  </div>
</div>
Cybercampbell
  • 2,486
  • 11
  • 48
  • 75

6 Answers6

49

I'll throw in my solution

$('.div2:parent').each(function () {
    $(this).insertBefore($(this).prev('.div1'));
});

Edit: Doesn't work for whitespace in div2. Here's an updated solution:

$('.div2').each(function () {
    if (!$(this).text().match(/^\s*$/)) {
        $(this).insertBefore($(this).prev('.div1'));
    }
});
Rusty Fausak
  • 7,355
  • 1
  • 27
  • 38
  • I added this line to add the class `$(this).next('.div1').addClass('new-class');` does that look correct? – Cybercampbell Jan 27 '12 at 08:25
  • 2
    I really like this solution. Very minimalist. – David Richard Jan 27 '12 at 08:35
  • 1
    Doesn't this create duplicates? – Lightness Races in Orbit Feb 02 '12 at 14:46
  • 1
    @LightnessRacesinOrbit Nope. "If an element selected this way is inserted elsewhere, it will be moved before the target (not cloned)". See http://api.jquery.com/insertBefore/ – Rusty Fausak Feb 02 '12 at 19:53
  • @rfausak: Thanks. I wouldn't have thought that! Odd. – Lightness Races in Orbit Feb 03 '12 at 01:36
  • didn't understand the code actually, but its awesome. It would be great if you could throw some light. :) – Max Apr 24 '15 at 17:06
  • 1
    @KiranP. I know it is 6 years ago but i still try to explain! ```$('.div2')``` is a Jquery Selector which selects every element with the class 'div2' --> With the .each you can iterate through each of those elements and apply a function to them, in which the elem is selected with $(this) --> with ```!$(this).text().match(/^\s*$/)``` you get true when the element from the current iteration has no spaces (->regex) --> with ```$(this).insertBefore($(this).prev('.div1'))``` you insert the Elem Before the element in brackets, which is the elem with class div1 that is directly before the elem itself – lxg95 Aug 23 '21 at 14:26
23

Here's an example:

http://jsfiddle.net/52xQP/1/

First you want to clone the elements. Then, check a condition if div2 is empty. Then, do the swap:

div1 = $('#div1');
div2 = $('#div2');

tdiv1 = div1.clone();
tdiv2 = div2.clone();

if(!div2.is(':empty')){
    div1.replaceWith(tdiv2);
    div2.replaceWith(tdiv1);

    tdiv1.addClass("replaced");
}
Vigrond
  • 8,148
  • 4
  • 28
  • 46
4
if(div1First){
 var div2 = ($('.div2')).detach();
 ($('.div1')).append(div2);
}else{
 var div1 = ($('.div1')).detach();
 ($('.div2')).append(div1);
}

Fiddle to try it.

3
var row2content = $('.div2').html();                //Get row 2s content
row2contentnospaces = row2content.replace(' ', ''); //Eliminate whitespace
if(!(row2contentnospaces == '')){                   //Check if row2 is empty
    var row2 = $('.div2');                          //Get row 2
    $('.div2').remove();                            //remove row2
    $('.div1').before(row2);                        //add row 2 before row 1
}
David Richard
  • 356
  • 1
  • 7
  • Thanks @David. This looks great. I forgot to add that I have to run this across multipul instanses on the same page. Will that change anything? – Cybercampbell Jan 27 '12 at 08:10
  • Assuming they are using the same class names over and over again, then yes it will cause issues. To fix this I would put each pairing in div, and then change some of the code around to look for siblings. IS that the case? – David Richard Jan 27 '12 at 08:14
  • Hi @David. What are your thoughts on rfausak's sollution? – Cybercampbell Jan 27 '12 at 08:27
  • 1
    It's a very elegant solution to the problem. I would go with it. – David Richard Jan 27 '12 at 08:34
2

I've found elegant jQuery plugin in 4 lines for that. Author Yannick Guinness.

/**
 * Swap an element with another one
 * @author: Yannick Guinness
 * @version: 0.1
 *
 * @params {Object} element - object that has to be swapped
 * @return: {jQuery Object}
 *
 * @usage:
 *     $('.one').swap('.two');
 *
 * @license: MIT
 * @date: 2013/07/22
 **/
$.fn.swap = function (elem) {
    elem = elem.jquery ? elem : $(elem);
    return this.each(function () {
        $(document.createTextNode('')).insertBefore(this).before(elem.before(this)).remove();
    });
};

$('.one').on('click', function () {
    alert(true);
});

$('input').click(function () {
    $('.one').swap('.two');
});

Run it in fiddle

While @Vigront's answer simple and great (I've upvoted it), it has one serious drawback - on cloning elements loose events, bound to them...

That plugin do not have such the problem. And even fiddle contains click event to demonstrate it.

Hubbitus
  • 5,161
  • 3
  • 41
  • 47
2

Well ... why are you trying to change the POSITION of the div elements. Does it matter? Why not changing the CONTENT?

var divOneText = $('#div1').html();
var divTwoText = $('#div2').html();

if (divOneText != '' && divTwoText != '') {
  $('#div1').html(divTwoText);
  $('#div2').html(divOneText);
}

Add trim() if you want to remove whitespace.

Grrbrr404
  • 1,809
  • 15
  • 17
  • Hi @Grrbrr404. I need to keep the classes relative to the content. Thanks for responding though. – Cybercampbell Jan 27 '12 at 08:02
  • Then change css aswell. Its much easier and faster then switching complete element – Grrbrr404 Jan 27 '12 at 08:03
  • 1
    @Grrbrr404: I disagree. If you know that you want everything about the `div`s to be swapped around, then the fool-proof approach is to swap the nodes themselves. If you instead create a _whitelist_ of content to swap, you're going to miss something: if not now, then later, when the markup changes. – Lightness Races in Orbit Feb 02 '12 at 14:47
  • 2
    I loved this solution more than "checking and copying non-space characters" solution. Simple and working! – trante May 06 '13 at 20:55