Background:
I just completed phase 1 of Flatiron's Software Engineering Flex program (I was supposed to complete this phase a few weeks ago, but that's the beauty of the flex program). I created a single-page application to keep track of those harder-to-realize accomplishments. The main idea is quite simple: complete tasks, level up corresponding skills, and earn rewards. A task log is located underneath the primary game bar to keep track of tasks completed:
Most of this functionality was achieved with the help of event listeners, namely click, submit, and keydown. I relied heavily on the event object to manipulate the DOM and get my application moving the way I wanted it to.
What is the event object?
From my own understanding, the event object is an object created once you satisfy the condition of the event listener. This event object is automatically passed into callback function, and you can access multiple points of useful information through that event object.
In the callback function itself, define a parameter to receive the event object. The name of the parameter can be really be anything, but by convention and just for ease of use, it's typical to name this parameter "event", or just simply "e". When working with the event object, I find it helpful to just console log the event at the start to remind myself of what I can do with it:
document.addEventListener('click', e => console.log(e))
Viewing the console, you get a seemingly endless amount of properties, with nested objects under certain keys:
But of course, the event object generated by clicking on a random location on the page does not tell you much (well it does, but there's no information I'm concerned with at this point). Adding event listeners to specific elements on the page gives much more relevant information to play around with.
How I used the event object in my project
For my project, I was primarily concerned with the information in the event object under e.target
. I was looking for the value of the ID attribute in the event object, which I defined in my HTML:
<button class='task-button' id="self-comp-1" >Took a break when I needed to</button><br/>
<button class='task-button' id="self-comp-2" >Used positive affirmations</button><br/>
<button class='task-button' id="pers-1">Had an 'aha!' moment </button><br/>
<button class='task-button' id="pers-2">All lab tests passing</button><br/>
<button class='task-button' id="gh-1">Coded along during a lesson</button><br/>
<button class='task-button' id="gh-2">Refactored code</button><br/>
<button class='task-button' id="supp-1">Received / gave support on Slack</button><br/>
<button class='task-button' id="supp-2">Paired with a technical coach</button><br/>
Using a for loop, I added a "click" event listener to each of eight task buttons on my application. In my callback function, I made use of a series of conditional statements to check the ID of the button that was clicked. If I click on the first button labeled "took a break when I needed to" e.target.id
evaluates to "self-comp-1", and a series of functions will execute from that point to update the corresponding skill of self compassion:
for (const node of taskButtons) {
node.addEventListener('click', e => {
if ((e.target.id === 'self-comp-1') || (e.target.id === 'self-comp-2')) {
if (selfCompPercentage < 100) {
selfCompPercentage = updatePercentage(selfCompPercentageNode, selfCompPercentage, ' - Self Compassion');
updateProgressBar(selfCompProgressBar, selfCompPercentage);
addTaskCompleted(e);
}
In the last line of the above code block, I passed the event object to another function, addTaskCompleted(e)
, which updates the task log at the bottom of the page. I needed to do this because I needed to list the text contained in the button that was clicked by the user, like so:
Using the same event object that was created when I clicked on the button, I first declared a variable completedTask
to create an element to store the name of the task. And to use the event object passed into the function, I set the textContent
of the completedTask
to e.target.textContent
, which corresponds with the text inside the button originally clicked. Lastly, I added the new element to a completedTasksContainer
:
function addTaskCompleted(e) {
const completedTask = document.createElement('p')
completedTask.textContent = e.target.textContent;
completedTasksContainer.appendChild(completedTask)
Also in the task log is an ability to add a comment, which also uses an event listener and a separate event object, as part of a 'submit' event. I created a form with a comment bar and a submit button, and then added an event listener upon submission of the simple form, with its own callback function:
// creates form next to the completed task
const inputForm = document.createElement('form')
inputForm.id = 'input-form'
completedTask.appendChild(inputForm)
// Adds comment bar
const inputText = document.createElement('input')
inputText.type = 'text'
inputText.value = ''
inputText.placeholder = 'Add comment..'
inputText.id = 'comment'
inputForm.appendChild(inputText)
// Adds submit button
const submitButton = document.createElement('input')
submitButton.type = 'submit'
submitButton.name = 'submit'
submitButton.value = 'Add'
inputForm.appendChild(submitButton)
// Adds comment to task completed upon submission of form
inputForm.addEventListener('submit', addCommentToTask)
When adding the comment bar itself, the most important thing to note here is inputText.id = 'comment'
. This allows me to access the text that was entered in the form in my callback function, once again with e.target
, and add that text as a bullet point under the completed task:
function addCommentToTask(e) {
e.preventDefault()
const comment = e.target.comment.value
const completedTask = e.target.parentNode
e.target.remove()
const commentNode = document.createElement('ul')
const commentText = document.createElement('li')
commentNode.appendChild(commentText)
commentText.textContent = `Comment: ${comment}`
completedTask.appendChild(commentNode)
}
A few things to note here:
e.preventDefault()
prevents the page from refreshing upon submission of the form.
const comment = e.target.comment.value
stores the value of the inputted text in a comment variable, using the ID of the comment bar itself.
const completedTask = e.target.parentNode
saves a reference to the task completed, to use a header for an bullet point
e.target.remove()
removes the comment bar and submit button from the task log.
After adding an unordered list bullet point, I set the text content of the bullet point to the comment
variable with some string interpolation:
commentText.textContent = `Comment: ${comment}`
The third and final event object I worked with was one created by a 'keydown' event. Upon reaching 100% in a skill, a function is called to display an emoji award. I implemented a completely useless but fun feature that allows you to rotate the axe awarded to the user upon completion of the persistence skill. The axe can be rotated plus or minus 45 degrees, depending on whether the left or right arrow is pressed down. To do this, I added a 'keydown' listener to the window (not to the axe itself, because I want the user to be able to rotate the axe at all times if the user has last clicked on the window itself):
function displayAward(node) {
rewardsTile.textContent = "Earned rewards:"
if (node.id === 'self-comp-percentage') {
addHeart();
} else if (node.id === 'pers-percentage') {
addAxe();
window.addEventListener('keydown', rotateAxe)
For 'keydown' events, a different event object is created, which includes the key that was pressed down as a property. Similar to the way I console logged the event object in response to the 'click' event, console logging the event object here leads me toward some conditional logic to use:
Notice the key:
and "ArrowLeft"
property. Along with the event object automatically passed into the callback function, in which I use 'e' as a parameter in the callback function itself, I toyed with e.key
to determine which direction the axe should rotate, using conditional logic:
function rotateAxe(e) {
const axeNode = document.getElementById('axe')
if (e.key === 'ArrowLeft') {
axeRotation-=45
} else if (e.key === 'ArrowRight') {
axeRotation+=45
}
axeNode.style.transform = `rotate(${axeRotation}deg)`
}
Final Note
Event objects are confusing. When I was first introduced to this topic, I couldn't wrap my head around how an object was automatically created and passed into callback functions. How was it passed into the callback function if i didn't explicitly pass it in? Why call it 'e' or 'event'? What is all this information dump that I have to work with? What else can I use in e.target
? These questions are okay, and to not have immediate answers to them is more than okay. I did learn a lot of technical mumbo jumbo through this mini-project, but most importantly, I learned to not be intimidated by the questions that lead to other questions.
Top comments (0)