Reputation: 5165
I am trying to build this Custom Kanban (TODO) board from scratch (Vanilla JS, CSS, and no external libraries - jQuery is fine (preferred vanilla JS))
I'm currently stuck in a place where I'm trying to move cards from one row to another when user clicks on '>' (next) or '<' (previous). I'm not sure how to go about implementing something like this.
Here's my code: (Full page preferred) Codepen
.container {
display: flex;
flex-wrap: nowrap;
justify-content: space-around;
position: relative;
}
.board-column {
display: flex;
flex-direction: column;
border: 1px solid grey;
margin-left: 25px;
box-sizing: border-box;
background: #f0f0f0;
}
.board-column:last-child {
margin-right: 25px;
}
.todo {
width: 25%;
text-align: center;
}
.board-column > .board-column-header {
position: relative;
height: 30px;
line-height: 30px;
text-align: center;
color: white;
padding: 0 36%;
background: #333;
}
.board-column.todo .board-column-header {
background: #4A9FF9;
}
.board-column.working .board-column-header {
background: #f9944a;
}
.board-column.done .board-column-header {
background: #2ac06d;
}
.board-column.backlog .board-column-header {
background: red;
}
.board-column-content {
position: relative;
border: 10px solid transparent;
min-height: 95px;
}
.board-item {
width: 100%;
margin: 10px 0;
}
.board-item-content {
position: relative;
padding: 20px;
background: #fff; /* White */
border-radius: 4px;
font-size: 17px;
cursor: pointer;
box-shadow: 0px 1px 3px 0 rgba(0,0,0,0.2);
}
.next {
position: relative;
float: right;
height: 21px;
margin-right: -10px;
}
.prev {
float: left;
height: 21px;
margin-left: -10px;
}
<article class="container">
<section class="board-column todo">
<section class="board-column-header"> TODO </section>
<section class="board-column-content">
<div class="board-item">
<div class="board-item-content">
<span>Item #</span>1<button class="action next"> > </button></div></div>
<div class="board-item"><div class="board-item-content"><span>Item #</span>2<button class="action next"> > </button></div></div>
<div class="board-item"><div class="board-item-content"><span>Item #</span>3<button class="action next"> > </button></div></div>
</section>
</section>
<section class="board-column todo working">
<section class="board-column-header"> Working </section>
<section class="board-column-content">
<div class="board-item"><div class="board-item-content">
<button class="action prev"> < </button>
<span>Item #</span>4<button class="action next"> > </button></div></div>
<div class="board-item"><div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>5<button class="action next"> > </button></div></div>
<div class="board-item"><div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>6<button class="action next"> > </button></div></div>
</section>
</section>
<section class="board-column todo done">
<section class="board-column-header"> Done </section>
<section class="board-column-content">
<div class="board-item"><div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>7<button class="action next"> > </button></div></div>
<div class="board-item"><div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>8<button class="action next"> > </button></div></div>
<div class="board-item"><div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>9<button class="action next"> > </button></div></div>
</section>
</section>
<section class="board-column todo backlog">
<section class="board-column-header"> Backlog </section>
<section class="board-column-content">
<div class="board-item"><div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>10</div></div>
<div class="board-item"><div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>11</div></div>
<div class="board-item"><div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>12</div></div>
</section>
</section>
</article>
How do I move cards from tow A to next row when user clicks on '>' (next) or '<' (previous)?
Can I make any optimizations for my current code to make it more readable?
Upvotes: 2
Views: 1275
Reputation: 3202
Logic overview:
As for structure, I wouldn't say it's too bad - one change I made was making it so that every item has previous/next buttons, but they are hidden via CSS where appropriate.
function findParentWithClass(el, className) {
while (el && !el.classList.contains(className)) {
el = el.parentElement;
}
return el;
}
function getElementChildIndex(el) {
let i = 0;
while (el = el.previousElementSibling) i++;
return i;
}
function swapClick(btn, dir) {
let item = findParentWithClass(btn, "board-item");
let sct1 = findParentWithClass(item, "board-column");
let sct2 = dir > 0 ? sct1.nextElementSibling : sct1.previousElementSibling;
if (!sct2) return;
//
let dest = sct2.querySelector('.board-column-content');
let pos = getElementChildIndex(item);
dest.insertBefore(item, dest.children[pos]);
}
for (let el of document.getElementsByClassName('prev')) {
el.addEventListener('click', (e) => swapClick(el, -1));
}
for (let el of document.getElementsByClassName('next')) {
el.addEventListener('click', (e) => swapClick(el, 1));
}
.container {
display: flex;
flex-wrap: nowrap;
justify-content: space-around;
position: relative;
}
.board-column {
display: flex;
flex-direction: column;
border: 1px solid grey;
margin-left: 25px;
box-sizing: border-box;
background: #f0f0f0;
}
.board-column:last-child {
margin-right: 25px;
}
.todo {
width: 25%;
text-align: center;
}
.board-column > .board-column-header {
position: relative;
height: 30px;
line-height: 30px;
text-align: center;
color: white;
padding: 0 36%;
background: #333;
}
.board-column.todo .board-column-header {
background: #4A9FF9;
}
.board-column.working .board-column-header {
background: #f9944a;
}
.board-column.done .board-column-header {
background: #2ac06d;
}
.board-column.backlog .board-column-header {
background: red;
}
.board-column-content {
position: relative;
border: 10px solid transparent;
min-height: 95px;
}
.board-item {
width: 100%;
margin: 10px 0;
}
.board-item-content {
position: relative;
padding: 20px;
background: #fff; /* White */
border-radius: 4px;
font-size: 17px;
cursor: pointer;
box-shadow: 0px 1px 3px 0 rgba(0,0,0,0.2);
}
.next {
position: relative;
float: right;
height: 21px;
margin-right: -10px;
}
.prev {
float: left;
height: 21px;
margin-left: -10px;
}
.board-column:first-child .action.prev { display: none }
.board-column:last-child .action.next { display: none }
<article class="container">
<section class="board-column todo">
<section class="board-column-header"> TODO </section>
<section class="board-column-content">
<div class="board-item"><div class="board-item-content">
<button class="action prev"> < </button>
<span>Item #</span>1
<button class="action next"> > </button>
</div></div>
<div class="board-item"><div class="board-item-content">
<button class="action prev"> < </button>
<span>Item #</span>2
<button class="action next"> > </button>
</div></div>
<div class="board-item"><div class="board-item-content">
<button class="action prev"> < </button>
<span>Item #</span>3
<button class="action next"> > </button>
</div></div>
</section>
</section>
<section class="board-column todo working">
<section class="board-column-header"> Working </section>
<section class="board-column-content">
<div class="board-item">
<div class="board-item-content">
<button class="action prev"> < </button>
<span>Item #</span>4
<button class="action next"> > </button></div>
</div>
<div class="board-item">
<div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>5
<button class="action next"> > </button></div>
</div>
<div class="board-item">
<div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>6
<button class="action next"> > </button></div>
</div>
</section>
</section>
<section class="board-column todo done">
<section class="board-column-header"> Done </section>
<section class="board-column-content">
<div class="board-item">
<div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>7
<button class="action next"> > </button></div>
</div>
<div class="board-item">
<div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>8
<button class="action next"> > </button></div>
</div>
<div class="board-item">
<div class="board-item-content"><button class="action prev"> < </button><span>Item #</span>9
<button class="action next"> > </button></div>
</div>
</section>
</section>
<section class="board-column todo backlog">
<section class="board-column-header"> Backlog </section>
<section class="board-column-content">
<div class="board-item"><div class="board-item-content">
<button class="action prev"> < </button>
<span>Item #</span>10
<button class="action next"> > </button>
</div></div>
<div class="board-item"><div class="board-item-content">
<button class="action prev"> < </button>
<span>Item #</span>11
<button class="action next"> > </button>
</div></div>
<div class="board-item"><div class="board-item-content">
<button class="action prev"> < </button>
<span>Item #</span>12
<button class="action next"> > </button>
</div></div>
</section>
</section>
</article>
Upvotes: 1