adilisi
adilisi

Reputation: 21

Javascript Function to setTimeout and when a button on page is clicked cancel the timeout and proceed with the remaining functions?

    <!DOCTYPE HTML>
<HTML>

<head>

  <center>
    <b> This is My Virtual Pet!</b>
  </center>
  <center> <img id="target" src="https://c402277.ssl.cf1.rackcdn.com/photos/14623/images/magazine_hero/WW188829.jpg?1509653431" width="300" height="250" />

    <br>
    <input type="button" onclick="changeImage()" value=" Scroll Through Emotions" /> </center>

  <br>
  <center>
    <input type="button" onclick="TimeoutStop()" onclick="changeImage(this)" data-values="1,2" value="Feed">
    <input type="button" onclick="TimeoutStop()" onclick="changeImage(this)" data-values="3,4,5" value="Pet">
    <input type="button" onclick="TimeoutStop()" onclick="changeImage(this)" data-values="3,0,4" value="Play">
  </center>


  <script>
    var target = document.getElementById('target');
    var counter = 0;
    var myVar;
    var myRhino = [
      "https://c402277.ssl.cf1.rackcdn.com/photos/14623/images/magazine_hero/WW188829.jpg?1509653431",

      "https://img04.deviantart.net/0594/i/2010/261/5/6/happy_rhino_by_ammut88-d2z0sto.jpg",

      "https://images.fineartamerica.com/images-medium-large-5/angry-rhino-daniel-eskridge.jpg",

      "https://c2.staticflickr.com/2/1340/1368093048_fa7ef85a5a_z.jpg?zz=1",

      "https://images.fineartamerica.com/images/artworkimages/mediumlarge/1/hungry-rhino-james-sarjeant.jpg",

      "http://m.rgbimg.com/cache1nulfB/users/z/za/zatrokz/600/meRoKDQ.jpg",

      "https://i.ytimg.com/vi/R_zz1GEkEk4/maxresdefault.jpg",
    ];

        myVar = setTimeout("TimeoutImg()",2000);

    function changeImage(btn) {
      if (!btn) {
        counter += 1;
        target.src = myRhino[counter % myRhino.length];
      } else {
        var data = btn.getAttribute('data-values');
        var pics = JSON.parse("[" + data + "]"); // Convert string of numbers to an array
        var num = pics.shift(); // remove index 0 from array and store it in num
        pics.push(num); // Add what was previously at index 0 to end of array
        target.src = myRhino[num];
        counter = num;
        btn.setAttribute('data-values', pics.join(','));
      }
    }
      function TimeoutImg(){
            target.src = myRhino[6];
        }

        function TimeoutStop(){
            clearTimeout(myVar);
        }
  </script>

</head>

<body>
</body>

</HTML>

This is the new code with the timeout function. How come when I click the button the timeout stops but It doesn't let me change any pictures on click.

I am trying to have the picture change in 10 seconds after the page opens if no buttons are clicked but if a button is clicked have the timer stop and proceed normallyy by clicked each of the three action buttons and having the image change.

Upvotes: 0

Views: 801

Answers (2)

Nick Parsons
Nick Parsons

Reputation: 50974

As you've edited your question to a new question, I'll post an additional answer.

The reason as to why your timer isn't working is because you have a few issues with your code:

  • myVar = setTimeout("TimeoutImg()",2000); isn't correct, your first argument for setTimeout should be a function callback, not a string. Here you've almost got it right, you just need to change your string to the function callback:

    var myVar = setTimeout(TimeoutImg, 2000);

    Also, generally in programming, it's not considered "good practice" to name your functions with capital letters at the start (as you use capitals for classes/objects). So from now on, I will use lowercase letters at the start of each function name.

  • Another issue is how you are stopping the timeout interval. You've got the right idea with having onlcick trigger the timeoutStop function, however, you're not going about it the right way. A HTML element should only have no repeated attributes on it, so in your case, you're repeating onclick twice:

    onclick="timeoutStop()" onclick="changeImage(this)"

    Instead, of having two onclick attributes, you can combine these into one:

    onclick="changeImage(this); timeoutStop()"

Fixing these issues will resolve your issue.

See working example below:

<!DOCTYPE HTML>
<HTML>

<head>

  <center>
    <b> This is My Virtual Pet!</b>
  </center>
  <center> <img id="target" src="https://c402277.ssl.cf1.rackcdn.com/photos/14623/images/magazine_hero/WW188829.jpg?1509653431" width="300" height="250" />

    <br>
    <input type="button" onclick="changeImage()" value=" Scroll Through Emotions" /> </center>

  <br>
  <center>
    <input type="button" onclick="changeImage(this); timeoutStop()" data-values="1,2" value="Feed">
    <input type="button" onclick="changeImage(this); timeoutStop()" data-values="3,4,5" value="Pet">
    <input type="button" onclick="changeImage(this); timeoutStop()" data-values="3,0,4" value="Play">
  </center>


  <script>
    var target = document.getElementById('target');
    var counter = 0;
    var myRhino = [
      "https://c402277.ssl.cf1.rackcdn.com/photos/14623/images/magazine_hero/WW188829.jpg?1509653431",

      "https://img04.deviantart.net/0594/i/2010/261/5/6/happy_rhino_by_ammut88-d2z0sto.jpg",

      "https://images.fineartamerica.com/images-medium-large-5/angry-rhino-daniel-eskridge.jpg",

      "https://c2.staticflickr.com/2/1340/1368093048_fa7ef85a5a_z.jpg?zz=1",

      "https://images.fineartamerica.com/images/artworkimages/mediumlarge/1/hungry-rhino-james-sarjeant.jpg",

      "http://m.rgbimg.com/cache1nulfB/users/z/za/zatrokz/600/meRoKDQ.jpg",

      "https://i.ytimg.com/vi/R_zz1GEkEk4/maxresdefault.jpg",
    ];

    var changeImageTimer = setTimeout(timeoutImg, 5000); // 5 second timer

    function changeImage(btn) {
      if (!btn) {
        counter += 1;
        target.src = myRhino[counter % myRhino.length];
      } else {
        var data = btn.getAttribute('data-values');
        var pics = JSON.parse("[" + data + "]"); // Convert string of numbers to an array
        var num = pics.shift(); // remove index 0 from array and store it in num
        pics.push(num); // Add what was previously at index 0 to end of array
        target.src = myRhino[num];
        counter = num;
        btn.setAttribute('data-values', pics.join(','));
      }
    }

    function timeoutImg() {
      target.src = myRhino[myRhino.length-1];
    }

    function timeoutStop() {
      clearTimeout(changeImageTimer);
    }
  </script>

</head>

<body>
</body>

</HTML>

Upvotes: 0

Nick Parsons
Nick Parsons

Reputation: 50974

You only need one function to achieve this. Firstly, you can create a function which is in charge of changing the pictures, which you currently have. In my example below I called this changeImage. This function can accept this as an argument, which refers to the current button you clicked on.

onclick="changeImage(this);" // When button is clicked, go to image at index 2

By using this we can get the button's attributes such as the data-values attribute I defined on your buttons.

<input type="button" onclick="changeImage(this)" data-values="1,2" value="Feed">

The data-values attribute allows you to specify the images you want to go to on each image click and the order in which it should follow. I made the data-values attribute work by:

  • Converting the string value to an array of numbers. Eg: "1,2" turns into [1, 2]. This allows me to manipulate the values easily.

  • Using this array, I then get the value at index 0 using .shift(). This removes the value at index 0 and also returns it. After using .shift() my array now looks like: [2].

  • However, because I used .shift() I was able to store the deleted value in num, which I use as the index for the image to display.

  • I then use .push() to push the deleted value (or num) back onto the end of my array. So it now looks like [2, 1].

  • Lastly, I updated the data-values attribute to be equal to this new array. I use .join(',') on the array to turn it into "2,1", and then use .setAttribute to update my data-values attribute. So my element now looks like:

    <input type="button" onclick="changeImage(this)" data-values="2,1" value="Feed">

Now, if I click on the button again, I will repeat this cycle, and the image displayed will be 2 and the data-values attribute will be updated to data-values="1,2" again.

However, if a button isn't passed through into the function, (detected by using if(!btn)), then you can simply just change the image based on the counter.

See working example below:

<!DOCTYPE HTML>
<HTML>

<head>

  <center>
    <b> This is My Virtual Pet!</b>
  </center>
  <center> <img id="target" src="https://c402277.ssl.cf1.rackcdn.com/photos/14623/images/magazine_hero/WW188829.jpg?1509653431" width="300" height="250" />

    <br>
    <input type="button" onclick="changeImage()" value=" Scroll Through Emotions" /> </center>

  <br>
  <center>
    <input type="button" onclick="changeImage(this)" data-values="1,2" value="Feed">
    <input type="button" onclick="changeImage(this)" data-values="3,4,5" value="Pet">
    <input type="button" onclick="changeImage(this)" data-values="3,0,4" value="Play">
  </center>


  <script>
    var target = document.getElementById('target');
    var counter = 0;
    var myRhino = [
      "https://c402277.ssl.cf1.rackcdn.com/photos/14623/images/magazine_hero/WW188829.jpg?1509653431",

      "https://img04.deviantart.net/0594/i/2010/261/5/6/happy_rhino_by_ammut88-d2z0sto.jpg",

      "https://images.fineartamerica.com/images-medium-large-5/angry-rhino-daniel-eskridge.jpg",

      "https://c2.staticflickr.com/2/1340/1368093048_fa7ef85a5a_z.jpg?zz=1",

      "https://images.fineartamerica.com/images/artworkimages/mediumlarge/1/hungry-rhino-james-sarjeant.jpg",

      "http://m.rgbimg.com/cache1nulfB/users/z/za/zatrokz/600/meRoKDQ.jpg",

      "https://i.ytimg.com/vi/R_zz1GEkEk4/maxresdefault.jpg",
    ];

    function changeImage(btn) {
      if (!btn) {
        counter += 1;
        target.src = myRhino[counter % myRhino.length];
      } else {
        var data = btn.getAttribute('data-values');
        var pics = JSON.parse("[" + data + "]"); // Convert string of numbers to an array
        var num = pics.shift(); // remove index 0 from array and store it in num
        pics.push(num); // Add what was previously at index 0 to end of array
        target.src = myRhino[num];
        counter = num;
        btn.setAttribute('data-values', pics.join(','));
      }
    }
  </script>

</head>

<body>
</body>

</HTML>

Upvotes: 2

Related Questions