Monday, March 14, 2016

JQuery UI Drag and Drop Introduction

This is an interesting javascript drag and drop game.
<!doctype html>
<html lang="en">
<head>

<title>A jQuery Drag-and-Drop Number Cards Game</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<link rel="stylesheet" type="text/css" href="style.css">

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>
<script type="text/javascript">

var correctCards = 0;
$( init );

function init() {
  // Hide the success message
  $('#successMessage').hide();
  $('#successMessage').css( {
    left: '580px',
    top: '250px',
    width: 0,
    height: 0
  } );

  // Reset the game
  correctCards = 0;
  $('#cardPile').html( '' );
  $('#cardSlots').html( '' );

  // Create the pile of shuffled cards
  var numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];

  // Sort the array with a randomizing sort function to shuffle the numbers
  numbers.sort( function() { return Math.random() - .5 } );
  
  // loop through each element in the numbers array, creating a div card element
  // for each number. Inside the div we place the number, so that it appears on 
  // the card in the page.
  for ( var i=0; i<10; i++ ) {
    $('<div>' + numbers[i] + '</div>').data( 'number', numbers[i] )
      .attr('id', 'card'+numbers[i] ).appendTo( '#cardPile' ).draggable({
          containment: '#content',
          //to ensure that the dragged card always sits on top of the other cards
          stack: '#cardPile div',  
          cursor: 'move',

          //to make the card slide back to its initial position when dropped, 
          //so that the user can try again. When the card has been dragged to the correct
          //the option will be set as false.
          revert: true 
      });
  }

  // Create the card slots
  var words = [ 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 
'eight', 'nine', 'ten' ];

  for ( var i=1; i<=10; i++ ) {
    // store the card's number in a 'number' key inside the object by 
    // using jQuery's data() method.
    $('<div>' + words[i-1] + '</div>').data( 'number', i ).appendTo( 
'#cardSlots' ).droppable( {
      accept: '#cardPile div',
      hoverClass: 'hovered',
      drop: handleCardDrop
    } );
  }
}

function handleCardDrop( event, ui ) {
  var slotNumber = $(this).data( 'number' );
  var cardNumber = ui.draggable.data( 'number' );

  // If the card was dropped to the correct slot,
  // change the card colour, position it directly
  // on top of the slot, and prevent it being dragged
  // again
  if ( slotNumber == cardNumber ) {
    ui.draggable.addClass( 'correct' );
    ui.draggable.draggable( 'disable' );
    $(this).droppable( 'disable' );
    ui.draggable.position( { of: $(this), my: 'left top', at: 'left top' } );
    ui.draggable.draggable( 'option', 'revert', false );
    correctCards++;
  } 
  
  // If all the cards have been placed correctly then display a message
  // and reset the cards for another go
  if ( correctCards == 10 ) {
    $('#successMessage').show();
    $('#successMessage').animate( {
      left: '380px',
      top: '200px',
      width: '400px',
      height: '100px',
      opacity: 1
    } );
  }
}
</script>

<body>
<div class="wideBox">
  <h1>Drag-and-Drop with jQuery: Your Essential Guide</h1>
  <h2>A Number Cards Game</h2>
</div>

<div id="content">
  <div id="cardPile"> </div>
  <div id="cardSlots"> </div>

  <div id="successMessage">
    <h2>You did it!</h2>
    <button onclick="init()">Play Again</button>
  </div>
</div>
</body>
</html>
      
The HTML part:

In the head area we've included the jQuery and jQuery UI libraries, and linked to a style.css file. In the body we have:
  • A "#content" div to contain the game
  • A "#cardPile" div that will contain the set of 10 unsorted cards
  • A "#cardSlots" div that will contain the 10 slots to drop the cards into
  • A "#successMessage" div to display a "You did it!" message, along with a button to play again. 
The init() function:
  1. $( init ) is to call our init() function when the document is ready.
  2. To create the pile of cards, we first make an array, numbers, containing the numbers 1 to 10, then sort the array with a randomizing sort function to shuffle the numbers.
  3. Then loop through each element in the numbers array, creating a div card element for each number. Inside the div we place the number, so that it appears on the card in the page. Once we've created the divobject, we store the card's number in a 'number' key inside the object by using jQuery's data() method.
  4. Give the card div an id of 'cardn', where n is the card number. This lets us give each card a different colour in the CSS. We then append the card to the #cardPile div.
  5. The interesting bit in the loop is, of course, the call to the draggable()method. This:
    • Makes the card draggable
    • Uses containment to constrain it to the #content div
    • Uses stack to ensure that the dragged card always sits on top of the other cards
    • Uses cursor to turn the mouse cursor into a move cursor during the drag, and
    • Sets the revert option to true. This makes the card slide back to its initial position when dropped, so that the user can try again. We'll turn this option off when the user has dragged the card to the correct slot, as we'll see in a moment.
  6. The last part of the init() function creates the 10 slots to drag the cards onto. We create an array called words that contains the words "one" to "ten", then loop through the elements of the words array, creating a slot div for each number. As before, we use data() to record the number of the slot, so we can test if the user has dragged the correct card to the correct slot, and we append the slot to the #cardSlots div.
  7. This time, we call the droppable() method so that the slot can receive a draggable card. We use the accept option with the selector "#cardPile div" to ensure that the slot will only accept our number cards, and not any other draggable element. The hoverClass option adds a CSS class to a droppable when a draggable is hovered over it — we use this option to add a class of 'hovered' to the element, which we'll highlight using CSS. Finally, we set up a drop event handler called handleCardDrop(), which is triggered when the user drops a card on the droppable. We'll write this handler next.
The CSS Part: 
body {

  margin: 30px;

  font-family: "Georgia", serif;

  line-height: 1.8em;

  color: #333;

}



/* Give headings their own font */



h1, h2, h3, h4 {

  font-family: "Lucida Sans Unicode", "Lucida Grande", sans-serif;

}



/* Main content area */



#content {

  margin: 80px 70px;

  text-align: center;

  -moz-user-select: none;

  -webkit-user-select: none;

  user-select: none;

}



/* Header/footer boxes */



.wideBox {

  clear: both;

  text-align: center;

  margin: 70px;

  padding: 10px;

  background: #ebedf2;

  border: 1px solid #333;

}



.wideBox h1 {

  font-weight: bold;

  margin: 20px;

  color: #666;

  font-size: 1.5em;

}



/* Slots for final card positions */



#cardSlots {

  margin: 50px auto 0 auto;

  background: #ddf;

}



/* The initial pile of unsorted cards */



#cardPile {

  margin: 0 auto;

  background: #ffd;

}



#cardSlots, #cardPile {

  width: 910px;

  height: 120px;

  padding: 20px;

  border: 2px solid #333;

  -moz-border-radius: 10px;

  -webkit-border-radius: 10px;

  border-radius: 10px;

  -moz-box-shadow: 0 0 .3em rgba(0, 0, 0, .8);

  -webkit-box-shadow: 0 0 .3em rgba(0, 0, 0, .8);

  box-shadow: 0 0 .3em rgba(0, 0, 0, .8);

}



/* Individual cards and slots */



#cardSlots div, #cardPile div {

  float: left;

  width: 58px;

  height: 78px;

  padding: 10px;

  padding-top: 40px;

  padding-bottom: 0;

  border: 2px solid #333;

  -moz-border-radius: 10px;

  -webkit-border-radius: 10px;

  border-radius: 10px;

  margin: 0 0 0 10px;

  background: #fff;

}



#cardSlots div:first-child, #cardPile div:first-child {

  margin-left: 0;

}



#cardSlots div.hovered {

  background: #aaa;

}



#cardSlots div {

  border-style: dashed;

}



#cardPile div {

  background: #666;

  color: #fff;

  font-size: 50px;

  text-shadow: 0 0 3px #000;

}



#cardPile div.ui-draggable-dragging {

  -moz-box-shadow: 0 0 .5em rgba(0, 0, 0, .8);

  -webkit-box-shadow: 0 0 .5em rgba(0, 0, 0, .8);

  box-shadow: 0 0 .5em rgba(0, 0, 0, .8);

}



/* Individually coloured cards */



#card1.correct { background: red; }

#card2.correct { background: brown; }

#card3.correct { background: orange; }

#card4.correct { background: yellow; }

#card5.correct { background: green; }

#card6.correct { background: cyan; }

#card7.correct { background: blue; }

#card8.correct { background: indigo; }

#card9.correct { background: purple; }

#card10.correct { background: violet; }





/* "You did it!" message */

#successMessage {

  position: absolute;

  left: 580px;

  top: 250px;

  width: 0;

  height: 0;

  z-index: 100;

  background: #dfd;

  border: 2px solid #333;

  -moz-border-radius: 10px;

  -webkit-border-radius: 10px;

  border-radius: 10px;

  -moz-box-shadow: .3em .3em .5em rgba(0, 0, 0, .8);

  -webkit-box-shadow: .3em .3em .5em rgba(0, 0, 0, .8);

  box-shadow: .3em .3em .5em rgba(0, 0, 0, .8);

  padding: 20px;

}

Source: http://www.elated.com/articles/drag-and-drop-with-jquery-your-essential-guide/
Game Link: http://www.elated.com/res/File/articles/development/javascript/jquery/drag-and-drop-with-jquery-your-essential-guide/card-game.html

No comments:

Post a Comment