Sunny
Sunny

Reputation: 932

Swap div in DOM and visually on click using jquery

I've a few divs which need to be swapped on click of the corresponding buttons.

<html>
    <head>
        <style>
            .box {
                height: 25%;
                width: 45%;
                padding: 1%;
                margin-left: 1%;    
                margin-top: 1%;
                border: 1px solid black;
                float: left;

            }

        </style>
        <script src="css/jquery-3.2.0.js"></script>
    </head>
    <body>
        <div class="container">
            <div class="box" id="one">
                <p>one</p>
                <button onclick="moveMe_right()">Swap with right!</button>
                <button onclick="moveMe_down()">Swap with down!</button>
            </div>

            <div class="box" id="two">
                <p>two</p>
                <button onclick="moveMe_left()">Swap with left!</button>
                <button onclick="moveMe_down()">Swap with down!</button>
            </div>

            <div class="box" id="three">
                <p>three</p>
                <button onclick="moveMe_right()">Swap with right!</button>
                <button onclick="moveMe_top()">Swap with top!</button>

            </div>

            <div class="box" id="four">
                <p>four</p>
                <button onclick="moveMe_left()">Swap with left!</button>
                <button onclick="moveMe_down()">Swap with down!</button>
            </div>

        </div>
    </body>
</html>

For e.g., when I click on Swap with right in div one, it should swap div one and div 2 visually as well as in the DOM it should change to -

<div class="container">
                <div class="box" id="two">
                    <p>two</p>
                    <button onclick="moveMe_right()">Swap with right!</button>
                    <button onclick="moveMe_down()">Swap with down!</button>
                </div>

                <div class="box" id="one">
                    <p>one</p>
                    <button onclick="moveMe_left()">Swap with left!</button>
                    <button onclick="moveMe_down()">Swap with down!</button>
                </div>

                <div class="box" id="three">
                    <p>three</p>
                    <button onclick="moveMe_right()">Swap with right!</button>
                    <button onclick="moveMe_top()">Swap with top!</button>

                </div>

                <div class="box" id="four">
                    <p>four</p>
                    <button onclick="moveMe_left()">Swap with left!</button>
                    <button onclick="moveMe_down()">Swap with down!</button>
                </div>

            </div>

Likewise, how would I also achieve the same for swapping with any of the left, top, down divs?

Upvotes: 0

Views: 1462

Answers (3)

Peter Stark
Peter Stark

Reputation: 608

It seems you have created multiple questions for this issue :).
I answered your previous question here.

jsfiddle here


Code

function resetButtons() {
  // enable and show all buttons
    $("button").prop("disabled", false).show();

  // First box (top left), disable and hide top and left
  var firstBox = $(".box").eq(0);
  firstBox.find(".top").prop("disabled", true).hide();
  firstBox.find(".left").prop("disabled", true).hide();

  // Second box (top right), disable and hide top and right
  var secondBox = $(".box").eq(1);
  secondBox.find(".top").prop("disabled", true).hide();
  secondBox.find(".right").prop("disabled", true).hide();

  // Third box (bottom left), disable and hide down and left
  var thirdBox = $(".box").eq(2);
  thirdBox.find(".down").prop("disabled", true).hide();
  thirdBox.find(".left").prop("disabled", true).hide();

  // Fourth box (bottom right), disable and hide down and right
  var fourthBox = $(".box").eq(3);
  fourthBox.find(".down").prop("disabled", true).hide();
  fourthBox.find(".right").prop("disabled", true).hide();
}

For swapping, we will play with array-index of the boxes and swap the html content of each box.

function swapContent(divA, divB) {
  var tempDiv = divA.html();
  divA.html(divB.html());
  divB.html(tempDiv);
}

For example, right button will swap current box and the one next to it (on its right).

$(".container").on("click", ".right", function(e) {
  var currentBox = $(this).parents('.box');
  var currentIndex = $(".box").index(currentBox);
  console.log(currentIndex, "right", currentBox);

  swapContent(
    currentBox,
    $(".box").eq(currentIndex+1)
  );

  resetButtons();
});

Upvotes: 1

Steve Padmore
Steve Padmore

Reputation: 1740

Basically, using insertBefore/After will not swap the divs, but move them along, this can be demonstrated by using your current method

$(toMove1).insertAfter($(toMove1).next());

To get the top left div to swap with the one below you could expand on this and use

$(toMove1).insertAfter($(toMove1).next().next());

But this would only move div 'one' to the place of div 'three'. Then div 'two' would fall into div 'one's slot, and 'three' into 'two's.

However, once a div has been moved what happens next? For example, if you keep clicking 'Swap with right' should it swap with the div below and to the left, should it re-label the button to 'Swap with left'?

I have added four positional divs (with a 'parent' class), so you can move the divs you want in the DOM, and also use rules for labels etc. within each area. I've demonstrated using 'topLeft', 'bottomRight' etc. but you could have an array of many different positions and use indexes if you want.

The code below can be refactored to selectively update event handlers, label changing, and code reduction, but to make it easy to see what is happening I have left it pretty verbose.

<html>
<head>
    <style>
        .box {
            height: 25%;
            width: 45%;
            padding: 1%;
            margin-left: 1%;
            margin-top: 1%;
            border: 1px solid black;
            float: left;
        }
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
    <div class="container">
        <div id="topLeft" class="parent">
            <div class="box" id="one">
                <p>one</p>
                <button class="right">Swap with right!</button>
                <button class="down">Swap with down!</button>
            </div>
        </div>
        <div id="topRight" class="parent">
            <div class="box" id="two">
                <p>two</p>
                <button class="left">Swap with left!</button>
                <button class="down">Swap with down!</button>
            </div>
        </div>
        <div id="bottomLeft" class="parent">
            <div class="box" id="three">
                <p>three</p>
                <button class="right">Swap with right!</button>
                <button class="top">Swap with top!</button>
            </div>
        </div>
        <div id="bottomRight" class="parent">
            <div class="box" id="four">
                <p>four</p>
                <button class="left">Swap with left!</button>
                <button class="top">Swap with top!</button>
            </div>
        </div>
    </div>
<script>
    $(document).ready(function () {
        // Set the event handlers on load...
        resetEvents();
    });

    function UpdateDivs(parent1, parent2, class1, class2) {
        var parent1Content = $('#' + parent1).children();
        var parent2Content = $('#' + parent2).children();

        $(parent1Content).find('.' + class1).each(function () {
            swapButtonClass(this);
        });

        $(parent2Content).find('.' + class2).each(function () {
            swapButtonClass(this);
        });

        $('#' + parent1).append(parent2Content);
        $('#' + parent2).append(parent1Content);

        resetEvents();
    }

    function resetEvents() {
        // Clear the current handlers - because the buttons will change their class.
        // The handlers are still attached to the buttons that were seen with that class initially.
        // This could be done selectively, but for demo purposes, just resets all of them when the DOM is changed.
        $('.right').unbind('click');
        $('.left').unbind('click');
        $('.top').unbind('click');
        $('.down').unbind('click');

        $('.right').click(function () {
            var parent1 = $(this).parents('.parent').attr('id');
            var parent2 = parent1.replace('Left', 'Right');

            UpdateDivs(parent1, parent2, 'right', 'left');
        });

        $('.left').click(function () {
            var parent1 = $(this).parents('.parent').attr('id');
            var parent2 = parent1.replace('Right', 'Left');

            UpdateDivs(parent1, parent2, 'left', 'right');
        });

        $('.down').click(function () {
            var parent1 = $(this).parents('.parent').attr('id');
            var parent2 = parent1.replace('top', 'bottom');

            UpdateDivs(parent1, parent2, 'down', 'top');
        });

        $('.top').click(function () {
            var parent1 = $(this).parents('.parent').attr('id');
            var parent2 = parent1.replace('bottom', 'top');

            UpdateDivs(parent1, parent2, 'top', 'down');
        });

        $('.container').eq(0);
    }

    function swapButtonClass(button) {
        // Swap class and labels when moving the divs around.
        switch (button.className) {
            case "right":
                $(button).removeClass('right').addClass('left').text($(button).text().replace('right', 'left'));
                break;
            case "left":
                $(button).removeClass('left').addClass('right').text($(button).text().replace('left', 'right'));
                break;
            case "top":
                $(button).removeClass('top').addClass('down').text($(button).text().replace('top', 'down'));
                break;
            case "down":
                $(button).removeClass('down').addClass('top').text($(button).text().replace('down', 'top'));
                break;
        }
    }
</script>
</body>
</html>

Upvotes: 1

Sunny
Sunny

Reputation: 932

Ok, I've got this to work for swapping with left & right divs. Now, stuck with top and down!

Here's my updated code.

<html>
    <head>
        <style>
            .box {
                height: 25%;
                width: 45%;
                padding: 1%;
                margin-left: 1%;    
                margin-top: 1%;
                border: 1px solid black;
                float: left;

            }

        </style>
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    </head>
    <body>
        <div class="container">
            <div class="box" id="one">
                <p>one</p>
                <button class="right">Swap with right!</button>
                <button class="down">Swap with down!</button>
            </div>

            <div class="box" id="two">
                <p>two</p>
                <button class="left">Swap with left!</button>
                <button class="down">Swap with down!</button>
            </div>

            <div class="box" id="three">
                <p>three</p>
                <button class="right">Swap with right!</button>
                <button class="top">Swap with top!</button>

            </div>

            <div class="box" id="four">
                <p>four</p>
                <button class="left">Swap with left!</button>
                <button class="down">Swap with down!</button>
            </div>
        </div>
        <script>
            $(document).ready(function() {
                $('.right').click(function(){
                    //alert('ok');
                    var toMove1 = $(this).parents('.box');
                    //toMove2 = toMove1.next();

                    $(toMove1).insertAfter($(toMove1).next());
                });

                $('.left').click(function(){
                    //alert('ok');
                    var toMove1 = $(this).parents('.box');
                    //toMove2 = toMove1.prev();

                    $(toMove1).insertBefore($(toMove1).prev());
                });

                $('.container').eq(0);
                /*
                $('.down').click(function(){
                    //alert('ok');
                    toMove1 = $(this).parents('.box');
                    //toMove2 = toMove1.prev();

                    var toMove2 = $(toMove1).insertAfter($(toMove1).next());
                    $(toMove2).insertAfter($(toMove2).next());
                });

                $('.top').click(function(){
                    //alert('ok');
                    toMove1 = $(this).parents('.box');
                    //toMove2 = toMove1.prev();

                    $(toMove1).insertAfter($(toMove1).prev());
                });



                $(".box").first().css({"background-color":"yellow"});

                $('.box:first-child').eq(3).removeClass('.left');
                $('.box:first-child').eq(3).addClass('.right');
                */
            });
        </script>
    </body>
</html>

Also, how do I ensure that the button swap with right changes to swap with left if it's a right element and similarily, changes accordingly for each button, when a div is swapped?

Upvotes: 0

Related Questions