Skip to content

Instantly share code, notes, and snippets.

@iankit3
Last active March 17, 2020 17:34
Show Gist options
  • Save iankit3/b42394f47f9abaaa863a5b64d60172a6 to your computer and use it in GitHub Desktop.
Save iankit3/b42394f47f9abaaa863a5b64d60172a6 to your computer and use it in GitHub Desktop.
Trello Clone
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
* {
box-sizing: border-box;
}
.main {
width: 75%;
margin: auto;
}
.wrapper {
margin: 100px 20px;
display: flex;
align-items: flex-start;
}
.card {
display: flex;
flex-basis: 250px;
box-shadow: 1px 2px 5px #222;
flex-direction: column;
margin: 0 10px;
position: relative;
}
.card-header {
background: #efefef;
padding: 10px;
font-size: 1.2em;
font-weight: bold;
}
.card-body {
margin-top: 2px;
margin-bottom: 30px;
}
.action-bar {
position: absolute;
bottom: 0;
}
.action-bar input {
width: 100%;
}
.task-each {
padding: 10px;
border-top: 1px solid;
}
.btn {
border-radius: 2px;
border: 0;
padding: 5px 10px;
outline: 0;
cursor: pointer;
background: #6a6a6a;
color: #fff;
}
.btn:hover {
background: #fefefe;
border: 1px solid;
color: #222;
}
.hidden {
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<link rel="stylesheet" href="./css/style.css" />
</head>
<body>
<div class="main">
<template id="t_card">
<div class="card">
<div class="card-header"></div>
<div class="card-body"></div>
<div class="action-bar">
<input
type="text"
class="card-input"
placeholder="Add a new list"
/>
</div>
</div>
</template>
<template id="t_task">
<div draggable="true" class="task-each"></div>
</template>
</div>
<script src="./scripts/script.js"></script>
</body>
</html>
var template = document.getElementById("t_card");
var t_template = document.getElementById("t_task");
const app = {
counterID: 0,
data: {},
init(config) {
app.data = config.data;
app.main();
},
main: () => {
var div = document.createElement("div");
div.classList.add("wrapper");
app.data.forEach(d => {
div.appendChild(app.createCard(d));
})
var main = document.querySelector(".main");
main.innerHTML = "";
main.appendChild(div);
app.attachListeners();
},
createCard: (cdata) => {
var card = template.content.cloneNode(true);
card.querySelector(".card-header").innerText = cdata.name;
var cardBody = card.querySelector(".card-body");
cdata.tasks.forEach(t => {
cardBody.appendChild(app.createTask(t, cdata.id));
})
return card;
},
createTask: (tdata, pid) => {
var task = t_template.content.cloneNode(true);
task.querySelector(".task-each").innerText = tdata.name;
task.querySelector(".task-each").id = pid+""+tdata.id;
return task;
},
attachListeners: () => {
document.querySelectorAll(".card").forEach(c => {
app.keyDown(c);
app.drag(c);
app.drop(c);
app.dragOver(c);
});
},
keyDown: c => {
c.addEventListener("keydown", ev => {
if (ev.target.matches(".card-input") && ev.keyCode == "13") {
var text = ev.target.value;
ev.target.parentElement.parentElement
.querySelector(".card-body")
.appendChild(app.createTask({name: text, id: app.counterID++}, 0));
ev.target.value = "";
}
});
},
drag: c => {
c.addEventListener("dragstart", ev => {
if (ev.target.matches(".task-each")) {
ev.dataTransfer.dropEffect = "move";
ev.dataTransfer.setData("text/plain", ev.target.id);
}
});
},
drop: c => {
c.addEventListener("drop", ev => {
ev.preventDefault();
const data = ev.dataTransfer.getData("text/plain");
if (ev.target.matches(".card")) {
ev.target
.querySelector(".card-body")
.appendChild(document.getElementById(data));
} else if (ev.target.matches(".task-each")) {
ev.target.parentElement.appendChild(document.getElementById(data));
}
});
},
dragOver: c => {
c.addEventListener("dragover", ev => {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move";
});
}
};
let config = {
data: [
{
name : "Todo",
id: 0,
tasks : [
{name: "DS", id: 0},
{name: "Algo", id: 1}
]
},
{
name : "Task",
id: 1,
tasks : [
{name: "Backtracking", id: 0},
{name: "DP", id: 1}
]
}
]
};
document.addEventListener("DOMContentLoaded", app.init.call(this, config));
@iankit3
Copy link
Author

iankit3 commented Mar 17, 2020

TODO: Sorting inside the card

A bit undoable if i am just replying on DOM opertaions, i should rather use app.data variable to hold the state and then manipulate that dta array instead of the DOM directly

@iankit3
Copy link
Author

iankit3 commented Mar 17, 2020

TODO: Pass some initial config to init({})

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment