Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implement Fill in the blanks using drag & drop jQuery in HTML

I am implementing a Fill in the blanks drag & drop functionality.

enter image description here

Codepen Link

Here I have a list of answers above i.e. one, two, three, etc. and empty spaces below where these answers will be filled.

Things which is done

1) Drag the options from answers list and fill in the empty boxes. Done

2) If I drag a answer from a filled box to an empty box, previous value should be blank. Done

Now comes the Issue

1) If I drag a answer from a filled box to an another filled box then how to switch the values and position of both the boxes. I have thought that we can get the position of the previous one and current one and then swap the position but don't know how to implement it.

2) If I drag a value from answers list to a filled box then how to swap them

Here what I have done so far:

$(document).ready(function() {
  var arr;
  $("span").droppable({
    accept: "ul > li",
    classes: {
      "ui-droppable-hover": "ui-state-hover"
    },
    drop: function(event, ui) {
      arr = [];
      var dragedElement = ui.draggable.text();
      $(this).addClass("ui-state-highlight");
      $(this).html(dragedElement);
      $('span').each(function() {
        arr.push($(this).text());
      });
      //console.log(JSON.stringify(arr));

      var matched = arr.filter((value) => value == dragedElement);
      //console.log(JSON.stringify(matched));

      $('span').each(function() {
        if ($(this).text() == matched[1]) {
          $(this).addClass('matched');
          //localStorage.setItem('prevValue', $(this).text());
          $('span.matched').text('');
          $(this).removeClass("ui-state-highlight");
          $(this).removeClass('matched');
        }
      });

      $(this).html(dragedElement);
      $(this).addClass("ui-state-highlight");

    }
  });

  $("ul > li").draggable({
    revert: "invalid"
  });
})
span {
  width: 100px;
  display: inline-block;
  height: 20px;
  background: #ffffff;
}

body {
  font: 13px Verdana;
}

ul {
  list-style: none;
  padding: 10px;
  background: yellow;
}

ul li {
  display: inline-block;
  margin: 0 10px;
  padding: 10px;
  background: rgb(0, 255, 213);
}

p {
  padding: 10px;
  background: rgb(255, 145, 0);
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<ul>
  <li>one</li>
  <li>two</li>
  <li>three</li>
  <li>four</li>
  <li>five</li>
  <li>six</li>
</ul>
<p>hello
  <span></span>hello
  <span></span>hello
  <span></span>
</p>
like image 985
Bhuwan Avatar asked Jan 12 '18 10:01

Bhuwan


2 Answers

I think you don't need to drag filled answer to another answer because users have multiple options and can drag every option to answer and when user do it answer modifies by latest option. It's make no sense user drags option after drop to answer. For doing this scenario you can do it like this:

$(document).ready(function() {
  $("span").droppable({
    accept: "ul > li",
    classes: {
      "ui-droppable-hover": "ui-state-hover"
    },
    drop: function(event, ui) {
      var dragedElement = ui.draggable.text();
      $(this).addClass("ui-state-highlight");
      $(this).html(dragedElement);
      $(this).addClass('matched');  
    }
  });

  $("ul li").draggable({
    helper:"clone",
    revert: "invalid"
  });

})

Online demo (jsFiddle)

Edit

If you want to drag answers you can do it like this:

$(document).ready(function() {
  // This code used for set order attribute for options
var numberOfItems = $("#options").find('li').length;
$.each($("#options").find('li'), function(index, item) {
    $(item).attr("order", index);
    var removeBotton = $('<i class="fa fa-times" style="display:none"></i>');
    removeBotton.click(function(){
        addToOlderPlace($(this).parent());        
      });
    $(item).append(removeBotton);

});

  $("span").droppable({
    accept: "li",
    classes: {
      "ui-droppable-hover": "ui-state-hover"
    },
    drop: function(event, ui) {
    // Check for existing another option
    if($(this).find('li').length > 0)
    addToOlderPlace($(this).find('li'));

      $(this).addClass("ui-state-highlight");
      $(this).addClass('matched');  

      $(ui.draggable).find('i').attr("style","");
      $(this).append($(ui.draggable));    

    }
  });

  $("li").draggable({
    helper:"clone",
    revert: "invalid"
  }); 


  // This function used for find old place of option
  // This function used for find old place of item


  function addToOlderPlace($item) {
        var indexItem = $item.attr('order');
        var itemList = $("#options").find('li');
        $item.find('i').hide();         

        if (indexItem === "0")
            $("#options").prepend($item);
        else if (Number(indexItem) === (Number(numberOfItems)-1))        
               $("#options").append($item);                       
        else
            $(itemList[indexItem - 1]).after($item);
    }

})

Online demo (jsFiddle)

like image 149
Ali Soltani Avatar answered Oct 30 '22 12:10

Ali Soltani


I made a fiddle some time ago to demonstrate how to solve a problem of this type. Including tolerance:intersect in the drop/droppable functions is key to the solution.

In this snippet, I have not imitated your code, but provided the example from my fiddle so that you can see how you can apply this solution to your own code.

$("#launchPad").height($(window).height() - 20);
var dropSpace = $(window).width() - $("#launchPad").width();
$("#dropZone").width(dropSpace - 70);
$("#dropZone").height($("#launchPad").height());

$(".card").draggable({
    appendTo: "#launchPad",
    cursor: "move",
    helper: 'clone',
    revert: "invalid",

});

$("#launchPad").droppable({
    tolerance: "intersect",
    accept: ".card",
    activeClass: "ui-state-default",
    hoverClass: "ui-state-hover",
    drop: function(event, ui) {
        $("#launchPad").append($(ui.draggable));
    }
});

$(".stackDrop1").droppable({
    tolerance: "intersect",
    accept: ".card",
    activeClass: "ui-state-default",
    hoverClass: "ui-state-hover",
    drop: function(event, ui) {        
        $(this).append($(ui.draggable));
    }
});

$(".stackDrop2").droppable({
    tolerance: "intersect",
    accept: ".card",
    activeClass: "ui-state-default",
    hoverClass: "ui-state-hover",
    drop: function(event, ui) {        
        $(this).append($(ui.draggable));
    }
});
body {
  margin: 0;
}

#launchPad {
  width: 200px;
  float: left;
  border: 1px solid #eaeaea;
  background-color: #f5f5f5;
}

#dropZone {
  float: right;
  border: 1px solid #eaeaea;
  background-color: #ffffcc;
}

.card {
  width: 150px;
  padding: 5px 10px;
  margin: 5px;
  border: 1px solid #ccc;
  background-color: #eaeaea;
}

.stack {
  width: 180px;
  border: 1px solid #ccc;
  background-color: #f5f5f5;
  margin: 20px;
}

.stackHdr {
  background-color: #eaeaea;
  border: 1px solid #fff;
  padding: 5px
}

.stackDrop1,
.stackDrop2 {
  min-height: 100px;
  padding: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link href="https://code.jquery.com/ui/1.12.1/themes/smoothness/jquery-ui.css" type="text/css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />


<div id="launchPad">
  <div class="card draggable">
    apple
  </div>
  <div class="card draggable">
    orange
  </div>
  <div class="card draggable">
    banana
  </div>
  <div class="card draggable">
    car
  </div>
  <div class="card draggable">
    bus
  </div>
</div>

<div id="dropZone">
  <div class="stack">
    <div class="stackHdr">
      Drop here
    </div>
    <div class="stackDrop1 droppable">

    </div>
  </div>

  <div class="stack">
    <div class="stackHdr">
      Or here
    </div>
    <div class="stackDrop2 droppable">

    </div>
  </div>
</div>

Here is the fiddle link also

Hope this helps

like image 1
Rachel Gallen Avatar answered Oct 30 '22 13:10

Rachel Gallen