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.)

## ### Homework 2 ### ##

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.

## ### Homework 3 ### ##

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 and ROUNDS 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.

## ### Dark-modal ### ##

------------ 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 using document.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), the toggleDarkMode 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: An h2 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.
      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 the nav element.
  • The content variable is set to the element with the ID dark-mode.
  • A new Modal instance is created with the name 'Settings', parent element, and content element.
  • The render method is called on the Modal 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();
⚠️ **GitHub.com Fallback** ⚠️