I am trying to build a slideshow that pretty much works by changing the margins in my CSS.
So far it's working well but I want the next and previous button to disappear when the margins have a certain value and I couldn't find a solution.
Here is my js code:
const nextBtn = document.querySelector('#slideNext');
const prevBtn = document.querySelector('#slidePrev');
const slider = document.querySelector('.boxes-container');
const slideWidth = 250;
// Slider initial margin
slider.style.marginLeft = "0";
nextBtn.onclick = function() {
slider.style.marginLeft = (parseInt(slider.style.marginLeft, 0) - slideWidth) + 'px';
}
prevBtn.onclick = function() {
slider.style.marginLeft = (parseInt(slider.style.marginLeft, 0) + slideWidth) + 'px';
}
if (slider.style.marginLeft == "0") {
prevBtn.style.display = "none";
} else if (slider.style.marginLeft == "-1000px") {
nextBtn.style.display = "none";
} else {
nextBtn.style.display = "inline-block";
prevBtn.style.display = "inline-block";
}
My issue is on the last part: I don't know how to deal with an if/else statement that would modify the display of my buttons when the margin reach a certain value.
It would be awesome if anyone could point me in the right direction as I've spent some time trying to solve this on my own but couldn't find the right solution.
Thanks for your help!!
You created the logic correctly. The problem is that you don't check the margin every time the button is clicked (javascript is not reactive by default).
You have to wrap the margin's logic into a function and then check the margin values every time the button is clicked.
const nextBtn = document.querySelector('#slideNext');
const prevBtn = document.querySelector('#slidePrev');
const slider = document.querySelector('.boxes-container');
const slideWidth = 250;
// Slider initial margin
slider.style.marginLeft = "0";
nextBtn.onclick = function() {
slider.style.marginLeft = (parseInt(slider.style.marginLeft, 0) - slideWidth) + 'px';
checkMargin();
}
prevBtn.onclick = function() {
slider.style.marginLeft = (parseInt(slider.style.marginLeft, 0) + slideWidth) + 'px';
checkMargin();
}
function checkMargin() {
if (slider.style.marginLeft == "0") {
prevBtn.style.display = "none";
} else if (slider.style.marginLeft == "-1000px") {
nextBtn.style.display = "none";
} else {
nextBtn.style.display = "inline-block";
prevBtn.style.display = "inline-block";
}
}
There are other methods to make the DOM reactive, like MutationObserver. But it may be an overkill to this task.
The reason why it wasn't working was because I wasn't checking for the margins when the buttons were clicked.
I changed my code as follow:
const nextBtn = document.querySelector('#slideNext');
const prevBtn = document.querySelector('#slidePrev');
const slider = document.querySelector('.boxes-container');
const slideWidth = 250;
// Slider initial margin
slider.style.marginLeft = "0px";
function check() {
if (slider.style.marginLeft == "0px") {
prevBtn.style.display = "none";
} else if (slider.style.marginLeft == "-1000px") {
nextBtn.style.display = "none";
} else {
nextBtn.style.display = "inline-block";
prevBtn.style.display = "inline-block";
}
}
window.onload = check(); // Check the margins when the page is loaded
nextBtn.onclick = function() {
slider.style.marginLeft = (parseInt(slider.style.marginLeft, 0) - slideWidth) + 'px';
check();
}
prevBtn.onclick = function() {
slider.style.marginLeft = (parseInt(slider.style.marginLeft, 0) + slideWidth) + 'px';
check();
}
Wrapped the margin logic inside of a check() function
Check this function on page load and everytime the buttons are clicked
Thanks to Gustavo for his precious help!
Related
i started js a few days ago and made a slider that changes the images when the button is clicked and a timer that changes images automatically every 5 sec. But when i clicked the buttons the timer didnt reset. I used clearInterval to stop the timer but i dont know how to call it to restart it. Here is my Js code.
//progression bar
var width = 1;
//the images
const images = [
"https://www.travelercar.com/wp-content/uploads/2016/04/4a36e314016aa914f203ea6b7d579dc6_large.jpeg",
"https://lemag.nikonclub.fr/wp-content/uploads/2017/07/08.jpg",
"https://www.yourvalleynews.co.uk/wp-content/uploads/2018/03/pic-outside-1080x675.jpg",
];
//the buttons
const suivant = document.getElementById('button1');
const precedent = document.getElementById('button2');
//change image every 5 sec
var counter = 0;
var imageChange;
imageChange = setInterval (function () {
if (counter >= 2 ){
counter -= 2;
document.getElementById("currentImage").src = images[counter];
}
else if (images[0]){
document.getElementById("currentImage").src = images[++counter];
};
}, 5000);
//make buttons work
precedent.onclick = function() {
width = 0;
clearInterval(imageChange);
//I know i have to put something on this line with v imageChange but i dont know what
if (counter <= 0){
counter += 2;
document.getElementById("currentImage").src = images[counter];
}
else{
document.getElementById("currentImage").src = images[--counter];
};
}
suivant.onclick = function() {
width = 0;
clearInterval(imageChange);
//I know i have to put something on this line with imageChange but i dont know what
if (counter >= 2 ){
counter -= 2;
document.getElementById("currentImage").src = images[counter];
}
else{
document.getElementById("currentImage").src = images[++counter];
};
}
//progression bar
function progression(){
var progres = document.getElementById('progression');
var temps = setInterval(frame, 50);
function frame() {
if (width >= 100){
width = 0;
}
else{
width++;
progres.style.width = width + '%';
}
}
}
window.onload = progression;
Feel free to say if have to change some of my ways in the code to make it cleaner. And thanks for taking to help me :)
The main thing is that you have to call setInterval again after you click, in order to restart the interval. Calling clearInterval stops the interval from running.
Here's a way to clean this up a bit:
let counter = 0;
let intervalId;
const getNextImage = (direction) => {
const increment = direction === 'forward' ? 1 : -1;
counter += increment;
if (counter > images.length - 1) {
counter = 0;
}
if (counter < 0) {
counter = images.length - 1;
}
document.getElementById("currentImage").src = images[counter];
};
const startImageLoop = (direction) => {
width = 0;
clearInterval(intervalId);
getNextImage(direction);
intervalId = setInterval(() => {
getNextImage(direction);
}, 5000);
}
precedent.onClick = () => startImageLoop('backward');
suivant.onClick = () => startImageLoop('forward');
var i = 0;
var txt = 'UNITING PEOPLE'; /* The text */
var txt2 = ' &';
var txt3 = 'DELIVERING ';
var txt4 = 'INTELLIGENCE';
var txt5 = 'Access your hub for Open Journalism';
var speed = 0;
function typeWriter(fade) {
if (i < txt.length + txt2.length + txt3.length + txt4.length + txt5.length) {
if(i < txt.length-1) {
var element = document.createElement("p");
element.style.display = "inline-block";
element.style.opacity = "0.1";
element.style.fontSize = "38px";
element.style.fontFamily = "Helvetica-Bold";
element.style.whiteSpace = "pre";
element.style.marginTop = "0";
element.textContent += txt.charAt(i);
document.getElementById("words").children[0].children[0].appendChild(element)
unfade(element, fade);
i++;
setTimeout(typeWriter(fade), 10*fade);
} else if(i==txt.length-1) {
var element = document.createElement("p");
element.style.display = "inline-block";
element.style.opacity = "0.1";
element.style.fontSize = "38px";
element.style.fontFamily = "Helvetica-Bold";
element.style.whiteSpace = "pre";
element.style.marginTop = "0";
element.textContent += txt.charAt(i);
document.getElementById("words").children[0].children[0].appendChild(element)
unfade(element, fade);
i++;
setTimeout(typeWriter(fade), 1500);
} else if(i < txt.length + txt2.length-1)
...
}
setTimeout(typeWriter(100), 1500);
function unfade(element, fade) {
var op = 0.1; // initial opacity
element.style.display = 'inline-block';
var timer = setInterval(function () {
if (op >= 1){
clearInterval(timer);
}
element.style.opacity = op;
element.style.filter = 'alpha(opacity=' + op * 100 + ")";
op += op * 0.1;
}, fade);
}
I'm not sure what the bug is. Each letter should fade through about 100ms, and it should wait until each letter is done before the next letter begins.
Each element comes in inline and begins with a small opacity in the right font and font size, with spaces making room for text with the whitespace set to pre.
The text content updates with just 1 character at a time, and it's appended to the correct section before being faded in. The fading in is set to be the same as the overall letter fade, before the increment is counted.
Once the set timeout occurs, the delay fade is simply ignored and it all begins at once, so it's like the fade is set to 0 over all.
And yet when the code is cut and one section implemented it does one letter at a time.
I need your precious help!!!
I have 2 slides on the top of the screen and they change after 10 seconds(loop). You can see here: http://packageonly.tk/test
If you click on FULL info - on both slides - you will see the contents on the bottom of the screen - i want them to be replaced. so only 1 info is being shown at the bottom - ORR - I wonder how can i connect the content at the bottom to the top - so the content would change accordingly.
thanks
I have use this code so far:
function myFunction() {
var x = document.getElementById("id1");
if (x.style.display === "none") {
x.style.display = "block";
} else {
x.style.display = "none";
}
}
function myFunction2() {
var x2 = document.getElementById("id2");
if (x2.style.display === "none") {
x2.style.display = "block";
} else {
x2.style.display = "none";
}
}
<div id="id1">This is id1</div>
<div id="id2">This is id2</div>
<button type="button" onclick="myFunction()">myFunction()</button>
<button type="button" onclick="myFunction2()">myFunction2()</button>
Looks like you're not making the old info disappear. Try this:
function myFunction() {
var x1 = document.getElementById("id1"); // renamed this
var x2 = document.getElementById("id2"); // added this
if (x1.style.display === "none") {
x1.style.display = "block";
x2.style.display = "none"; // added this to remove the old info
} else {
x1.style.display = "none";
}
}
function myFunction2() {
var x1 = document.getElementById("id1");
var x2 = document.getElementById("id2");
if (x2.style.display === "none") {
x2.style.display = "block";
x1.style.display = "none";
} else {
x2.style.display = "none";
}
}
This works fine at all times except for the first time tab_toggle(0) is called.
when the first time this function is called the #box_home has display:block; so the function shouldn't do anything but whats happening is #box_port(the next div) is getting display:block; and #box_home remaining display:block as before. why is this happening. is it because when the function is called the variable has value undefined so doing some random thing.
Please answer this in javascript only, dont answer in jquery.
i couldnt make it work just this part in jsfiddle so i am sharing the entire webpage code
http://goo.gl/dhTUDH
<!-- Javascript -->
<script>
function tab_toggle(x) {
console.log("tab_toggle");
var home = document.getElementById("box_home").style;
var port = document.getElementById("box_port").style;
var about = document.getElementById("box_about").style;
var contact = document.getElementById("box_contact").style;
var box = [home,port,about,contact];
switch (x) {
case 0:
if (home.display == "block") {
console.log('end');
} else if (port.display == "block") {
box[0].display = "block";
box[1].display = "none";
} else if (about.display == "block") {
box[1].display = "block";
box[2].display = "none";
} else {
box[2].display = "block";
box[3].display = "none";
}
break;
default:
if (home.display == "block") {
box[0].display = "none";
box[1].display = "block";
} else if (port.display == "block") {
box[1].display = "none";
box[2].display = "block";
} else if (about.display == "block") {
box[2].display = "none";
box[3].display = "block";
} else {}
break;
}
}
<!-- HTML -->
◀
▶
<div id="box_home"></div>
<div id="box_port"></div>
<div id="box_about"></div>
<div id="box_contact"></div>
<!-- CSS -->
#box_home{display:block;}\
#box_port{display:none;}
#box_about{display:none;}
#box_contact{display:none;}
You can't access a style directly as a property, as in
home.display
Instead, use the getComputedStyle() method
getComputedStyle(home).display
element.style will get the element's inline style. Try getComputedStyle or add a class.
getComputedStyle(box[0]).getPropertyValue("display")
Not sure what would you achieve, but this should work:
var currentElement = 0;
(tab_toggle = function (x) {
var home = document.getElementById("box_home").style;
var port = document.getElementById("box_port").style;
var about = document.getElementById("box_about").style;
var contact = document.getElementById("box_contact").style;
var box = [home, port, about, contact];
if (currentElement + x < 0 || currentElement + x > box.length - 1)
return;
currentElement += x;
console.log("toggled " + currentElement);
for (var i = 0; i < box.length; i++) {
box[i].display = "none";
}
box[currentElement].display = "block";
})(0);
I am trying to make a js game though when I try and trigger a function using onclick nothing happens and then when I went onto console it came up with this error message everytime I clicked it:
Uncaught TypeError: undefined is not a function
This is how I define my function:
var myfunction = function () {
I know that it is nothing to do with the function though as I call it after I make it and it works fine.
I have also checked whether it is the click by putting an alert in the onclick though that worked fine.
I know this is a common problem, though have looked at others and found nothing.
http://jsfiddle.net/Hive7/DQnmF/
JavaScript:
var attack = function () {
while (slaying === true) {
if (youHit !== 1) {
totalDamage = totalDamage += damageThisRound;
document.getElementById('hit').style.display = 'inline';
//alert('You hit!!! ' + totalDamage * 10 + ' damage');
health = health - totalDamage * 10;
setTimeout(function(){document.getElementById('health').style.width = health + 'px'}, 400);
setTimeout(function(){document.getElementById('hit').style.display = 'none'}, 500);
if (totalDamage >= 4) {
//alert('the dragons dead');
slaying = false;
}
} else {
document.getElementById('miss').style.display = 'inline';
setTimeout(function(){document.getElementById('miss').style.display = 'none'}, 500);
//alert('You missed');
}
slaying = false;
}
}
document.getElementById('character').style.color = '#ccc';
document.getElementById('enemy').style.position = 'absolute';
document.getElementById('enemy').style.right = '0';
document.getElementById('game').style.position = 'relative';
document.getElementById('game').style.width = '1004px';
document.getElementById('characters').style.position = 'relative';
document.getElementById('health-container').style.right = '0';
document.getElementById('health-container').style.position = 'absolute';
document.getElementById('health-container').style.bottom = '30px';
document.getElementById('health-container').style.width = '200px';
document.getElementById('health-container').style.height = '41px';
document.getElementById('health').style.backgroundColor = 'red';
document.getElementById('health').style.height = '41px';
document.getElementById('health').style.width = '200px';
document.getElementById('miss').style.position = 'absolute';
document.getElementById('miss').style.right = '20px';
document.getElementById('miss').style.bottom = '120px';
document.getElementById('miss').style.display = 'none';
document.getElementById('hit').style.position = 'absolute';
document.getElementById('hit').style.right = '20px';
document.getElementById('hit').style.bottom = '120px';
document.getElementById('hit').style.display = 'none';
var slaying = true;
var youHit = Math.floor(Math.random() * 6 + 1);
var totalDamage = 0;
var damageThisRound = Math.floor(Math.random() * 4 + 1);
var num = document.getElementById('health').style.width.length - 2;
var health = document.getElementById('health').style.width;
health = health.substring(0, num);
attack();
I found the answer in the end. I used this instead of using the onclick method:
document.getElementById('attack').addEventListener('click', function() {
myfunction();
}, false);