Skip to content

Commit 3c8bcb4

Browse files
committed
Finish comments
1 parent 6a0f296 commit 3c8bcb4

File tree

4 files changed

+84
-75
lines changed

4 files changed

+84
-75
lines changed

public/css/style.css

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
/* Style <h1> elements with a text color of red */
12
h1{
23
color: red;
34
}
5+
/* Style elements with a class of `completed` with a text color of grey and text-decoration of line-through (strikethrough) */
46
.completed{
57
color: gray;
68
text-decoration: line-through;

public/js/main.js

+21-17
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,69 @@
1-
// get all the DOM elements with a class of `fa-trash` and assign the NodeList to deleteBtn
1+
// Assign a NodeList of all HTMLElements with a class of `fa-trash` to the constant variable `deleteBtn`
22
const deleteBtn = document.querySelectorAll('.fa-trash')
3-
// get all of the DOM elements that are spans and descendants of elements with a class of `item`, and assign to the item variable
3+
// Assign a NodeList of all HTMLElements that are <span>s and descendants of elements with a class of `item` to the constant variable `item`
44
const item = document.querySelectorAll('.item span')
5-
// get all of the DOM elements that are spans with a class of `completed` and are descendants of elements with a class of `item`, assigning them to the `itemCompleted` variable.
5+
// Assign a NodeList of all HTMLElements that are <span>s with a class of `completed` and descendants of elements with a class of `item` to the constant variable `itemCompleted`
66
const itemCompleted = document.querySelectorAll('.item span.completed')
77

8-
// convert deleteBtn NodeList to an array, then call .forEach on the array
8+
// Convert `deleteBtn` to an array of HTMLElements, then call `forEach` on it
99
Array.from(deleteBtn).forEach((element)=>{
10-
// adding the deleteItem function as a click event listener for each item in deleteBtn
10+
// Add an click event listener to each element, calling `deleteItem`
1111
element.addEventListener('click', deleteItem)
1212
})
1313

14-
//creating an array form the nodelist assigned to item. looping through it and adding an event listener to each element that will
15-
//'listen' for a click and passing the function "markComplete"
14+
// Convert `item` to an array of HTMLElements, then call `forEach` on it
1615
Array.from(item).forEach((element)=>{
16+
// Add an click event listener to each element, calling `markComplete`
1717
element.addEventListener('click', markComplete)
1818
})
19-
//creating an array form the nodelist assigned to itemCompleted. looping through it and adding an event listener to each element that will
20-
//'listen' for a click and passing the function "markUnComplete"
19+
20+
// Convert `itemCompleted` to an array of HTMLElements, then call `forEach` on it
2121
Array.from(itemCompleted).forEach((element)=>{
22+
// Add an click event listener to each element, calling `markUnComplete`
2223
element.addEventListener('click', markUnComplete)
2324
})
2425

25-
2626
async function deleteItem(){
27+
// From the current <span> (bound to this by the event listener), get the parentNode - the <li> - then get the 1th childNode - the <span>, then retrieve the text content of it by reading the `innerText` property
2728
const itemText = this.parentNode.childNodes[1].innerText
2829
try{
30+
// Make a fetch to the relative path `deleteItem`
2931
const response = await fetch('deleteItem', {
32+
// Set method of request to DELETE
3033
method: 'delete',
34+
// Set header `Content-Type` to `application/json` so it knows we're sending JSON, and how to parse our data
3135
headers: {'Content-Type': 'application/json'},
36+
// Send the object with a property of itemFromJS and value of the `itemText` of the current item as a JSON string
3237
body: JSON.stringify({
3338
'itemFromJS': itemText
3439
})
3540
})
41+
// Attempt to load and parse the response body as JSON, assigning it to data
3642
const data = await response.json()
3743
console.log(data)
44+
// Reload the webpage
3845
location.reload()
3946

4047
}catch(err){
48+
// If there are any errors, console.log them
4149
console.log(err)
4250
}
4351
}
4452

4553
async function markComplete(){
46-
// get the innerText of the <span>
4754
const itemText = this.parentNode.childNodes[1].innerText
4855
try{
49-
// make fetch to markComplete path
56+
// Make a fetch to the relative path `markComplete`
5057
const response = await fetch('markComplete', {
51-
// set request method to PUT
58+
// Set method of request to PUT
5259
method: 'put',
53-
// set Content-Type header to application/json - so it knows we're sending JSON
5460
headers: {'Content-Type': 'application/json'},
55-
// send the object with a property of itemFromJS and value of the itemText of the current item as a string of JSON
5661
body: JSON.stringify({
5762
'itemFromJS': itemText
5863
})
5964
})
60-
// attempt to load and parse the response body as JSON, assigning it to data
6165
const data = await response.json()
6266
console.log(data)
63-
// reload the webpage
6467
location.reload()
6568

6669
}catch(err){
@@ -72,6 +75,7 @@ async function markComplete(){
7275
async function markUnComplete(){
7376
const itemText = this.parentNode.childNodes[1].innerText
7477
try{
78+
// Make a fetch to the relative path `markUnComplete`
7579
const response = await fetch('markUnComplete', {
7680
method: 'put',
7781
headers: {'Content-Type': 'application/json'},

server.js

+40-43
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,99 @@
1-
// assign the express module to the imported module express
1+
// Assign the imported `express` module to the constant variable `express`
22
const express = require('express')
3-
// create a new express application, assigned to the app variable
3+
// Assign the newly created express application to the constant variable `app`
44
const app = express()
5-
// Require the mongodb module, to connect to the database
5+
// Assign the MongoClient class that's attached to the `connect` method exported by the `mongodb` module to the constant variable `MongoClient`
66
const MongoClient = require('mongodb').MongoClient
7-
8-
// set the port variable that we're giong to listen for
7+
// Assign the default port number `2121` to the constant variable `PORT`
98
const PORT = 2121
10-
// import the dotenv module and call the config method, which reads from the .env file nearby and adds them all to process.env
9+
// Call the `config` method on the imported `dotenv` module, loading the environment variables from the `.env` file into `process.env`
1110
require('dotenv').config()
1211

13-
//we are declaring three variables here: db, connectionstr and dbname and initializing two of them.
14-
//dbconnectionstring holds the value of the enviroment variable we set up in .env as DB_STRING
15-
//dbname holds the string todo.
12+
13+
// Declare three mutable variables, `db` to store the Db class instance, `connectionString` to store the connection string read from the `DB_STRING` environment variable, and `dbName` to store the name of the database we want to use.
1614
let db,
1715
dbConnectionStr = process.env.DB_STRING,
1816
dbName = 'todo'
1917

20-
//we are using the connect method in the mongoclient (imported above) and passing our db string(initialized above as dbconnectionstr)
21-
//we are passing the useunifiedtopology (deprecated, it's default as true in newer versions of mongo) and setting it as true
22-
//after this connection is completed(is a promise) we are console logging to know we are actually connected (and showing the dbname with template literals)
23-
//finally, we are initializing the db variable
18+
// Call the static `connect` method on the `MongoClient` class, passing the `dbConnectionStr` and an options object with the `useUnifiedTopology` property set to `true` to use the new Server Discover and Monitoring engine.
2419
MongoClient.connect(dbConnectionStr, { useUnifiedTopology: true })
20+
// As no callback is provided, the `connect` method returns a Promise that will resolve to a `MongoClient` instance, so use the .then method to execute our callback with the said `MongoClient`.
2521
.then(client => {
22+
// Console log the connection string, notifying the user that we are connected to the database.
2623
console.log(`Connected to ${dbName} Database`)
24+
// Assign the desired `Db` instance - returned by the `db` method on the `MongoClient` instance - to the `db` variable.
2725
db = client.db(dbName)
2826
})
29-
30-
//setting the templating engine to use ejs
27+
28+
// Call the `set` method of our express application, settings the default engine extension, allowing us to omit said extension when specifying view names.
3129
app.set('view engine', 'ejs')
32-
//setting the static files location to the public folder
30+
// Add the `serve-static` middleware to our express application, serving any files requested from the root found in the `public` directory.
3331
app.use(express.static('public'))
34-
// using express urlencoded to enable express grab data from the form element by adding it to the request body property, setting the extended option to true to allow for object & array support
32+
// Add the `body-parser` `urlencoded` middleware to our express application, parsing the content of any requests with a `Content-Type` of `application/x-www-form-urlencoded` to a JavaScript object assigned to the request `body` property - additionally setting the `extended` property to `true` within the options object to allow for nested objects via the `qs` module.
3533
app.use(express.urlencoded({ extended: true }))
36-
37-
// this allows us to be able to use express
34+
// Add the `body-parser` `json` middleware to our express application, parsing the content of any requests with a `Content-Type` of `application/json` to a JavaScript object assigned to the request `body` property.
3835
app.use(express.json())
3936

40-
// this is the GET request where we're going to read (get something back) the items in the todo list
41-
app.get('/', async (request, response)=>{
42-
// access collection called 'todos' from connected database and find all documents, as an array, then await the promise, assigning the documents to todoItems
37+
38+
// Add a custom request handler to the `GET` method of the `/` path
39+
app.get('/',async (request, response)=>{
40+
// Access the `todos` collection from the connected database, calling `find` with no filter object to retrieve all the documents, and finally call `toArray` to turn this query into a Promise that will resolve with an array of document objects.
4341
const todoItems = await db.collection('todos').find().toArray()
44-
// access collection named 'todos' from connected database and get the count of all documents that match the filter - have an property of completed with a value of false, awaiting this promise and assigning to itemsLeft
42+
// Access the `todos` collection from the connected database, calling `countDocuments` with a filter to only include documents that have a `completed` property set to `false`.
4543
const itemsLeft = await db.collection('todos').countDocuments({completed: false})
46-
// tell express to tell EJS to render index.ejs with this object - which EJS will make into variables
44+
// Tell express to render the `index.ejs` view with the options of the `todoItems` and `itemsLeft` variables, which EJS will use as variables in the view.
4745
response.render('index.ejs', { items: todoItems, left: itemsLeft })
4846
// db.collection('todos').find().toArray()
49-
// .then(todoItems => {
47+
// .then(data => {
5048
// db.collection('todos').countDocuments({completed: false})
5149
// .then(itemsLeft => {
52-
// response.render('index.ejs', { items: todoItems, left: itemsLeft })
50+
// response.render('index.ejs', { items: data, left: itemsLeft })
5351
// })
5452
// })
5553
// .catch(error => console.error(error))
5654
})
5755

58-
59-
//using POST request (create) to add items in the todo list
56+
// Add a custom request handler to the `POST` method of the `/addTodo` path
6057
app.post('/addTodo', (request, response) => {
61-
//selecting our collection here and indicating that we are inserting one item (obj) with the key properties "thing" and 'completed', assigning the values of the todoItem
62-
//(taken from the body of the request) and the boolean false
58+
// Access the `todos` collection from the connected database, calling `insertOne` with an object containing the properties `thing` and `completed` set to the values of the `request.body.todoItem` - parsed by the `urlencoded` middleware - and `false` respectively.
6359
db.collection('todos').insertOne({thing: request.body.todoItem, completed: false})
64-
//once the previous promise is completed, we console log a message and redirect to /
60+
// After the insertion is successful, redirect the user to the `/` path.
6561
.then(result => {
6662
console.log('Todo Added')
6763
response.redirect('/')
6864
})
69-
//if the promise was rejected, we log the error
65+
// If the insertion fails, log the error to the console.
7066
.catch(error => console.error(error))
7167
})
7268

73-
74-
//PUT request (update) to update one item in the todo list
69+
// Add a custom request handler to the `POST` method of the `/markComplete` path
7570
app.put('/markComplete', (request, response) => {
76-
//selecting the 'todos' collection of our db and updating one item(object: key= thing, value= itemFromJs)
71+
// Access the `todos` collection from the connected database, calling `updateOne` with a filter object containing the property `thing` set to the value of the `request.body.itemFromJS` property - parsed by the `json` middleware
7772
db.collection('todos').updateOne({thing: request.body.itemFromJS},{
78-
//we are using the $set operator from mongo to change the completed key to true
73+
// UpdateFilter containing the `$set` Update Operator, telling MongoDB to setting the `completed` property to `true`.
7974
$set: {
8075
completed: true
8176
}
8277
},{
83-
//using the mongo sort method to sort by id. -1 means that we are getting the latest first (descending order)
78+
// Attempt to sort the document _id's descending to get the latest document first - this works because the `_id` is a `ObjectId` and these contain the second they were created encoded within them.
8479
sort: {_id: -1},
85-
//setting the upsert (insert + update) mongo method to false (which is the default value)
80+
// Disable the upsert - if the document does not exist, do not create it - this is
8681
upsert: false
8782
})
88-
//when this promise is completed, we console log 'marked as completed' and send the same as json.
83+
// After the update is successful, redirect the user to the `/` path.
8984
.then(result => {
9085
console.log('Marked Complete')
9186
response.json('Marked Complete')
9287
})
93-
//if the promise was rejected, we log the error
88+
// If the update fails, log the error to the console.
9489
.catch(error => console.error(error))
9590

9691
})
9792

93+
// Add a custom request handler to the `PUT` method of the `/markUnComplete` path
9894
app.put('/markUnComplete', (request, response) => {
9995
db.collection('todos').updateOne({thing: request.body.itemFromJS},{
96+
// UpdateFilter containing the `$set` Update Operator, telling MongoDB to setting the `completed` property to `false`.
10097
$set: {
10198
completed: false
10299
}
@@ -112,9 +109,9 @@ app.put('/markUnComplete', (request, response) => {
112109

113110
})
114111

115-
// DE-LAY-TAY handler at `/deleteItem` that deletes a todo document from the collection
112+
// Add a custom request handler to the `DELETE` method of the `/deleteTodo` path
116113
app.delete('/deleteItem', (request, response) => {
117-
// accessing the 'todos' collection, delete one document that matches the filter, has an property of thing equal to itemFromJS
114+
// Access the `todos` collection from the connected database, calling `deleteOne` with a filter object containing the property `thing` set to the value of the `request.body.itemFromJS` property - parsed by the `json` middleware - to delete the first document that matches the filter.
118115
db.collection('todos').deleteOne({thing: request.body.itemFromJS})
119116
.then(result => {
120117
console.log('Todo Deleted')
@@ -124,7 +121,7 @@ app.delete('/deleteItem', (request, response) => {
124121

125122
})
126123

127-
// listen to the port that we established in the variable or the port that is available with heroku, for example
124+
// Start the server listening on either the PORT provided via environment variable or the default port stored in the PORT variable.
128125
app.listen(process.env.PORT || PORT, ()=>{
129126
console.log(`Server running on port ${PORT}`)
130127
})

views/index.ejs

+21-15
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,56 @@
1-
<!-- set doctype to HTML5 to disable quarks mode, telling browsers we are following the HTML5 spec-->
1+
<!-- Declare browsers that the latest HTML specification is being followed, and not to enable quarks mode -->
22
<!DOCTYPE html>
3-
<!-- set page language to en -->
3+
<!-- Declare document language as `en` -->
44
<html lang="en">
55
<head>
6-
<!-- set character encoding to UTF-8 -->
6+
<!-- Declare character encoding as `UTF-8` - the only possible value -->
77
<meta charset="UTF-8">
8+
<!-- Tell Microsoft browsers which version of Internet Explorer the document should be rendered as -->
89
<meta http-equiv="X-UA-Compatible" content="IE=edge">
9-
<!-- set width to device width and make mobile responsive -->
10+
<!-- Declare the width and initial scale (zoom level) of the viewport, as the full width of the device and 1.0 accordingly -->
1011
<meta name="viewport" content="width=device-width, initial-scale=1.0">
11-
<!-- set bookmark/tab title of the page-->
12-
<title>voice-01 Todo List App</title>
12+
<!-- Declare the document title, used in the title bar, bookmarks, etc -->
13+
<title>Document</title>
14+
<!-- Link to Font Awesome stylesheet -->
15+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
16+
<!-- Link to local stylesheet -->
17+
<link rel="stylesheet" href="css/style.css">
1318
</head>
1419
<body>
1520
<h1>Todo List: </h1>
16-
<!-- unorded list with a class of todoItems -->
21+
<!-- Unordered list with a class of `todoItems` -->
1722
<ul class="todoItems">
18-
<!-- loop through every mongodb document in the items array -->
23+
<!-- Loop through every object in the `items` array -->
1924
<% for(let i=0; i < items.length; i++) {%>
20-
<!-- create list item with class of item-->
25+
<%# List item with class of `item` %>
2126
<li class="item">
22-
<!-- if current item has a completed property that equals true, add a class of 'completed'-->
27+
<%# Create span containing text of current item `thing`, with optional class of `completed` if the current item `completed` property is equal to `true` %>
2328
<% if(items[i].completed === true) {%>
2429
<span class='completed'><%= items[i].thing %></span>
2530
<% }else{ %>
2631
<span><%= items[i].thing %></span>
2732
<% } %>
28-
<!-- font awesome trashcan icon -->
33+
<%# Font Awesome Trash icon %>
2934
<span class='fa fa-trash'></span>
3035
</li>
3136
<% } %>
3237
</ul>
3338

34-
<!-- output the content of left, the number of todo documents that have a completed property of false -->
39+
<!-- Output the value of left into the page -->
3540
<h2>Left to do: <%= left %></h2>
3641

3742
<h2>Add A Todo:</h2>
3843

39-
<!-- form that will make a POST request to /addTodo when submitted -->
44+
<!-- Form that will make a `POST` request to `/addTodo` when submitted -->
4045
<form action="/addTodo" method="POST">
41-
<!-- text input field with placeholder (grey text) of Thing To Do and a name of todoItem, which will become the key of the request body object-->
46+
<!-- Text input field with `placeholder` of `Thing To Do` and `name` of `todoItem`, which will become the key when the value is transmitted -->
4247
<input type="text" placeholder="Thing To Do" name="todoItem">
43-
<!-- submit button -->
48+
<!-- Submit button -->
4449
<input type="submit">
4550
</form>
4651

4752

53+
<!-- Link to local JavaScript file -->
4854
<script src='js/main.js'></script>
4955
</body>
5056
</html>

0 commit comments

Comments
 (0)