Image element becoming null on src change? Slideshow - javascript

Working on building a library, trying to put in a fading image slider, it shows the first image, but then when it tries to change I get TypeError: document.querySelector(...) is null. Any help would be great!
export let styl = (function() {
let slideIndex = 0;
return {
simpleSlideShow: function() {
//automatic Slider
let i;
let slides = document.getElementsByClassName("mySlides");
console.log("Image change");
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slideIndex++;
if (slideIndex > slides.length) {
slideIndex = 1;
}
slides[slideIndex - 1].style.display = "block";
},
slideShowImageSetup: function(timeDelay, id, images) {
//Building HTML with given array of images
let i;
for (i = 0; i < images.length; i++) {
let elem = document.createElement("img");
elem.setAttribute("alt", "image");
elem.setAttribute("src", images[i]);
elem.setAttribute("class", "mySlides");
document.querySelector(id).appendChild(elem);
}
setTimeout(styl.simpleSlideShow, 1);
setInterval(styl.simpleSlideShow, timeDelay);
return 1;
},
fadingSlideShow: function(id, images) {
document.querySelector(id).className += "fadeOut";
setTimeout(function() {
document.querySelector(id).src = images[slideIndex];
document.querySelector(id).className = "";
slideIndex++;
if (slideIndex == images.length) {
slideIndex = 0;
}
setTimeout(styl.fadingSlideShow(id, images), 3000);
}, 1000);
},
};
})();
Where I'm calling the function
let images = [
"https://cdn141.picsart.com/297231911148201.jpg?c256x256",
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSQIfOEjoaYJNDHGmdgRa8EQp50VCicpK0R_0QpZLftE2zzgJky"
];
styl.fadingSlideShow("#slider", images);
<img id="slider"></img>
css that makes the fade effect
#slider {
opacity: 1;
transition: opacity 3s;
}
#slider.fadeOut {
opacity: 0;
}

Your second setTimeout is not sending in the id or images to styl.fadingSlideShow.
setTimeout(function(){styl.fadingSlideShow(id, images)}, 3000);
Also, put the second setTimeout inside the first one.

Related

Overlapped slide still getting clicked

The slide that I turned the opacity to 0 on is still clickable even though I set pointer events to none. Basically I have 2 slides on this slideshow and even if i'm on the first slide when I click on it, it goes to the 2nd slides hyperlink. Image This image shows the code is changing the pointer event and also the opacity correctly but for some reason when I click on the first slide on the website it still sends me to the second slides hyperlink.
//programming slideshow
$(function () {
var slide_index = 1;
displaySlides(slide_index);
function nextSlide() {
displaySlides(slide_index++);
}
function prevslide() {
displaySlides(slide_index--);
}
function displaySlides() {
var i;
var slides = document.getElementsByClassName("programming-slides");
if (slide_index > slides.length) { slide_index = 1 }
if (slide_index < 1) { slide_index = slides.length }
for (i = 0; i < slides.length; i++) {
slides[i].style.opacity = 0;
}
slides[slide_index - 1].style.opacity = 1;
for (var i = 0; i < slides.length; i++) {
// If the slide is not visible, set its pointer-events to none
if (slides[i].style.opacity === '0') {
slides[i].style.pointerEvents = 'none';
} else {
// Otherwise, set its pointer-events to auto
slides[i].style.pointerEvents = 'auto';
}
}
}
var next = document.getElementById('programming-next');
next.addEventListener('click', nextSlide);
var prev = document.getElementById('programming-prev');
prev.addEventListener('click', prevslide);
})
Started to fix it by adding in z index to the code in the slides js and also to some other css elements that fixed the overlapping problem and now all the features are working
for (var i = 0; i < slides.length; i++) {
// If the slide is not visible, set its pointer-events to none
if (slides[i].style.opacity === '0') {
slides[i].style.pointerEvents = 'none';
slides[i].style.zIndex = 0;
} else {
// Otherwise, set its pointer-events to auto
slides[i].style.pointerEvents = 'auto';
slides[i].style.zIndex = 1;
}

Could you explain this simple image slider code line by line?

Are you able explain this simple image slider code line by line?
I'm particularly interested in where the n and no values come from in currentSlide(no) + plusSlides(n).
var slideIndex = 0;
var slides = document.getElementsByClassName("mySlides");
var interval;
var pauseButton = document.getElementById("pause");
showSlides();
playSlideshow();
function showSlides() {
var i;
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slideIndex++;
if (slideIndex > slides.length) {
slideIndex = 1;
}
slides[slideIndex - 1].style.display = "block";
}
// Manual control
function currentSlide(no) {
var i;
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slideIndex = no;
slides[no - 1].style.display = "block";
}
function plusSlides(n) {
var newslideIndex = slideIndex + n;
if (newslideIndex < 6 && newslideIndex > 0) {
currentSlide(newslideIndex);
}
}
Edited to add rest of the code.
// Pause
var playing = true;
function pauseSlideshow() {
var pauseButton = document.getElementById("pause");
pauseButton.innerHTML = "▸";
playing = false;
clearInterval(interval);
}
function playSlideshow() {
pauseButton.innerHTML = "⏸";
playing = true;
interval = setInterval(showSlides, 5000);
}
pauseButton.onclick = function () {
if (playing) {
pauseSlideshow();
} else {
playSlideshow();
}
};
As per the comments, I have added additional code.
Yes, can do!
The first function showSlides is called. It first makes every element with the mySlides class invisible (basically hides all your slides). Then it increments the slide index and checks to see if the index is over the total amount of slides so it can start from the beginning again. Finally it shows the slide that the index is referring to.
The currentSlide function sets the active slide to the index provided in the no argument. First it hides all the slides and then sets the new slide index to what no is and then shows that slide.
Finally plusSlides goes forward (or backwards if using a negative number) n slides. The if statement checks if the index is between 1 and 5. If it is the slide that corresponds with the new index is shown.
A few notes
for loops can be written without a variable declaration preceding it like this
for(let x = 0; x < 100; x++){
console.log(x);
}
In your plusSides function, you check for a specific range, but you could base it off of the amount of slides with slides.length like in showSlides. Also, I would recommend making sure that if the index does happen to fall out of this range to set the index to a default value.
if (newslideIndex < slides.length && newslideIndex > 0) {
currentSlide(newslideIndex);
} else {
currentSlide(1);
}
That is all!

Autoplaying javascript slideshow that has multiple slideshows on one page not working

I'm trying to make a simple javascript slideshow, that will use prev and next buttons to cycle through, and autoplay. Plus, require to have multiple slideshows on one page.
Can't get the autoplay on load to work? Am I missing something?
The code I've been using works with multiple on one page, and prev and next buttons work. However the auto play doesn't work on the window load, but does start to work when you click one of the previous and next buttons.
Thanks.
var slideIndex = [1,1,1,1,1]
var slideId = ["mySlides1", "mySlides2", "mySlides3", "mySlides4", "mySlides5"]
showSlides(1, 0);
showSlides(1, 1);
showSlides(1, 2);
showSlides(1, 3);
showSlides(1, 4);
var myTimer;
window.addEventListener("load",function() {
showSlides(slideIndex[no], no);
myTimer = setInterval(function(){plusSlides(1, no)}, 4000);
})
function plusSlides(n, no){
clearInterval(myTimer);
if (n < 0){
showSlides(slideIndex[no] -= 1, no);
} else {
showSlides(slideIndex[no] += 1, no);
}
if (n === -1){
myTimer = setInterval(function(){plusSlides(n + 2, no)}, 4000);
} else {
myTimer = setInterval(function(){plusSlides(n + 1, no)}, 4000);
}
}
function currentSlide(n, no){
clearInterval(myTimer);
myTimer = setInterval(function(){plusSlides(n + 1, no)}, 4000);
showSlides(slideIndex[no] = n, no);
}
function showSlides(n, no){
var i;
var slides = document.getElementsByClassName(slideId[no]);
var dotname = "dot" + no;
var dots = document.getElementsByName(dotname);
if (n > slides.length) {slideIndex[no] = 1}
if (n < 1) {slideIndex[no] = slides.length}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active_slide", "");
}
slides[slideIndex[no]-1].style.display = "block";
dots[slideIndex[no]-1].className += " active_slide";
}
I suggest you don't reset your interval.
If you have an array like so:
const slides = [
'slideOne', 'slideTwo',
'slideThree', 'slideFour',
'slideFive', 'slideSix'
];
you can just do:
let autoSliderInterval;
let currentSlideIndex = 0;
function _autoSlide() {
// Increase Slide index
currentSlideIndex++;
// If slides are at the end begin from the start
if(currentSlideIndex >= slides.length) currentSlideIndex = 0;
// Display current slide
displaySlide(currentSlideIndex);
}
Then if you want to acutoscroll just set the timeout:
autoSliderInterval = setInterval(_autoSlide, <your time>);
And if you want to stop auto sliding (for example this could happen when the user clicks on one button) just do:
clearInterval(autoSliderInterval).
Basic example:
const display = document.getElementById('display');
const button_sliderPrevious = document.getElementById('button_sliderPrevious');
const button_sliderNext = document.getElementById('button_sliderNext');
button_sliderPrevious.addEventListener('click', () => shiftSlide(-1));
button_sliderNext.addEventListener('click', () => shiftSlide(1));
const slides = [
'slideOne', 'slideTwo',
'slideThree', 'slideFour',
'slideFive', 'slideSix'
];
let autoSliderInterval = setInterval(_autoSlide, 500);
let currentSlideIndex = 0;
function shiftSlide(amount) {
// Stop the inverval
if(autoSliderInterval !== null) {
clearInterval(autoSliderInterval);
autoSliderInterval = null;
}
// Shift the slide index
currentSlideIndex += amount;
// Check if below zero (if yes set to max)
if(currentSlideIndex < 0) currentSlideIndex = slides.length - 1;
// Check if over max (set to zero)
if(currentSlideIndex >= slides.length) currentSlideIndex = 0;
// Display the slide
displaySlide(currentSlideIndex);
}
function _autoSlide() {
// Increase Slide index
currentSlideIndex++;
// If slides are at the end begin from the start
if(currentSlideIndex >= slides.length) currentSlideIndex = 0;
// Display current slide
displaySlide(currentSlideIndex);
}
function displaySlide(slideIndex) {
display.innerText = slides[slideIndex];
}
#display {
text-align: center;
height: 50px;
width: 100%;
border: 1px solid lightgray;
}
<div id="display"></div>
<button id="button_sliderPrevious">Previous</button>
<button id="button_sliderNext">Next</button>
Try this one.
i hope it will work for you.
<script type="text/javascript">
var slideIndex = [1,1];
var slideId = ["mySlides1", "mySlides2"]
showSlides(1, 0);
showSlides(1, 1);
function plusSlides(n, no) {
showSlides(slideIndex[no] += n, no);
}
function showSlides(n, no) {
var i;
var x = document.getElementsByClassName(slideId[no]);
if (n > x.length) {slideIndex[no] = 1}
if (n < 1) {slideIndex[no] = x.length}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex[no]-1].style.display = "block";
}
setInterval(function(){
$(".next.slide_buttons").click();
},3000);
</script>

Dynamically generated slideshow bug

I have a slideshow that takes image sources from JSON and generates a list for the amount of images . This is the code :
//Json
var sidenav = $('.sidenav');
$.getJSON('http://localhost:8080/data.json', function(result){
for (var i = 0 ; i < result.length ; i++) {
sidenav.append(`<li class="selected"><img src="${result[i].src}" alt="${result[i].alt}"></li>`);
var slides = $('.sidenav li');
var slideIndex = 0;
var slideTime = animate();
slideTo(slides[0]);
slides.click(function() {
clearInterval(slideTime);
slideTime = animate();
var selectedIndex = $(this).index();
var slide = slides[selectedIndex];
slideTo(slide);
});
}
function slideTo(slide) {
slides.removeClass("selected");
$(slide).addClass("selected");
slideIndex = jQuery(slide).index();
}
function animate() {
return setInterval(function() {
var slide = slides[slideIndex];
slideTo(slide)
slideIndex++;
if (slideIndex == slides.length) {
slideIndex = 0;
}
},3000);
}
<div class="slider">
<ul class="sidenav">
</ul>
</div>
CSS is all over the place but not really important here . This works as it gets the first li item and adds a class selected . But than for some reason it jumps to the last one and doesn't move from there . I feel like I missed something small but important .. Any opinions ?
OK the answer was to move the part where slides change out of the for loop..
var sidenav = $('.sidenav');
$.getJSON('http://localhost:8080/data.json', function(result){
for (var i = 0 ; i < result.length ; i++) {
sidenav.append(`<li class="selected"><img src="${result[i].src}" alt="${result[i].alt}"></li>`);
}
var slides = $('.sidenav li');
var slideIndex = 0;
var slideTime = animate();
slideTo(slides[0]);
slides.click(function() {
clearInterval(slideTime);
slideTime = animate();
var selectedIndex = $(this).index();
var slide = slides[selectedIndex];
slideTo(slide);
});
function slideTo(slide) {
slides.removeClass("selected");
$(slide).addClass("selected");
slideIndex = jQuery(slide).index();
}
function animate() {
return setInterval(function() {
var slide = slides[slideIndex];
slideTo(slide)
slideIndex++;
if (slideIndex == slides.length) {
slideIndex = 0;
}
},3000);
}

creating fade out/in instead of display none/block

I am trying to make the slides fade in and out instead of display none/block using JS. Is this going to need to be done using css or can i do it just in JS. Thanks
code:
var slideIndex = 1;
showSlides(slideIndex);
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentDot(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
console.log('SHOWSLIDES');
var i;
var slides = document.getElementsByClassName("mySlides");
var dots = document.getElementsByClassName("nav-dot");
if (n > slides.length) {slideIndex = 1}
if (n < 1) {slideIndex = slides.length}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
for (i = 0; i < dots.length; i++) {
dots[i].className = dots[i].className.replace(" active", "");
}
slides[slideIndex-1].style.display = "block";
dots[slideIndex-1].className += " active";
}
or would it be better converting this to jquery and using .fadeOut() / .fadeIn()
Before: Just look a little bit into it source of jQuery:
.fadeIn()
http://james.padolsey.com/jquery/#v=1.11.2&fn=fadeIn
.animation()
http://james.padolsey.com/jquery/#v=1.11.2&fn=animate
Here is an approach how you could possibly do it:
var fadeInBtn = document.getElementById('fadeIn');
fadeInBtn.addEventListener('click', function() {
var testString = document.getElementById('test');
fadeIn(testString, 30);
});
var fadeOutBtn = document.getElementById('fadeOut');
fadeOutBtn.addEventListener('click', function() {
var testString = document.getElementById('test');
fadeOut(testString, 60);
});
function fadeIn(element, speed) {
var interval = setInterval(function () {
var opacity = parseFloat(element.style.opacity);
if(opacity >= 1.0) {
clearInterval(interval);
}
element.style.opacity = opacity + 0.1;
}, speed);
};
function fadeOut(element, speed) {
var interval = setInterval(function () {
var opacity = parseFloat(element.style.opacity);
if(opacity <= 0) {
clearInterval(interval);
}
element.style.opacity = opacity - 0.1;
}, speed);
}
div {
font-size: 300%;
}
<button id="fadeIn">Test .fadeIn()</button>
<button id="fadeOut">Test .fadeOut()</button>
<div id="test" style="opacity: 0">Example String</div>
Another solution is to use CSS(3) for this. I reference this already asked question here: Using CSS for fade-in effect on page load

Categories

Resources