JS DOM - 03.03 - Events Practice

Attaching Listeners to group of nodes

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
		});
});

Hiding a div with button click

<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>

Self hiding button

<input type='button' onclick='this.hidden=true'  value='Click to hide'>

A Drop-down list

<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:blocktakes 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');
};

Move the ball across the field

<!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>

Add a closing button

position: abolute

Carousel

a image carosel to scroll through