Multiple ID's for getElementById - javascript

See this code:
https://www.w3schools.com/code/tryit.asp?filename=FFFP03OMYA94
I've got two buttons (or even more). When I click on the first button, it should display the first div. When I click on the second button, it should display the other div.
This is only a snippet of my problem. I want to achieve, that when I click on a button, then it should open the div with the passed ID. Normally I have an unique ID, so I could also save the ID like this:
<div id="myModal+${person.id}" class="modal">
My problem is: How can I pass the ID to my javaScript and open the specific div for the passed ID?

You can store this ID in a data-* attribute, like this:
// Here, I used a class for the buttons, since there are multiple ones
var btns = document.getElementsByClassName('myBtn'),
// These variables will hold the currently open modal and close button
modal, closeBtn;
// For each button
for(var i=0; i<btns.length; i++) {
// On click
btns[i].addEventListener('click', function(){
// Get the modal ID
var modalId = this.getAttribute('data-modal');
// Retrieve the corresponding modal
modal = document.getElementById(modalId);
// Retrieve the close button
closeBtn = modal.querySelector('.close');
// Show the modal
modal.style.display = "block";
}, false);
}
window.addEventListener('click', function(event) {
// If we clicked on the backdrop or the close button
if (event.target == modal || event.target == closeBtn) {
// Hide the modal
modal.style.display = "none";
}
}, false);
.modal{display:none;position:fixed;z-index:1;padding-top:100px;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,.4)}.modal-content{background-color:#fefefe;margin:auto;padding:20px;border:1px solid #888;width:80%}.close{color:#aaa;float:right;font-size:28px;font-weight:700}.close:focus,.close:hover{color:#000;text-decoration:none;cursor:pointer}
<h2>Modal Example</h2>
<button class="myBtn" data-modal="myModalA">Open Modal A</button>
<div id="myModalA" class="modal"><div class="modal-content"><span class="close">×</span><p>This is myModalA</p></div></div>
<button class="myBtn" data-modal="myModalB">Open Modal B</button>
<div id="myModalB" class="modal"><div class="modal-content"><span class="close">×</span><p>This is myModalB</p></div></div>
<button class="myBtn" data-modal="myModalC">Open Modal C</button>
<div id="myModalC" class="modal"><div class="modal-content"><span class="close">×</span><p>This is myModalC</p></div></div>
<button class="myBtn" data-modal="myModalD">Open Modal D</button>
<div id="myModalD" class="modal"><div class="modal-content"><span class="close">×</span><p>This is myModalD</p></div></div>

Related

How to addeventlistener to modal buttons in handlebars template

I am creating a web app that connects to a news API and shows articles.
For each article, I have created a card and a modal in handlebars.
Upon clicking the button on each respective card, I would like a modal to open with its unique information.
I am trying to add an event listener for the button on the card to open the modal.
<div class="">
{{!-- #each article --}}
<div class="row">
{{#each articles}}
<div class="col-12-sm col-6-md col-3-lg">
<div class="card m-2">
<div class="card-body">
<h5 class="card-title">{{title}}</h5>
<p class="card-text">{{description}}</p>
</div>
<img class="card-image" src="{{urlToImage}}" alt="Card image cap">
<button id="mybtn" class="{{#index}}">Open Modal</button>
{{#index}}
</div>
</div>
{{/each}}
</div>
</div>
{{#each articles}}
<!-- The Modal -->
<div id="modid" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..</p>
</div>
</div>
{{/each}}
<script>
let modal = document.getElementById("modid");
let btn = document.getElementById("mybtn");
let span = document.getElementsByClassName("close")[0];
btn.onclick = function() {
modal.style.display = "block";
}
span.onclick = function() {
modal.style.display = "none";
}
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
const btn = document.querySelector('.{{#index}}');
btn.addEventListener('click', function(event){
console.log('Button Clicked');
}
</script>
Clicking on the "Open Modal" button does nothing, nor does it give an error.
I am unsure if the button class {{#index}} is being read properly by the script.
Any assistance or tips would be greatly appreciated!
First, I think a better approach than using class="{{#index}} on each button would be to use a data-attribute, like data-open-modal="{{#index}}". This will allow us to use a query selector to get all of the open modal buttons as well as allow us to get the specific index in our click handler.
Next, we cannot use a single id for each of our modal elements as you are doing with id="modid". This leads to multiple elements with the same id, "modid", which is invalid HTML. Also, it prevents us from specifying which modal we want to open. Let's just remove that id.
In our JavaScript, we can select all of the open modal buttons and modals and store them in variables:
const openModalButtons = document.querySelectorAll('[data-open-modal]');
const modals = document.querySelectorAll('.modal');
Next, we can loop through all of openModalButtons and assign a click handler to each.
openModalButtons.forEach(openModalButton => {
openModalButton.addEventListener('click', (event) => {
const openIndex = Number(event.target.dataset.openModal);
modals.forEach((modal, index) => {
modal.classList.toggle('open', index === openIndex);
modal.classList.toggle('closed', index !== openIndex)
});
});
});
Notice that our click handler gets the data-open-modal index value from the button that was clicked. This is the index of the modal to show.
Next, it loops over each modal element and sets the "open" class if the index is equal to the index we want to show; otherwise, it sets the "closed" class.
I have created a fiddle for reference.
Update: To handle "close" button clicks:
The close button is very similar to the open button. You would need to attach an event listener and you would need a way to know which modal element to target. We could use a data-attribute again, like <button class="close" data-close-modal="{{#index}}">×</button>. Note: To be semantically correct, a close button should be a <button element, not a <span>.
Our click event listener for the close buttons would be very similar to that of the open buttons. This time, however, we won't loop through all of the modals; we will just update the modal whose index in the array of modal elements is equal to the data-close-modal attribute value of the clicked close button.
const closeModalButtons = document.querySelectorAll('[data-close-modal]');
closeModalButtons.forEach(closeModalButton => {
closeModalButton.addEventListener('click', (event) => {
const closeIndex = Number(event.target.dataset.closeModal);
modals[closeIndex].classList.remove('open');
modals[closeIndex].classList.add('closed');
});
});
Note: You may very well not require an .open and a .closed class for you modals - one may be sufficient. This is just an example.
An updated fiddle has been creeated.

How to adjust JavaScript for modal window

I need to make a modal window appear when I click on the button. I wrote a post view and added a button and a W3Schools script to display the modal window. It turned out something like:
<% #posts.each do |post| %>
<div class="row">
<div class="leftcolumn">
<div class="card">
<h2 lang="ru"><%= post.title %></h2>
<p lang="ru"><%= post.body %></p>
<button id="myBtn">Open Modal</button> <!-- taken from the site -->
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p><%= post.translation %></p>
</div>
</div>
</div>
</div>
</div>
<% end %>
<script>
// Get the modal
var modal = document.getElementById("myModal");
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks on the button, open the modal
btn.onclick = function () {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function () {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function (event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
Everything works fine, but only for the very first post. The script processes only the very first button. I think I know why this happens, but how do I fix it? It seems that getElementById is taken here when creating variables.
getElementById will only ever return the first element that matches the given id. It is generally assumed that each ID given to an element is unique. That is what is happening.
If you need to have a unique modal for each post, then you could append each id of the modal with the id of the post, this ensures they are unique.
You should also get rid of all the global variable for modal, button, span, since they are only ever referencing the same element.
Give your <button> and onclick attribute and call a function and pass in the unique id of the post, that should let you locate all the appropriate elements for that post.
<button id="myBtn_<%= post.id %>" onclick="showModal(<%= post.id %>);">Open Modal</button>
function showModal(id) {
var modal = document.getElementById("myModal_" + id);
var btn = document.getElementById("myBtn_" + id);
// show your modal and anything else that happens on click
}
You should update span to be similarly selectable instead of just having a class.
Hope that helps!

How to determine which modal to open from multiple modals?

I'm making a webpage with a lot of references. I want to open modal when pressed on one reference to show more data about that said reference. I achieved that with one reference, but now when I have more references inserted it wont open other modals but always the same one if I do it with class, if I leave id (yea I know, I wasn't thinking ahead and did this with id) it will only open the first one, others wont even open.
Here is my HTML code:
<!-- reference item -->
<div class="grid-item set-bg osobj" data-setbg="img/portfolio/1.jpg">
<a id="myBtn"></a>
<div id="myModal" class="modal1">
<!-- Modal content -->
<div class="modal1-content">
<span class="close1">×</span>
<h2>REFERENCE NAME</h2>
<div class="post1-container">
<div class="post1-content">
<p>nekitext</p>
<h3>Neki header</h3>
</div>
</div>
</div>
</div>
</div>
<!-- reference item -->
<div class="grid-item set-bg osobj" data-setbg="img/portfolio/1.jpg">
<a id="myBtn"></a>
<div id="myModal" class="modal1">
<!-- Modal content -->
<div class="modal1-content">
<span class="close1">×</span>
<h2>REFERENCE NAME</h2>
<div class="post1-container">
<div class="post1-content">
<p>nekitext</p>
<h3>Neki header</h3>
</div>
</div>
</div>
</div>
</div>
and here is my JS:
var modal = document.getElementById('myModal');
// Get the button that opens the modal
var btn = document.getElementById("myBtn");
console.log(btn);
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close1")[0];
// When the user clicks on the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
I've tried using onclick event to determine which tag is myBtn but in this case it only works for one modal. Others wont open or work.
PS: I have modals pinned on an image.
EDIT:
I know I have multiple IDs and that IDs are unique in HTML. I didn't plan this ahead enough as I thought I'll have only one item and now I have multiple and the system collapsed. There has to be a better way to do this than to give each item a different id, right?
EDIT2:
I DO NOT WANT TO USE IDs. The question is about javascript as to how to determine which modal to open. If I do it with classes it will open only one modal that always has the same content.
You will want to give each button a common class name, i.e.:
<a class="myButton"></a> // For the buttons
And then loop through those (and the closing span's) and add an event listener to each one, i.e.:
const buttons = document.querySelectorAll(".myButton");
const spans = document.querySelectorAll(".close1");
for(let i=0; i< buttons.length; i++) {
buttons[i].addEventListener("click", openModal);
}
for(let i=0; i< spans.length; i++) {
spans[i].addEventListener("click", closeModal);
}
function openModal(e) {
e.preventDefault();
const currentModal = e.currentTarget.parentNode.getElementsByClassName("modal1")[0];
currentModal.style.display = "block";
}
function closeModal(e) {
const currentModal = e.currentTarget.closest(".modal1");
currentModal.style.display = "none";
}
This will find the closest modal to the button that was clicked, and toggle that instead of a hardcoded reference to a modal ID.
EDIT - See it in action
Hope that helps!

How do I display different modal/modal content when I clicking on the different Icons (Not Bootstrap)

I would like to get the other icons to work how the "Operations Management" is working. But I want it to say different things.
PLEASE HELP :(
Here is my fiddle : https://jsfiddle.net/RonaLochner/p4kt6oy1/
The Code:
<div class='circle-container'>
<a href='#' class='center'>
<h4 style="text-align:center;">Microsoft Dynamics 365</h4>
</a>
<div id="operations-management">
<img src='http://www.businesscentral.co.za/wp-content/uploads/2018/08/Business-Solutions-Icon2.png'>
</div>
<div id="reporting">
<img src='http://www.businesscentral.co.za/wp-content/uploads/2018/08/Business-Solutions-Icon3.png' id="myBtn">
</div>
<div id="supplychain">
<img src='http://www.businesscentral.co.za/wp-content/uploads/2018/08/Business-Solutions-Icon4.png' id="myBtn">
</div>
<div id="sales">
<img src='http://www.businesscentral.co.za/wp-content/uploads/2018/08/Business-Solutions-Icon5.png' id="myBtn">
</div>
<div id="financial">
<img src='http://www.businesscentral.co.za/wp-content/uploads/2018/08/Business-Solutions-Icon6.png' id="myBtn">
</div>
<div id="project">
<img src='http://www.businesscentral.co.za/wp-content/uploads/2018/08/Business-Solutions-Icon1.png' id="myBtn">
</div>
</div>
The model:
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>OPERATIONS MANAGEMENT</p>
</div>
</div>
The Script
<script>
// Get the modal
var modal = document.getElementById('myModal')
// Get the button that opens the modal
var btn = document.getElementById("operations-management");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close")[0];
// When the user clicks the button, open the modal
btn.onclick = function() {
modal.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span.onclick = function() {
modal.style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
</script>
I have tried to target using different ID's but not sue how to fix this.
So first thing you want to do is add a class to each of the icons/buttons like so;
<div class="toggle" id="operations-management">
<img src='http://www.businesscentral.co.za/wp-content/uploads/2018/08/Business-Solutions-Icon2.png'>
</div>
Then you want to call them using querySelectorAll and convert it to array
// Get the button that opens the modal
var btns = Array.from(document.querySelectorAll(".toggle"));
We convert it to array because querySelectorAll returns a node list but we need an array to iterate through all the buttons so thats where the Array. So then we itierate over all of the buttons and add a event listener that points to a new function showModal
btns.forEach(function(btn) {
btn.addEventListener("click", showModal);
});
The showModal function will show the modal.
function showModal(e) {
modal.style.display = "block";
}
now you have you probably want to have different content in each modal right? I would make the p tag in your modal with an id and then using the (e) variable from the showModal function I would find the id of the button and then have an if statment that would change the modal p tag depending on the id that is passed from e. (if you set console.log(e) just before I set the modal.style.display you will see an object and there you can find the id.

Modal with link

I use a modal I got from w3school and I modified it to put several modals on the same page.
I would like to know if I can make these modals generate their own links.
Example: I open modal 4 and the page link will change to mywebsite.com/modal4
The code I use is more or less like this
JS
// Get the modal
var modal = document.getElementsByClassName('modal');
// Get the button that opens the modal
var btn = document.getElementsByClassName("myBtn");
// Get the <span> element that closes the modal
var span = document.getElementsByClassName("close");
// When the user clicks the button, open the modal
btn[0].onclick = function() {
modal[0].style.display = "block";
}
btn[1].onclick = function() {
modal[1].style.display = "block";
}
// When the user clicks on <span> (x), close the modal
span[0].onclick = function() {
modal[0].style.display = "none";
}
span[1].onclick = function() {
modal[1].style.display = "none";
}
// When the user clicks anywhere outside of the modal, close it
window.onclick = function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
}
HTML
<h2>Modal Example1</h2>
<!-- Trigger/Open The Modal -->
<button id="myBtn" class="myBtn">Open Modal1</button>
<!-- The Modal -->
<div id="myModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span class="close">×</span>
<p>Some text in the Modal..1</p>
</div>
</div>
<h2>Modal Example2</h2>
<!-- Trigger/Open The Modal -->
<button id="myBtn" class="myBtn">Open Modal2</button>
<!-- The Modal -->
<div id="myModal2" class="modal">
<!-- Modal content -->
<div class="modal2-content">
<span class="close">×</span>
<p>Some text in the Modal..2</p>
</div>
</div>
You can change the current URL of the page when opening the modal, as seen in this answer: Modify the URL without reloading the page. To load the modal if you go to mywebsite.com/modal4, you can write some js logic to get the link, see if it addresses a modal, and then open that modal.
You may have to write some backend code to handle links like that, however, you can try to pass link parameters and then use js to parse the parameters out of the link string: How to get the value from the GET parameters?
As JagdeeshKumar pointed out below, you can also navigate to website.com/htmlpage.html#modal4, and you can use js to get that location and load up the modal. See https://www.w3schools.com/jsref/prop_loc_hash.asp
you can use
your URL will be like root/#modal4window.location.hash = 'something';

Categories