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>
Related
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>
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>
I'm working on a simple page with 8 different languages, it's just a simple onepager.
All the text in the different languages are set in divs with a style="display:none" to be hidden, until the language is choosen then the div with that particular language is shown.
Currently the main language is English and that div is shown on pageload but when selecting a language will load the div UNDER the english div, but this need to be replaced.
I'm not good in Javascript, but found some codes here which I implemented, but it's still not working as it should be.
This is the JS code:
<script type="text/javascript">
var _hidediv = null;
function toggle_visibility(id) {
if(_hidediv)
_hidediv();
var div = document.getElementById(id);
div.style.display = 'block';
_hidediv = function () { div.style.display = 'none'; };
}
</script>
and in my language selector I've the following as example:
EN | ES | SV
What am I doing wrong here, the default language is english, so the div is as follows: and the other languages have style="display:none"
<div id="english" style="display:block">
How about using CSS to hide/show the divs and only use js/jQuery to change a class on body or any parent element?
$('button').click(function() {
$('#body').removeClass().addClass($(this).data('lang'));
});
.lang {
display: none;
}
#body.en .en {
display: block;
}
#body.es .es {
display: block;
}
#body.de .de {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="body" class="en">
<button data-lang="en">English</button>
<button data-lang="es">Spanish</button>
<button data-lang="de">German</button>
<div class="lang en">English</div>
<div class="lang es">Spanish</div>
<div class="lang de">German</div>
<br/>
<div class="lang en">English 2</div>
<div class="lang es">Spanish 2</div>
<div class="lang de">German 2</div>
</div>
You need to handle the default case of English language also. Only that's missing.
var _hidediv = null;
function toggle_visibility(id) {
if(_hidediv) {
_hidediv();
} else {
document.getElementById('english').style.display = 'none';
}
var div = document.getElementById(id);
div.style.display = 'block';
_hidediv = function () { div.style.display = 'none'; };
}
Language:
English
Spanish
Hindi
French
<div id="content">
<div id="english">
English
</div>
<div id="spanish" style="display: none;">
Spanish
</div>
<div id="hindi" style="display: none;">
Hindi
</div>
<div id="french" style="display: none;">
French
</div>
</div>
Problems in your code
_hidediv will never fire because it is always null.
Logic you used in _hidediv is wrong. It is supposed to set div.style.display = 'none' to other divs than the div you passing as parameter in 'toggle_visibility(id)'. According to your code, even if you manage to fire your _hidediv function, it will reset your target div from div.style.display = 'block' to div.style.display = 'none'.
A jQuery-based solution would work like in this example: https://codepen.io/shikifujin/pen/PowqOjB
You create CSS-classes for .language (hidden by default) and .language.active (visible):
div.language {
display: none;
}
div.language.active {
display: block;
}
Then, create all language divs with content like so (only the default one is given the active class) with the id= property containing the content's language:
<div id="english" class="language active">
english content
</div>
<div id="spanish" class="language">
contenido en espaƱol
</div>
Then you need to have jQuery sourced in your document, as well as the <script> below to make the language switching work. Once the DOM is loaded, all .switch-language elements (they do not need to be necessarily) need to have the id= attribute specify the language to switch to (exactly matching the id of the corresponding div):
EN
Once the entire DOM is loaded, or after the content and switching elements are present, you can enable the switcher by handling each click on any of them with the following actions:
get language to switch to from id (switchTo)
hide all content divs
show the desired one (with id switchTo)
This can be done with vanilla javascript, too, but I chose to use jQuery:
<script>
$(document).ready(function() {
$(".switch-language").on("click", function() {
var switchTo = $(this).data("language");
$(".language").hide();
$(".language#" + switchTo).show();
});
});
</script>
Again, you may try it out here: https://codepen.io/shikifujin/pen/PowqOjB
<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).
Now am using fade in fadeout to toggle the content on button click.
the script i used for the same is
function showHide(divId){
if (document.getElementById(divID).style.display == "none") {
$('#'+divID).fadeIn(3000);
} else {
$('#'+divID).fadeOut(3000);
}
}
how to modify the above code to show content on button click.
consider i have 2 buttons
<button> button1</button>
<button> button2</button>
<div id="div1"> content of button 1 </div>
<div id="div2" style="display:hidden"> content of button 2</div>
i wanna show either of the div, when button1 is clicked, button 2 content shouldn't be visible and vice verse.
Update showHide
function showHide(divID) {
$("div").not("#" + divID).fadeOut(3000);
Choosing to fade them out every time is fine since hiding a div would not show another. You should probably also give all of these divs a class and use that instead of just "div"
You can use the onclick event on button.
<button id="button1" onclick="ShowHideDiv(this);">button1</button>
<button id="button2" onclick="ShowHideDiv(this);">button2</button>
<div id="div1"> content of button 1 </div>
<div id="div2" style="display:hidden"> content of button 2</div>
In the script tag, this function can be used.
function ShowHide(element)
{
if ($(element).attr("id") == "button1")
{
$("#div1").fadeIn(3000);
$("#div2").fadeOut(3000);
}
else if ($(element).attr("id") == "button2")
{
$("#div2").fadeIn(3000);
$("#div1").fadeOut(3000);
}
}
If you want to hide all the divs except one, you can use code similar to the following:
$("div").fadeOut(3000);
This will hide all the divs.
Then this will show the proper div:
$("#divId").fadeIn(3000);
Use proper Id of div in divId
I'm a beginner at js, but try this:
HTML:
<button id="btn1"> button1</button>
<button id="btn2"> button2</button>
<div id="div1"> content of button 1 </div>
<div id="div2" class="hidden"> content of button 2</div>
CSS:
.hidden { display: none;}
JS:
$('#btn1').click(function(){
$('#div2').addClass('hidden');
$('#div1').removeClass('hidden');
})
$('#btn2').click(function(){
$('#div1').addClass('hidden');
$('#div2').removeClass('hidden');
})
Here's a demo.
Please change your HTML into this :
<button id="btn1" onclick="ShowHideDiv(this);"> button1</button>
<button id="btn2" onclick="ShowHideDiv(this);"> button</button>
<div id="div1" class='divShowHide'> content of button 1 </div>
<div id="div2" class='divShowHide'> content of button 2</div>
now try this code :
firstCall this function on domready:
$(document).on('click',function(){
$('.divShowHide').fadeOut(30);
});
function ShowHideDiv(divId){
$('.divShowHide').fadeOut(3000);
$(divId).fadeIn(3000);
}