Issue
I am trying to make a table in which we can interchange colored boxes via drag and drop with animation. It is working fine sometimes but in some cases the table is getting collapsed .Steps to replicate the problem.
- Move 100 - 400
- Move 100 -500
- Move 100 - 200
- Move 100 - 300
You can find my code in this attached link :
https://jsfiddle.net/manikathuria2001/oveq91Lu/6/
HTML
var columns = document.querySelectorAll('.card');
var draggingClass = 'dragging';
var dragSource;
Array.prototype.forEach.call(columns, function (col) {
col.addEventListener('dragstart', handleDragStart, false);
col.addEventListener('dragenter', handleDragEnter, false)
col.addEventListener('dragover', handleDragOver, false);
col.addEventListener('dragleave', handleDragLeave, false);
col.addEventListener('drop', handleDrop, false);
col.addEventListener('dragend', handleDragEnd, false);
});
function handleDragStart (evt) {
dragSource = this;
evt.target.classList.add(draggingClass);
evt.dataTransfer.effectAllowed = 'move';
}
function handleDragOver (evt) {
evt.dataTransfer.dropEffect = 'move';
evt.preventDefault();
}
function handleDragEnter (evt) {
this.classList.add('over');
}
function handleDragLeave (evt) {
this.classList.remove('over');
}
function handleDrop (evt) {
evt.stopPropagation();
if (dragSource !== this) {
$(this).swap($(dragSource),300);
}
evt.preventDefault();
}
function handleDragEnd (evt) {
Array.prototype.forEach.call(columns, function (col) {
['over', 'dragging'].forEach(function (className) {
col.classList.remove(className);
});
});
}
(function( $ ){
$.fn.swap = function(other,speed) {
//get the position
var position1 = $(this).offset();
var position2 = other.offset();
//position this where it is
$(this).css({
top: position1.top + 'px',
left: position1.left + 'px',
position: 'absolute'
});
//position the other element where it is
other.css({
top: position2.top + 'px',
left: position2.left + 'px',
position: 'absolute'
});
$(this).animate({
'top': position2.top + 'px',
'left': position2.left + 'px',
position: 'absolute'
}, speed, function() {
// Animation complete.
});
other.animate({
'top': position1.top + 'px',
'left': position1.left + 'px',
position: 'absolute'
}, speed, function() {
// Animation complete.
});
};
})( jQuery );
.container {
font-family: sans-serif;
display: flex;
justify-content: center;
align-items: center;
vertical-align: middle;
text-align: center;
}
#table1 {
width: 100%;
height: 50%;
}
#table1,
.block {
border: 1px solid black;
border-collapse: collapse;
}
.block {
padding: 30px !important;
margin: 100px !important;
/* min-width: 200px !important;
min-height: 400px !important; */
}
.card {
width: 100px;
height: 60px;
border-radius: 25px;
/* display: inline-block; */
/* margin-right: 1.2%; */
box-sizing: border-box;
font-size: larger;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
vertical-align: middle;
text-align: center;
z-index: 100;
}
.card.dragging {
opacity: 0.5;
}
.card.over {
border: 3px dashed #000;
}
.box1 {
background-color: #E74C3C;
}
.box2 {
background-color: #8E44AD;
}
.box3 {
background-color: #5DADE2;
}
.box4 {
background-color: #1ABC9C;
}
.box5 {
background-color: #F1C40F;
}
.box6 {
background-color: #F39C12;
}
.box7 {
background-color: #34495E;
}
.box8 {
background-color: #FF00FF;
}
.box9 {
background-color: #008080;
}
[draggable] {
user-select: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link rel="stylesheet" href="./styles.css">
<title>Document</title>
</head>
<body>
<div class="container">
<table id="table1" cellspacing="0" cellpadding="0">
<tr class="columns">
<td class="block">
<div class="card box1" draggable="true">100</div>
</td>
<td class="block">
<div class="card box2" draggable="true">200</div>
</td>
<td class="block">
<div class="card box3" draggable="true">300</div>
</td>
</tr>
<tr class="columns">
<td class="block">
<div class="card box4" draggable="true">400</div>
</td>
<td class="block">
<div class="card box5" draggable="true">500</div>
</td>
<td class="block">
<div class="card box6" draggable="true">600</div>
</td>
</tr>
<tr class="columns">
<td class="block">
<div class="card box7" draggable="true">700</div>
</td>
<td class="block">
<div class="card box8" draggable="true">800</div>
</td>
<td class="block">
<div class="card box9" draggable="true">900</div>
</td>
</tr>
</table>
</div>
<script src="./index.js"></script>
</body>
</html>
Solution
The height of .block is dependent on the .card inside it. But when the card is moved it gets position: absolute;, so it's out of the flow, and the block collapses. You don't notice this until all the cards on the same row are moved, then the row collapses.
Give .block a fixed height in CSS and the problem goes away.
There's a similar problem with the column widths if you drag all the cards in the same column, so you also have to give .block a fixed width.
var columns = document.querySelectorAll('.card');
var draggingClass = 'dragging';
var dragSource;
Array.prototype.forEach.call(columns, function (col) {
col.addEventListener('dragstart', handleDragStart, false);
col.addEventListener('dragenter', handleDragEnter, false)
col.addEventListener('dragover', handleDragOver, false);
col.addEventListener('dragleave', handleDragLeave, false);
col.addEventListener('drop', handleDrop, false);
col.addEventListener('dragend', handleDragEnd, false);
});
function handleDragStart (evt) {
dragSource = this;
evt.target.classList.add(draggingClass);
evt.dataTransfer.effectAllowed = 'move';
}
function handleDragOver (evt) {
evt.dataTransfer.dropEffect = 'move';
evt.preventDefault();
}
function handleDragEnter (evt) {
this.classList.add('over');
}
function handleDragLeave (evt) {
this.classList.remove('over');
}
function handleDrop (evt) {
evt.stopPropagation();
if (dragSource !== this) {
$(this).swap($(dragSource),300);
}
evt.preventDefault();
}
function handleDragEnd (evt) {
Array.prototype.forEach.call(columns, function (col) {
['over', 'dragging'].forEach(function (className) {
col.classList.remove(className);
});
});
}
(function( $ ){
$.fn.swap = function(other,speed) {
//get the position
var position1 = $(this).offset();
var position2 = other.offset();
//position this where it is
$(this).css({
top: position1.top + 'px',
left: position1.left + 'px',
position: 'absolute'
});
//position the other element where it is
other.css({
top: position2.top + 'px',
left: position2.left + 'px',
position: 'absolute'
});
$(this).animate({
'top': position2.top + 'px',
'left': position2.left + 'px',
position: 'absolute'
}, speed, function() {
// Animation complete.
});
other.animate({
'top': position1.top + 'px',
'left': position1.left + 'px',
position: 'absolute'
}, speed, function() {
// Animation complete.
});
};
})( jQuery );
.container {
font-family: sans-serif;
display: flex;
justify-content: center;
align-items: center;
vertical-align: middle;
text-align: center;
}
#table1 {
width: 100%;
height: 50%;
}
#table1,
.block {
border: 1px solid black;
border-collapse: collapse;
}
.block {
padding: 30px !important;
margin: 100px !important;
/* min-width: 200px !important;
min-height: 400px !important; */
height: 60px; /* prevent collapse when card is moved */
width: 340px;
}
.card {
width: 100px;
height: 60px;
border-radius: 25px;
/* display: inline-block; */
/* margin-right: 1.2%; */
box-sizing: border-box;
font-size: larger;
color: #fff;
display: flex;
justify-content: center;
align-items: center;
vertical-align: middle;
text-align: center;
z-index: 100;
}
.card.dragging {
opacity: 0.5;
}
.card.over {
border: 3px dashed #000;
}
.box1 {
background-color: #E74C3C;
}
.box2 {
background-color: #8E44AD;
}
.box3 {
background-color: #5DADE2;
}
.box4 {
background-color: #1ABC9C;
}
.box5 {
background-color: #F1C40F;
}
.box6 {
background-color: #F39C12;
}
.box7 {
background-color: #34495E;
}
.box8 {
background-color: #FF00FF;
}
.box9 {
background-color: #008080;
}
[draggable] {
user-select: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js"></script>
<link rel="stylesheet" href="./styles.css">
<title>Document</title>
</head>
<body>
<div class="container">
<table id="table1" cellspacing="0" cellpadding="0">
<tr class="columns">
<td class="block">
<div class="card box1" draggable="true">100</div>
</td>
<td class="block">
<div class="card box2" draggable="true">200</div>
</td>
<td class="block">
<div class="card box3" draggable="true">300</div>
</td>
</tr>
<tr class="columns">
<td class="block">
<div class="card box4" draggable="true">400</div>
</td>
<td class="block">
<div class="card box5" draggable="true">500</div>
</td>
<td class="block">
<div class="card box6" draggable="true">600</div>
</td>
</tr>
<tr class="columns">
<td class="block">
<div class="card box7" draggable="true">700</div>
</td>
<td class="block">
<div class="card box8" draggable="true">800</div>
</td>
<td class="block">
<div class="card box9" draggable="true">900</div>
</td>
</tr>
</table>
</div>
<script src="./index.js"></script>
</body>
</html>
Answered By - Barmar
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.