Skip to content

Latest commit

 

History

History
651 lines (517 loc) · 19.1 KB

Day 4 .md

File metadata and controls

651 lines (517 loc) · 19.1 KB

💎 Day 4 💎



Events & Handlers 🎯🚀

How to make our web page interactive !

addEventListener() 💫

method lets us listen for events on a DOM element


👉 Note:

addEventListener() takes 2 parameters:

  1. The name of the event to listen to (e.g. "click")
  2. A handler function that JS calls when that event is fired on this element

document.addEventListener("click", () => {
    console.log("clicked")
});

Optional parameter: 🔮🫧

JS passes an event object to the handler function with information about the event.

If we accept this as a parameter, we can use it to get details

document.addEventListener("click", (event) => {
    console.log(event);
});

event.target: ✨⚡️

Is the element the event fired on (in this case, which element was clicked)

document.addEventListener("click", (event) => {
    console.log(event.target);
});

Some events: 💻🔥

  1. "click"
  2. "dblclick"
  3. "mouseover"
  4. "mouseout"
let b = document.getElementsByName("true")[0]
b.addEventListener("mouseover", () => {
    console.log("The carser is in the button")
});

b.addEventListener("mouseout", () => {
    console.log("The carser is out the button")
});

Exercise:⏳🔥

The code in Project section or this link

/*
	In the console, on our quiz add event listeners to the buttons so that:
	
	When the "true" button is clicked, the button's text becomes "clicked true"
	When the "false" button is clicked, the "explanation" div text becomes 
	"clicked false"
*/

let bt = document.getElementsByName("true")[0]
bt.addEventListener("click",()=>{b.textContent="clicked true"})

let bf = document.getElementsByName("false")[0]
bf.addEventListener("click",()=>{
		document.getElementById("explanation").textContent = "clicked false"
})


Example ✨☄️

<!DOCTYPE html>
<html>
<head>
  <title>Very Exciting Web Page</title>
  <style>
    .box {
      border: 3px solid grey;
      padding: 1em;
    }

    .hidden {
      display: none;
    }

    #clickme {
      background-color: purple;
      color: white;
      margin-top: 1em;
      padding: 1em;
      border: 0px;
      border-radius: 5px;
    }
  </style>
</head>
<body>
  <h1>Very Exciting Web Page</h1>

  <div class="box">
    <p id="in">Hello I am in a box</p>
  </div>

  <p id="out" class="hidden">Now I have escaped</p>

  <button id="clickme">Click me</button>

  <script>
    const button = document.getElementById("clickme");
    const paragraphs = document.querySelectorAll("p");

    button.addEventListener("click", event => {
      for (let p of paragraphs) {
        p.classList.toggle("hidden");
      }
    });
  </script>
</body>
</html>


Conditionals 👩🏻‍💻🤔

If statment: ❓🌟

If it's given some other value, JS will convert it to a boolean and decide based on its "truthiness”

if ("nonempty strings are truthy") {
    console.log("this line will run");
}

Exercise: 🍄🍃

/*
  1. Write a conditional that logs a message saying whether your first name 
  or last name is longer 
*/

	if ("Sarah".length >= "Abu irmeileh".length){
	    console.log("First name is longer");
	}else{
	    console.log("Last name is longer");
	}


/*
2. Write a function isEmpty(array) that returns whether a given array is empty
*/

const isEmpty = (array)=>{array.length === 0 }


// 3. Is an empty array truthy or falsy? Write a conditional to find out 

if ([]){
    console.log("empty array is a truth value");
}else{
    console.log("empty array is a false value");
} // truth value

Loops:🔥💫

enhanced loop: 🎆🌟

const numbers = [1,2,3];
for (let i = 0; i < numbers.length; i++) {
    console.log(numbers[i]);
}
for (let n of numbers) {
    console.log(n);
}


Complete the project: ✏️📝

for (let b of optionButtons){
        b.addEventListener("click", event =>{
                        
            explanation.textContent = fact.explanation

            for (let allB of optionButtons)
                disable(allB)
        

            if (isCorrect(b.value)){
                b.classList.add("correct")
            }else{
                b.classList.add("incorrect")
            }

        })
    }


map & filter: 🌟🌠

The map & filter methods also let us process all the items in an array

map : 🗺️🌐

 Calls a function on each item in an array to create a new array

const spices = [
   {name: "Emma", nickname: "Baby"},
   {name: "Geri", nickname: "Ginger"},
   {name: "Mel B", nickname: "Scary"},
   {name: "Mel C", nickname: "Sporty"},
   {name: "Victoria", nickname: "Posh"}
];
const nicknames = spices.map(s => `${s.nickname} Spice`;);

/*
   [
     'Baby Spice',
     'Ginger Spice',
     'Scary Spice',
     'Sporty Spice',
     'Posh Spice'
   ]
*/

filter : 🫧🪐

Calls a true/false function on each item and creates a new array with only the items where the function returns true

const mels = spices.filter(s => s.name.includes("Mel"));

Exercise: ⏰🔍

/* From the spices array, use map and filter to:

create a new array names with only the name of each girl
create a new array endInY with just the girls whose nickname ends in "y" */

const spices = [
    {name: "Emma", nickname: "Baby"},
    {name: "Geri", nickname: "Ginger"},
    {name: "Mel B", nickname: "Scary"},
    {name: "Mel C", nickname: "Sporty"},
    {name: "Victoria", nickname: "Posh"}
];

const names = spices.map(s=>s.name)
const endInY = spices.filter(s=>s.nickname.endsWith("y"))


Spread (...): 💎🔮

It lets us take all the items in an array and spread 'em around

const oldBurns = ["square", "wack"];
const newBurns = ["basic", "dusty", "sus"];

const burnBook = [...oldBurns, ...newBurns];
// equivalent to
const burnBook = oldBurns.concat(newBurns);


Doggo Fetch Project 🧐🪩

<!DOCTYPE html>
<!-- saved from url=(0068)https://anjana.dev/javascript-first-steps/3-doggofetch-finished.html -->
<html lang="en-US"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    
    <title>Doggo Fetch</title>
    <style>
        body {
            margin: 1rem auto;
            padding: 3rem;
            font-family: sans-serif;
        }
        header {
            width: 70%;
            margin: 1em auto;
        }
        main {
            max-width: 70%;
            margin: 0px auto;
            display:flex; 
            flex-direction: column;
        }
        img {
            max-width: 100%;
        }
        #image-frame {
            font-size: x-large;
            text-align: center;
            margin: 1rem auto;
        }
        #explanation, #score {
            padding: 1rem;
            text-align: center;
        }
        #options {
            max-width: 100%;
            display: flex;
            flex-direction: column;
        }
        button {
            padding: 0.5rem;
            font-size: medium;
            border-radius: 5px;
        }
        .correct {
            background-color: lightgreen;
        }
        .incorrect {
            background-color: lightpink;
        }
        .hidden {
            display: none;
        }
    </style>
  </head>
  <body>
    <header>
    <h1>Guess the Doggo</h1>
    <p>What breed is the dog in this image?</p>

    </header>

    <main>
    <div id="image-frame"><img src="./Final_files/PXL_20210220_100624962.jpg"></div>
    <div id="options">
    <button name="medium poodle" value="medium poodle" class="correct">medium poodle</button><button name="australian terrier" value="australian terrier" class="incorrect">australian terrier</button><button name="french bulldog" value="french bulldog">french bulldog</button></div>

    </main>

  


  <script type="module">

    const RANDOM_IMG_ENDPOINT = "https://dog.ceo/api/breeds/image/random";

    const BREEDS = ["affenpinscher", "african", "airedale", "akita", "appenzeller", "shepherd australian", "basenji", "beagle", "bluetick", "borzoi", "bouvier", "boxer", "brabancon", "briard", "norwegian buhund", "boston bulldog", "english bulldog", "french bulldog", "staffordshire bullterrier", "australian cattledog", "chihuahua", "chow", "clumber", "cockapoo", "border collie", "coonhound", "cardigan corgi", "cotondetulear", "dachshund", "dalmatian", "great dane", "scottish deerhound", "dhole", "dingo", "doberman", "norwegian elkhound", "entlebucher", "eskimo", "lapphund finnish", "bichon frise", "germanshepherd", "italian greyhound", "groenendael", "havanese", "afghan hound", "basset hound", "blood hound", "english hound", "ibizan hound", "plott hound", "walker hound", "husky", "keeshond", "kelpie", "komondor", "kuvasz", "labradoodle", "labrador", "leonberg", "lhasa", "malamute", "malinois", "maltese", "bull mastiff", "english mastiff", "tibetan mastiff", "mexicanhairless", "mix", "bernese mountain", "swiss mountain", "newfoundland", "otterhound", "caucasian ovcharka", "papillon", "pekinese", "pembroke", "miniature pinscher", "pitbull", "german pointer", "germanlonghair pointer", "pomeranian", "medium poodle", "miniature poodle", "standard poodle", "toy poodle", "pug", "puggle", "pyrenees", "redbone", "chesapeake retriever", "curly retriever", "flatcoated retriever", "golden retriever", "rhodesian ridgeback", "rottweiler", "saluki", "samoyed", "schipperke", "giant schnauzer", "miniature schnauzer", "english setter", "gordon setter", "irish setter", "sharpei", "english sheepdog", "shetland sheepdog", "shiba", "shihtzu", "blenheim spaniel", "brittany spaniel", "cocker spaniel", "irish spaniel", "japanese spaniel", "sussex spaniel", "welsh spaniel", "english springer", "stbernard", "american terrier", "australian terrier", "bedlington terrier", "border terrier", "cairn terrier", "dandie terrier", "fox terrier", "irish terrier", "kerryblue terrier", "lakeland terrier", "norfolk terrier", "norwich terrier", "patterdale terrier", "russell terrier", "scottish terrier", "sealyham terrier", "silky terrier", "tibetan terrier", "toy terrier", "welsh terrier", "westhighland terrier", "wheaten terrier", "yorkshire terrier", "tervuren", "vizsla", "spanish waterdog", "weimaraner", "whippet", "irish wolfhound"];

    
    // Utility function to get a randomly selected item from an array
    function getRandomElement(array) {
        const i = Math.floor(Math.random() * array.length);
        return array[i];
    }

    // Utility function to shuffle the order of items in an array in-place
    function shuffleArray(array) {
        return array.sort((a,b) => Math.random() - 0.5);
    }



    // TODO 1
    // Given an array of possible answers, a correct answer value, and a number of choices to get,
    // return a list of that many choices, including the correct answer and others from the array
    function getMultipleChoices(n, correctAnswer, array) {
        // Use a while loop and the getRandomElement() function
        // Make sure there are no duplicates in the array
        const choices = [correctAnswer];
        while (choices.length < n) {
            let candidate = getRandomElement(array);
            if (choices.indexOf(candidate) < 0) { // check if this is already in the array
                choices.push(candidate); // if not, add it
            }
        }
        return shuffleArray(choices);
    }

    
    // TODO 2
    // Given a URL such as "https://images.dog.ceo/breeds/poodle-standard/n02113799_2280.jpg"
    // return the breed name string as formatted in the breed list, e.g. "standard poodle"
    function getBreedFromURL(url) {
        // The string method .split(char) may come in handy
        // Try to use destructuring as much as you can
        const [,path] = url.split("/breeds/");
        const [breedID] = path.split("/");
        const [breed, subtype] = breedID.split("-");
        return [subtype, breed].join(" ");
    }



    // TODO 3
    // Given a URL, fetch the resource at that URL, 
    // then parse the response as a JSON object,
    // finally return the "message" property of its body
    async function fetchMessage(url) {
        const response = await fetch(url);  // Fetch the resource at the given URL
        const {message} = await response.json(); // Parse the response as JSON & remember its 'message' value
        return message; // Return the message
    }


    // Function to add the multiple-choice buttons to the page
    function renderButtons(choicesArray, correctAnswer) {

        // Event handler function to compare the clicked button's value to correctAnswer
        // and add "correct"/"incorrect" classes to the buttons as appropriate
        function buttonHandler(e) {
            if (e.target.value === correctAnswer) {
                e.target.classList.add("correct");
            } else {
                e.target.classList.add("incorrect");
                document.querySelector(`button[value="${correctAnswer}"]`).classList.add("correct");
            }
        }

        const options = document.getElementById("options"); // Container for the multiple-choice buttons

        // TODO 4
        // For each of the choices in choicesArray,
        // Create a button element whose name, value, and textContent properties are the value of that choice,
        // attach a "click" event listener with the buttonHandler function,
        // and append the button as a child of the options element
        choicesArray.map(choice => {
            let button = document.createElement("button");
            button.value = button.name = button.textContent = choice;
            button.addEventListener("click", buttonHandler);
            options.appendChild(button);
        })
    }


    // Function to add the quiz content to the page
    function renderQuiz(imgUrl, correctAnswer, choices) {
        const image = document.createElement("img");
        image.setAttribute("src", imgUrl);
        const frame = document.getElementById("image-frame");

        image.addEventListener("load", () => {
            // Wait until the image has finished loading before trying to add elements to the page
            frame.replaceChildren(image);
            renderButtons(choices, correctAnswer);
        })
        
    }

    // Function to load the data needed to display the quiz
    async function loadQuizData() {
        document.getElementById("image-frame").textContent = "Fetching doggo...";
        
        const doggoImgUrl = await fetchMessage(RANDOM_IMG_ENDPOINT);
        const correctBreed = getBreedFromURL(doggoImgUrl);
        const breedChoices = getMultipleChoices(3, correctBreed, BREEDS);

        return [doggoImgUrl, correctBreed, breedChoices];
    }

    // TODO 5
    // Asynchronously call the loadQuizData() function,     
    // Then call renderQuiz() with the returned imageUrl, correctAnswer, and choices 
    const [imageUrl, correctAnswer, choices] = await loadQuizData();
    renderQuiz(imageUrl, correctAnswer, choices);
    


  </script>

</body></html>


(A)synchronous code: 💡💎

Some things that take time: ✨🎀

  1. Waiting for user events
  2. Asking a user to pick a file
  3. Getting permission to access the camera/mic
  4. Loading data from the interwebs

Learning about asynchronous JS: ✏️📋

1. MDN: Introducing Asynchronous JS

2. Philip Roberts: What the heck is the event loop anyway?



💡 Notes:

  1. querySelector: this method returns the first element while querySelectorAll: this method returns a NodeList containing all elements that match the specified selector


Coding Exercises for challenges: 🔥💪

  1. Write Concise Declarative Functions with ES6 My solution:
// Only change code below this line
const bicycle = {
  gear: 2,
  setGear(newGear) {
    this.gear = newGear;
  }
};
// Only change code above this line
bicycle.setGear(3);
console.log(bicycle.gear);
  1. Use class Syntax to Define a Constructor Function My solution:
// Only change code below this line
class Vegetable {
  constructor (name){
    this.name = name
  }
}
// Only change code above this line

const carrot = new Vegetable('carrot');
console.log(carrot.name); // Should display 'carrot'
  1. Use getters and setters to Control Access to an Object My solution:
// Only change code below this line
class Thermostat {
  constructor(fahrenheit) {
    this.fahrenheit = fahrenheit;
  }
  
  get temperature() {
    return (5 / 9) * (this.fahrenheit - 32);
  }
  
  set temperature(celsius) {
    return this.fahrenheit = (celsius * 9.0) / 5 + 32;
  }
}
// Only change code above this line

const thermos = new Thermostat(76); // Setting in Fahrenheit scale
let temp = thermos.temperature; // 24.44 in Celsius
thermos.temperature = 26;
temp = thermos.temperature; // 26 in Celsius
  1. Create a Module Script My solution:
<html>
  <body>
    <!-- Only change code below this line -->
    <script type="module" src="index.js"></script>
    <!-- Only change code above this line -->
  </body>
</html>
  1. Use export to Share a Code Block My solution:
const uppercaseString = (string) => {
  return string.toUpperCase();
}

const lowercaseString = (string) => {
  return string.toLowerCase()
}

export { uppercaseString, lowercaseString };


Problem Solving: 💪🚀

  1. Find the next perfect square! My solution:
function findNextSquare(sq) {
    const root = Math.sqrt(sq)
    return Math.sqrt(sq)===Math.ceil(Math.sqrt(sq)) ? (root+1)**2  : -1
  }
  1. Two to One My 1st solution:
function longest(s1, s2) {
    let mySet = new Set()
    let ans = ""
    for(let s of s1+s2){
        if(!mySet.has(s)){
            mySet.add(s)
            ans+=s
        }
    }
    
    return ans.split('').sort().join('')
  }

My 2nd solution:

 const longest = (s1, s2) => [...new Set(s1+s2)].sort().join('')