- Take the hard-coded HTML for the Wizard card, bring it into index.js and then inject it back into its div with JavaScript.
- Do the same for Orc card.
-
Strip out the hero and monster data (element id, name, avatar, health and dice score) and store them in variables
-
Write a renderCharacter() function that accepts the 5 new variables as parameters and renders out a character with this data
-
Call renderCharacter() twice. Once with the hero variables and once with the monster variables to that both are rendered
- Convert our consts into two objects called "monster" and "hero".
- Update the renderCharacter() function so that it accepts a single object "data" as its parameter instead of five string/numbers, reducing the number of arguments to pass in from five to one.
- Update the template now each variable is coming from "data".
- Update the function call.
let user = { // an object
name: "John", // by key "name" store value "John"
age: 30 // by key "age" store value 30
}
- Deconstruct the data object
- Update the template string as necessary
- declare a let called diceHtml and initialize it with an empty string.
- Use a for loop to update diceHtml so that it contains the HTML for our dice. The number of dice needed is specified in the diceCount property of the objects.
- Each dice should have the following HTML:
<div class="dice">6</div>
- For now, each dice will display 6
- Swap out the diceRoll variable for diceHtml in the template
Update this for loop so it uses a value from the new diceRoll array to render out the dice so the wizard's dice have values of 3, 1 and 4, and the orc's single dice has a value of 2.
- Instead of the for loop, map over the diceRoll array and save the new array to diceHTML.
- Remember to deal with the commas between dice.
- What keyword should be used to declare diceHTML?
- Create a function called getDiceRollArray that uses a for loop to return an array of random numbers between 1-6.
- The function should have diceCount as a parameter and the array it returns should be diceCount length.
- For testing purposes, call the function with a diceCount of 3 and log out the result. check out hint.md for extra help!
- Math.random() - will generate a random number between 0 and 1 but not inclusive of 1.
- Math.floor() - will round a number down to the nearest integer
- Create a function called getDiceHtml.
- getDiceHtml should map over the array of dice rolls returned from getDiceRollArray to generate the html we need to render our dice with random values. This is the HTML:
`<div class="dice">DICE VALUE HERE</div>`
- Think about the parameters and arguments!
- Down in renderCharacter(), set diceHtml equals to our new getDiceHtml function. Remember to give it the argument it needs.
- Delete any code we no longer need.
- Your function should take in diceCount as a parameter.
- It should then return the array it gets by calling getDiceRollArray(). Remember to use as an argument.
- There's no need to set up a new variable - you can map over the array returned by getDiceRollArray directly to return the html template for each dice.
Changed/Deleted:
function getDiceRollArray(diceCount){
const newDiceRolls = []
for(let i = 0; i < diceCount; i++){
newDiceRolls.push(Math.floor(Math.random() *6 ) + 1)
}
return newDiceRolls
}
getDiceRollArray(3)
const poisonMushrooms = new Array(10).fill('🍄').map(function(mushroom){
return `<div class="box">${mushroom}</div>`
}).join('')
document.getElementById('mushrooms').innerHTML = poisonMushrooms
.mushroom-container{
display: flex;
flex-wrap: wrap;
gap: 5px;
padding: 20px;
}
.box{
padding: 20px;
border: 3px solid skyblue;
border-radius: 5px;
}
<html>
<head>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div class="mushroom-container" id="mushrooms"></div>
<script src="index.pack.js"></script>
</body>
</html>
- Instead of the for loop, use an Array constructor to create a new array which is diceCount length.
- Fill the new array with zeros as its initial state.
- Map over the new array directly (no need to declare a new variable) and return a random number from 1-6 in each element.
- Delete all unnecessary code.
Note: Constructor Function Example
const animalForRelease1 = {
name: 'Tilly',
species: 'tiger',
weightKg: 56,
age: 2,
dateOfRelease: '03-02-2022'
}
const animalForRelease2 = {
name: 'Nelly',
species: 'elephant',
weightKg: 320,
age: 16,
dateOfRelease: '03-02-2022'
}
function Animal(data){
this.name = data.name
this.species = data.species
this.weightKg = data.weightKg
this.age = data.age
this.dateOfRelease = data.dateOfRelease
}
const tillyTheTiger = new Animal(animalForRelease1)
const nellyTheElephant = new Animal(animalForRelease2)
console.log(tillyTheTiger)
console.log(nellyTheElephant)
- Methods are properties on objects that contain functions
- If you can write a function, you can write a method.
function Animal(data){
this.name = data.name
this.species = data.species
this.weightKg = data.weightKg
this.age = data.age
this.dateOfRelease = data.dateOfRelease
this.summariseAnimal = function(){
console.log(`${this.name} is a ${this.age} year old
${this.species} which weighs ${this.weightKg}kg and was
released into the wild on ${this.dateOfRelease}`)
}
}
const tillyTheTiger = new Animal(animalForRelease1)
const nellyTheElephant = new Animal(animalForRelease2)
tillyTheTiger.summariseAnimal()
nellyTheElephant.summariseAnimal()
- Create a new constructor function called Character which takes our data as a paramenter.
- Set up "this" for each of the 5 properties in our objects (eg: this.health = data.health).
- Create a method called getCharacterHtml that performs the same tasks as our current renderCharacter function.
- Create two new instances of Character. One for a hero, called "wizard", and one for a monster, called "orc". Render both of them on the page.
- Delete both the old renderCharacter function and the two lines of code at the bottom of the page which invoke that function.
- Object.assign copies properties from a source object to a target object, then returns the new version of the target object
Object.assign(target, source)
For example:
const studentDetails = {
firstName: 'janaka',
lastName: 'siriwardena',
age: 28,
country: 'sri lanka',
email: 'j.siri@totalinternet.com',
discordUsername: 'JS1',
}
function Student(data) {
// No longer need these four lines of code because Object.assign replaces them.
// this.firstName = data.firstName
// this.lastName = data.lastName
// this.age = data.age
// this.country = data.country
// this.email = data.email
// this.discordUsername = data.discordUsername
Object.assign(this, data)
this.summariseStudent = function () {
console.log(`${this.firstName} ${this.lastName} is ${this.age} years old
and comes from ${this.country}. Their email is ${this.email} and you can find them on discord as ${this.discordUsername}`)
}
}
const newStudent = new Student(studentDetails)
newStudent.summariseStudent()
-Use what you learned in the previous scrim to remove the following 5 lines of code:
this.elementId = data.elementId
this.name = data.name
this.avatar = data.avatar
this.health = data.health
this.diceCount = data.diceCount
- Add this function as a method of our character constructor
function getDiceHtml(diceCount) {
return getDiceRollArray(diceCount).map(function(num){
return `<div class="dice">${num}</div>`
}).join('')
}
- Make a small change to getCharacterHtml to make the app work again
- instead of setting the innerHTML from right here in the constructor (see below for before change), make it so that we just return that literal string of HTML
- This will break the app. Don't worry!
this.getCharacterHtml = function () {
const { elementId, name, avatar, health, diceCount } = this;
let diceHtml = this.getDiceHtml(diceCount);
document.getElementById(elementId).innerHTML =
`<div class="character-card">
<h4 class="name"> ${name} </h4>
<img class="avatar" src="${avatar}" />
<div class="health">health: <b> ${health} </b></div>
<div class="dice-container">
${diceHtml}
</div>
</div>`;
- Make the wizard and orc render
- The .getCharacterHtml method of our constructor is returning a string containing HTML.
- For each character we need to call the .getCharacterHtml method so that the HTML it returns goes into the innerHTML of the correct div.
- Each character in our objects has an elementId property.
- Use that property to grab the right element and then set it equals to the render method for that character.
- Create one render() function that calls both wizard and orc so we can control when they render.
- Call the function.
-Create a new const called characterData and set it equals to an object which holds both our hero and monster objects. -Think about how we access the data from our new object when we set up new characters down at the very bottom of the app. -See if you can work out what needs to change there to keep the app working.
- Create a file called 'utils.js'.
- Cut and paste the getDiceRollArray() function into it.
- Decide if this should be a default or named export. Think about this!!
- Import back it into index.js
- Create a file called 'Character.js'
- Cut and paste the constructor function into it.
- Decide if this should be a default or named export. Think about this!!
- Import it into index.js
- You will hit a problem! Solve the problem!
- Constructor Functions
- The "this" keyword
- Methods on constructor functions
- Object.assign
- Import/Export
-
(Adding an existing project to GitHub using the command line by Alex Chin)[https://gist.github.com/alexpchin/102854243cd066f8b88e]
-
I was having issues until I used the following command
Error:
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Force it:
< git push --set-upstream origin main --force >