I am creating a Kanban Board in HTML/JS/CSS and am close to finishing my MVP here. Everything is working as expected, except for one thing. When I create a new task, I am able to drag it (seemingly) but not DROP it into any other columns. The sample tasks I have do not have this problem and I am ripping my hair out trying to figure out what the issue is. When I attempt to drag and drop newly created tasks into other columns, I get this error:
TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.
at drop (/script.js:31:13)
at HTMLDivElement.ondrop (/:45:112)
I am using basic drag and drop API stuff for HTML and JS and literally only need to make this work in order to finish my MVP. Any help is appreciated. NOTE: The line numbers in the above error change based on what column I try to drop the new task into but the error itself stays the same.
Here is my code:
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>Christopher's Kanban Board</title>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div class="new-task-window" id="new_task_form">
<div class="header">
<div class="title">New Task</div>
<button class="btn-close-window" data-target="#new_task_form">X</button>
</div>
<div class="body">
<input type="text" id="new-task-name" />
<input type="submit" value="New Task" id="new-task-submit" />
</div>
</div>
<!--Kanban Board-->
<div class="kanban-container">
<div class="kanban-container-section" id="todo" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>To Do</strong>
<div class="task-button-block">
<button class="task-button" id="task-button" data-target="#new_task_form">+ New Task</button>
</div>
<div class="task" id="task1" draggable="true" ondragstart="drag(event)">
<span contenteditable="true">Task #1</span>
<!--<button class="edit_button" id="edit_button">Edit</button>-->
</div>
<div class="task" id="task2" draggable="true" ondragstart="drag(event)">
<span contenteditable="true">Task #2</span>
</div>
<div class="task" id="task3" draggable="true" ondragstart="drag(event)">
<span contenteditable="true">Task #3</span>
</div>
<div class="task" id="task4" draggable="true" ondragstart="drag(event)">
<span contenteditable="true">Task #4</span>
</div>
</div>
<div class="kanban-container-section" id="inprogress" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>In Progress</strong>
</div>
<div class="kanban-container-section" id="done" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>Done</strong>
</div>
<div class="kanban-container-section" id=" blocked" ondrop="drop(event)" ondragover="allowDrop(event)">
<strong>Blocked</strong>
</div>
</div>
<div id="overlay"></div>
<script src="script.js"></script>
</body>
</html>
script.js:
const task = document.querySelector('.task');
const buttons = document.querySelectorAll("[data-target]");
const close_buttons = document.querySelectorAll(".btn-close-window");
//Allow the New Task Button to open the New Task Creation Window.
buttons.forEach(btn => {
btn.addEventListener('click', () => {
document.querySelector(btn.dataset.target).classList.add("active");
overlay.classList.add("active");
});
});
close_buttons.forEach((btn) => {
btn.addEventListener('click', () => {
document.querySelector(btn.dataset.target).classList.remove("active");
overlay.classList.remove("active");
});
});
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
const new_task_submit = document.getElementById("new-task-submit");
if(new_task_submit) {
new_task_submit.addEventListener('click', createTask);
}
function createTask() {
const task_div = document.createElement("div");
const input_value = document.getElementById("new-task-name").value;
//Take the text from the above input and create a task with that text.
const text = document.createTextNode(input_value);
task_div.appendChild(text);
//Add the proper class (task in this case) to the newly created task.
task_div.classList.add("task");
//Add the draggable attribute to the newly created task and set it to true to allow drag and drop.
if(task_div){
task_div.setAttribute("draggable", "true");
task_div.setAttribute("contenteditable", "true");
}
//task_div.innerHTML += `
//<div class="task" id="${input_value.toLowerCase().split(" ").join("")}"
//draggable="true" ondragstart="drag(event)>
//<span contenteditable="true">${input_value}</span>
//</div>
//`
//Add the new task to the To Do section of the Kanban Board.
const todo = document.getElementById("todo");
todo.appendChild(task_div);
document.getElementById("new-task-name").value = "";
new_task_form.classList.remove("active");
overlay.classList.remove("active");
}
style.css (the error would indicate that this file is not the problem):
.kanban-container {
display: grid;
grid-auto-columns: 250px;
grid-auto-flow: column;
grid-gap: 8px;
height: 100vh;
overflow: auto;
}
.kanban-container-section {
background: #EBEBEB;
border-radius: 3px;
display: grid;
grid-auto-rows: max-content;
grid-gap: 10px;
padding: 10px;
}
.kanban-container-section strong {
background: #2C89BF;
font-size: 16px;
margin: 0 0 12px 0;
padding: 10px;
}
.task {
background: #FFFFFF;
box-shadow: 0 1px 0 rgba(9,30,66,.25);
border-radius: 3px;
padding: 10px;
}
.task-button {
width: 40%;
background: #FFFFFF;
border-radius: 3px;
box-shadow: 0 1px 0 rgba(9,30,66,.25);
border: 0.1rem;
cursor: pointer;
}
.task.button:active {
transform: scale(0.9);
}
.btn-close-window {
padding: 0.5rem 1rem;
border: 1px solid #ccc;
border-radius: 3px;
cursor: pointer;
}
.new-task-window {
width: 450px;
position: fixed;
top: -50%;
left: 50%;
transform: translate(-50%, -50%);
border: 1px solid #ccc;
z-index: 2;
background-color:#FFFFFF;
}
.new-task-window.active {
top: 15%;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.5rem 1rem;
background-color: rgba(0, 0, 0, 0.03);
border-bottom: 1px solid #ccc;
}
#overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.2);
}
#overlay.active {
display: block;
}
#new-task-name, #new-task-submit {
padding: 1rem 1rem;
width: 90%;
margin: 0.25rem;
align-items: center;
}
#new-task-submit {
background-color: #2C89BF;
border: none;
color: #FFFFFF;
align-items: center;
}
Again, if anyone knows what my issue is here, the help is greatly appreciated. Thanks!