Reputation: 27
There are 5 buttons where each button will do a different thing.
The first button will change a paragraph to green (in HTML file, Id="button1"
).
The second button will change a paragraph to blue (in HTML file, Id="button2"
).
window.onload = pageLoad;
function pageLoad() {
this.onclick = makeChange;
}
function makeChange() {
var paragraph = document.getElementById("paragraph");
if (this.id = "button1") {
paragraph.style.color = "green";
} else {
// change the color
}
}
This doesn't work because I can't get the id of the button, I tried to debug it using:
paragraph.innerHTML = this.id;// I got "undefined"
Is there anyway I can get which button is pressed, and based on which button is pressed, change the text color differently? I want to use only 1 function(exclude pageLoad)
to do this and I don't to have 5 variableS and 5 onclick
lines and no jquery.
var paragraph = document.GetElementById("button1");
var paragraph = document.GetElementById("button2");
var paragraph = document.GetElementById("button3");
....
Upvotes: 1
Views: 185
Reputation: 43910
Using an event listener to leverage Event Delegation has a few advantages over an on event (ex. onclick) property or attribute event handler:
Unlike on event handlers, event listeners can be used multiple times on multiple objects and elements.
By setting the 3rd parameter to true, you can listen for events in capture phase. It's rarely needed.
We can setup a pattern to take advantage of the 3 Event.eventPhases:
#set
) the event chain goes down the DOM tree to the end of this phase is...#btn*
).In simpler terms, e.target
is the element clicked, checked, changed, etc. This element will be the context related to the event, in many ways e.target
is like this
(in this demo, e.target
is one of the buttons and this
is the ancestor (fieldset#set
, e.cT)... e.target
, this context allows us to identify the clicked button)e.target
. This gives us a powerful and eloquent way to handle an unlimited amount of elements with a single event listener. No on event handler is capable of doing this under normal circumstances without the use of specialized interface.More details are commented in demo
/* Reference an ancestor element of all the buttons.
|| In this case the best choice would be
|| fieldset#set. You could also use <body>, document,
|| or even window, but the further the ancestor is,
|| the chances of unwanted behavior from other elements
|| become greater.
*/
var set = document.getElementById('set');
/* Register #set on the click event.
|| Now #set is considered the Event.currentTarget.
|| The e.cT (#set) will listen for the event (click)
|| to occur upon itself and any of its decsendants.
|| Once event occurs, #set (e.cT) will run the
|| callback function (findBtn).
*/
set.addEventListener('click', findBtn, false);
/* This is the callback function which is a normal
|| function that is called when a registered event
|| happens.
*/
function findBtn(e) {
// An array of 5 colors
var rainbow = ['purple', 'blue', 'green', 'yellow', 'red'];
// Reference to the paragraph (<p>)
var text = document.querySelector('p');
/* if e,target (the element clicked), is NOT
|| e.cT, then...
*/
if (e.target !== e.currentTarget) {
/*...and if e.T (Event.target) tagName is
|| 'BUTTON', then...
*/
if (e.target.tagName === 'BUTTON') {
// ...get the button's #id
var tgtID = e.target.id;
/* The id of each button is basically just
|| an index number. Although I do not
|| recommend it normally, it is valid to start
|| with a number for an #id.
|| This statement uses the style property to
|| access the paragraph's CSS color property
|| and changes the value according to the
|| index of the rainbow array which in turn is
|| determined by the e.T (button clicked) #id
*/
text.style.color = rainbow[tgtID];
}
}
// End function
return false;
}
<fieldset id='set'>
<legend>Event Delegation</legend>
<button id='0'>Purple</button>
<button id='1'>Blue</button>
<button id='2'>Green</button>
<button id='3'>Yellow</button>
<button id='4'>Red</button>
</fieldset>
<p>Click any of the five buttons to change this text.</p>
Upvotes: 1
Reputation: 1011
You could try something like this. Keep the color you want to change the paragraph to inside the button, using a custom data-*
attribute. Then access it with .getAttribute()
. So your JS would be something like this:
function makeChange() {
var paragraph = document.getElementById("paragraph");
var newColor = this.getAttrbiute('data-color');
paragraph.style.color = newColor;
}
And your buttons would be like this:
<button data-color="green">Green</button>
<button data-color="blue">Blue</button>
This way you can easily change the target color by changing the data-color
attribute.
As a side note, do make sure you're listening for the click event with your buttons, like this:
var buttons = document.querySelectorAll('button');
for (var i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', makeChange);
}
Upvotes: 1