Skip to content

Instantly share code, notes, and snippets.

@mnichols08
Last active March 16, 2024 00:48
Show Gist options
  • Save mnichols08/9d7593c55fd2f468a1e41fbb4e1e3e4f to your computer and use it in GitHub Desktop.
Save mnichols08/9d7593c55fd2f468a1e41fbb4e1e3e4f to your computer and use it in GitHub Desktop.
Stage 3/3 of MVC Example
// Define a Controller class
class Controller {
// Initialize the controller
init = () => {
// Initialize the view
app.view.init();
// Add a click event listener to the title that calls the editTitle method
app.view.element
.querySelector("h1")
.addEventListener("click", (e) => app.view.editTitle(e));
// Add a click event listener to the increment button that calls the view's increment method
app.view.element
.querySelector("button#increment")
.addEventListener("click", app.view.increment);
// Add a click event listener to the reset button that calls the view's reset method
app.view.element
.querySelector("button#reset")
.addEventListener("click", app.controller.resetState);
};
// Save the title and make it non-editable
setTitle = (title) => {
app.state.title = title;
app.view.updateTitle();
};
// Increment the count and update the view
incrementCount = () => {
app.state.count++;
app.view.updateCount();
};
// Reset the state and view
resetState = () => {
(app.state = { title: "Hello World!", count: 0 }), app.view.resetView();
};
}
// Define a View class
class View {
// Constructor for the View class
constructor(tag, innerHTML, parentElement) {
// Create a new HTML element with the given tag
this.element = document.createElement(tag);
// Set the inner HTML of the element to the given HTML
this.element.innerHTML = innerHTML;
// Append the new element to the given parent element
parentElement.append(this.element);
}
// Initialize the view
init = () => {
// Create a new View instance
new View(
"main",
`
<h1>${app.state.title}</h1>
<h2>Welcome to the app.</h2>
<p>Click the title to edit it.</p>
<p> or </p>
<p>Click the button to increase the count.</p>
<h3>Count:</h3>
<p id="count">${app.state.count}</p>
<button id="increment">Click me</button>
<button id="reset">Reset</button>
`,
this.element
);
};
// Update the title in the view
updateTitle = () =>
(app.view.element.querySelector("h1").innerText = app.state.title);
// Reset the view and re-initialize it
resetView = () => {
app.view.element.innerHTML = "";
app.controller.init();
};
// Increment the count
increment = () => app.controller.incrementCount();
// Update the count in the view
updateCount = () =>
(app.view.element.querySelector("#count").innerText = app.state.count);
// Make the title editable when it's clicked
editTitle = (e) => {
const title = e.target;
title.contentEditable = true;
title.focus();
// Set the title when Enter is pressed
title.addEventListener("keypress", (e) => {
if (e.key === "Enter") {
title.contentEditable = false;
app.controller.setTitle(title.innerText);
}
});
// Set the title when it loses focus
title.addEventListener("blur", () => {
app.controller.setTitle(title.innerText);
title.contentEditable = false;
});
};
}
// Define a Model class
class Model {
// Constructor for the Model class
constructor() {
// Initialize the state with a title and count
this.state = {
title: "Hello World!",
count: 0
};
// Create a new View instance with a div element, no inner HTML, and append it to the body of the document
this.view = new View("div", "", document.body);
// Create a new Controller instance and pass the view instance to it
this.controller = new Controller(this.view);
}
}
// Create a new instance of the Model class and assign it to the constant "app"
const app = new Model();
// Call the init method on the controller property of the app instance
// This initializes the view and adds event listeners to the HTML elements
document.onload = app.controller.init();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Model View Controller Exercise</title>
<link rel="stylesheet" href="./styles.css">
<script src="./app.js" defer></script>
</head>
<body>
<noscript>
<h1>Sorry, but JavaScript must be enable to view this application.</h1>
</noscript>
</body>
</html>
body {
background: linear-gradient(45deg, #080404, #020606);
height: 100%;
color: #fff;
text-align: center;
font-family: monospace;
}h1 {
font-size: 2.5em;
font-weight: bold;
color: #FF6347;
text-shadow: 2px 2px 4px #000000;
}
h3 {
display: inline-block;
}
p:nth-of-type(2),p:nth-of-type(4){
display: inline;
}
p {
font-size: 1.2em;
line-height: 1.6;
color: #ddd;
text-align: justify;
margin: 0 auto;
max-width: 800px;
}
button {
background-color: #4CAF50;
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin: 4px 2px;
transition-duration: 0.4s;
cursor: pointer;
transition: all .2s;
}
button:hover {
background-color: #473599;
color: white;
transform: scale(1.1) rotate3d(1, 1, 1, -10deg) translate(10px, 10px);
border-radius: 10px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment