0

I have a list of element ids, for example 1, 2, 3 .....

I want to append a div to element 1, wait 1 second, remove the appended div from element 1 and then append a div to element 2, and so on for each element listed in seqIDs

Below is my code but I can't figure out how to remove the previous appended element or how to delay the loop by 1 second. I'm using vanilla javascript, so please no jQuery answers

for (var i = 0, len = seqIDs.length; i < len; i++) {
    var newDiv = document.createElement('div');
    document.getElementById(seqIDs[i]).appendChild(newDiv);
    setTimeout(this.reset, 1000);
}
totalitarian
  • 3,606
  • 6
  • 32
  • 55

1 Answers1

2

You can use setTimeout() to walk through the sequence, removing one and adding another on each timer call until you get to the end of the array:

(function() {
    var cntr = 0;
    var lastItem;

    function next() {
        if (lastItem) {
            lastItem.parentNode.removeChild(lastItem);
            lastItem = null;
        }
        if (cntr < seqIDs.length) {
            var newDiv = document.createElement("div");
            document.getElementById(seqIDs[cntr++]).appendChild(newDiv);
            lastItem = newDiv;
            setTimeout(next, 1000);
        }
    }
    next();
})();

If you want it to just repeat itself over and over again, you can put it in a function that takes an argument for whether to repeat itself and then wrap cntr back to 0:

function cycleDiv(forever) {
    var cntr = 0;
    var lastItem;

    function next() {
        if (lastItem) {
            lastItem.parentNode.removeChild(lastItem);
            lastItem = null;
        }
        if (forever && cntr >= seqIDs.length) {
            // wrap back to zero
            cntr = 0;
        }
        if (cntr < seqIDs.length) {
            var newDiv = document.createElement("div");
            document.getElementById(seqIDs[cntr++]).appendChild(newDiv);
            lastItem = newDiv;
            setTimeout(next, 1000);
        }
    }
    next();
}

cycleDiv(true);

To make one that you can start or stop at any time, you could do this:

function cycleDiv(forever) {
    var cntr = 0;
    var lastItem;

    function next() {
        if (lastItem) {
            lastItem.parentNode.removeChild(lastItem);
            lastItem = null;
        }
        if (forever && cntr >= seqIDs.length) {
            // wrap back to zero
            cntr = 0;
        }
        if (cntr < seqIDs.length) {
            var newDiv = document.createElement("div");
            document.getElementById(seqIDs[cntr++]).appendChild(newDiv);
            lastItem = newDiv;
            this.timer = setTimeout(next, 1000);
        }
    }

    this.stop = function() {
        clearTimeout(this.timer);
        this.timer = null;
    }

    this.start = function() {
        if (!this.timer) {
            next();
        }
    }
}


var cycler = new cycleDiv(true);
cycler.start();

// then some time later
cycler.stop();

Also, it's a bit inefficient to keep creating and removing a new div element every second. I don't know what you're doing with the content of this div (since there's nothing in it in this code), but you could just have one div that you move from one parent to the next rather than continually making new div elements.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Great stuff! Works perfectly. Any idea how to get it to loop the sequence indefinitely? – totalitarian Feb 16 '14 at 23:10
  • What do you want it to do when it gets to the end of the `seqID` array? Repeat itself? – jfriend00 Feb 16 '14 at 23:13
  • Yes please. It would be good if this could be set by a bool too – totalitarian Feb 16 '14 at 23:14
  • @totalitarian - a loop forever option added to the end of my answer. – jfriend00 Feb 16 '14 at 23:17
  • Thanks again! One last request if possible. Can a method be created to stop the loop, for example, after a button click? – totalitarian Feb 16 '14 at 23:23
  • It would probably be more efficient to store the created divs in an array and loop through them. Or better yet, put them all in the DOM and just show and hide them as appropriate. – RobG Feb 16 '14 at 23:28
  • @RobG - Point taken. It would probably be the most efficient to just move the one div from one parent to the next since there's no unique content being shown here. – jfriend00 Feb 16 '14 at 23:35
  • @Yes, but I expect there is more to the div content than is being shown here. Many ways to skin a cat. :-) – RobG Feb 16 '14 at 23:40
  • @totalitarian - one more version added that has start/stop methods. – jfriend00 Feb 16 '14 at 23:42