Why I have to click 2 times to run this function? - javascript

This is the code i'm working on, and i don't know why everytime that i refresh the page i need to click 2 times to open the menu. Once i click the second time all works correctly.
This is the html of the button:
var x = document.getElementById("overlay-menu");
x.style.height = "0%";
function showMenu() {
var x = document.getElementById("overlay-menu");
if (x.style.height === "0%") {
x.style.height = "100%";
} else {
x.style.height = "0%";
}
}
.overlay-menu {
width: 100%;
height: 0%;
padding: 0;
margin: 0;
background-color: #ffffff;
z-index: 10000;
position: fixed;
color: #0A0A0A;
overflow: hidden;
display: block;
transition: .5s cubic-bezier(.55, .03, .26, 1.01);
}
.nav-menu-text {
width: fit-content;
height: fit-content;
margin: 0;
padding: 0;
color: #EB761D;
font-size: 15px;
position: relative;
top: 2.8em;
cursor: pointer;
}
<p class="nav-menu-text" onclick="showMenu()">MENU</p>
<div class="overlay-menu" id="overlay-menu">
<!-- code of the menu -->
</div>

x.style.height is probably not "0%" when your code runs, try changing the condition from:
if (x.style.height === "0%") {
to
if (x.style.height !== "100%") {

Related

Why do I keep getting 4 slides when there are only 3 div elements?

I created a slideshow with 3 slides but for some reason, it keeps adding an additional slide
const slideshow = document.getElementById("slideshow");
const slides = slideshow.children;
let currentSlide = 0;
function goToSlide(n) {
slides[currentSlide].classList.remove("active");
currentSlide = (n + slides.length) % slides.length;
slides[currentSlide].classList.add("active");
updateSlideshowCounter();
}
function nextSlide() {
goToSlide(currentSlide + 1);
}
function prevSlide() {
goToSlide(currentSlide - 1);
}
function updateSlideshowCounter() {
const slideshowCounter = document.getElementById("slideshow-counter");
slideshowCounter.textContent = `${currentSlide + 1} / ${slides.length}`;
}
const prevButton = document.getElementById("prev-button");
prevButton.addEventListener("click", prevSlide);
const nextButton = document.getElementById("next-button");
nextButton.addEventListener("click", nextSlide);
updateSlideshowCounter();
#slideshow {
position: relative;
text-align: center;
width: 400px;
height: 300px;
border: 1px black solid;
}
.slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 1s;
}
.slide.active {
opacity: 1;
}
#slideshow-controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
}
#prev-button,
#next-button {
padding: 10px 20px;
border: none;
background-color: #333;
color: #fff;
cursor: pointer;
}
#prev-button {
margin-right: 20px;
}
#next-button {
margin-left: 20px;
}
#slideshow-counter {
margin: 0 20px;
}
<div id="slideshow">
<div class="slide">Slide 1</div>
<div class="slide">Slide 2</div>
<div class="slide">Slide 3</div>
<div id="slideshow-controls">
<button id="prev-button">Prev</button>
<span id="slideshow-counter"></span>
<button id="next-button">Next</button>
</div>
</div>
Can someone tell me what my mistake is and how I can get 3 slides in the output instead of 4.
You're defining your slides with the statement const slides = slideshow.children;. Your slideshow has a total of 4 direct children, so the counter is technically correct (see slide 1, slide 2, slide 3, and slideshow-controls).
One approach to get just the slides you want is to use const slides = document.getElementsByClassName("slide"). I hope this helps!
The problem is your slides variable is not assigned to the correct list of elements, as the previous answer said, you should replace slideshow.children with either document.getElementsByClassName('slide') or document.querySelectorAll('.slide'), use any of the two.
By using slideshow.children, you're not getting .slide classes, you're getting all children of #slideshow.
So, your variable in line 67, should be as the following:
const slides = document.querySelectorAll('.slide');
or
const slides = document.getElementsByClassName('.slide');
You should keep slideshow controls out of your slideshow div. I am attaching Code Below. Run it and check.
const slideshow = document.getElementById("slideshow");
const slides = slideshow.children;
let currentSlide = 0;
function goToSlide(n) {
slides[currentSlide].classList.remove("active");
currentSlide = (n + slides.length) % slides.length;
slides[currentSlide].classList.add("active");
updateSlideshowCounter();
}
function nextSlide() {
goToSlide(currentSlide + 1);
}
function prevSlide() {
goToSlide(currentSlide - 1);
}
function updateSlideshowCounter() {
const slideshowCounter = document.getElementById("slideshow-counter");
slideshowCounter.textContent = `${currentSlide + 1} / ${slides.length}`;
}
const prevButton = document.getElementById("prev-button");
prevButton.addEventListener("click", prevSlide);
const nextButton = document.getElementById("next-button");
nextButton.addEventListener("click", nextSlide);
updateSlideshowCounter();
#slideshowbox {
position: relative;
width: 400px;
height: 300px;
}
#slideshow {
position: relative;
text-align: center;
width: 400px;
height: 300px;
border: 1px black solid;
}
.slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 1s;
}
.slide.active {
opacity: 1;
}
#slideshow-controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
align-items: center;
}
#prev-button,
#next-button {
padding: 10px 20px;
border: none;
background-color: #333;
color: #fff;
cursor: pointer;
}
#prev-button {
margin-right: 20px;
}
#next-button {
margin-left: 20px;
}
#slideshow-counter {
margin: 0 20px;
}
<div id="slideshowbox">
<div id="slideshow">
<div class="slide">Slide 1</div>
<div class="slide">Slide 2</div>
<div class="slide">Slide 3</div>
</div>
<div id="slideshow-controls">
<button id="prev-button">Prev</button>
<span id="slideshow-counter"></span>
<button id="next-button">Next</button>
</div>
</div>
Your slideshow div childs is throwing 4 because your 4th div is slideshow-controls. You may want to add -1 to the counter or redifine the way you make your div. Best of luck!

Different events based on number of clicks

I have been struggling to get something to work:
https://jsfiddle.net/CreativeAU/ys12ed05/
warningbutton.onclick = function buttonClicks() {
count += 1;
if (count > 1) {
window.location.href = "http://www.google.com.au";
}
else {
warningbutton.onclick = function() {warningpopup.style.display = "block";}
}};
What I'm currently trying to do
The first time a user clicks 'Go To Page 2', a warning popup will appear. Once they close the warning and click the button again - it will take them to Page 2.
Right now:
Nothing happens on the first button click.
On the second click, and every button click after = the warning popup appears.
Ideally what I want
When a user arrives to a page (let's call it Page1), I want them to have to have clicked Box 1 OR Box 2 at least once - before clicking the 'Go To Page 2' button. If they haven't - then a 'warning popup' will appear over the screen telling them that they need to. I have very little idea how to code this using other divs.
If anyone is able to help me solve 'Ideally what I want' that would be awesome, but otherwise I will settle for what 'I'm currently trying to do'.
I've set it all up on the JsFiddle page just so you can visualise what I'm after.
this does what you want i think.
the link to google wont work, but this is because of stackoverflow.
var counter = 0;
$(document).ready(function(){
$('#first').click(function(){
counter++
});
$('#second').click(function(){
counter++
});
$('#next-page').click(function(){
if (counter >= 1) {
window.location.href = "http://www.google.com.au";
}else{
$('#warning-popup').css("display", "block");
}
});
$('#warning-popup').click(function(){
$(this).css("display", "none");
});
});
#wrapper {
max-width: 1200px;
margin: 0 auto;
}
#first, #second, #next-page {
text-align: center;
vertical-align: middle;
line-height: 125px;
font-size: 25px;
color: #FFF;
margin: 10px;
}
#first, #second {
display: inline-block;
background-color: #189a3d;
width: 125px;
height: 125px;
}
#next-page {
display: block;
background-color: #2e82d0;
width: 270px;
height: 125px;
}
.overlay {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.75);
text-align: center;
padding-top: 25px;
font-size: 40px;
color: #FFF;
}
#close {
color: orange;
float: right;
font-size: 30px;
text-decoration: underline;
margin-top: -0.35em;
}#wrapper {
max-width: 1200px;
margin: 0 auto;
}
#first, #second, #next-page {
text-align: center;
vertical-align: middle;
line-height: 125px;
font-size: 25px;
color: #FFF;
margin: 10px;
}
#first, #second {
display: inline-block;
background-color: #189a3d;
width: 125px;
height: 125px;
}
#next-page {
display: block;
background-color: #2e82d0;
width: 270px;
height: 125px;
}
.overlay {
display: none;
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0,0,0,0.75);
text-align: center;
padding-top: 25px;
font-size: 40px;
color: #FFF;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="wrapper">
<div id="first">B1</div>
<div id="second">B2</div>
<div id="warning-popup" class="overlay">
WARNING TEXT HERE
</div>
<div id="next-page">Go to Page 2</div>
</div>
The following code should work, showing the alert if clicked the first time, and redirecting to google after another click.
var count = 0;
warningbutton.onclick = function buttonClicks() {
count += 1;
if (count > 1) {
window.location.href = "http://www.google.com.au";
}
else {
warningpopup.style.display = "block";
}
};
You need to change your else code.
You bind a new event on click, but do not trigger a click. You simply need to change the display attribute of your warning pop-up, without binding it on the click event.
A simple fix:
if (count > 1) {
window.location.href = "http://www.google.com.au";
}
else {
warningpopup.style.display = "block";
}};
you are basically registering a new function with the onclick event when the count is not greater than 1. solution should be
warningbutton.onclick = function buttonClicks() {
count += 1;
console.log(count);
if (count > 1) {
window.location.href = "http://www.google.com.au";
}
else {
warningpopup.style.display = "block";
}};

How to create a toggle button to switch between panels

In my application I have 2 toggle buttons and 3 panels. Button1 switches between panel 1 and 2. And button2 switches between panel 1 and 3. I could make it work some how by giving display: none; property to div panels. but once it only works once for each button and then it makes all sub divs to display: none;
Have a look at the sample please:
$(function () {
$("button.panel2").on("click", function() {
var visibleObj = $('.mainSection div:visible');
if ($("div.panel2").css("display") == "none") {
var inVisibleObj = $("div.panel2")
}
else {
var inVisibleObj = $("div.panel1")
}
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
})
});
$("button.panel3").on("click", function() {
var visibleObj = $('.mainSection div:visible');
if ($("div.panel3").css("display") == "none") {
var inVisibleObj = $("div.panel3")
}
else {
var inVisibleObj = $("div.panel1")
}
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
})
});
});
div.app {
margin:50px auto;
width: 400px;
height: 400px;
border-radius:10px;
overflow: hidden;
position: relative;
}
div.app > .blur {
width: 100%;
height: 100%;
background: url(http://goo.gl/0VTd9W);
-webkit-filter: blur(5px);
}
div.mainSection, div.dashboard{
position: absolute;
left: 0px;
text-align:center;
color:#fff;
font-size:20px;
}
div.mainSection{
width:100%;
height:85%;
background:rgba(0,0,0,0.5);
top:0;
}
div.dashboard{
width:100%;
height:15%;
background:rgba(255,0,0,0.5);
bottom:0;
}
div.mainSection > .panel1,
div.mainSection > .panel2,
div.mainSection > .panel3 {
width: 100%;
Height: 100%;
Background: rgba(0, 0, 0, 0.5);
position: absolute;
left: 0px;
top: 0px;
}
div.mainSection > .panel3 > p{
margin-top:80px;
}
.grid-button {
background: none;
border: none;
padding: 3px;
width: 100%;
}
.grid {
display: inline-block;
height: 4px;
position: relative;
width: 32px;
transition: all 0.3s ease-in-out;
}
.grid:after, .grid:before {
content: '';
position: absolute;
background-color: #FFF;
display: inline-block;
height: 4px;
left: 0;
width: 32px;
transition: all 0.3s ease-in-out;
}
.grid.open {
background-color: #FFF;
}
.grid.open:after {
top: 10px;
}
.grid.open:before {
top: -10px;
}
.grid.close {
background-color: transparent;
transform: scale(0.9);
}
.grid.close:after, .grid.close:before {
top: 0;
transform-origin: 50% 50%;
}
.grid.close:before {
transform: rotate(135deg);
}
.grid.close:after {
transform: rotate(45deg);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="app">
<div class="blur"></div>
<div class="mainSection">
<div class="panel1">
<div>panel1</div>
<div>panel1</div>
</div>
<div class="panel2" style="display: none;">
<div>panel2</div>
</div>
<div class="panel3" style="display: none;">
<p>Panel3</p>
<div>panel3</div>
<div>panel3</div>
</div>
</div>
<div class="dashboard">
<button class="panel2">button1</button>
<button class="panel3">button2</button>
</div>
</div>
As you can see, each panel has some inner divs. the first time, it shows all inner divs. but once you switch between panels, it will not show inner divs inside. I tried to disappear the panels div only but it seems it does it for every div within that panel.
So any idea to keep make it work so switching between panels will not affect the inner divs?
You need to change your javascript in this way:
$(function () {
$("button.panel2").on("click", function() {
var visibleObj = $('.mainSection > div:visible');
if ($("div.panel2").css("display") == "none") {
var inVisibleObj = $("div.panel2")
}
else {
var inVisibleObj = $("div.panel1")
}
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
});
});
$("button.panel3").on("click", function() {
var visibleObj = $('.mainSection > div:visible');
if ($("div.panel3").css("display") == "none") {
var inVisibleObj = $("div.panel3")
}
else {
var inVisibleObj = $("div.panel1")
}
visibleObj.fadeOut(500, function() {
inVisibleObj.fadeIn(500);
})
});
});
The problem is in your selector $('.mainSection div:visible');. This select also the child div and when you try to show the correct panel the child div are hidden. If you use $('.mainSection > div:visible'); you get only the direct child divs.

A javascript slider array issue

Having a slider with images implementation from array, cant figure out why images dont want to be shown up from array, tryed to make a path but it didnt work.I want this code to reflect this image every time a push the button: fpoimg.com/100x100.
Im trying to fix it only with clean javascript.
Here is a sandbox
var slider = {
slides: ['100x100', '100x100', '100x100', '100x100'],
frame:0,
set:function(image){
path = path || 'http://fpoimg.com/';
document.getElementById('scr').style.backgroundImage ="url ("+path+ image+")";
},
init:function() {
this.set(this.slides[this.frame]);
},
left:function() {
this.frame--;
if(frame < 0) this.frame = this.slides.length - 1;
this.set(this.slides[this.frame]);
},
right:function() {
if(this.frame == this.slides.length) this.frame = 0;
this.set(this.slides[this.frame]);
}
};
window.onload = function() {
slider.init();
setInterval(function() {
slider.right();
},5000);
};
.scr {
margin:20px auto;
width: 600px;
height: 320px;
margin-top:20px;
background-color: white;
background-size:cover;
}
button {
position: absolute;
top: 150px;
width: 25px;
height: 150px;
font-size: 30px;
text-align: center;
background:none;
border:none;
}
.left {
left:25px;
}
.right {
right:25px;
}
<body>
<button class="left" onclick="slider.left();"><</button>
<div class="scr"></div>
<button class="right" onclick="slider.right();">></button>
</body>
On Line 6 of your Javascript, you have used getElementById('scr'). You have no element with an Id or scr, you needed to use getElementsByClassName('scr')
Your new code:
var slider = {
slides: ['100x100', '100x100', '100x100', '100x100'],
frame: 0,
set: function(image) {
path = path || 'http://fpoimg.com/';
document.getElementsByClassName('scr').style.backgroundImage = "url (" + path + image + ")";
},
init: function() {
this.set(this.slides[this.frame]);
},
left: function() {
this.frame--;
if (frame < 0) this.frame = this.slides.length - 1;
this.set(this.slides[this.frame]);
},
right: function() {
if (this.frame == this.slides.length) this.frame = 0;
this.set(this.slides[this.frame]);
}
};
window.onload = function() {
slider.init();
setInterval(function() {
slider.right();
}, 5000);
};
.scr {
margin: 20px auto;
width: 600px;
height: 320px;
margin-top: 20px;
background-color: white;
background-size: cover;
}
button {
position: absolute;
top: 150px;
width: 25px;
height: 150px;
font-size: 30px;
text-align: center;
background: none;
border: none;
}
.left {
left: 25px;
}
.right {
right: 25px;
}
<body>
<button class="left" onclick="slider.left();">
</button>
<div class="scr"></div>
<button class="right" onclick="slider.right();"></button>
</body>
It seems you've got getElementById() when you meant getElementsByClassName()

lightbox with 2 different progress bar inside

I have created a lightbox in javascript and I have placed inside it a progress bar that I have also created it in javascript. My problem is that when I was trying to insert a second progress bar inside my lightbox only the first works. Any idea how to fix this?
this is my jsfiddle :http://jsfiddle.net/QHMKk/3/
and my code is this:
my javascript is:
function show() {
document.getElementById('light').style.display='block';
document.getElementById('fade').style.display='block';
}
function start() {
var stepSize = 50;
setTimeout((function() {
var filler = document.getElementById("filler"),
percentage = 0;
return function progress() {
filler.style.height = percentage + "%";
percentage +=1;
if (percentage <= 100) {
setTimeout(progress, stepSize);
}
}
}()), stepSize);
}
function start() {
var stepSize = 50;
setTimeout((function() {
var filler2 = document.getElementById("filler2"),
percentage = 0;
return function progress() {
filler.style.height = percentage + "%";
percentage +=1;
if (percentage <= 100) {
setTimeout(progress, stepSize);
}
}
}()), stepSize);
}
this is my html:
OPEN
<div id="light" class="white_content_stats">
<div class="prog">
<div id="filler" class="filler"></div>
</div>
</br>
<div class="prog2">
<div id="filler2" class="filler2"></div>
</div>
<a href = "javascript:void(0)" onclick = " document.getElementById('light').style.display='none';document.getElementById('fade').style.display='none'; ">
</br>CLOSE</a>
and this is my CSS:
.black_overlay_stats{
display: none;
position: absolute;
top: 0%;
left: 0%;
width: 100%;
height: 50%;
z-index:1001;
-moz-opacity: 0.6;
opacity:.70;
filter: alpha(opacity=70);
}
.white_content_stats {
display: none;
position:fixed;
top: 15%;
width: 300px;
padding: 30px;
margin-left:10px;
background-color:#F2F2F2;
border-radius: 0px;
box-shadow: 0px 0px 0px 20px rgba(0,0,0,0.6);
z-index:1002;
}
.prog {
height: 100px;
width: 30px;
border: 1px solid white;
position: relative;
}
.filler {
height: 0%;
width: 30px;
position: absolute;
bottom: 0;
background-color: grey;
}
.prog2 {
height: 100px;
width: 30px;
border: 1px solid white;
position: relative;
}
.filler2 {
height: 0%;
width: 30px;
position: absolute;
bottom: 0;
background-color: grey;
}
You define 2 functions with the same name start, so the second will be used and only it will be run, hence you can see only 1 progress bar works. You can modify the function start to make it accept an argument of id like this:
function start(id) {
//...
var filler = document.getElementById(id)
//...
}
Then call both start('filler') and start('filler2'):
OPEN
Updated Demo.
Note that you should not use inline event property.

Categories