0

I am trying below code to get auto-slide for images that is 4 to 5 images should appear one after another continuously. For this I wrote below code using for loop and setTimeout to delay images till end of list.

The problem I am facing here is I am able to view the image after some delay but I am able to see only last image of the list not all images.

Unable to trace out the issue.

<article id="images" >

</article>
<script>
    var ima = ['11.jpg','12.jpg' ];
    var txt="'"+"Images/"+ima[0]+"'"; */
    var x = document.createElement("IMG");
    for (i = 0; i < ima.length; i++) {
        var x = document.createElement("IMG");
        x.setAttribute("src", "Images/"+ima[i]);
        x.setAttribute("width", "200");
        x.setAttribute("height", "200");
        setTimeout(function(){document.getElementById("images").appendChild(x);}, 1000);
    }
</script>

With above code only 12.jpg is shown in window but not 11.jpg.

My expectation is:

  • firstly, 11.jpg should get displayed
  • then 1 second later, 11.jpg should be invisible and 12.jpg should be visible.
Pineda
  • 7,435
  • 3
  • 30
  • 45
Siva
  • 9,043
  • 12
  • 40
  • 63
  • Welcome to StackOverflow, your question should contain a [Minimal, Complete and Verifiable Example](http://stackoverflow.com/help/mcve). – hungerstar Apr 06 '17 at 16:27
  • @hungerstar sir this is the whole code that I have written... should I paste full jsp code? – Siva Apr 06 '17 at 16:28
  • Thanks for reply....Sorry sir forgot to remove that slide part from article part... first I wrote code in slide function but its not working.. so removed that wrote this way... if not article what should be used to get slide functionality – Siva Apr 06 '17 at 16:33
  • Sir.. I am totally lost.. can you please help how to get the code worked. – Siva Apr 06 '17 at 16:35
  • Possible duplicate of [setTimeout in for-loop does not print consecutive values](http://stackoverflow.com/questions/5226285/settimeout-in-for-loop-does-not-print-consecutive-values) – Heretic Monkey Apr 06 '17 at 16:41

3 Answers3

3

This is an asynchronous issue. setTimeout triggers it callback after the loop has finished running. The value stored in x will not be different for each iteration of the loop with the code you provided.

When setTimeout eventually calls this line:

document.getElementById("images").appendChild(x);

the value of x is going to be whatever the value of x is after the last iteration of the loop. So if you have 5 elements , you'll be making 5 calls to setTimeout where x.src === "Images"+ima[4]


To get round this you can use a closure to keep the scope of the x variable intact when it is called:

for (i = 0; i < ima.length; i++) {

  var x = document.createElement("IMG");
  x.setAttribute("src", "Images/"+ima[i]);
  x.setAttribute("width", "200");
  x.setAttribute("height", "200");

  // create a closure to pass to set interval
  appendImg = function(x){
    return function(){
      document.getElementById("images").appendChild(x);
    };
  }(x);

  // pass closure to setInterval, the x value will be enclosed in the closure for each
  //value of x
  setTimeout(appendImg, 1000);
}
Pineda
  • 7,435
  • 3
  • 30
  • 45
  • Sir.. this didn't work aswell... I got 2 images side by side instead of slide – Siva Apr 06 '17 at 16:48
  • Just corrected a line. I was accidentally invoking the return function, rather than passing back a closure – Pineda Apr 06 '17 at 16:49
  • Made my amendments, try it now. – Pineda Apr 06 '17 at 16:51
  • Thanks sir.. I have tried the code but I am getting 2 images side by side after 1 second but not one by one with 1 sec gap – Siva Apr 06 '17 at 16:56
  • I see. It seems to be what you are asking for is a carousel type of functionality. Is this correct? If so you may want to update your original question or create a new one describing your actual requirement. The solution provided is a fix for the fact that you had only one image showing up. This will save this question from becoming too clogged up with answers and comments pertaining to the original question as written – Pineda Apr 06 '17 at 17:01
  • sure sir.. will do that – Siva Apr 06 '17 at 17:07
  • Cool. Btw, @Rounin seems to have provided a solution that might meet your requirements. – Pineda Apr 06 '17 at 17:08
  • Thanks sir.. for your time and support – Siva Apr 07 '17 at 09:24
  • No need for the formalities dude. Helping others is what SO is about :) – Pineda Apr 07 '17 at 09:25
2

For the setup you describe, it strikes me that you might be better off using

  • presentational CSS

    rather than

  • behavioural javascript.

Here is an example:

.picture-frame {
position: relative;
width: 160px;
height: 160px;
background-color: rgb(15, 15, 127);
overflow-x: hidden;
}

.picture-frame img {
position: absolute;
top: 0;
right: -160px;
z-index: 6;
width: 160px;
height: 160px;
}

.picture-frame img:nth-of-type(1) {
animation: slide-left-1 12s linear infinite;  
}

.picture-frame img:nth-of-type(2) {
animation: slide-left-2 12s linear infinite;  
}

.picture-frame img:nth-of-type(3) {
animation: slide-left-3 12s linear infinite;  
}

.picture-frame img:nth-of-type(4) {
animation: slide-left-4 12s linear infinite;  
}

.picture-frame img:nth-of-type(5) {
z-index: 3;
animation: slide-left-5 12s linear infinite;  
}

@keyframes slide-left-1 {
      0% {right: -160px;}
 10%, 20% {right: 0;}
 30%, 100% {right: 160px;}
}

@keyframes slide-left-2 {
  0%, 20% {right: -160px;}
 30%, 40% {right: 0;}
 50%, 100% {right: 160px;}
}

@keyframes slide-left-3 {
  0%, 40% {right: -160px;}
 50%, 60% {right: 0;}
 70%, 100% {right: 160px;}
}

@keyframes slide-left-4 {
  0%, 60% {right: -160px;}
 70%, 80% {right: 0;}
 90%, 100% {right: 160px;}
}

@keyframes slide-left-5 {
        0% {right: 0;}
  10%, 20% {right: 160px;}
  30%, 80% {right: -160px;}
  90%, 100% {right: 0;}
}
<div class="picture-frame">
<img src="http://placekitten.com/150/150" />
<img src="http://placekitten.com/152/152" />
<img src="http://placekitten.com/153/153" />
<img src="http://placekitten.com/156/156" />
<img src="http://placekitten.com/158/158" />
</div>

Explanation:

There are two types of CSS animated presentation. Simple animations (usually involving a simple shift from one state to another and back) can be described using transition:.

More complex animations (like the animations above) are handled using animation: and a corresponding @keyframes set of sequenced animation rules.

In the example above the default starting position of all five images is just to the right of their parent container. Since the latter has a declaration of overflow-x: hidden all five images are effectively out of sight.

Then, each image has its own animation which describes:

  • how long it remains out of sight to the right of the container
  • when it slides leftwards into the parent container (and how long that slide takes)
  • how long it remains in view in the middle of the container
  • when it slides leftwards out of the parent container (and how long that slide takes)

Each separate image animation takes place simultaneously over a 12 second period. The entire set of animations then begins again and runs for 12 seconds. And so on ad infinitum.

For instance this animation:

@keyframes slide-left-3 {
  0%, 40% {right: -160px;}
 50%, 60% {right: 0;}
 70%, 100% {right: 160px;}
}

Describes the following:

  • Between 0% and 40% of 12 seconds, remain in the initial out of sight position (right of the parent)
  • Between 40% and 50% of 12 seconds move leftwards fully into sight
  • Between 50% and 60% of 12 seconds remain fully in sight
  • Between 60% and 70% of 12 seconds move leftwards fully out of sight
  • Between 70% and 100% of 12 seconds remain fully out of sight (left of the parent)

The entire set of animations is structured so that when one image is sliding out of view, the next image is always sliding into view.

Community
  • 1
  • 1
Rounin
  • 27,134
  • 9
  • 83
  • 108
  • 1
    up-voted for providing an answer to the question the OP was _trying_ to ask. – Pineda Apr 06 '17 at 17:04
  • thanks for your reply sir.. your answer was almost close but I need to continously repeat those images one by one without any break – Siva Apr 06 '17 at 17:06
  • and for quite an elegant solution for this particular context. – Pineda Apr 06 '17 at 17:06
  • Okay, I've juggled it a bit. In order for the animation to continue as an _infinite loop_, each image needed to have its own separate animation. – Rounin Apr 06 '17 at 17:45
  • 1
    @Rounin thank you very much for your time and intrest sir... You are really a champion. If you don't mind can you please help to explain how code exactly works may be in 2 to 3 lines on concepts used...I am newbie in css and javascript part. – Siva Apr 07 '17 at 09:23
  • I've added an explanation to the post above. Do ask if you have any further questions. – Rounin Apr 07 '17 at 09:49
  • 1
    Thank you very much sir.. your explanation is very much clear and precise – Siva Apr 07 '17 at 15:19
1

Problem is you are calling timeout twice in your loop. Try this instead

var ima = ['11.jpg','12.jpg' ];
var counter = 0;

function slide() {
  if(x > ima.length ) counter = 0;
  var txt="'"+"Images/"+ima[0]+"'"; 
  var x = document.createElement("IMG");
  for (i = 0; i < ima.length; i++) {

    var x = document.createElement("IMG");
    x.setAttribute("src", "Images/"+ima[i]);
    x.setAttribute("width", "200");
    x.setAttribute("height", "200");
  }
  document.getElementById("images").appendChild(x);

  counter++;
  setTimeout(function(){slide()}, 1000);
}

slide();
serdar.sanri
  • 2,217
  • 1
  • 17
  • 21