How can I make a reusable function? - javascript

I am trying to apply this function to multiple projects and I want to not repeat it. How can I do it in Vanilla JS? See the code below.
let slideIndex = 1;
showDivs(slideIndex);
function plusDivs(n) {
showDivs(slideIndex += n);
}
function showDivs(n) {
let i;
let x = document.getElementsByClassName("slides");
if (n > x.length) {
slideIndex = 1
}
if (n < 1) {
slideIndex = x.length
}
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[slideIndex - 1].style.display = "block";
document.getElementsByClassName("pagination")[0].innerText = slideIndex + ' / ' + x.length;
}
<div class="project1">
<div class="pagination"></div>
<div class="imgslide noselect">
<div class="prev" onclick="plusDivs(-1)"></div>
<div class="next" onclick="plusDivs(1)"></div>
<img class="slides" src="img/project-1/Scan-4.jpg">
<!-- <img class="slides" src="img/Scan-8.jpg"> -->
<img class="slides" src="img/project-1/Scan-24.jpg">
<img class="slides" src="img/project-1/Scan-35.jpg">
<img class="slides" src="img/project-1/Scan-39.jpg">
<img class="slides" src="img/project-1/Scan-40.jpg">
</div>
</div>
<div class="project2">
<div class="pagination"></div>
<div class="imgslide noselect">
<div class="prev" onclick="plusDivs(-1)"></div>
<div class="next" onclick="plusDivs(1)"></div>
<img class="slides" src="img/project-1/Scan-41.jpg">
<!-- <img class="slides" src="img/Scan-8.jpg"> -->
<img class="slides" src="img/project-1/Scan-22.jpg">
<img class="slides" src="img/project-1/Scan-33.jpg">
<img class="slides" src="img/project-1/Scan-38.jpg">
<img class="slides" src="img/project-1/Scan-49.jpg">
</div>
</div>
Divs with class project1 and project2 should be separated and the function simply changes image once clicked. I want to apply the same function for multiple projects without re-writing it every time.

Instead of getting all the slides document.getElementsByClassName("slides") you should get the slides of the appropriate project document.getElementById("projectN").getElementsByClassName("slides"). You'll have to change both functions to accept another parameter for specifying the project.
let projectIndexes = {
project1: 1,
project2: 1
}
showDivs("project1", projectIndexes.project1);
showDivs("project2", projectIndexes.project2);
function plusDivs(project, n) {
showDivs(project, projectIndexes[project] += n);
}
function showDivs(project, index) {
let i;
let x = document.getElementById(project).getElementsByClassName("slides");
if (index > x.length) { index = 1 }
if (index < 1) { index = x.length }
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[index - 1].style.display = "block";
document.getElementById(project).getElementsByClassName("pagination")[0].innerText = index + ' / ' + x.length;
projectIndexes[project] = index;
}
.slides {
display: none;
}
<div id="project1">
<div class="pagination"></div>
<div class="imgslide noselect">
<button class="prev" onclick="plusDivs('project1', -1)">Previous</button>
<button class="next" onclick="plusDivs('project1', 1)">Next</button>
<img class="slides" src="img/project-1/Scan-4.jpg" alt="project1 slide1">
<img class="slides" src="img/project-1/Scan-24.jpg" alt="project1 slide2">
<img class="slides" src="img/project-1/Scan-35.jpg" alt="project1 slide3">
<img class="slides" src="img/project-1/Scan-39.jpg" alt="project1 slide4">
<img class="slides" src="img/project-1/Scan-40.jpg" alt="project1 slide5">
</div>
</div>
<br />
<div id="project2">
<div class="pagination"></div>
<div class="imgslide noselect">
<button class="prev" onclick="plusDivs('project2', -1)">Previous</button>
<button class="next" onclick="plusDivs('project2', 1)">Next</button>
<img class="slides" src="img/project-1/Scan-41.jpg" alt="project2 slide1">
<img class="slides" src="img/project-1/Scan-22.jpg" alt="project2 slide2">
<img class="slides" src="img/project-1/Scan-33.jpg" alt="project2 slide3">
<img class="slides" src="img/project-1/Scan-38.jpg" alt="project2 slide4">
<img class="slides" src="img/project-1/Scan-49.jpg" alt="project2 slide5">
</div>
</div>

I see you have a good answer but I am adding this as an alternative.
I would suggest using a class for a more generic selector to the parent then use that. Note I also added the option here to set a predefined displayed image by using the data-slide-index attribute, then set that to the value of the currently selected image. If that were saved to a cookie for example, you could restore from that also.
You could remove the project1 and project2 classes if you wanted to.
I also used data-direction so that I could remove the click handler from the markup and not really care which button was clicked.
a bit cleaner markup without the event, making it more generic there without the group name need
restore the last viewed/first to view (with cookie addition or from back-end)
used a hidden class and toggled that for the show/hide
used a 0 based internally numbers as arrays are 0 based and makes coding simpler to maintain but added 1 for the display for normal people.
importantly, NO use of global variables
(function setup() {
// add event listener to buttons
let els = document.getElementsByClassName("project-container");
for (let i = 0; i < els.length; i++) {
let prevnext = els[i].getElementsByClassName("prevnext");
for (let p = 0; p < prevnext.length; p++) {
prevnext[p].addEventListener("click", plusMinusDivs, false);
}
//hide/show for each group, avoid this call by adding classes to markup
showImage(els[i]);
}
})();
function plusMinusDivs() {
let parent = this.closest(".project-container");
let slider = this.closest(".imgslide");
let slideIndex = slider.dataset.slideIndex * 1;
let nd = this.dataset.direction * 1;//*1 to avoid parse
slideIndex = slideIndex += nd;
let slides = parent.querySelectorAll(".slides");
if (slideIndex >= slides.length) {
slideIndex = 0;
}
if (slideIndex < 0) {
slideIndex = slides.length - 1;
}
slider.dataset.slideIndex = slideIndex + "";
showImage(parent);
}
function showImage(parent) {
let slides = parent.querySelectorAll(".slides");
let len = slides.length;
for (let s = 0; s < len; s++) {
slides[s].classList.toggle("hidden", true);
}
let slider = parent.querySelector(".imgslide");
let slideIndex = slider.dataset.slideIndex * 1;//*1 to avoid parse
slides[slideIndex].classList.toggle("hidden", false);
let pageText = (slideIndex + 1) + ' / ' + len;
parent.querySelector(".pagination").innerText = pageText;
}
.hidden {
display: none;
}
.prevnext {
background-color: #AAEEDD;
}
<div class="project-container project1">
<div class="pagination"> </div>
<div class="imgslide noselect" data-slide-index="0">
<button class="prevnext prev" data-direction="-1"><<</button>
<button class="prevnext next" data-direction="1">>></button>
<img class="slides" src="img/project-1/Scan-4.jpg" alt="4" />
<img class="slides" src="img/project-1/Scan-24.jpg" alt="24" />
<img class="slides" src="img/project-1/Scan-35.jpg" alt="35" />
<img class="slides" src="img/project-1/Scan-39.jpg" alt="39" />
<img class="slides" src="img/project-1/Scan-40.jpg" alt="40" />
</div>
</div>
<div class="project-container project2">
<div class="pagination"> </div>
<div class="imgslide noselect" data-slide-index="3">
<button class="prevnext prev" data-direction="-1"><<</button>
<button class="prevnext next" data-direction="1">>></button>
<img class="slides" src="img/project-1/Scan-41.jpg" alt="2-41" />
<img class="slides" src="img/project-1/Scan-22.jpg" alt="2-42" />
<img class="slides" src="img/project-1/Scan-33.jpg" alt="2-33" />
<img class="slides" src="img/project-1/Scan-38.jpg" alt="2-38" />
<img class="slides" src="img/project-1/Scan-49.jpg" alt="2-49" />
</div>
</div>

Related

How can I reset my html image gallery to start with first image after leaving it?

I have a website with multiple image galleries on different parts of the website. When you click on the image of specific gallery it changes to next one of that gallery and so on.
What I am trying to achieve is to reset the previous gallery to image 1 when you start clicking on a different gallery. So when the user goes back to the previous gallery, it would start from the first image.
Code used for the galleries:
let projectIndexes = {
project1: 1,
project2: 1,
}
showDivs("project1", projectIndexes.project1);
showDivs("project2", projectIndexes.project2);
function plusDivs(project, n) {
showDivs(project, projectIndexes[project] += n);
}
function showDivs(project, index) {
let i;
let x = document.getElementById(project).getElementsByClassName("slidess");
if (index > x.length) { index = 1 }
if (index < 1) { index = x.length }
for (i = 0; i < x.length; i++) {
x[i].style.display = "none";
}
x[index - 1].style.display = "block";
projectIndexes[project] = index;
let elements = document.getElementById(project).querySelector('.imgslide').children;
let imgNames = [];
for (let i = 0; i < elements.length; i++) {
imgNames.push(elements[i].children[0].children[0].alt);
}
}
<div class="slide">
<div class="slide-content">
<div class="nextt" onclick="plusDivs('project1', 1)"></div>
</div>
<div class="image-container container prjct">
<div class="projects" id="project1">
<div class="imgslide noselect">
<div class="content-container slidess">
<div class="style-3 style-3-left">
<img class="imageName" alt="Img" src="">
</div>
<div class="style-3 style-3-middle">
<img class="imageName" alt="Img" src="">
</div>
<div class="style-3 style-3-right">
<img class="imageName" alt="Img" src="">
</div>
</div>
</div>
</div>
</div>
</div>
<div class="slide">
<div class="slide-content">
<div class="nextt" onclick="plusDivs('project2', 1)"></div>
</div>
<div class="image-container container prjct">
<div class="projects" id="project2">
<div class="imgslide noselect">
<div class="content-container slidess">
<div class="style-3 style-3-left">
<img class="imageName" alt="Img" src="">
</div>
<div class="style-3 style-3-middle">
<img class="imageName" alt="Img" src="">
</div>
<div class="style-3 style-3-right">
<img class="imageName" alt="Img" src="">
</div>
</div>
<!-- <div class="img-name"></div> -->
</div>
</div>
</div>
</div>
I know a way to force show the first element, but it turns out it does that for all projects.
What I was not able to find is a way to recognise when clicking on a new project, that the previous and only previous project needs to reset to first image.
I have been struggling with this for a while now and cannot make it work, so any help would be highly appreciated. And if something is not clear, let me know and I will clarify things.
If I'm following you correctly, the following should do it.
function resetPriorGalleries(currentProject) {
var projectDivs = document.getElementsByClassName("projects");
for (let i = 0; i < projectDivs.length; i++) {
if (projectDivs[i].id === currentProject)
return;
showDivs(projectDivs[1].id, 1);
}
}
The best place to call it would probably be in the onclicks.
onclick="plusDivs('project2', 1); resetPriorGalleries('project2');"

Automatic Cycling Carousel for several divs and different img

I am trying to write a function, that will automatically carousel cycle through img thumbs on my site with 12 different sets of images, which are just put together in one div. The javascript below works, but only as long, as I have the same amount of images in every div. I am also sure, that I took the long route of telling javascript, what to do in terms of variables so my question is, what should I change, so that I can have different amounts of img in my separate divs?
Thanks a lot for any tips!
var myIndex = 0;
carousel();
function carousel() {
var i;
var u = document.getElementsByClassName("thumbs1");
var v = document.getElementsByClassName("thumbs2");
var w = document.getElementsByClassName("thumbs3");
// and so on ...
for (i = 0; i < w.length; i++) {
u[i].style.display = "none";
v[i].style.display = "none";
w[i].style.display = "none";
// ...
}
myIndex++;
if (myIndex > w.length) {myIndex = 1}
u[myIndex-1].style.display = "inline-block";
v[myIndex-1].style.display = "inline-block";
w[myIndex-1].style.display = "inline-block";
// ...
setTimeout(carousel, 1200); // Change image every 2 seconds
}
<div class="imageholder">
<img class="thumbs1" src="image11.jpg">
<img class="thumbs1" src="image12.jpg">
<img class="thumbs1" src="image13.jpg">
<img class="thumbs1" src="image14.jpg">
</div>
<div class="imageholder">
<img class="thumbs2" src="image21.jpg">
<img class="thumbs2" src="image22.jpg">
<img class="thumbs2" src="image23.jpg">
</div>
<div class="imageholder">
<img class="thumbs3" src="image31.jpg">
<img class="thumbs3" src="image32.jpg">
<img class="thumbs3" src="image33.jpg">
<img class="thumbs3" src="image34.jpg">
<img class="thumbs3" src="image35.jpg">
</div>
<!-- ... -->
Keep counting the myIndex (so do not reset it) and use the modulus % operator with the array length of each image set.
Further notes:
The value of Timeout/Interval is in milliseconds. So 2000ms = 2s
You do not need to get all elements' references again with each call to carousel(). Just do it once at the beginning.
If something is not clear, please ask.
var myIndex = 0;
var i;
var u = document.getElementsByClassName("thumbs1");
var v = document.getElementsByClassName("thumbs2");
var w = document.getElementsByClassName("thumbs3");
var allThumbs = [u, v, w];
var myInterval = setInterval(carousel, 2000); // Change image every 2 seconds
function carousel() {
myIndex++;
for (i = 0; i < allThumbs.length; i++) {
allThumbs[i][(myIndex - 1) % allThumbs[i].length].style.display = "none";
allThumbs[i][myIndex % allThumbs[i].length].style.display = "inline-block";
}
}
.thumbs1:not(:first-child),
.thumbs2:not(:first-child),
.thumbs3:not(:first-child) {
display: none;
}
<div class="imageholder">
<img class="thumbs1" src="image11.jpg" alt="1">
<img class="thumbs1" src="image12.jpg" alt="2">
<img class="thumbs1" src="image13.jpg" alt="3">
<img class="thumbs1" src="image14.jpg" alt="4">
</div>
<div class="imageholder">
<img class="thumbs2" src="image21.jpg" alt="1">
<img class="thumbs2" src="image22.jpg" alt="2">
<img class="thumbs2" src="image23.jpg" alt="3">
</div>
<div class="imageholder">
<img class="thumbs3" src="image31.jpg" alt="1">
<img class="thumbs3" src="image32.jpg" alt="2">
<img class="thumbs3" src="image33.jpg" alt="3">
<img class="thumbs3" src="image34.jpg" alt="4">
<img class="thumbs3" src="image35.jpg" alt="5">
</div>

Image Slider is not working properly

I want my javascript to work separately with both id="wrapper" and id="wrapper2" but it is not doing so.....i really don't know what to do next pls help...is i am doing something wrong or i have to make different javascripts for my different image sliders on same page. or any editing in this code will help??
<div id="wrapper">
<div class="slides">
<img src="slide1/1.jpeg" alt="image" width="100%" height="100%"/>
</div>
<div class="slides">
<img src="slide1/2.jpeg" alt="image" width="100%" height="100%"/>
</div>
<div class="slides">
<img src="slide1/3.jpeg" alt="image" width="100%" height="100%"/>
</div>
<button class="btn" onclick="plusIndex(1)" id="btn1">&#10094</button>
<button class="btn" onclick="plusIndex(-1)" id="btn2">&#10095</button>
</div>
<div id="wrapper2">
<div class="slides">
<img src="slide2/1.jpeg" alt="image" width="100%" height="100%"/>
</div>
<div class="slides">
<img src="slide2/2.jpeg" alt="image" width="100%" height="100%"/>
</div>
<div class="slides">
<img src="slide2/3.jpeg" alt="image" width="100%" height="100%"/>
</div>
<button class="btn" onclick="plusIndex(1)" id="btn1">&#10094</button>
<button class="btn" onclick="plusIndex(-1)" id="btn2">&#10095</button>
</div>
here is the javascript
var index = 1;
function plusIndex(n){
index = index + n;
showImage(index);
}
showImage(index);
function showImage(n){
var i;
var x = document.getElementsByClassName("slides");
if(n > x.length){
index = 1;
}
if(n <=0 ){
index = x.length;
}
for(i=0; i<x.length;i++){
x[i].style.display = "none";
}
x[index - 1].style.display = "block";
}
In your html put the class name of the wrapper in your plusIndex call, thus:
<button class="btn" onclick="plusIndex(1, 'wrapper')" id="btn1">&#10094</button>
<button class="btn" onclick="plusIndex(-1, 'wrapper')" id="btn2">&#10095</button>
and
<button class="btn" onclick="plusIndex(1, 'wrapper2')" id="btn1">&#10094</button>
<button class="btn" onclick="plusIndex(-1, 'wrapper2')" id="btn2">&#10095</button>
Then in the js, keep an associative array for index, not a single number, thus:
var indexes = {'wrapper': 1, 'wrapper2': 1};
then the rest is easy:
function plusIndex(n, id){
indexes[id] += n;
showImage(indexes[id], id);
}
function showImage(n, id){
var i;
var el = document.getElementById(id);
var x = el.querySelector('slides');
if(n > x.length){
indexes[id] = 1;
}
if(n <=0 ){
indexes[id] = x.length;
}
for(i=0; i<x.length;i++){
x[i].style.display = "none";
}
x[indexes[n] - 1].style.display = "block";
}
Haven't tested the code, but should get you there mostly.

html and css slider not loading on page refresh but works well when click on nxt or pre button?

Here is the html code and JavaScript code, on page refresh slider images does not get loaded but after clicking the next button of slider it works well but after page refresh images disappear.
<div class="slide-banner">
<div class="slide">
<img src="assets/3387c282bae062cc6efada9402ef42ad.jpg" />
</div>
<div class="slide">
<img src="assets/iPhone-Text-Monitoring-on-Apple-Devices-Yes-And-So-Much-More.jpg" />
</div>
<div class="slide">
<img src="assets/pexels-photo-168765.jpeg" />
</div>
<div class="slide">
<img src="assets/pexels-photo-355988.jpeg" />
</div>
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>
Please review my snippet it may help to resolve your issue.
You should use absolute path rather than the relative path in image src. And called plusSlides(1) method rather than showSlides().
var slideIndex = 1;
plusSlides(1);
function plusSlides(n) {
showSlides(slideIndex += n);
}
function currentSlide(n) {
showSlides(slideIndex = n);
}
function showSlides(n) {
var i;
var slides = document.getElementsByClassName("slide");
if (n > slides.length) {
slideIndex = 1
}
if (n < 1) {
slideIndex = slides.length
}
for (i = 0; i < slides.length; i++) {
slides[i].style.display = "none";
}
slides[slideIndex - 1].style.display = "block";
}
document.addEventListener("DOMContentLoaded", function(event) {
plusSlides(1);
});
<div class="slide-banner">
<div class="slide">
<img src="https://dummyimage.com/600x400/000/fff" />
</div>
<div class="slide">
<img src="https://dummyimage.com/600x400/000/fff" />
</div>
<div class="slide">
<img src="https://dummyimage.com/500x700/000/fff" />
</div>
<div class="slide">
<img src="https://dummyimage.com/100x200/000/fff" />
</div>
<a class="prev" onclick="plusSlides(-1)">❮</a>
<a class="next" onclick="plusSlides(1)">❯</a>

Changing all images on timer with JS

I have this 3x3 img gallery. I need all of them to change every certain time with JS.
So far I managed to do this to one of the images. I don't know how to target them all.
<script>
var images = ["http://lorempixel.com/250/200/", "http://lorempixel.com/250/150/"];
var i = 0;
var renew = setInterval(function(){
if(images.length == i){
i = 0;
}
else {
document.getElementByClassName('galleryItem').src = images[i];
i++;
}
},1000);
</script>
<div class="galleryWrapper">
<div class="galleryItem item1">
<img id="image1" src="http://lorempixel.com/250/200/" alt="picture1">
</div>
<div class="galleryItem item2">
<img id="image2" src="http://lorempixel.com/250/200/" alt="picture2">
</div>
<div class="galleryItem item3">
<img id="image3" src="http://lorempixel.com/250/200/" alt="picture3">
</div>
<div class="galleryItem item4">
<img id="image4" src="http://lorempixel.com/250/200/" alt="picture4">
</div>
<div class="galleryItem item5">
<img id="image5" src="http://lorempixel.com/250/200/" alt="picture5">
</div>
<div class="galleryItem item6">
<img id="image6" src="http://lorempixel.com/250/200/" alt="picture6">
</div>
<div class="galleryItem item7">
<img id="image7" src="http://lorempixel.com/250/200/" alt="picture7">
</div>
<div class="galleryItem item8">
<img id="image8" src="http://lorempixel.com/250/200/" alt="picture8">
</div>
<div class="galleryItem item9">
<img id="image9" src="http://lorempixel.com/250/200/" alt="picture9">
</div>
</div>
I don't know JS at all so don't be too harsh.
Thanks in advance.
Remove the onload from your body element (Using DOMContentLoaded event instead it is less intrusive).
var imageList = ["http://lorempixel.com/250/200/", "http://lorempixel.com/250/150/"],
imageListCounter = 0,
imageEls;
function swapImages() {
var i = 0, len = imageEls.length;
for (i = 0; i < len; i++) {
imageEls[i].src = imageList[imageListCounter];
}
imageListCounter++;
if (imageListCounter > imageList.length - 1) {
imageListCounter = 0;
}
}
document.addEventListener('DOMContentLoaded', function(event) {
imageEls = document.querySelectorAll('.galleryItem img');
setInterval(swapImages, 1000);
});
What we are doing here is:
on document ready store all the image elements in imageEls
then start a timer, calling swapImages every 1 second
swapImages iterates over images and changes the .src to what is in the next one in imageList
when the imageListCounter reaches the end of imageList it resets to 0
So the complete html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Simple Gallery</title>
<link rel="stylesheet" href="style.css">
<script>
var imageList = ["http://lorempixel.com/250/200/", "http://lorempixel.com/250/150/"],
imageListCounter = 0,
imageEls;
function swapImages() {
var i = 0, len = imageEls.length;
for (i = 0; i < len; i++) {
imageEls[i].src = imageList[imageListCounter];
}
imageListCounter++;
if (imageListCounter > imageList.length - 1) {
imageListCounter = 0;
}
}
document.addEventListener('DOMContentLoaded', function(event) {
imageEls = document.querySelectorAll('.galleryItem img');
setInterval(swapImages, 1000);
});
</script>
</head>
<body>
<div class="galleryWrapper">
<div class="galleryItem item1">
<img src="http://lorempixel.com/250/200/" alt="picture1">
</div>
<div class="galleryItem item2">
<img src="http://lorempixel.com/250/200/" alt="picture2">
</div>
<div class="galleryItem item3">
<img src="http://lorempixel.com/250/200/" alt="picture3">
</div>
<div class="galleryItem item4">
<img src="http://lorempixel.com/250/200/" alt="picture4">
</div>
<div class="galleryItem item5">
<img src="http://lorempixel.com/250/200/" alt="picture5">
</div>
<div class="galleryItem item6">
<img src="http://lorempixel.com/250/200/" alt="picture6">
</div>
<div class="galleryItem item7">
<img src="http://lorempixel.com/250/200/" alt="picture7">
</div>
<div class="galleryItem item8">
<img src="http://lorempixel.com/250/200/" alt="picture8">
</div>
<div class="galleryItem item9">
<img src="http://lorempixel.com/250/200/" alt="picture9">
</div>
</div>
</body>
</html>
Where you set the image name to image1, you can just change to 'image'+i+''
document.getElementById('image'+i+'').src = images[i];
for (var e = 1; e < 10; e++)
{
var ImgID = 'image' + e;
document.getElementById(ImgID).src = images[i];
}
If you were using jquery you could just do a foreach on all the img elements. but the above will work. if you have 9 images with the ID of image1, image2, image3... you get the idea.
write this code in your else block
var imgs = document.getElementsByTagName('img');
for(j=0;j<imgs.length;j++){
imgs[j].src = images[i];
}
i++;
instead of this
document.getElementByClassName('gallery').src = images[i];
i++;
Give all your images a class attribute with the same value.
assuming you use the value "imagetags", replace your document.getElementById() line with the following:
var elements = document.GetElementsByClassName("imagetags");
for (var elem in elements){
elements[elem].src = images[i];
}

Categories