简体   繁体   中英

How can I make a reusable function?

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">&nbsp;</div> <div class="imgslide noselect" data-slide-index="0"> <button class="prevnext prev" data-direction="-1">&lt;&lt;</button> <button class="prevnext next" data-direction="1">&gt;&gt;</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">&nbsp;</div> <div class="imgslide noselect" data-slide-index="3"> <button class="prevnext prev" data-direction="-1">&lt;&lt;</button> <button class="prevnext next" data-direction="1">&gt;&gt;</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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM