Need help with my JS/HTML Kanban Board
I've been working on a selfmade Kanban Board in Ninox for some weeks now. I am a beginner and just starting courses + searching for code snippets everywhere.
Today I finally got a Kanban Board running on Ninox, with example cards that could be draged+dropped and an "add"-field.
Then I replaced the example content and succeeded filling the swimlanes with cards that represent one appointment from another table each. When you click on the card, the corresponding appointment pops up.
But unfortunately, now the JS-Functions (drag/drop and add) do not work anymore. Plus, after a while I restarted from scratch and now, I don't get the functions going, neither with my data nor with the example content.
Can someone with JS knowledge have a look, what I am doing wrong now?
let upApp := (select Appointments where Status = 1);
let finApp := (select Appointments where Status = 2);
let canApp := (select Appointments where Status = 3);
let css := "<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
font-family: sans-serif;
-ms-overflow-style: none; /* IE and Edge */
scrollbar-width: none; /* Firefox */
}
*::-webkit-scrollbar {
display: none;
}
.board {
width: 100%;
height: 100vh;
overflow: scroll;
background-position: center;
background-size: cover;
}
/* ---- FORM ---- */
#todo-form {
padding: 32px 32px 0;
}
#todo-form input {
padding: 12px;
margin-right: 12px;
width: 225px;
border-radius: 4px;
border: none;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.25);
background: white;
font-size: 14px;
outline: none;
}
#todo-form button {
padding: 12px 32px;
border-radius: 4px;
border: none;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.25);
background: #ffffff;
color: black;
font-weight: bold;
font-size: 14px;
cursor: pointer;
}
/* ---- BOARD ---- */
.lanes {
display: flex;
align-items: flex-start;
justify-content: start;
gap: 16px;
padding: 24px 32px;
overflow: scroll;
height: 100%;
}
.heading1 {
font-size: 22px;
font-weight: bold;
margin-bottom: 8px;
}
.swim-lane {
display: flex;
flex-direction: column;
gap: 12px;
background: #f4f4f4;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.25);
padding: 12px;
border-radius: 4px;
width: 225px;
min-height: 120px;
flex-shrink: 0;
}
.task {
background: white;
color: black;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.15);
padding: 12px;
border-radius: 4px;
font-size: 16px;
cursor: move;
}
.is-dragging {
scale: 1.05;
box-shadow: 0px 5px 15px rgba(0, 0, 0, 0.25);
background: rgb(50, 50, 50);
color: white;
}
</style>";
let jsDrag := "<script>
const draggables = document.querySelectorAll('.task');
const droppables = document.querySelectorAll('.swim-lane');
draggables.forEach((task) => {
task.addEventListener('dragstart', () => {
task.classList.add('is-dragging');
});
task.addEventListener('dragend', () => {
task.classList.remove('is-dragging');
});
});
droppables.forEach((zone) => {
zone.addEventListener('dragover', (e) => {
e.preventDefault();
const bottomTask = insertAboveTask(zone, e.clientY);
const curTask = document.querySelector('.is-dragging');
if (!bottomTask) {
zone.appendChild(curTask);
} else {
zone.insertBefore(curTask, bottomTask);
}
});
});
const insertAboveTask = (zone, mouseY) => {
const els = zone.querySelectorAll('.task:not(.is-dragging)');
let closestTask = null;
let closestOffset = Number.NEGATIVE_INFINITY;
els.forEach((task) => {
const { top } = task.getBoundingClientRect();
const offset = mouseY - top;
if (offset < 0 && offset > closestOffset) {
closestOffset = offset;
closestTask = task;
}
});
return closestTask;
};
</script>";
let jsAdd := "<script>
const form = document.getElementById('todo-form');
const input = document.getElementById('todo-input');
const todoLane = document.getElementById('todo-lane');
form.addEventListener('submit', (e) => {
e.preventDefault();
const value = input.value;
if (!value) return;
const newTask = document.createElement('p');
newTask.classList.add('task');
newTask.setAttribute('draggable', 'true');
newTask.innerText = value;
newTask.addEventListener('dragstart', () => {
newTask.classList.add('is-dragging');
});
newTask.addEventListener('dragend', () => {
newTask.classList.remove('is-dragging');
});
todoLane.appendChild(newTask);
input.value = '';
});
</script>";
let body := ---
<div class="board">
<form id="todo-form">
<input type="text" placeholder="New TODO..." id="todo-input" />
<button type="submit">Add +</button>
</form>
<div class="lanes">
<div class="swim-lane" id="todo-lane">
<h3 class="heading1">Upcoming</h3>{ for app in upApp do }
<aside class="task" draggable="true"><span onclick=ui.popupRecord('{ app }')> { app.Projects.Clients.Name } </span> </aside>{ end }
</div>
<div class="swim-lane">
<h3 class="heading1">Finished</h3>{ for app in finApp do }
<aside class="task" draggable="true"><span onclick=ui.popupRecord('{ app }')> { app.Projects.Clients.Name } </span> </aside>{ end }
</div>
<div class="swim-lane">
<h3 class="heading1">Canceled</h3>{ for app in canApp do }
<aside class="task" draggable="true"><span onclick=ui.popupRecord('{ app }')> { app.Projects.Clients.Name } </span> </aside>{ end }
</div>
</div>
</div>
---;
html(css + jsDrag + jsAdd + body)
4 replies
-
When I build the Kanban in Visual Studio Code, it only works when I add "defer" to the script source in the head section:
<link rel='stylesheet' href='styles.css' /> <script src='drag.js' defer></script> <script src='todo.js' defer></script>
any idea how I can achieve this in ninox (where I can't just refer to external scripts)?
-
Hi I realize now that many of the problems I encounter when trying to run javascript snippets inside the html() function are precisely due to delay issues.
See in this post how uses the The
setTimeout()
method to achieve delay.It would be nice if an expert could give us general instructions about the subject!
-
Hi
I got the drag and drop to work through trial and error elimination. I changed a little bit of the CSS just for clarity in my testing. I'm not sure about the adding part and don't know when I can work on it. I thought this was interesting and had a go at it. Hopefully, it will nudge you further down the path.
Content aside
- 6 mths agoLast active
- 4Replies
- 227Views
-
3
Following