Skip to content

Commit 90269aa

Browse files
committed
add module 'Practice - OOPs, Classes and DOM'
1 parent 3398dd7 commit 90269aa

File tree

4 files changed

+334
-0
lines changed

4 files changed

+334
-0
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
class DOMHelper {
2+
static clearEventListeners(element){
3+
const clonedElement = element.cloneNode(true);
4+
element.replaceWith(clonedElement);
5+
return clonedElement;
6+
}
7+
8+
static moveElement(elementId, newDestinationSelector) {
9+
const element = document.getElementById(elementId);
10+
const destinationElement = document.querySelector(newDestinationSelector);
11+
destinationElement.append(element);
12+
}
13+
}
14+
15+
class Component {
16+
constructor(hostElementId, insertBefore=false) {
17+
if (hostElementId) {
18+
this.hostElement = document.getElementById(hostElementId);
19+
} else {
20+
this.hostElement = document.body;
21+
}
22+
this.insertBefore = insertBefore;
23+
}
24+
25+
detach() {
26+
if (this.element) {
27+
this.element.remove();
28+
// this.element.parentElement.removeChild(this.element);
29+
}
30+
}
31+
32+
attach() {
33+
this.hostElement.insertAdjacentElement(this.insertBefore ? 'afterbegin' : 'beforeend', this.element);
34+
}
35+
}
36+
37+
class Tooltip extends Component {
38+
constructor(closeNotifierFunction) {
39+
super();
40+
this.closeNotifier = closeNotifierFunction;
41+
this.create();
42+
}
43+
44+
closeToolTip = () => {
45+
this.detach();
46+
this.closeNotifier();
47+
};
48+
49+
create() {
50+
const toolTipElement = document.createElement('div');
51+
toolTipElement.className = 'card';
52+
toolTipElement.textContent = "Dummmy";
53+
toolTipElement.addEventListener('click', this.closeToolTip);
54+
this.element = toolTipElement;
55+
}
56+
}
57+
58+
class ProjectItem {
59+
hasActiveTooltip = false;
60+
61+
constructor(id, updateProjectListFunction, type) {
62+
this.id = id;
63+
this.updateProjectListHandler = updateProjectListFunction;
64+
this.connectMoreInfoButton();
65+
this.connectSwitchButton(type);
66+
}
67+
68+
showMoreInfoHandler() {
69+
if (this.hasActiveTooltip) {
70+
return;
71+
}
72+
const tooltip = new Tooltip(() => {
73+
this.hasActiveTooltip = false;
74+
});
75+
tooltip.attach();
76+
this.hasActiveTooltip = true;
77+
}
78+
79+
connectMoreInfoButton(){
80+
const prjItemElement = document.getElementById(this.id);
81+
const moreInfoBtn = prjItemElement.querySelector('button:first-of-type');
82+
moreInfoBtn.addEventListener('click', this.showMoreInfoHandler);
83+
}
84+
85+
connectSwitchButton(type) {
86+
const prjItemElement = document.getElementById(this.id);
87+
let switchBtn = prjItemElement.querySelector('button:last-of-type');
88+
switchBtn = DOMHelper.clearEventListeners(switchBtn);
89+
switchBtn.textContent = type === 'active' ? 'Finish' : 'Activate';
90+
switchBtn.addEventListener('click', this.updateProjectListHandler.bind(null, this.id));
91+
}
92+
93+
update(updateProjectListFn, type) {
94+
this.updateProjectListHandler = updateProjectListFn;
95+
this.connectSwitchButton(type);
96+
}
97+
}
98+
99+
class ProjectList {
100+
projects = [];
101+
102+
constructor(type) {
103+
this.type = type;
104+
const prjItems = document.querySelectorAll(`#${type}-projects li`);
105+
for (const prjItem of prjItems) {
106+
this.projects.push(new ProjectItem(prjItem.id, this.switchProject.bind(this), this.type));
107+
}
108+
}
109+
110+
setSwitchHandlerFunction(switchHandlerFunction) {
111+
this.switchHandler = switchHandlerFunction;
112+
}
113+
114+
addProject(project) {
115+
this.projects.push(project);
116+
DOMHelper.moveElement(project.id, `#${this.type}-projects ul`);
117+
project.update(this.switchProject.bind(this), this.type);
118+
}
119+
120+
switchProject(projectId) {
121+
// adding project to another bucket
122+
this.switchHandler(this.projects.find(p => p.id === projectId));
123+
124+
// remove project
125+
// One way to do it
126+
// const projectIndex = this.projects.findIndex(p => p.id === projectId);
127+
// this.projects.splice(projectIndex, 1);
128+
129+
// Another way of removing the project
130+
this.projects = this.projects.filter(p => p.id !== projectId);
131+
}
132+
}
133+
134+
class App {
135+
static init(){
136+
const activeProjectsList = new ProjectList('active');
137+
const finishedProjectsList = new ProjectList('finished');
138+
activeProjectsList.setSwitchHandlerFunction(finishedProjectsList.addProject.bind(finishedProjectsList));
139+
finishedProjectsList.setSwitchHandlerFunction(activeProjectsList.addProject.bind(activeProjectsList));
140+
}
141+
}
142+
143+
App.init();
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
* {
2+
box-sizing: border-box;
3+
}
4+
5+
html {
6+
font-family: sans-serif;
7+
}
8+
9+
body {
10+
margin: 0;
11+
}
12+
13+
#main-header {
14+
width: 100%;
15+
height: 6rem;
16+
display: flex;
17+
justify-content: center;
18+
align-items: center;
19+
background: #ff0062;
20+
}
21+
22+
#main-header h1 {
23+
color: white;
24+
margin: 0;
25+
}
26+
27+
footer {
28+
position: absolute;
29+
bottom: 0;
30+
left: 0;
31+
width: 100%;
32+
text-align: center;
33+
}
34+
35+
ul {
36+
list-style: none;
37+
margin: 0;
38+
padding: 0;
39+
}
40+
41+
li {
42+
margin: 1rem 0;
43+
}
44+
45+
section {
46+
margin: 1rem auto;
47+
width: 40rem;
48+
max-width: 90%;
49+
}
50+
51+
section ul {
52+
padding: 1rem;
53+
max-height: 20rem;
54+
overflow: scroll;
55+
}
56+
57+
section > h2 {
58+
color: white;
59+
margin: 0;
60+
}
61+
62+
button {
63+
font: inherit;
64+
background: #ff0062;
65+
color: white;
66+
border: 1px solid #ff0062;
67+
padding: 0.5rem 1.5rem;
68+
cursor: pointer;
69+
}
70+
71+
button.alt {
72+
background: white;
73+
color: #ff0062;
74+
}
75+
76+
button:focus {
77+
outline: none;
78+
}
79+
80+
button:hover,
81+
button:active {
82+
background: #ff2579;
83+
border-color: #ff2579;
84+
color: white;
85+
}
86+
87+
.card {
88+
border-radius: 10px;
89+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.26);
90+
padding: 1rem;
91+
background: white;
92+
}
93+
94+
#active-projects {
95+
border: 1px solid #870099;
96+
}
97+
98+
#active-projects > header {
99+
background: #870099;
100+
padding: 1rem;
101+
display: flex;
102+
justify-content: space-between;
103+
align-items: center;
104+
}
105+
106+
#active-projects header h2 {
107+
color: white;
108+
margin: 0;
109+
}
110+
111+
#finished-projects {
112+
border: 1px solid #535353;
113+
}
114+
115+
#finished-projects > header {
116+
background: #535353;
117+
padding: 1rem;
118+
display: flex;
119+
justify-content: space-between;
120+
align-items: center;
121+
}
122+
123+
#finished-projects header h2 {
124+
color: white;
125+
margin: 0;
126+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
7+
<title>Project Board</title>
8+
<link rel="stylesheet" href="assets/styles/app.css" />
9+
<script src="assets/scripts/app.js" defer></script>
10+
</head>
11+
<body>
12+
<!-- Consider this page renders after some action and response was sent by backend and we will now practice what we've learnt -->
13+
<header id="main-header">
14+
<h1>Project Planner</h1>
15+
</header>
16+
<section id="active-projects">
17+
<header>
18+
<h2>Active Projects</h2>
19+
</header>
20+
<ul>
21+
<li
22+
id="p1"
23+
data-extra-info="Got lifetime access, but would be nice to finish it soon!"
24+
class="card"
25+
>
26+
<h2>Finish the Course</h2>
27+
<p>Finish the course within the next two weeks.</p>
28+
<button class="alt">More Info</button>
29+
<button>Finish</button>
30+
</li>
31+
<li
32+
id="p2"
33+
data-extra-info="Not really a business topic but still important."
34+
class="card"
35+
>
36+
<h2>Buy Groceries</h2>
37+
<p>Don't forget to pick up groceries today.</p>
38+
<button class="alt">More Info</button>
39+
<button>Finish</button>
40+
</li>
41+
</ul>
42+
</section>
43+
<section id="finished-projects">
44+
<header>
45+
<h2>Finished Projects</h2>
46+
</header>
47+
<ul>
48+
<li
49+
id="p3"
50+
data-extra-info="Super important conference! Fictional but still!"
51+
class="card"
52+
>
53+
<h2>Book Hotel</h2>
54+
<p>
55+
Academind conference takes place in December, don't forget to book a
56+
hotel.
57+
</p>
58+
<button class="alt">More Info</button>
59+
<button>Activate</button>
60+
</li>
61+
</ul>
62+
</section>
63+
</body>
64+
</html>

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
- [More on Objects](More-on-Objects/README.md)
1212
- [Classes and Object Oriented Programming (OOP)](Classes-and-Object-Oriented-Programming/README.md)
1313
- [Constructor Functions and Prototypes](Constructor-Functions-and-Prototypes/README.md)
14+
- [Practice - OOPs, Classes and DOM](Practice-OOPs_Classes_and_DOM/)
1415

1516
## References
1617

0 commit comments

Comments
 (0)