Title here
Summary here
We can get a NodeList of all the items matching a specific selector with querySelectorAll("selector")
.
In order to add listeners to each of them, we need to iterate through the whole list.
<div id= "container">
<button id="one">Click Me</button>
<button id="two">Click Me</button>
<button id="three">Click Me</button>
</div>
const buttons = document.querySelectorAll("button");
// buttons is now a nodelist, somewhat like an array
// using .forEach method to iterate through each button
buttons.forEach( (button) => {
button.addEvenetListener("click", () => {
alert(button.id);
// for each one we add a 'click' listener
});
});
<input type='button' id='hider' value='Click to hide text' />
<div id='text'>Text Here</div>
<script>
let btn = document.querySelector('#hider');
btn.addEventListener( 'click', () => {
document.querySelector('#text').hidden = true;
});
btn.addEventListener( 'click', () => {
let text = document.querySelector('#text');
text.style.display = 'none';
</script>
<input type='button' onclick='this.hidden=true' value='Click to hide'>
<div class='menu' id='sweets'>
<span class='title'>Sweets (Click me)</span>
<ul>
<li>Cake</li>
<li>Chololate</li>
<li>Honey</li>
</ul>
</div>
span
is used instead of div
because it is display:block
takes up all horizontal space so clicking anywhere can trigger the event.
span
has display:inline
so only occupies enough space for the text.
.menu ul {
margin: 0;
list-style: none;
padding-left: 20px;
display: none;
}
.menu .title {
font-size: 18px;
cursor: pointer;
}
.menu .title::before {
content: '▶ ';
font-size: 80%;
color: green;
}
.menu.open .title::before {
content: '▼ ';
}
.menu.open ul {
display: block;
}
let menu = document.querySelector('#sweets');
let title = menu.querySelector('.title');
title.onclick = function() {
menue.classList.toggle('open');
};
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<style>
#field {
width: 200px;
height: 150px;
border: 10px solid black;
background-color: #00FF00;
position: relative;
overflow: hidden;
cursor: pointer;
}
#ball {
position: absolute;
left: 0;
top: 0;
width: 40px;
height: 40px;
transition: all 1s;
}
</style>
</head>
<body style="height:2000px">
Click on a field to move the ball there.
<br>
<div id="field">
<img src="https://en.js.cx/clipart/ball.svg" id="ball">
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
</div>
<script>
field.onclick = function(event) {
// window-relative field coordinates
let fieldCoords = this.getBoundingClientRect();
// the ball has position:absolute, the field: position:relative
// so ball coordinates are relative to the field inner left-upper corner
let ballCoords = {
top: event.clientY - fieldCoords.top - field.clientTop - ball.clientHeight / 2,
left: event.clientX - fieldCoords.left - field.clientLeft - ball.clientWidth / 2
};
// prevent crossing the top field boundary
if (ballCoords.top < 0) ballCoords.top = 0;
// prevent crossing the left field boundary
if (ballCoords.left < 0) ballCoords.left = 0;
// prevent crossing the right field boundary
if (ballCoords.left + ball.clientWidth > field.clientWidth) {
ballCoords.left = field.clientWidth - ball.clientWidth;
}
// prevent crossing the bottom field boundary
if (ballCoords.top + ball.clientHeight > field.clientHeight) {
ballCoords.top = field.clientHeight - ball.clientHeight;
}
ball.style.left = ballCoords.left + 'px';
ball.style.top = ballCoords.top + 'px';
}
</script>
</body>
</html>
position: abolute
a image carosel to scroll through