Search code examples
javascripthtmlpost-incrementuncaught-exceptionpre-increment

Javascript $('li').length call throws uncaught exception


I've built a little webpage with a carousel image slider. The slider has buttons which when clicked upon trigger an image change and also some corresponding text to appear below the slider. Right now the slider has four images. When I click the 'next image' button past the fourth image, the slideshow and corresponding text blurbs are supposed to start over, but instead my Javascript or JSON throws an error. The same error is thrown if I click the 'previous image' button when the page first loads. This leads me to believe that the problem is near the increment decrement functions, but of course I could be wrong. The error is below and I apologize in advance for its weird codeblock format. I'm not experienced with js exceptions so I was unsure what the best format was for posting them. I threw all of my html, css and js in one codeblock because I'm unsure if it's the html or js that is causing the exception to be thrown. Any insights would be greatly appreciated!

Uncaught TypeError: Cannot read property 'Imagedes' of undefinedmoveRight @ ShowcaseWebsiteTest.html:272(anonymous function) @ ShowcaseWebsiteTest.html:281m.event.dispatch @ jquery-latest.min.js:3m.event.add.r.handle @ jquery-latest.min.js:3


<html>
<title>Showcase Website</title>
<meta charset="UTF-8">
<head>
<style>
header {
      width:100%;
      background-color:lightblue;
      text-align:center;
      padding:5px;
  }
  /*Use of the child selector Combinator*/
  header > h1 {
      color: black;
}
  /*Use of Pseudo-Class*/
  p::first-letter {
      font-size: x-large;
}
  /*Use of the Navigation Bar*/
  nav {
      line-height:30px;
      background-color:#8f8f8f;
      height:1500px;
      width:100px;
      float:left;
      padding:5px;
      position: relative;
  }
  /*Pseudo-Class*/
  a:visited {
      color: #00BDA0;
}
  /*Using Box Model, Border, Outline, Margin, Padding, Dimension, Float*/
  section {
      height:350px;
      width:100%;
      padding:10px 0 30px 2px;
      border: 3px solid gray;
      margin: 0px 1px 5px 25px;
  }
  /*Using the "display: none" property to hide a previous title*/
  h1.hidden{
      display: none;
  }
  /*Using Positioning*/
  article.art1 {
      height:350px;
      width:350px;
      float:center;
      padding-top:100px;
      padding-left:50px;
      position: relative;
      top: 125px;
      left: 85px;
  }
/*Using Positioning*/
  aside {
      height:350px;
      width:350px;
      float:right;
      padding-top:10px;
      padding-right:150px;
      position: relative;
      top: 45px;
      left: 45px;
      right: 50px;
  }
  footer {
      background-color:lightblue;
      color:white;
      clear:both;
      text-align:center;
      padding:5px;
  }

@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,300,600);

html {
border-top: 5px solid #fff;
background: #58DDAF;
color: #2a2a2a;
}

html, body {
margin: 0;
padding: 0;
font-family: 'Open Sans';
}

h1 {
color: #fff;
text-align: center;
font-weight: 300;
}

#slider {
position: relative;
overflow: hidden;
margin: 20px auto 0 auto;
border-radius: 4px;
}

#slider ul {
position: relative;
margin: 0;
padding: 0;
height: 200px;
list-style: none;
}

#slider ul li {
position: relative;
display: block;
float: left;
margin: 0;
padding: 0;
width: 500px;
height: 300px;
background: #ccc;
text-align: center;
line-height: 300px;
}

button.control_prev, button.control_next {
position: absolute;
top: 40%;
z-index: 999;
display: block;
padding: 2% 2%;
width: auto;
height: auto;
background: #2a2a2a;
color: #fff;
text-decoration: none;
font-weight: 600;
font-size: 10px;
opacity: 0.8;
cursor: pointer;
border:solid transparent;
}

button.control_prev:hover, button.control_next:hover {
opacity: 1;
-webkit-transition: all 0.2s ease;
}

button.control_prev {
border-radius: 0 2px 2px 0;
}

button.control_next {
right: 0;
border-radius: 2px 0 0 2px;
}

.slider_option {
  position: relative;
  margin: 10px auto;
  width: 160px;
  font-size: 18px;
}

.active{
    color:red;
}
.imageDes{
    color:red;
}
</style>
</head>
<body>
  <main>
    <header>
      <h1>Text</h1>
    </header>

    <nav>
       <a href="">Home</a>
      <br><a href="">How To</a>
      <br><a href="">Additional</a>
      <br>
    </nav>

    <section class="section3">
      <h1>Text</h1>
      <p>
        Text
      </p>
      <ul>
        <li>Text</li>
        <li>Text</li>
        <li>Text</li>
      </ul>
    </section>


<div id="slider">

  <button class="control_next">></button>
  <button class="control_prev"><</button>
  <ul>
     <li class="active" data-des="Image 1">SLIDE 1</li>
     <li data-des="Image 2" style="background: #aaa;">SLIDE 2</li>
     <li data-des="Image 3">SLIDE 3</li>
     <li data-des="Image 4" style="background: #aaa;">SLIDE 4</li>
  </ul>  
</div>
<div class="imageDes"></div>

<footer>
Name Here
    </footer>


  </main>
<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script>
var dataJson=[{"Imagedes":"Description for Image one which can be so long that it might extend upto 2 lines in most of the cases and that has to be rendered on image change"},
    {"Imagedes":"Description for Image two which can be so long that it might extend upto 2 lines in most of the cases and that has to be rendered on image change"},
    {"Imagedes":"Description for Image three which can be so long that it might extend upto 2 lines in most of the cases and that has to be rendered on image change"},
        {"Imagedes":"Description for Image four which can be so long that it might extend upto 2 lines in most of the cases and that has to be rendered on image change"}]

var index=0;
$('.imageDes').text(dataJson[0].Imagedes);
jQuery(document).ready(function ($) {

  $('#checkbox').change(function(){
    setInterval(function () {
    moveRight();
   }, 3000);
 });

var slideCount = $('#slider ul li').length;
var slideWidth = $('#slider ul li').width();
var slideHeight = $('#slider ul li').height();
var sliderUlWidth = slideCount * slideWidth;

$('#slider').css({ width: slideWidth, height: slideHeight });

$('#slider ul').css({ width: sliderUlWidth, marginLeft: - slideWidth });

$('#slider ul li:last-child').prependTo('#slider ul');

function moveLeft() {
    $('#slider ul').animate({
        left: + slideWidth
    }, 200, function () {
        $('#slider ul li:last-child').prependTo('#slider ul');
        $('#slider ul').css('left', '');

    });
    if(index<=0)
        index=$('li').length-1;
    else
        index--
    $('.imageDes').text(dataJson[index].Imagedes);
};

function moveRight() {
    $('#slider ul').animate({
        left: - slideWidth
    }, 200, function () {
        $('#slider ul li:first-child').appendTo('#slider ul');
        $('#slider ul').css('left', '');
    });

    if(index+1>=$('li').length)
        index=0;
    else
        index++
     $('.imageDes').text(dataJson[index].Imagedes);

};

$('button.control_prev').click(function () {
    moveLeft();
});

$('button.control_next').click(function () {
    moveRight();
});

});
</script>
</body>
</html>

Solution

  • Change $('li').length in your moveRight() and moveLeft() functions to use your slideCount variable.

    Right now $('li').length returns the total number of li elements on the page (which is greater than the number of carousel slides). This results in your index variable being set to values that are out-of-bounds for your dataJson array, and therefore causing dataJson[index] to return undefined.