Last Updated
Viewed 13 Times
           

I'm using Draggable and Droppable in jQuery UI to create a Solitaire card game. If a dragged card has other cards over it and all these cards are in a descending straight flush (like 5 of clubs in this example), all these cards should be dragged at once and appended to the card the they are dropped onto.

I've tried to solve this by adding some code the start event of draggable();:

var thisAndAllNextCards = $(this).nextAll().addBack();

if (thisAndAllNextCards.length > 1) {
  $(thisAndAllNextCards).each(function(){
    if ($(this).data("value") == $(this).next('.card').data("value") +1 $(this).data("value") == $(this).next('.card').data("value") +1 && $(this).data("suit") == $(this).next('.card').data("suit")) {

      $(this).nextAll().addBack().wrapAll( "<div class='cardGroup'/>");

      /* All the cards in the variable thisAndAllNextCards (i.e. all the cards in the div with class 'cardGroup')
         should be dragged as a group and appended to the card they are dropped onto */

    }
  });
}

The code checks wether the cards are in a descending straight flush and, if so, wraps them in a temporary div. Then I'm stuck. The positioning of the cards gets messed up and I don't know how to drag the wrapping div instead of the clicked card. I don't even know if my idea of wrapping the cards in a new div is good.

My question: How do I select the cards in the flush, keep them in place (visually and in DOM) while dragging them and then append them to the card they are dropped onto?

Click Show code snippet below to see the code in it's entirety.

$(document).ready(function(){

    var column1 = [];
    var column2 = [];
    var column3 = [];
    var column4 = [];
    var column5 = [];
    var column6 = [];
    var column7 = [];
    var column8 = [];
    var column9 = [];
    var column10 = [];
    
    var decksAmount = 2;
    var suits = ["spades", "diamonds", "clubs", "hearts"];
    var values = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"];
    var unshuffledDeck;
    var shuffledDeck;
    
    init();
    appendCardsToColumns();

    function init() {

        unshuffledDeck = getUnshuffledDeck();
    
        shuffledDeck = shuffleDeck(unshuffledDeck);

        divideCardsInColumns(shuffledDeck);

    }

    function getUnshuffledDeck() {
        
        var deck = new Array();

        var id = 1;
        
        for (var y = 0; y < decksAmount; y++ ) {
            for(var i = 0; i < suits.length; i++) {
                for(var x = 0; x < values.length; x++) {
                    var card = {value: values[x], suit: suits[i], status: 'hidden', class: 'card', id: id, 'status': 'hidden'};
                    id++
                    deck.push(card);
                }
            }
        }

        return deck;
    }
    
        
    function shuffleDeck(array) {
        
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }

        return array;
      
    }

    function divideCardsInColumns(cards) {


        $(cards).slice(0, 6).each(function(index) {
            column1.push(this);
        });

        $(cards).slice(6, 12).each(function(index) {
            column2.push(this);
        });

        $(cards).slice(12, 18).each(function(index) {
            column3.push(this);
        });

        $(cards).slice(18, 24).each(function(index) {
            column4.push(this);
        });

        $(cards).slice(24, 29).each(function(index) {
            column5.push(this);
        });

        $(cards).slice(29, 34).each(function(index) {
            column6.push(this);
        });

        $(cards).slice(34, 39).each(function(index) {
            column7.push(this);
        });

        $(cards).slice(39, 44).each(function(index) {
            column8.push(this);
        });

        $(cards).slice(44, 49).each(function(index) {
            column9.push(this);
        });

        $(cards).slice(49, 54).each(function(index) {
            column10.push(this);
        });

    }

    function appendCardsToColumns() {

        var columns = [];

        columns.push(column1, column2, column3, column4, column5,column6, column7, column8, column9, column10);

        $(columns).each(function(index) {

            var column = $(".column")[index];

            var numberOfCardsInColumn = this.length;

            $(this).each(function(index) {

                $('<div id="' + this.id + '" class="' + this.class + '" data-value="' + this.value + '" data-suit="' + this.suit + '" data-status="' + this.status + '">' + this.value + " of " + this.suit + '<div/>').appendTo(column);

                // Get last card in column
                var lastCard = index == numberOfCardsInColumn -1;

                // Make last card in column draggable and open after it has been appended
                if (lastCard) {
                    $("#" + this.id).attr("data-status","open");
                    $("#" + this.id).draggable({ revert: 'invalid' });
                }

            });

        });

        initializeDragAndDrop();

        function initializeDragAndDrop() {

            // Make open cards droppable and only accept a cards with a value one less than itself
            $(".card[data-status='open']").droppable({     

                accept: function(d) {

                    if ($(d[0]).data("value") == $(this).data("value") -1) {

                        return true;

                    }

                }

            });

            $( ".card[data-status='open']" ).draggable({

                start: function( event, ui ) {

                    var allZIindex = [];
                    
                    $('.card').each(function(){

                        if ($(this)[0].style.zIndex == null) {
                            $(this)[0].style.zIndex = 1;
                        }

                        allZIindex.push($(this)[0].style.zIndex);

                    });

                    var highestZIndex = Math.max.apply(Math, allZIindex);

                    $(this)[0].style.zIndex = highestZIndex + 1;

                    var thisAndAllNextCards = $(this).nextAll().addBack();

                    if (thisAndAllNextCards.length > 1) {
                        $(thisAndAllNextCards).each(function(){
                            if ($(this).data("value") == $(this).next('.card').data("value") +1 && $(this).data("suit") == $(this).next('.card').data("suit")) {

                              $(this).nextAll().addBack().wrapAll( "<div class='cardGroup'/>");

                                // All the cards in the variable thisAndAllNextCards (i.e. all the cards in div with class 'cardGroup') should be dragged as a group and appended to the droppable when dropped

                            }
                        });
                    }
                    
                }

            });

        }

        $( ".card" ).on( "drop", function( event, ui ) {

            $(ui.draggable).prev().attr("data-status","open");

            $(ui.draggable).prev().draggable({ revert: 'invalid' });

            $(ui.draggable).insertAfter('#' + $(this).attr("id"));

            $(ui.draggable).css('top', '').css('left', '');

            initializeDragAndDrop();

        } );

    }


});
.some-page-wrapper {
    margin: 15px;
}

.row {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
    width: 100%;
}

.column {
    /*border: 1px solid;*/
    display: flex;
    flex-direction: column;
    flex-basis: 100%;
    flex: 1;
    height: 100vh;
    margin-left: 2px;
    margin-right: 2px;
}


.card[data-status='hidden'] {
    background-color: DarkGray;
    color: DarkGray;
}

.card {
  background-color: LightGray;
  border-style: solid;
  border-width: 1px;
  border-color: black;
  font-size: 1vw;
  border-radius: 3px;
  height: calc(8vw * 1.4);
  width: 8vw;
  position: relative;
  margin-top: -10vw;
}

.column .card:first-child {
    margin-top: 0;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Spindelharpan</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.4/jquery-ui.css">
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script
  src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"
  integrity="sha256-T0Vest3yCU7pafRw9r+settMBX6JkKN06dqBnpQ8d30="
  crossorigin="anonymous"></script>
</head>

<body>

<div class='some-page-wrapper'>
    <div class='row'>
        <div class='column' id='column1'></div>
        <div class='column' id='column2'></div>
        <div class='column' id='column3'></div>
        <div class='column' id='column4'></div>
        <div class='column' id='column5'></div>
        <div class='column' id='column6'></div>
        <div class='column' id='column7'></div>
        <div class='column' id='column8'></div>
        <div class='column' id='column9'></div>
        <div class='column' id='column10'></div>
    </div>
</div>

</body>

</html>

I am trying to replicate the functionality found at the following: http://carbonstudio.co.uk using jquery drag and drop.

Below you will find where I am upto at the moment. The two issues I am initially facing is how do I go about changing what happens when you drag a list item into the navigation execute box so it changes to the company logo (or anything) then it will redirect off to a new page.

The second issue is I need to get these boxes to go around the navigation execute area like the above sample.

MY CODE AS IT CURRENTLY STANDS: http://jsfiddle.net/elogicmedia/GG5EL/7/

Thankyou

JS CODE (FROM JS FIDDLE)

$(function() {
// there's the gallery and the trash
var $gallery = $( "#gallery" ),
  $trash = $( "#trash" );

// let the gallery items be draggable
$( "li", $gallery ).draggable({
  cancel: "a.ui-icon", // clicking an icon won't initiate dragging
  revert: "invalid", // when not dropped, the item will revert back to its initial position
  containment: "document",
  helper: "clone",
  cursor: "move"
});

// let the trash be droppable, accepting the gallery items
$trash.droppable({
  accept: "#gallery > li",
  activeClass: "ui-state-highlight",
  drop: function( event, ui ) {
    deleteImage( ui.draggable );
  }
});

// let the gallery be droppable as well, accepting items from the trash
$gallery.droppable({
  accept: "#trash li",
  activeClass: "custom-state-active",
  drop: function( event, ui ) {
    recycleImage( ui.draggable );
  }
});

// image deletion function
var recycle_icon = "<a href='link/to/recycle/script/when/we/have/js/off' title='Recycle this image' class='ui-icon ui-icon-refresh'>Recycle image</a>";
function deleteImage( $item ) {
  $item.fadeOut(function() {
    var $list = $( "ul", $trash ).length ?
      $( "ul", $trash ) :
      $( "<ul class='gallery ui-helper-reset'/>" ).appendTo( $trash );

    $item.find( "a.ui-icon-trash" ).remove();
    $item.append( recycle_icon ).appendTo( $list ).fadeIn(function() {
      $item
        .animate({ width: "48px" })
        .find( "img" )
          .animate({ height: "36px" });
    });
  });
}

// image recycle function
function recycleImage( $item ) {
  $item.fadeOut(function() {
    $item
      .find( "a.ui-icon-refresh" )
        .remove()
      .end()
      .css( "width", "96px")
      .find( "li" )
        .css( "height", "96px" )
      .end()
      .appendTo( $gallery )
      .fadeIn();
  });
}


// resolve the icons behavior with event delegation
$( "ul.gallery > li" ).click(function( event ) {
  var $item = $( this ),
    $target = $( event.target );

  if ( $target.is( "a.ui-icon-trash" ) ) {
    deleteImage( $item );
  } else if ( $target.is( "a.ui-icon-zoomin" ) ) {
    viewLargerImage( $target );
  } else if ( $target.is( "a.ui-icon-refresh" ) ) {
    recycleImage( $item );
  }

  return false;
});
});

Similar Question 2 : jQuery Layouts with Drag and Drop

Ideally, what I'd like to do is have some layouts with designated spots that allow certain kinds of media to be dragged and dropped in those spots.

What recommendation do you have to accomplishing such a task? Should I just stick to the jQuery UI, or are there frameworks or plug-ins out there that would be better suited for the task?

Here is an example layout. Each section accepts a certain kind of content (that's all custom programming): enter image description here

Full HTML file below. Question below that.

<!DOCTYPE html>
<html>
<head>


<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>

<title>slider</title>

<style>

.container{
    width: 100%;
    heght: 100%;
    margin: 0 0 0 0;
    padding: 0 0 0 0;
    overflow: hidden;
}

.test{
    ooverflow: hidden;
    border: 1px solid green;
}

.header{
    height: 100px;
    border: 1px solid orange;
    margin-bottom: 1px;
}

.pices{
    width: 255px;
    height: 600px;
    border: 1px solid black;
    overflow-x: scroll;
    margin-bottom: 40px;
    margin-right: 25px;
    position:absolute;
}

.image{
    width: 90%;
    height: 200px;
    background-color: lightblue;
    margin: 10px 0 10px 10px;
}


.board{
    width: calc(100% - 300px);
    height: 600px;
    border: 1px solid red;
    float: right;
    margin: 0;
}


</style>


  <script>

  $(document).ready(function(){
        $(".image").draggable({ 
            opacity: 0.7, 
            helper: function(event) {
                return $(event.target).clone().css({
                    width: $(event.target).width()
                });

            }
        });  

        $(".board").droppable({
            accept: ".image",
            drop: function(event,ui){
                var itemToClone = $(ui.draggable);
                $(this).append(itemToClone.clone().css({
                    width: itemToClone.width(),
                    margin: 0
                }));
            }
        });
    });


 </script>


</head>
  <body>
    <div class="container">

        <div class="header">



        </div>
        <div class="test">
            <div class="pices">

                <div class="image"></div>
                <div class="image"></div>
                <div class="image"></div>
                <div class="image"></div>
                <div class="image"></div>

            </div>

            <div class="board">



            </div>
        </div>

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

So, I have been trying to Get the divs from the scrollbox to drag out with no luck. It seems they are stuck inside that div due to the overflow-x: scroll but, I need this. Then when they do drop in the right side div they are not the same size or if they are the same size they are not movable. I have tried the following code to get it to work with no luck. Any advice would be helpful thank you. I also have a jsfiddle for working example

/*
    // there's the gallery and the trash
    var $gallery = $( ".pices" ),
    $board = $( ".board" );

    // let the gallery items be draggable
    $( "div", $gallery ).draggable({
        cancel: "a.ui-icon", // clicking an icon won't initiate dragging
        revert: "invalid", // when not dropped, the item will revert back to its initial position
        containment: "document",
        helper: "clone",
        cursor: "move"
    });*/

    /*$(function() {

        $( ".image" ).draggable({
            helper: 'clone',
            appendTo: 'div.board'
        });

        $(".image").draggable({ 
            zIndex: 999
        });

        $( ".board" ).droppable( {
            accept: '.image',
        });

     });*/

     /*$(function() {

        $( ".image" ).draggable({
            containment: $('.pices'),
            helper: 'clone'
        });

        $( ".board" ).droppable( {
            accept: '.image'
        });

     });*/


     /*$(function() {

        $( ".image" ).draggable({
            revert: true,
            zIndex: 9999,
            appendTo: 'board',
            start: startedDrag,
            stop:stoppedDrag
        });

        function startedDrag() {

            $('.pices').css({
                overflow: 'visible',
            });
            $('.test').css({
                overflow: 'hidden',
            });
        }

         function stoppedDrag() {

            $('.pices').css({
                overflow: 'scroll',
            });
        }


        $( ".board" ).droppable( {
            accept: '.image'
        });

     });*/



    /*$(function() {

        $( ".image" ).draggable({
            scroll: false,
            revert: 'invalid'
        });

        $( ".board" ).droppable( {
            drop: function(event, ui) {
                //jQuery(this).addClass('dropped');

                var clone = ui.draggable;
                clone.appendTo(this);

                // this assumes the mouse grabbed in the middle of the div

                //var width = clone.width();
                //var height = clone.height();
                //clone.offset({'top':event.pageY-height/2 ,
                             // 'left':event.pageX-width/2 })
            }
        });

    });*/


    /*$( document ).ready(function() {

        $( ".image" ).draggable({
            helper: 'clone',
            zIndex: 9999999
        });

        $( ".board" ).droppable({
            accept: '.image',
            drop: function( event, ui ) {
                $(ui.draggable).clone().appendTo($(this));
            }
        });
    });*/

    /*$( document ).ready(function() {

        $( ".image" ).draggable({
            helper: 'clone',
            zIndex: 9999999
        });

        $(".board").droppable({
            accept: ".image",
            drop: function(event, ui) {
                var cloned = $(ui.helper).clone();
                cloned.attr("id", "clonedElem" + counter);
                var pos = $(ui.helper).offset();

                var draggableOffset = ui.helper.offset(),
                    droppableOffset = $(this).offset(),
                    left = draggableOffset.left - droppableOffset.left,
                    thisTop = draggableOffset.top - droppableOffset.top;

                cloned.css({
                    "position": "absolute",
                    "left": left,
                    "top": thisTop
                });

                cloned.attr("visible", "true");

                cloned.draggable({
                    containment: 'parent',
                    stop:function(ev, ui) {
                        console.log("aqui");
                    }
                });
                $(".board").append(cloned);
                    counter++;
            }
        });
    });*/



    /*$( document ).ready(function() {

        $( ".image" ).draggable({
            helper: 'clone',
            zIndex: 9999999
        });

        $( ".board" ).droppable({
            accept: '.image',
            drop: function( event, ui ) {
                $(ui.draggable).clone().appendTo(this);
            }
        });
    });*/

Similar Question 4 (1 solutions) : Jquery UI Draggable and Swappable

Similar Question 5 (2 solutions) : jQuery drag and drop over reflowable content

Similar Question 8 (1 solutions) : jQuery UI draggable/droppable overflow hidden

Similar Question 9 (1 solutions) : jQuery-UI draggable/droppable Jumping

cc