It is a simple thing that is taking me a lot of time.
I want to open a modal when clicking on any product image:
This is the HTML of the page:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="icon" th:href="@{/favicon_heladeria.png}" />
<link rel="stylesheet" th:href="@{/vendor/materialize/css/materialize.css}" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<link rel="stylesheet" th:href="@{/app.css}" />
<title>Copito de Nieve | Home</title>
</head>
<body>
<div class="navbar-fixed">
<nav>
<div class="container">
<a th:href="@{/}" class="brand-logo">Heladeria</a>
<a href="#" data-activates="mobile-nav" class="button-collapse right"><i class="material-icons">menu</i></a>
<ul class="right hide-on-med-and-down">
<li class="active"><a th:href="@{/}">Home</a></li>
<li><a th:href="@{/gustos}">Gustos</a></li>
<li><a th:href="@{/ingresar}">Ingresar</a></li>
</ul>
<ul id="mobile-nav" class="side-nav">
<li class="active"><a th:href="@{/}">Home</a></li>
<li><a th:href="@{/gustos}">Gustos</a></li>
<li><a th:href="@{/ingresar}">Ingresar</a></li>
</ul>
</div>
</nav>
</div>
<div class="search-bar container">
<div class="row">
<div class="col s12">
<form action="#" method="get">
<div class="input-field">
<input name="q" type="search" placeholder="Buscar todos los helados..." required="required" autocomplete="off"/>
<i class="material-icons">search</i>
</div>
</form>
</div>
</div>
</div>
<div>
<h2 class="mid-title">Productos</h2>
</div>
<div class="helados container">
<div class="row">
<div th:each="producto : ${productos}" class="col s12 l4">
<img id="prod-img" th:src="@{'/images/' + ${producto.nombre} +'.png'}" />
<p class="product-name" th:text="${producto.nombre}"></p>
<p class="desc" th:text="${producto.descripcion}"></p>
</div>
</div>
</div>
<!-- Modal -->
<div id="prodModal" class="modal">
<div>
<div class="modal-content">
<h4 class="modal-title">Haga su pedido</h4>
<p class="flavour" th:each="gusto : ${gustos}" th:text="${gusto.nombre}"></p>
</div>
</div>
</div>
<script th:src="@{/vendor/jquery/jquery-1.11.3.js}"></script>
<script th:src="@{/vendor/materialize/js/materialize.js}"></script>
<script th:src="@{/home.js}"></script>
</body>
</html>
Clicking the modal opens with all the ice cream flavors from the database as expected, the problem is that it opens whenever you click anywhere on the page and not when you click on the images, which is how it should open
This is my JS:
var prodImages = document.querySelectorAll('#prod-img');
console.log(prodImages);
prodImages.forEach(elm => {
addEventListener('click', () => {
var element = document.querySelector('#prodModal');
var modal = M.Modal.init(element, {});
modal.open();
}, false);
});
I'm using the materialize library and I think the materialize.js is the one doing the mess.
Here you should not occupy IDs, if not classes
Anyway, continuing with your code, by not putting the listener in the element, by default it takes the window or document, so that was it:
Update: event.stopPropagation;
Stop propagation applies when there are nested objects. Suppose we have a
<div><img /></div>
And both
div
eimg
have eventsclick
however if you click insideimg
, this causes a click to be madediv
and may not be what you want.stopPropagation()
It helps prevent that, and respect only the click in the designated area.Other things come into play here, such as position, z-index, visibility, etc.