I am implementing a Fill in the blanks drag & drop functionality.
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>
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)
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With