简体   繁体   中英

Javascript function is not defined on click event

EDIT: I have made a js fiddle with the answer that still returns undefined function.

I am struggling to find out why my function is returning undefined. My html:

<div class="slideshow">
            <div class="slide">  
                <div class="work-info col-3">
                    <div class="block-orange">
                        <h3>Work</h3>
                        <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Nisi ipsum iure esse nemo facere ea, iste deserunt odit provident labore exercitationem nihil, laborum, sit vel nostrum illo ducimus possimus dolorum.</p>
                    </div>
                </div>
            </div>
            <div class="slide">
            </div>
            <div class="slide">
            </div>
            <div class="slide">
            </div>

            <div class="dot-cont">
              <div class="dot" onclick="clickChangeSlide(0)"></div>
              <div class="dot" onclick="clickChangeSlide(1)"></div>
              <div class="dot" onclick="clickChangeSlide(2)"></div>
              <div class="dot" onclick="clickChangeSlide(3)"></div>
            </div>
            <button class="arrow-button left-arrow" onclick="clickChangeSlide(i-1)">&#60;</button>
            <button class="arrow-button right-arrow" onclick="clickChangeSlide(i+1)">&#62;</button>      
    </div>

The js is being loaded at the bottom of the page. JS:

document.addEventListener("DOMContentLoaded", function(event) {
  let i = -1;
  let time = 5000;
  let slideTimer;
  let slides = document.getElementsByClassName('slide');
  let slideDots = document.getElementsByClassName('dot');

  function clickChangeSlide(n){
    clearTimeout(slideTimer);
    changeSlide(n, true);
  }

  function changeSlide(n = i, manual = false){

    for(let j = 0; j < slides.length; j++){
      if(j == i) {
        slides[j].classList.add('prev-slide');
        slides[j].classList.remove('active-slide');
        slideDots[j].classList.remove('active-dot');
        continue; 
      }
      slideDots[j].classList.remove('active-dot');
      slides[j].classList.remove('prev-slide'); 
      slides[j].classList.remove('active-slide');
    }
    if(manual){
      if(n < 0) i = slides.length - 1
      else if(n > slides.length - 1) i = 0
      else i = n
    }else i = i < slides.length - 1 ? i+1 : 0;

    slides[i].classList.add('active-slide');
    slideDots[i].classList.add('active-dot');

    slideTimer = setTimeout(changeSlide, time);
  }

  window.onload = changeSlide();
});

I tried to remove the DomcontentLoaded, as I thought this maybe effecting it but to no prevail. When I click the button, ClickChangeSlide does not fire. Any ideas?

You are defining clickChangeSlide() inside the callback so it's scope does not exist throughout the document.

you have to define it outside the callback like:

let i = -1;
let time = 5000;
let slideTimer;
let slides = document.getElementsByClassName('slide');
let slideDots = document.getElementsByClassName('dot');    
document.addEventListener("DOMContentLoaded", function(event) {
window.onload = changeSlide();
});

function clickChangeSlide(n){
    clearTimeout(slideTimer);
    changeSlide(n, true);
  }

  function changeSlide(n = i, manual = false){

    for(let j = 0; j < slides.length; j++){
      if(j == i) {
        slides[j].classList.add('prev-slide');
        slides[j].classList.remove('active-slide');
        slideDots[j].classList.remove('active-dot');
        continue; 
      }
      slideDots[j].classList.remove('active-dot');
      slides[j].classList.remove('prev-slide'); 
      slides[j].classList.remove('active-slide');
    }
    if(manual){
      if(n < 0) i = slides.length - 1
      else if(n > slides.length - 1) i = 0
      else i = n
    }else i = i < slides.length - 1 ? i+1 : 0;

    slides[i].classList.add('active-slide');
    slideDots[i].classList.add('active-dot');

    slideTimer = setTimeout(changeSlide, time);
  }

Your DOM tries to access functions that aren't available at DOM build time, onclick=clickChangeSlide(0)... is responsible for that. Put both functions changeSlide(...) and clickChangeSlide(...) outside, of your actual DOMContentLoaded event listener to access these functions during DOM build time.

It could look like this:

<div class="slideshow">
    <div class="slide">  
        <div class="work-info col-3">
            <div class="block-orange">
                <h3>Work</h3>
                <p>Lorem ipsum...</p>
            </div>
        </div>
    </div>
    <div class="slide"></div>
    <div class="slide"></div>
    <div class="slide"></div>
    <div class="dot-cont">
         <div class="dot" onclick="clickChangeSlide(0)"></div>
         <div class="dot" onclick="clickChangeSlide(1)"></div>
         <div class="dot" onclick="clickChangeSlide(2)"></div>
         <div class="dot" onclick="clickChangeSlide(3)"></div>
    </div>
    <button class="arrow-button left-arrow" onclick="clickChangeSlide(i-1)">&#60;</button>
    <button class="arrow-button right-arrow" onclick="clickChangeSlide(i+1)">&#62;</button>
</div>

Your javascript code should look like this:

let i = -1;
var slideTimer;
let time = 5000;
let slides = document.getElementsByClassName('slide');
let slideDots = document.getElementsByClassName('dot');

function changeSlide(n = i, manual = false) {
    for (let j = 0; j < slides.length; j++) {
        if (j == i) {
            slides[j].classList.add('prev-slide');
            slides[j].classList.remove('active-slide');
            slideDots[j].classList.remove('active-dot');
            continue; 
        }
        slideDots[j].classList.remove('active-dot');
        slides[j].classList.remove('prev-slide'); 
        slides[j].classList.remove('active-slide');
    }
    if (manual) {
        if(n < 0) i = slides.length - 1
        else if(n > slides.length - 1) i = 0
        else i = n
    } else i = i < slides.length - 1 ? i+1 : 0;

    slides[i].classList.add('active-slide');
    slideDots[i].classList.add('active-dot');

    slideTimer = setTimeout(changeSlide, time);
};

function clickChangeSlide(n) {
    clearTimeout(slideTimer);
    changeSlide(n, true);
};

document.addEventListener("DOMContentLoaded", function(event) {
    window.onload = changeSlide();
});

You also have to change the scope of your variables i, slides, slideDots, ... because you access changeSlide before your variables were declared. Load you javascript code at the top of you html code, with <script src="javascript.js"></script> , otherwise your DOM is not able intialize any function to the onload function of your div elements.

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