Issue
I'm helping a friend design a class organizer for one of their classes. I have a list of classes that show up on a search bar on the left of the screen and they need to be dragged into boxes on the right side of the screen. the JS I have for the draggable items works just fine if I manually add the element to the HTML, but when I use JS to add the element using data from a CSV file they are unable to be dragged around. The only solution I've found is I need to read the listeners for the dragging function in the loop that creates the items but that hasn't fixed the problem for me. Ive added the html js and css below. I am not using any libraries other than papaparse for the CSV data extraction.
//dynamically add lines to search menu
var data;
Papa.parse('test.csv', {
header: true,
download: true,
dynamicTyping: true,
complete: function(results) {
console.log(results);
data = results.data;
console.log(data.length);
// Create and append draggable elements
for(var i = 0; i < data.length; i++) {
var opt = data[i].Title;
var el = document.createElement("p");
el.setAttribute("class","draggable");
el.setAttribute("draggable","true");
el.value = opt;
el.textContent = opt;
el.addEventListener('dragstart', () => {
el.classList.add('dragging')
})
el.addEventListener('dragend', () => {
el.classList.remove('dragging')
})
classitem.appendChild(el);
}
}
});
//allows elements to be draggable
const draggables = document.querySelectorAll('.draggable')
const containers = document.querySelectorAll('.container')
draggables.forEach(draggable => {
draggable.addEventListener('dragstart', () => {
draggable.classList.add('dragging')
})
draggable.addEventListener('dragend', () => {
draggable.classList.remove('dragging')
})
})
containers.forEach(container => {
container.addEventListener('dragover', e => {
e.preventDefault()
const afterElement = getDragAfterElement(container, e.clientY)
const draggable = document.querySelector('.dragging')
if (afterElement == null) {
container.appendChild(draggable)
} else {
container.insertBefore(draggable, afterElement)
}
})
})
function getDragAfterElement(container, y) {
const draggableElements = [...container.querySelectorAll('.draggable:not(.dragging)')]
return draggableElements.reduce((closest, child) => {
const box = child.getBoundingClientRect()
const offset = y - box.top - box.height / 2
if (offset < 0 && offset > closest.offset) {
return { offset: offset, element: child }
} else {
return closest
}
}, { offset: Number.NEGATIVE_INFINITY }).element
}
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
function filterFunction() {
var input, filter, ul, li, a, i;
input = document.getElementById("myInput");
filter = input.value.toUpperCase();
div = document.getElementById("myDropdown");
p = div.getElementsByTagName("p");
for (i = 0; i < p.length; i++) {
txtValue = p[i].textContent || p[i].innerText;
if (txtValue.toUpperCase().indexOf(filter) > -1) {
p[i].style.display = "";
} else {
p[i].style.display = "none";
}
}
}
<!DOCTYPE html>
<html lang="en" >
<head>
<script src="papaparse.min.js"></script>
<meta charset="UTF-8">
<title></title>
<link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Merriweather|Open+Sans'><link rel="stylesheet" href="./haha.css">
<style>
header {
font-family: "Open Sans", sans-serif;
font-size: 16px;
font-weight: 100;
}
body {
font-family: Merriweather, serif;
}
</style>
</head>
<body>
<div class="header">
<h1>test</h1>
</div>
<p id="classdata"></p>
<p id="classdata2"></p>
<p style="height: 100px;"></p>
<h2 style="text-align: centre; position: relative; padding-left: 200px; padding-top: 0px; display:inline-block;">Courses</h2>
<h2 style="text-align: centre; position: relative; padding-left: 200px; padding-top: 0px; display:inline-block;">Four year plan</h2>
<div class="row">
<div class="column">
<!--dropdown-->
<div class="dropdown">
<button onclick="myFunction()" class="dropbtn">Core Classes</button>
<div id="myDropdown" class="dropdown-content">
<input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()">
<div id="classitem" class="container" style="width: 70%; background-color: white; border: none;">
<p class="draggable" draggable="true">CHEM1000</p>
</div>
</div>
</div>
</div>
<div class="column2">
<div class="top">
<div class="container">
</div>
<div class="container">
</div>
<div class="container">
</div>
<div class="container">
</div>
</div>
<div class="bot">
<div class="container">
</div>
<div class="container">
</div>
<div class="container">
</div>
<div class="container">
</div>
</div>
</div>
</div>
<script src="./hehe.js"></script>
</body>
</html>
body {
margin: 0;
}
.row {
display: flex;
}
.header {
padding: 10px;
text-align: left;
background: #982828;
color: white;
letter-spacing: 16px;
font-weight: 100;
}
.column {
flex: 20%;
}
.column2 {
flex: 80%;
}
.container {
background-color: white;
border-radius: 10px;
width: 20%;
border: 1px solid black;
height: 17rem;
padding: .5rem;
margin: .1rem;
float:d left;
overflow: auto;
}
.top {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.bot {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.draggable {
margin-top: .5rem;
padding: .4rem;
border-radius: 10px;
width: auto;
background-color: white;
border: 1px solid black;
cursor: move;
}
/* ===== Scrollbar CSS ===== */
/* Firefox */
* {
scrollbar-width: auto;
scrollbar-color: #565252 #ffffff;
}
/* Chrome, Edge, and Safari */
*::-webkit-scrollbar {
width: 14px;
}
*::-webkit-scrollbar-track {
background: #ffffff;
}
*::-webkit-scrollbar-thumb {
background-color: #565252;
border-radius: 10px;
border: 3px solid #ffffff;
}
.draggable.dragging {
opacity: .5;
}
#myInput {
box-sizing: border-box;
background-image: url('searchicon.png');
background-position: 14px 12px;
background-repeat: no-repeat;
position: relative;
border-radius: 5px;
width: 220px;
font-size: 16px;
padding: 14px 20px 12px 45px;
border: 1px solid black;
}
#myInput:focus {outline: 3px solid #ddd;}
.dropdown {
position: relative;
left: 50%;
margin-left: -150px;
display: inline-block;
}
.dropbtn {
display: inline-block;
background-color: white;
border: 1px solid black;
color: black;
padding: 16px;
position: relative;
margin-top: .1rem;
font-size: 16px;
border-radius: 5px;
width: 300px;
cursor: pointer;
}
.dropbtn:hover, .dropbtn:focus {
background-color: white;
}
.dropdown-content {
display: none;
position: absolute;
border-radius: 5px;
background-color: white;
margin: 24px 17px 24px 33px;
min-width: 250px;
z-index: 1;
}
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {background-color: #ddd;}
.show {display: block;}
Solution
Hmm, I see ... Have you tried to make a separate JS file for making elements darggable ? like hehe1.js
where is your main code and hehe2.js
for dragging things ? or, the library you used to read the CSV files take a long time to perform a function, so try to make the code like this :
function makeEmDragging(){
let draggables = document.querySelectorAll('.draggable')
let containers = document.querySelectorAll('.container')
draggables.forEach(draggable => {
draggable.addEventListener('dragstart', () => {
draggable.classList.add('dragging')
})
draggable.addEventListener('dragend', () => {
draggable.classList.remove('dragging')
})
})
containers.forEach(container => {
container.addEventListener('dragover', e => {
e.preventDefault()
const afterElement = getDragAfterElement(container, e.clientY)
const draggable = document.querySelector('.dragging')
if (afterElement == null) {
container.appendChild(draggable)
} else {
container.insertBefore(draggable, afterElement)
}
})
})
function getDragAfterElement(container, y) {
const draggableElements = [...container.querySelectorAll('.draggable:not(.dragging)')]
return draggableElements.reduce((closest, child) => {
const box = child.getBoundingClientRect()
const offset = y - box.top - box.height / 2
if (offset < 0 && offset > closest.offset) {
return { offset: offset, element: child }
} else {
return closest
}
}, { offset: Number.NEGATIVE_INFINITY }).element
}
}
var data;
Papa.parse('test.csv', {
header: true,
download: true,
dynamicTyping: true,
complete: function(results) {
console.log(results);
data = results.data;
console.log(data.length);
// Create and append draggable elements
for(var i = 0; i < data.length; i++) {
var opt = data[i].Title;
var el = document.createElement("p");
el.setAttribute("class","draggable");
el.setAttribute("draggable","true");
el.value = opt;
el.textContent = opt;
el.addEventListener('dragstart', () => {
el.classList.add('dragging')
})
el.addEventListener('dragend', () => {
el.classList.remove('dragging')
})
classitem.appendChild(el);
makeEmDragging()
}
}
});
Edit : put your code inside the makeEmDragging()
function, make any changes to my code, as it is your program
Answered By - hasan darwish
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.