Flama
Flama

Reputation: 868

Javascript function not working well when called for the first time

I'm basically trying to use this code on my page: https://www.w3schools.com/w3css/tryit.asp?filename=tryw3css_slideshow_dots2

The thing is I want to create that slideshow, but turns out when I load the page for the first time, no images display. When I click on the circles, then an image appears and everything works fine. I get the following error:

Uncaught TypeError: Cannot read property 'style' of undefined
   at showDivs (details.js:26)
   at details.js:2

Here's the fragment of code for the slideshow:

        <div class="w3-content w3-display-container" style="max-width:800px">
          <img class="mySlides" src="<c:url value="/resources/pics/casa1.jpg" />" style="width:100%">
          <img class="mySlides" src="<c:url value="/resources/pics/casa2.jpg" />" style="width:100%">
          <img class="mySlides" src="<c:url value="/resources/pics/casa3.jpg" />" style="width:100%">
          <img class="mySlides" src="<c:url value="/resources/pics/casa4.jpg" />" style="width:100%">
          <div class="w3-center w3-container w3-section w3-large w3-text-white w3-display-bottommiddle" style="width:100%">
            <div class="w3-left w3-hover-text-khaki" onclick="plusDivs(-1)">&#10094;</div>
            <div class="w3-right w3-hover-text-khaki" onclick="plusDivs(1)">&#10095;</div>
            <span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(1)"></span>
            <span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(2)"></span>
            <span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(3)"></span>
            <span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(4)"></span>
          </div>
        </div>

And my details.js

    var slideIndex = 1;
    showDivs(slideIndex);


    function plusDivs(n) {
      showDivs(slideIndex += n);
    }

    function currentDiv(n) {
      showDivs(slideIndex = n);
    }

    function showDivs(n) {

      var i;
      var x = document.getElementsByClassName("mySlides");
      var dots = document.getElementsByClassName("demo");
      if (n > x.length) {slideIndex = 1}    
      if (n < 1) {slideIndex = x.length}
      for (i = 0; i < x.length; i++) {
         x[i].style.display = "none";  
      }
      for (i = 0; i < dots.length; i++) {
         dots[i].className = dots[i].className.replace(" w3-white", "");
      }
      x[slideIndex-1].style.display = "block";  
      dots[slideIndex-1].className += " w3-white";
    }

Upvotes: 0

Views: 1538

Answers (2)

Scott Marcus
Scott Marcus

Reputation: 65806

Make sure that you place your entire <script> element at the bottom of your HTML, just before the closing body tag (</body>). I'll bet that right now, you've got your code prior to the .mySlides HTML so that when the code first runs, none of those elements have been parsed into memory yet.

In addition, your HTML for your src image attributes is invalid for two reasons.

  1. You have double quotes nested inside of double quotes.
  2. You have < and > characters embedded in the attribute value, which is not allowed.

If you really wanted that code in the attribute, the code would need to look like this:

<img class="mySlides" src="&lt;c:url value='/resources/pics/casa4.jpg&gt;'">

But, why are you trying to make the src equal to another tag?

Also, stay far away from W3 Schools as it is widely known to have incomplete, incorrect, and or outdated code there. Your example includes outdated techniques that you really should avoid, like inline HTML event attributes such as onclick and inline styles.

Here's a working version:

.mySlides {height:100px; }
<!doctype html>
<html>
<head>
</head>
<body>
<div class="w3-content w3-display-container" style="max-width:800px">
          <img class="mySlides" src="http://cdn.shopify.com/s/files/1/0885/7466/products/smiley-decal_1024x1024.png?v=1434998018">
          <img class="mySlides" src="https://imgc.allpostersimages.com/img/posters/have-a-nice-day-smiley-face_u-L-F59IP80.jpg?src=gp&w=300&h=375">
          <img class="mySlides" src="https://images-na.ssl-images-amazon.com/images/I/41q0g8iq5iL.jpg">
          <img class="mySlides" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQjg89JZEZ2SAr1Qd6b__1RO3XoyaiVJStnzJZ5lqwoD45yKRLp">
          <div class="w3-center w3-container w3-section w3-large w3-text-white w3-display-bottommiddle" style="width:100%">
            <span class="w3-left w3-hover-text-khaki" onclick="plusDivs(-1)">&#10094;</span>
            <span class="w3-right w3-hover-text-khaki" onclick="plusDivs(1)">&#10095;</span>
            <span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(1)"></span>
            <span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(2)"></span>
            <span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(3)"></span>
            <span class="w3-badge demo w3-border w3-transparent w3-hover-white" onclick="currentDiv(4)"></span>
          </div>
        </div>
<script>

    var slideIndex = 1;
    showDivs(slideIndex);


    function plusDivs(n) {
      showDivs(slideIndex += n);
    }

    function currentDiv(n) {
      showDivs(slideIndex = n);
    }

    function showDivs(n) {

      var i;
      var x = document.getElementsByClassName("mySlides");
      var dots = document.getElementsByClassName("demo");
      if (n > x.length) {slideIndex = 1}    
      if (n < 1) {slideIndex = x.length}
      for (i = 0; i < x.length; i++) {
         x[i].style.display = "none";  
      }
      for (i = 0; i < dots.length; i++) {
         dots[i].className = dots[i].className.replace(" w3-white", "");
      }
      x[slideIndex-1].style.display = "block";  
      dots[slideIndex-1].className += " w3-white";
    }
  </script>
  </body>
</html>

Upvotes: 1

Marat Badykov
Marat Badykov

Reputation: 844

When you call your script code directly as you do here, your document might not have loaded completely, so it can't find the element. Try to run your code when the page has finished loading, like this:

  window.addEventListener('load', function() {
     var slideIndex = 1;
      showDivs(slideIndex)
    };

    function plusDivs(n) {
      showDivs(slideIndex += n);
    }

    function currentDiv(n) {
      showDivs(slideIndex = n);
    }

    function showDivs(n) {

      var i;
      var x = document.getElementsByClassName("mySlides");
      var dots = document.getElementsByClassName("demo");
      if (n > x.length) {slideIndex = 1}    
      if (n < 1) {slideIndex = x.length}
      for (i = 0; i < x.length; i++) {
         x[i].style.display = "none";  
      }
      for (i = 0; i < dots.length; i++) {
         dots[i].className = dots[i].className.replace(" w3-white", "");
      }
      x[slideIndex-1].style.display = "block";  
      dots[slideIndex-1].className += " w3-white";
    }

Upvotes: 3

Related Questions