I have an XML DB with movies. Each movies comes with a picture. On click on the picture modal opens and in the modal you can see the information about the movie. With the following code I am able to iterate over all my pictures, which are buttons.
btn.forEach(element => {
element.addEventListener("click", () => {
modal.style.display = "block";
} );
} );
Problem is, this opens the same modal all the time, meaning, the content is not dynamically changing, depending on the movie I click. I tried the following
btn.forEach(element => {
element.addEventListener("click", () => {
modal.forEach(item => {
item.style.display = "block";
});
});
});
But this changes the content to the last on the data base, showing again same modal all the time and also breaking the close span for all modals. How do I show a correct modal for each movie?
I would recommend not to use arrow functions here because of context or so to say binding 'this' the best way is to use a plain old function and some DOM traversing
The thing is you havent supplied code for btn so I don't know how are you selcting all buttons but I would do it like so:
Array.from(document.getElementsByClassName('btn')).map(btn => btn.addEventListener('click', function(){
const theContainer = this.closest('.container')
theContainer.getElementsByClassName('modal')[0].classList.add('show')
theContainer.getElementsByClassName('close')[0].onclick = function(){
this.closest('.modal').classList.toggle('show')
}
}))
.modal {
display: none;
}
.show {
display: block;
border: 1px solid red;
}
<div class='container'>
<div class='modal'>
<p> modal </p>
<button class='close'>X</button>
</div>
<button class='btn'>0</button>
</div>
<div class='container'>
<div class='modal'>
<p> modal 1</p>
<button class='close'>X</button>
</div>
<button class='btn'>1</button>
</div>
<div class='container'>
<div class='modal'>
<p> modal 2</p>
<button class='close'>X</button>
</div>
<button class='btn'>2</button>
</div>
<div class='container'>
<div class='modal'>
<p> modal 3</p>
<button class='close'>X</button>
</div>
<button class='btn'>3</button>
</div>
Related
I am currently learning a bit of JavaScript, and doing a project I have run into a problem. My HTML code would be something like this:
<div class="main">
<button id="button1" onclick="hideBlock()">Hide Block 1</button>
<div id="block1"></div>
<button id="button2" onclick="hideBlock()">Hide Block 2</button>
<div id="block2"></div>
</div>
What I want is that with each button I can show and hide each block. This is the JavaScript code for the first block I have written:
function hideBlock() {
var block = document.getElementById("block1");
if (block.style.display === "none") {
block.style.display = "block";
} else {
block.style.display = "none";
}
}
And this works, but I think it is not correct to repeat the code for each block. How could I connect each button with its respective block to do everything from the same code? Thanks a lot.
Navigate to the adjacent block by using nextElementSibling, and attach the event listeners properly by using addEventListener instead:
for (const button of document.querySelectorAll('button')) {
button.addEventListener('click', () => {
button.nextElementSibling.classList.toggle('hidden');
});
}
button {
display: block;
}
.hidden {
display: none;
}
<div class="main">
<button>Hide Block 1</button>
<div>block 1</div>
<button>Hide Block 2</button>
<div>block 2</div>
</div>
I have numerous buttons on a page. Each is related to its own separate div on the page. When button 1 is clicked div 1 is shown. When button 2 is clicked div 2 is shown and so on.
What's the best way to write the following jQuery below, so I don't have to keep writing a new function for every new button and new div that will need to be added?
$("#bio-1").click(function () {
$('.one').toggle();
});
$("#bio-2").click(function () {
$('.two').toggle();
});
$("#bio-3").click(function () {
$('.three').toggle();
});
$("#bio-4").click(function () {
$('.four').toggle();
});
You can try using data-* attribute which on clicking you can use to find only the specific element to toggle.
Demo:
$("[id^=bio-").click(function () {
$(`div[data-id=${this.id}]`).toggle();
});
div{
width: 100%;
border: 1px solid lightgray;
margin: 5px;
padding: 2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="bio-1">Button-1</button>
<button id="bio-2">Button-2</button>
<button id="bio-3">Button-3</button>
<button id="bio-4">Button-4</button>
<div class="one" data-id="bio-1">One</div>
<div class="two" data-id="bio-2">Two</div>
<div class="three" data-id="bio-3">Three</div>
<div class="four" data-id="bio-4">Four</div>
It depends on how you initialize your display... hidden or all visible divs. This is like a toggle based on a common identifier that would let you keep your actual HTML code and shorten and organize your javascript code.
To use a toggle function, you should initialize your styles following the expected visibility logic.
$('div[data-id!=""]').hide();
$("[id^=bio-]").on("click", function () {
$('div[data-id!=""]').hide();
$('div[data-id="'+$(this).data('id')+'"]').show();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="bio-1" data-id="1">One</button>
<button id="bio-2" data-id="2">Two</button>
<button id="bio-3" data-id="3">Three</button>
<button id="bio-4" data-id="4">Four</button>
<div class="one" data-id="1">One</div>
<div class="two" data-id="2">Two</div>
<div class="three" data-id="3">Three</div>
<div class="four" data-id="4">Four</div>
Demo
you have to used toggle as well as show jquery function.
$(".clickBUtton").click(function () {
var id = this.id; // click class id
$("#DIV"+id).show(); // toggle and you also add show
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<button class="clickBUtton" id="one">ONE</button>
<button class="clickBUtton" id="two">TWO</button>
<div id="DIVone" style="display:none;">one div</div>
<div id="DIVtwo" style="display:none;">two div</div>
<div class="gallery-container">
<?php while (have_rows('gallery')): ?>
[...]
<div class="toggle-container">
<button class="toggle-button active" onclick="gridView()">Grid</button>
<button class="toggle-button" onclick="listView()">List</button>
</div>
<div class="gallery-items grid-items">
[...Gallery Items...]
</div>
<?php endwhile; ?>
</div>
What would be the best way to select specific elements on a page when the elements are created with a while loop shown above. It's an ever-growing list and elements can also be removed.
In this example I am generating a page full of small galleries together with the toggle buttons for the Grid/List view next to each gallery.
I am trying to make all of those buttons work with just the gallery they are generated together with.
I know how to select them based on their index manually, but I don't know how I could tweak the code to be able to make it work with every small gallery separately.
This is what I came up with to make it work with the first gallery:
<script>
const button = document.getElementsByClassName('toggle-button');
const element = document.getElementsByClassName('gallery-items');
function listView() {
if ( element[0].classList.contains('grid-items') ){
element[0].classList.remove("grid-items");
}
button[0].classList.toggle('active');
button[1].classList.toggle('active');
}
function gridView() {
if ( !element[0].classList.contains('grid-items') ){
element[0].classList.add("grid-items");
}
button[0].classList.toggle('active');
button[1].classList.toggle('active');
}
</script>
You might consider using event delegation instead: add a click listener to .gallery-container. If the clicked target is a .toggle-button, run the appropriate logic, selecting the relevant surrounding elements on click:
document.querySelector('.gallery-container').addEventListener('click', ({ target }) => {
if (!target.matches('.toggle-button')) {
return;
}
const toggleContainer = target.parentElement;
const btns = toggleContainer.children;
if (target === btns[0]) {
btns[0].classList.add('active');
btns[1].classList.remove('active');
} else {
btns[0].classList.remove('active');
btns[1].classList.add('active');
}
const galleryItems = toggleContainer.nextElementSibling;
if (target === btns[0]) {
galleryItems.classList.add('grid-items');
} else {
galleryItems.classList.remove('grid-items');
}
});
.active {
background-color: yellow;
}
.grid-items {
background-color: red;
}
<div class="gallery-container">
<div class="toggle-container">
<button class="toggle-button active">Grid</button>
<button class="toggle-button">List</button>
</div>
<div class="gallery-items grid-items">
[...Gallery Items...]
</div>
<div class="toggle-container">
<button class="toggle-button active">Grid</button>
<button class="toggle-button">List</button>
</div>
<div class="gallery-items grid-items">
[...Gallery Items 2...]
</div>
</div>
Note that there's no need to explicitly test if a classList.contains a particular class before adding it (though, there's no harm in doing so, it's just unnecessary).
I have created a popover so that if I click on the image the popover should appear.
The popover is working. what my main problem is I have inserted buttons in the popover.
so I want to write javascript or jquery code for the button when it is clicked. Can anyone help on this?
I have tried but it's not working!!!!
$(function() {
$('button').click(function() {
var x = $(this).attr('class');
alert(x);
});
});
$(function() {
$("[data-toggle=popover]").popover({
html: true,
container: 'body',
content: function() {
var content = $(this).attr("data-popover-content");
return $(content).children(".popover-body").html();
},
title: function() {
var title = $(this).attr("data-popover-content");
return $(title).children(".popover-heading").html();
},
placement: "auto"
});
});
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="./isobar.js">
</script>
<span>
<img src="./img/more_options_icon.png" data-toggle="popover" tabindex="5" data-trigger="focus" data-popover-content="#moreoptions">
</span>
<div id="moreoptions" class="hidden">
<div class="popover-body">
<div class="list-group">
<button type="button" class="list-group-item"><span class="gap"></span>Edit</button>
<button type="button" class="list-group-item"><span class="gap"></span>Logic Builder</button>
<button type="button" class="list-group-item"><span class="gap"></span>Uneploy</button>
</div>
</div>
</div>
O.k. Here is an updated version of my answer and checked and working code. A secret of a popover is to fire the correspondence function in a right time with a popover firing. So the JS code is:
function firePopover() {
$('.hidden').css('display', 'block');
var delay = 100;
setTimeout(function () {
$('button:not(.main)').unbind('click');
$('button:not(.main)').click(function () {
var x = $(this).attr('class');
alert(x);
$('.hidden').css('display', 'none');
});
}, delay);
}
Here I an using html selector
:not(.main)
to prevent binding and unbinding events to the main button. In addition, we have to pay attention on the fact that every popover rising binds a new event handler to each button. This means that after n popover risings every button will fire it's alert n times. To prevent this effect, it is possible to bind events in the first rising only, or as I did, to unbind an event from a button every popover rising. As to html code, here it is:
<button class="main" onclick="firePopover()">Fire Popover</button>
<div id="moreoptions" class="hidden" hidden>
<div class="popover-body">
<div class="list-group">
<button class="class-0 list-group-item"><span class="gap"></span>Edit</button>
<button class="class-1 list-group-item"><span class="gap"></span>Logic Builder</button>
<button class="class-2 list-group-item"><span class="gap"></span>Uneploy</button>
</div>
</div>
</div>
I only added the ".main" button to accept a simulation, and each button got additional corresponding class "class-0", "class-1", "class-2" for successful demonstration. Now, when you push on the main button, other 3 buttons appear. And to the contrary, pushing on any of those 3 buttons, is following by alert firing and disappearing of all of them. I hope this will help you.
function firePopover() {
$('.hidden').css('display', 'block');
var delay = 100;
setTimeout(function () {
$('button:not(.main)').unbind('click');
$('button:not(.main)').click(function () {
var x = $(this).attr('class');
alert(x);
$('.hidden').css('display', 'none');
});
}, delay);
}
.hidden {
display: none;
}
button {
float: left;
}
.class-0 {
clear: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<button class="main" onclick="firePopover()">Fire Popover</button>
<div id="moreoptions" class="hidden" hidden>
<div class="popover-body">
<div class="list-group">
<button class="class-0 list-group-item"><span class="gap"></span>Edit</button>
<button class="class-1 list-group-item"><span class="gap"></span>Logic Builder</button>
<button class="class-2 list-group-item"><span class="gap"></span>Uneploy</button>
</div>
</div>
</div>
I am creating a mobile web app, I have a login/ signup page where users can choose the method they want.
In order to reduce the refresh rate of pages I am hiding and showing objects depending on what the user clicks with jquery.
I have virtual back buttons on each of the 'pages' which hide/show the objects including the back buttons themselves, each time I need to add an extra 'page' I have to add and call the different buttons.
Is there a way I can have one button and use that depending on what elements are hidden/shown?
e.g
html
<div id="go_button"</div>
<div id="next_button"</div
<div id="backbutton1"</div>
<div id="backbutton2"</div>
<div id="page1"
<p> some information here </p>
</div>
<div id="page2"
<p> some more information here </p>
</div>
jQuery
$("#gobutton").click(function(){
$('#backbutton1').fadeIn(250);
$('#page1').fadeIn(250);
$('#next_button').fadeIn(250);
});
$('#next_button').click(function(){
$('#backbutton1').hide();
$('#backbutton2').show();
$('#page1').fadeOut(250);
$('#page2').fadeIn(250);
$('#next_button').fadeOut(250);
$("#backbutton1").click(function(){
$('#backbutton1').fadeOut(250);
$('#page1').fadeOut(250);
$('#next_button').fadeOut(250);
});
etc etc
Would something like this work for you?
I checked the currently visible page, and based on that and what button is clicked, it would go forward or back.
var
$go = $('#go_button'),
$next = $('#next_button'),
$back = $('#backbutton'),
$pages = $('div[id^=page]');
$go.click(function() {
$next.fadeIn(250);
$back.fadeIn(250);
$pages.first().fadeIn(250);
});
$next.click(function() {
var $current = $pages.filter(':visible'); // Get currently visible page
if (!$current.is($pages.last())) { // If this is not the last page, do something
$current
.hide() // hide current page
.next() // get next page
.fadeIn(250); // fade in next page
}
});
// Opposite of the $next.click
$back.click(function() {
var $current = $pages.filter(':visible');
if (!$current.is($pages.first())) {
$current
.hide()
.prev()
.fadeIn(250);
}
});
div[id^=page] {
padding: 5px 10px;
border: 1px solid #ddd;
display: none;
}
#next_button,
#backbutton {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="go_button">go</button>
<button id="next_button">next</button>
<button id="backbutton">back</button>
<div id="page1">
<p> 1 some information here </p>
</div>
<div id="page2">
<p> 2 some more information here </p>
</div>
<div id="page3">
<p> 3 more information here </p>
</div>
<div id="page4">
<p> 4 more! more! more! more!</p>
</div>
Make a function ..
function operation(name){
if(name == "go_button"){
//operation
}else if(name == "next_button"){
//do this.
}
}
now in html
<div id="go_button" onclick="operation('go_button')" > </div>
<div id="next_button" onclick="operation('next_button')" ></div