The goals
💪🏻Practice and apply what we learned
✌🏻Handling form submission with Javascript & creating objects with the "new" keyword
👍🏻Managing data with JavaScript, HTML and the "data-" attributes
Page / Project Features
Configure player names
Form with input field in modal overlay; also validate user input and show validation feedback
(Re-)Start Game
"Start Game" button should clear current game board or "Game Over" messsage
Turn-based Gameplay
Turns should switch automatically between the two players, every player has his / her own symbol
Select Fields & Check for Winner
Game fields are clickable & the player's symbol is displayed; Check for winner (regualr Tic-Tac-Toe rules) after every turn
Show "Game Over" Window
Present "Game Over" message which highlights winner (or draw) once the game ends
Let's try!
Event.preventDefault()
The preventDefault() method of the Event interface tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be.
The event continues to propagate as usual, unless one of its event listeners calls stopPropagation() or stopImmediatePropagation(), either of which terminates propagation at once.
As noted below, calling preventDefault() for a non-cancelable event, such as one dispatched via EventTarget.dispatchEvent(), without specifying cancelable: true has no effect.
FormData()
The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the fetch() or XMLHttpRequest.send() method. It uses the same format a form would use if the encoding type were set to "multipart/form-data".
You can also pass it directly to the URLSearchParams constructor if you want to generate query parameters in the way a <form> would do if it were using simple GET submission.
An object implementing FormData can directly be used in a for...of structure, instead of entries(): for (const p of myFormData) is equivalent to for (const p of myFormData.entries()).
Web APIs
Web API as the name suggests, is an API over the web which can be accessed using HTTP protocol. It is a concept and not a technology. We can build Web API using different technologies such as Java, .NET etc. For example, Twitter's REST APIs provide programmatic access to read and write data using which we can integrate twitter's capabilities into our own application.
When writing code for the Web, there are a large number of Web APIs available. Web APIs are typically used with JavaScript, although this doesn't always have to be the case.
object.trim()
The trim() method removes whitespace from both ends of a string and returns a new string, without modifying the original string. Whitespace in this context is all the whitespace characters (space, tab, no-break space, etc.) and all the line terminator characters (LF, CR, etc.).
.classList
The Element.classList is a read-only property that returns a live DOMTokenList collection of the class attributes of the element. This can then be used to manipulate the class list.
Using classList is a convenient alternative to accessing an element's list of classes as a space-delimited string via element.className.
.classList and className
Using "classList", we can add or remove a class without affecting any others the element may have. But if we assign "className", it will wipe out any existing classes while adding the new one (or if we assign an empty string it will wipe out all of them).
Assigning "className" can be a convenience for cases where we are certain no other classes will be used on the element, but it normally uses the "classList" methods exclusively.
And "classList" also has handy "toggle" and "replace" methods.
data attribute and dataset
The dataset read-only property of the HTML Element interface provides read/write access to custom data attributes (data-*) on elements. It exposes a map of strings (DOMStringMap) with an entry for each data-* attribute.
Note: The dataset property itself can be read, but not directly written. Instead, all writes must be to the individual properties within the dataset, which in turn represent the data attributes.
Name conversion
A custom data attribute name is transformed to a key for the DOMStringMap entry by the following:
- Lowercase all ASCII capital letters (A to Z);
- Remove the prefix data- (including the dash);
- For any dash (U+002D) followed by an ASCII lowercase letter a to z, remove the dash and uppercase the letter;
- Other characters (including other dashes) are left unchanged.
The opposite transformation, which maps a key to an attribute name, uses the following:
- Restriction: Before transformation, a dash must not be immediately followed by an ASCII lowercase letter a to z;
- Add the data- prefix;
- Add a dash before any ASCII uppercase letter A to Z, then lowercase the letter;
- Other characters are left unchanged.
For example, a data-abc-def attribute corresponds to dataset.abcDef.
Accessing values
- Attributes can be set and read by the camelCase name/key as an object property of the dataset: element.dataset.keyname.
- Attributes can also be set and read using bracket syntax: element.dataset['keyname'].
- The in operator can check if a given attribute exists: 'keyname' in element.dataset.
Setting values
- When the attribute is set, its value is always converted to a string. For example: element.dataset.example = null is converted into data-example="null".
- To remove an attribute, you can use the delete operator: delete element.dataset.keyname.
<div id="user" data-id="1234567890" data-user="johndoe" data-date-of-birth>John Doe</div>
const el = document.querySelector('#user');
// el.id === 'user'
// el.dataset.id === '1234567890'
// el.dataset.user === 'johndoe'
// el.dataset.dateOfBirth === ''
// set a data attribute
el.dataset.dateOfBirth = '1960-10-03';
// Result on JS: el.dataset.dateOfBirth === '1960-10-03'
// Result on HTML: <div id="user" data-id="1234567890" data-user="johndoe" data-date-of-birth="1960-10-03">John Doe</div>
delete el.dataset.dateOfBirth;
// Result on JS: el.dataset.dateOfBirth === undefined
// Result on HTML: <div id="user" data-id="1234567890" data-user="johndoe">John Doe</div>
if (!('someDataAttr' in el.dataset)) {
el.dataset.someDataAttr = 'mydata';
// Result on JS: 'someDataAttr' in el.dataset === true
// Result on HTML: <div id="user" data-id="1234567890" data-user="johndoe" data-some-data-attr="mydata">John Doe</div>
}
DOM traversal
One of the most important skills of a web developer is DOM traversal and being able to select HTML elements with JavaScript.
- The entire document is a document node
- Every HTML element is an element node
- The text inside HTML elements are text nodes
- All comments are comment nodes
- parentNode
- previousSibling
- nextSibling
- firstChild
- lastChild
- childNodes[nodeNumber]
effect of "return"in if-statement
When a return statement is used in a function body, the execution of the function is stopped. If specified, a given value is returned to the function caller. For example, the following function returns the square of its argument, x, where x is a number.
A function immediately stops at the point where return is called.
Self Training💪🏻
1. Build HTML
Answer
<body>
<div id="backdrop"></div>
<header id="main-header">
<h1>Play Tic, Tac, Toe</h1>
<p>Built with HTML, CSS, JavaScript and - of course - lots of love!</p>
</header>
<main>
<aside class="modal" id="config-overlay">
<h2>Choose your name</h2>
<form>
<div class="form-control">
<label for="playername">Player name</label>
<input type="text" name="playername" id="playername" required />
</div>
<p id="config-errors"></p>
<div>
<button type="reset" class="btn btn-alt" id="cancel-config-btn">
Cancel
</button>
<button type="submit" class="btn">Confirm</button>
</div>
</form>
</aside>
<section id="game-configuration">
<ol>
<li>
<article id="player-1-data">
<h2>Player 1</h2>
<h3>PLAYER NAME</h3>
<p class="player-symbol">X</p>
<button
class="btn btn-alt"
id="edit-player-1-btn"
data-playerid="1"
>
Edit
</button>
</article>
</li>
<li>
<article id="player-2-data">
<h2>Player 2</h2>
<h3>PLAYER NAME</h3>
<p class="player-symbol">O</p>
<button
class="btn btn-alt"
id="edit-player-2-btn"
data-playerid="2"
>
Edit
</button>
</article>
</li>
</ol>
<button class="btn" id="start-game-btn">Start New Game</button>
</section>
<section id="active-game">
<article id="game-over">
<h2>You won, <span id="winner-name">PLAYER NAME</span>!</h2>
<p>Click "Start New Game" above, to start a new game!</p>
</article>
<p>It's your turn <span id="active-player-name">PLAYER NAME</span>!</p>
<ol id="game-board">
<li data-col="1" data-row="1"></li>
<li data-col="2" data-row="1"></li>
<li data-col="3" data-row="1"></li>
<li data-col="1" data-row="2"></li>
<li data-col="2" data-row="2"></li>
<li data-col="3" data-row="2"></li>
<li data-col="1" data-row="3"></li>
<li data-col="2" data-row="3"></li>
<li data-col="3" data-row="3"></li>
</ol>
</section>
</main>
</body>
Mine
<body>
<header>
<h1>Play Tic, Tac, Toe</h1>
<p>Built with HTML, CSS, JavaScript and - of course - lots of love!</p>
</header>
<main>
<aside id="config-player">
<h2>Choose your name</h2>
<p>Player name</p>
<input type="text" id="playername-set" />
<button>Cancel</button>
<button>Confirm</button>
</aside>
<div class="player-card">
<section>
<div>
<p>Player 1</p>
<h2 id="player-1">PLAYER NAME</h2>
<p class="player-symbol">X</p>
<a href="#config-player">Edit</a>
</div>
</section>
<section>
<div>
<p>Player 2</p>
<h2>PLAYER NAME</h2>
<p class="player-symbol">O</p>
<a href="#config-player">Edit</a>
</div>
</section>
</div>
<button id="start-new-game" type="reset">Start New Game</button>
</main>
<footer>
</footer>
</body>
👀Differences
1. An instructor used form inside aside which I didn't use
2. He used ol, li and put article inside. But I used section and div
2. Use CSS
👀Differences
1. colors are different obviously....at least found some similar colors tho!
2. I think I suck at positioning....
3. Need to control some margin and padding
Answer
body {
margin: 0;
font-family: 'Open-Sans', sans-serif;
color: rgb(44, 41, 44);
background-color: rgb(247, 239, 247);
}
#main-header {
background-color: rgb(140, 0, 255);
color: white;
padding: 2rem 5%;
text-align: center;
}
.btn {
font: inherit;
padding: 0.5rem 1.5rem;
background-color: rgb(140, 0, 255);
border: 1px solid rgb(140, 0, 255);
color: white;
border-radius: 4px;
cursor: pointer;
}
.btn-alt {
background-color: transparent;
border-color: transparent;
color: rgb(140, 0, 255);
}
.btn:hover {
background-color: rgb(79, 10, 190);
border-color: rgb(79, 10, 190);
}
.btn-alt:hover {
background-color: rgb(230, 201, 252);
border-color: transparent;
}
Mine
body {
font-family: 'Open-Sans', sans-serif;
background-color: rgb(249, 242, 255);
margin: 0;
height: 100%;
width: 100%;
}
header {
width: 100%;
height: 10rem;
margin: 0;
padding: 0;
background-color: rgb(143, 51, 255);
color: white;
text-align: center;
}
main {
text-align: center;
}
header h1 {
margin: 0;
padding: 2rem 5% 0;
}
.player-card {
display: flex;
text-align: center;
justify-content: space-around;
margin: 0 25%;
}
section {
width: 90%;
background-color: rgb(243, 228, 255);
margin: 4rem 1rem;
border-radius: 3px;
box-shadow: 2px 2px rgba(177, 177, 177, 0.421);
}
section div {
margin: 0;
padding: 1rem 0rem;
}
section p {
font-weight: bold;
margin: 8px auto;
}
section h2 {
color: rgb(91, 26, 152);
margin: 8px 0;
}
section .player-symbol {
font-size: 30px;
}
section a {
text-decoration: none;
color: blueviolet;
}
#start-new-game {
width: 12rem;
height: 2rem;
font-size: 16px;
margin: 0;
border: none;
border-radius: 3px;
background-color: blueviolet;
color: white;
margin: 0 2rem;
}
😭😭😭😭😭😭😭
Since I am just a beginner I used too many code lines...and it looks messy....let me fix it step by step...🥺
and he separated some parts of website into different css file...
What I need to prepare more
1. how to put body items in the middle
-not only width 50%
=> it was 'text-align'
2. what is 'width: 90%' for?
3. how to use media query
Sources
https://developer.mozilla.org/en-US/docs/Web/API
Web APIs | MDN
When writing code for the Web, there are a large number of Web APIs available. Below is a list of all the APIs and interfaces (object types) that you may be able to use while developing your Web app or site.
developer.mozilla.org
https://developer.mozilla.org/en-US/docs/Web/API/FormData
FormData - Web APIs | MDN
The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the fetch() or XMLHttpRequest.send() method. It uses the same format a form would use if the e
developer.mozilla.org
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/trim
String.prototype.trim() - JavaScript | MDN
The trim() method removes whitespace from both ends of a string and returns a new string, without modifying the original string. Whitespace in this context is all the whitespace characters (space, tab, no-break space, etc.) and all the line terminator char
developer.mozilla.org
Difference between className and classList
Which one of the following should be preferred under what circumstances? btnElement.classList.add('btn'); btnElement.className = 'btn';
stackoverflow.com
https://medium.com/codex/how-to-traverse-the-dom-in-javascript-7fece4a7751c
How To Traverse The DOM In JavaScript
Must know methods in DOM traversal
medium.com
return - JavaScript | MDN
The return statement ends function execution and specifies a value to be returned to the function caller.
developer.mozilla.org