Annie's Dev Diary - TheEvergreenStateCollege/upper-division-cs-23-24 GitHub Wiki
Placeholder text (sua trang nay them cua chi la duoc, nhan cai nut edit ben goc phai tren cung ay, sua xong thi nhan nut save page mau xanh la o goc phai duoi cung la duoc)
Great start, Annie (em co gang cho ket qua thanh cong nhe.)
let buffer = "0"; let runningTotal = 0; let previousOperator = null; const screen = document.querySelector('.screen');
- buffer: Holds the current input value as a string.
- runningTotal: Keeps track of the cumulative total during calculations.
- previousOperator: Stores the last operator used in the calculation.
- screen: References the HTML element where the output is displayed.
------buttonClick------
function buttonClick(value) { console.log(value); if (isNaN(parseInt(value))) { handleSymbol(value); } else { handleNumber(value); } rerender(); }
- If the clicked value is symbol, it ==> handleSymbol.
- If the clicked value is a number, it ==> handleNumber.
- After that, it updates the display by calling rerender.
--------handleNumber-------
function handleNumber(number) { if (buffer === "0") { buffer = number; } else { buffer += number; } }
- If the buffer is "0", it replaces it with the clicked number.
- Otherwise, it appends the clicked number to the buffer.
--------handleSymbol-------
function handleSymbol(symbol) { switch (symbol) { case "AC": buffer = "0"; break; case '=': if (previousOperator === null) { return; } flushOperation(parseInt(buffer)); previousOperator = null; buffer = String(runningTotal); runningTotal = 0; break; case "Del": if (buffer.length === 1) { buffer = '0'; } else { buffer = buffer.substring(0, buffer.length - 1); } break; case '+': case '-': case '/': case 'x': handleMath(symbol); break; } }
- AC: clear the calc by resetting the buffer to "0".
- = : computes the result using the last operator, updates the buffer, or resets the running total.
- Del: deletes the last digit from the buffer.
- (+, -, x, /): calls func handleMath to initiate the mathematical operation.
------handleMath--------
function handleMath(value) { if (buffer === "0") { return; } const intBuffer = parseInt(buffer); if (runningTotal === 0) { runningTotal = intBuffer; } else { flushOperation(intBuffer); } previousOperator = value; buffer = "0"; }
- If the buffer is not zero, it converts the buffer to an integer by using parseInt.
- It updates the running total based on the previous operator and current buffer.
- Sets the previousOperator to the clicked operator and resets the buffer.
-----flushOperation-------
function flushOperation(intBuffer) { if (previousOperator === '+') { runningTotal += intBuffer; } else if (previousOperator === '-') { runningTotal -= intBuffer; } else if (previousOperator === 'x') { runningTotal *= intBuffer; } else { runningTotal /= intBuffer; } }
Checks the value of the previousOperator:
- If it's '+', it adds the intBuffer to the runningTotal.
- If it's '-, it subtracts the intBuffer from the runningTotal.
- If it's 'x', it multiplies the runningTotal by the intBuffer.
- If it's /, it divides the runningTotal by the intBuffer.
-------rerender-------
function rerender() { screen.innerText = buffer; }
The func rerender calls, the display would show the current buffer. Like if I press the button number 1, the buffer would update to number 1, then call the func rerender, and it sets the screen.innerText to number 1.
-------------init---------
function init() { document.querySelector('.calc-buttons').addEventListener("click", function(event) { buttonClick(event.target.innerText); }); } init();
When a button inside this element is clicked, the func buttonClick is called with the inner text of the clicked button as an argument. The func init is called to set up the event listener when the script is loaded. This allows the calculator to respond to button clicks and perform calculations.
This project is to create a word guessing game where the player has six attempts to guess a five-letter word, with feedback provided on each guess. The game initializes correctly, handles user input, validates guesses, and updates the display. Further improvements could include enhancing the UI and adding additional features such as difficulty levels or a hint system.
---------Initial Setup and Global Variables-------------
-
Define the global constants and select necessary HTML elements.
-
Defined
ANSWER_LENGTH
andROUNDS
to set the game parameters. -
Selected all letter elements and the loading indicator from the DOM:
const ANSWER_LENGTH = 5; const ROUNDS = 6; const letters = document.querySelectorAll(".scoreboard-letter"); const loadingDiv = document.querySelector(".info-bar");
- Successfully set up the initial game parameters and DOM references.
----------- Fetching the Word of the Day--------------
-
Implement functions to fetch and validate words.
-
Created
fetchWord
to get the word of the day from the API:async function fetchWord() { const res = await fetch("https://words.dev-apis.com/word-of-the-day"); const { word: wordRes } = await res.json(); return wordRes.toUpperCase(); }
-
Created
validateWord
to check if a guessed word is valid:async function validateWord(word) { const res = await fetch("https://words.dev-apis.com/validate-word", { method: "POST", body: JSON.stringify({ word }), }); const { validWord } = await res.json(); return validWord; }
- Implemented functions to fetch and validate words.
-----------Initialization and Loading--------
-
Wrote the
init
function to set up the game state and start the game:`async function init() { let currentRow = 0; let currentGuess = ""; let done = false; let isLoading = true;
try { const word = await fetchWord(); const wordParts = word.split(""); isLoading = false; setLoading(isLoading); // Additional setup and event listeners here } catch (error) { console.error("Error occurred during initialization:", error); isLoading = false; setLoading(isLoading); } } init();`
-
Implemented
setLoading
to toggle the loading indicator:function setLoading(isLoading) { loadingDiv.classList.toggle("hidden", !isLoading); }
- The game initializes correctly and handles loading state.
---------Handling User Input and Display Updates----------
-
Created
addLetter
to manage letter input:function addLetter(letter) { currentGuess += letter; if (currentGuess.length > ANSWER_LENGTH) { currentGuess = currentGuess.slice(0, ANSWER_LENGTH); } updateLettersDisplay(); }
-
Created
backspace
to handle backspace key:function backspace() { currentGuess = currentGuess.slice(0, -1); updateLettersDisplay(); }
-
Created
updateLettersDisplay
to update the display with the current guess:function updateLettersDisplay() { for (let i = 0; i < currentGuess.length; i++) { letters[currentRow * ANSWER_LENGTH + i].innerText = currentGuess[i]; } }
- Implemented user input handling and display update functions.
-------Committing a Guess and Providing Feedback--------
-
Created
commit
to process and validate the guess:`async function commit() { if (currentGuess.length !== ANSWER_LENGTH) { return; }
isLoading = true; setLoading(isLoading);
try { const validWord = await validateWord(currentGuess); isLoading = false; setLoading(isLoading);
if (!validWord) { markInvalidWord(); return; } const guessParts = currentGuess.split(""); const map = makeMap(wordParts); let allRight = true; for (let i = 0; i < ANSWER_LENGTH; i++) { if (guessParts[i] === wordParts[i]) { letters[currentRow * ANSWER_LENGTH + i].classList.add("correct"); map[guessParts[i]]--; } } for (let i = 0; i < ANSWER_LENGTH; i++) { if (guessParts[i] === wordParts[i]) { // do nothing } else if (map[guessParts[i]] && map[guessParts[i]] > 0) { allRight = false; letters[currentRow * ANSWER_LENGTH + i].classList.add("close"); map[guessParts[i]]--; } else { allRight = false; letters[currentRow * ANSWER_LENGTH + i].classList.add("wrong"); } } currentRow++; currentGuess = ""; if (allRight) { alert("You Won!!"); document.querySelector(".brand").classList.add("winner"); done = true; } else if (currentRow === ROUNDS) { alert(`You lose, the word was ${word}`); done = true; }
} catch (error) { console.error("Error occurred during word validation:", error); isLoading = false; setLoading(isLoading); } }`
- Successfully processes guesses, validates them, and updates the UI with feedback.
-------Add utility Functions and Event Listeners-------
-
Created
makeMap
to count letter occurrences:function makeMap(array) { const obj = {}; for (let i = 0; i < array.length; i++) { if (obj[array[i]]) { obj[array[i]]++; } else { obj[array[i]] = 1; } } return obj; }
-
Created
isLetter
to check if a character is a letter:function isLetter(letter) { return /^[a-zA-Z]$/.test(letter); }
-
Set up event listeners for key presses:
document.addEventListener("keydown", function handleKeyPress(event) { if (done || isLoading) { return; } const action = event.key; if (action === "Enter") { commit(); } else if (action === "Backspace") { backspace(); } else if (isLetter(action)) { addLetter(action.toUpperCase()); } });
- Added utility functions and configured key event listeners.
------------ theme.js----------- This script handles the functionality to toggle between dark and light modes on a web page. Initialize Document Element:
- The
doc
variable is set to the document's root element usingdocument.documentElement
. This typically refers to the<html>
element of the document.
const doc = document.documentElement;
** Define toggleDarkMode
Func **:
- This func changes the theme of the webpage when it is called. ** Get the Current Theme **:
- The current value of the
data-theme
attribute from the document root.
const currentTheme = doc.getAttribute('data-theme');
```
** Determine the New Theme **:
- It checks if the current theme is 'dark'. If it is, the new theme will be 'light'. Otherwise, it will be 'dark'.
```javascript
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
```
**Update the Theme**:
- It sets the `data-theme` attribute to the new theme, toggling between 'dark' and 'light'.
```javascript
doc.setAttribute('data-theme', newTheme);
```
**Get Toggle Element**:
- The `toggle` variable is set to the element with the ID `toggle`. This is likely a checkbox or a similar control element that will be used to toggle the theme.
```javascript
const toggle = document.getElementById('toggle');
Add Event Listener to Toggle Element:
- An event listener is added to the
toggle
element. When the element's value changes (like checkbox is checked or unchecked), thetoggleDarkMode
function is called.
toggle.addEventListener("change", toggleDarkMode);
----------------modal.js---------------
This script defines two classes, Form
and Modal
, which together handle the creation and display of a modal dialog with a form inside it.
Define Form
Class:
- This class creates a form element with a heading and a close button.
--
element
: A form element. --heading
: Anh2
element for the form title. --closeButton
: A button element to close the form.
class Form {
element = document.createElement('form');
heading = document.createElement('h2');
closeButton = document.createElement('button');
- The constructor initializes the form by setting its attributes and appending child elements.
Set Form Type:
- The form's type is set based on the
type
parameter.
- The form's type is set based on the
this.element.setAttribute('type', type);
```
**Set Heading Text**:
- The heading's text content is set to the `title` parameter.
```javascript
this.heading.textContent = title;
```
**Close Button**:
- The close button's type is set to 'submit'.
- The button is given a CSS class 'secondary'.
- The button's text content is set to 'Close'.
```javascript
this.closeButton.setAttribute('type', 'submit');
this.closeButton.classList.add('secondary');
this.closeButton.textContent = 'Close';
Append Child Elements: - The heading, content, and close button are appended to the form.
this.element.appendChild(this.heading);
this.element.appendChild(content);
this.element.appendChild(this.closeButton);
```
```javascript
constructor(type, title, content) {
this.element.setAttribute('type', type)
this.heading.textContent = title;
this.closeButton.setAttribute('type', 'submit')
this.closeButton.classList.add('secondary');
this.closeButton.textContent = 'Close';
this.element.appendChild(this.heading);
this.element.appendChild(content);
this.element.appendChild(this.closeButton);
}
}
Define Modal
Class:
- This class creates a modal dialog with an open button and a dialog element.
-
openButton
: A button element that will open the modal dialog. -
dialog
: A dialog element that contains the form.
class Modal {
openButton = document.createElement('button');
dialog = document.createElement('dialog');
- The constructor initializes the modal by setting its properties and calling internal methods to set up the form and register event listeners. Set Modal Name and Parent:
- The modal's name is set to the
name
parameter. - The parent element is set to the
parentElement
parameter. - The content element is set to the
contentElement
parameter.
this.name = name;
this.parent = parentElement;
this.content = contentElement;
```
**Open Button**:
- The open button's ID and text content are set to the modal's name.
```javascript
this.openButton.setAttribute('id', name);
this.openButton.textContent = name;
```
**Call Internal Methods**:
- `#setupForm` method is called to set up the form inside the modal.
- `#registerOpenListener` method is called to add an event listener to the open button.
```javascript
this.#setupForm();
this.#registerOpenListener();
```
**Internal Method `#setupForm`**:
- This method creates the form and appends it to the dialog.
**Create Article Element**:
- An article element is created to contain the form.
```javascript
const article = document.createElement('article');
```
**Create Form Instance**:
- A new `Form` instance is created with the dialog type, modal name, and content.
- The form element is appended to the article.
```javascript
const form = new Form('dialog', this.name, this.content);
article.appendChild(form.element);
Append Article to Dialog:
- The article is appended to the dialog.
this.dialog.appendChild(article);
Add Submit Event Listener: - An event listener is added to the form's submit event to close the dialog when the form is submitted.
form.element.addEventListener('submit', function (event) {
event.preventDefault();
dialog.close();
});
#setupForm() {
const article = document.createElement('article');
const form = new Form('dialog', this.name, this.content);
article.appendChild(form.element);
this.dialog.appendChild(article);
const dialog = this.dialog;
form.element.addEventListener('submit', function (event) {
event.preventDefault();
dialog.close();
});
}
Internal Method #registerOpenListener
:
- In this method adds an event listener to the open button to show the dialog when clicked.
```javascript
#registerOpenListener() {
const dialog = this.dialog;
this.openButton.addEventListener("click", () => {
dialog.showModal();
});
}
**Method `render`**:
- This method replaces the parent's children with the open button and appends the dialog to the parent.
```javascript
render() {
this.parent.replaceChildren(this.openButton);
this.parent.appendChild(this.dialog);
}
Modal Instance:
- The
parent
variable is set to thenav
element. - The
content
variable is set to the element with the IDdark-mode
. - A new
Modal
instance is created with the name 'Settings', parent element, and content element. - The
render
method is called on theModal
instance to display the modal.
const parent = document.querySelector('nav');
const content = document.getElementById('dark-mode');
const darkModal = new Modal('Settings', parent, content);
darkModal.render();