Skip to main content
Corrected annoying bug in the example code that might have tripped up future generations.
Source Link
Thriggle
  • 1.3k
  • 9
  • 23
// Accepts an array of elements and a final callback function
// Returns a function to show all elements and execute the callback
function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex === "undefined" ? 0 : currentIndex;
    if (i === elements.length - 1) {
        // atafter the final element, show the element and call the callback
        return function () {
            elements[i].fadeIn();
            callback();
        };
    } else {
        // for any preceding element, show the element and call a timeout
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].fadeIn();
            setTimeout(nextMethod, 1000);
        };
    }
}
var els = document.querySelectorAll(".showme");
var sprite = {
    play: function () {
        alert("sprite.play");
    }
};
createAudio("audio/test.mp3", els);

function createAudio(filename, elements) {
    var audio = document.querySelector("button"); //new Audio(filename);
    audio.addEventListener("click", function () {
        getFunctionToShowElements(elements, function () {
            sprite.play();
        })();
    });
}


function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex == "undefined" ? 0 : currentIndex;
    if (i === elements.length - 1) {
        
        return function () {
            elements[i].style.display = "inherit";
            callback();
        };
    } else {
        
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].style.display = "inherit";
            setTimeout(nextMethod, 1000);
        };
    }
}
.showme {
    background-color:red;
    display:none;
}
<button>Click me</button>
<div class="showme">Number 1</div>
<div class="showme">Number 2</div>
<div class="showme">Number 3</div>
<div class="showme">Number 4</div>
// Accepts an array of elements and a final callback function
// Returns a function to show all elements and execute the callback
function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex === "undefined" ? 0 : currentIndex;
    if (i === elements.length - 1) {
        // at the final element, show the element and call the callback
        return function () {
            elements[i].fadeIn();
            callback();
        };
    } else {
        // for any preceding element, show the element and call a timeout
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].fadeIn();
            setTimeout(nextMethod, 1000);
        };
    }
}
var els = document.querySelectorAll(".showme");
var sprite = {
    play: function () {
        alert("sprite.play");
    }
};
createAudio("audio/test.mp3", els);

function createAudio(filename, elements) {
    var audio = document.querySelector("button"); //new Audio(filename);
    audio.addEventListener("click", function () {
        getFunctionToShowElements(elements, function () {
            sprite.play();
        })();
    });
}


function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex == "undefined" ? 0 : currentIndex;
    if (i === elements.length - 1) {
        
        return function () {
            elements[i].style.display = "inherit";
            callback();
        };
    } else {
        
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].style.display = "inherit";
            setTimeout(nextMethod, 1000);
        };
    }
}
.showme {
    background-color:red;
    display:none;
}
<button>Click me</button>
<div class="showme">Number 1</div>
<div class="showme">Number 2</div>
<div class="showme">Number 3</div>
<div class="showme">Number 4</div>
// Accepts an array of elements and a final callback function
// Returns a function to show all elements and execute the callback
function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex === "undefined" ? 0 : currentIndex;
    if (i === elements.length) {
        // after the final element, call the callback
        return function () {
            callback();
        };
    } else {
        // for any preceding element, show the element and call a timeout
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].fadeIn();
            setTimeout(nextMethod, 1000);
        };
    }
}
var els = document.querySelectorAll(".showme");
var sprite = {
    play: function () {
        alert("sprite.play");
    }
};
createAudio("audio/test.mp3", els);

function createAudio(filename, elements) {
    var audio = document.querySelector("button"); //new Audio(filename);
    audio.addEventListener("click", function () {
        getFunctionToShowElements(elements, function () {
            sprite.play();
        })();
    });
}


function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex == "undefined" ? 0 : currentIndex;
    if (i === elements.length) {
        
        return function () {
            callback();
        };
    } else {
        
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].style.display = "inherit";
            setTimeout(nextMethod, 1000);
        };
    }
}
.showme {
    background-color:red;
    display:none;
}
<button>Click me</button>
<div class="showme">Number 1</div>
<div class="showme">Number 2</div>
<div class="showme">Number 3</div>
<div class="showme">Number 4</div>
added 1 character in body
Source Link
Thriggle
  • 1.3k
  • 9
  • 23
// Accepts an array of elements and a final callback function
// Returns a function to show all elements and execute the callback
function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex ===== "undefined" ? 0 : currentIndex;
    if (i === elements.length - 1) {
        // at the final element, show the element and call the callback
        return function () {
            elements[i].fadeIn();
            callback();
        };
    } else {
        // for any preceding element, show the element and call a timeout
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].fadeIn();
            setTimeout(nextMethod, 1000);
        };
    }
}
// Accepts an array of elements and a final callback function
// Returns a function to show all elements and execute the callback
function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex == "undefined" ? 0 : currentIndex;
    if (i === elements.length - 1) {
        // at the final element, show the element and call the callback
        return function () {
            elements[i].fadeIn();
            callback();
        };
    } else {
        // for any preceding element, show the element and call a timeout
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].fadeIn();
            setTimeout(nextMethod, 1000);
        };
    }
}
// Accepts an array of elements and a final callback function
// Returns a function to show all elements and execute the callback
function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex === "undefined" ? 0 : currentIndex;
    if (i === elements.length - 1) {
        // at the final element, show the element and call the callback
        return function () {
            elements[i].fadeIn();
            callback();
        };
    } else {
        // for any preceding element, show the element and call a timeout
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].fadeIn();
            setTimeout(nextMethod, 1000);
        };
    }
}
Source Link
Thriggle
  • 1.3k
  • 9
  • 23

To generate those nested, nearly identical setTimeout calls, instead of coding them all manually you could have a recursive function that builds and returns a function for you. Something like this would work:

// Accepts an array of elements and a final callback function
// Returns a function to show all elements and execute the callback
function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex == "undefined" ? 0 : currentIndex;
    if (i === elements.length - 1) {
        // at the final element, show the element and call the callback
        return function () {
            elements[i].fadeIn();
            callback();
        };
    } else {
        // for any preceding element, show the element and call a timeout
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].fadeIn();
            setTimeout(nextMethod, 1000);
        };
    }
}

Then you could set up a function for creating audio objects and attaching the event listener to fade in the given elements.

function createAudio(filename,elements){
    var audio = new Audio(filename);
    audio.addEventListener("ended",function(){
        getFunctionToShowElements(elements,function(){sprite.play();})(); // get the function and execute it immediately
    });
    return audio;
}

At this point you'll be able to create an audio object with the desired event handler like so:

var audio = createAudio("audio/test.mp3",[element1,element2,element3]);

That's just to give you an idea of how you could go about cleaning it up.

There are other improvements you'd want to make in your final code, such as using a variable for the timeout delay, and wrapping up the relevant code sections in closures as necessary. We'd need to see the full code to identify other areas for improvement.

Proof that the concept works:

var els = document.querySelectorAll(".showme");
var sprite = {
    play: function () {
        alert("sprite.play");
    }
};
createAudio("audio/test.mp3", els);

function createAudio(filename, elements) {
    var audio = document.querySelector("button"); //new Audio(filename);
    audio.addEventListener("click", function () {
        getFunctionToShowElements(elements, function () {
            sprite.play();
        })();
    });
}


function getFunctionToShowElements(elements, callback, currentIndex) {
    var i = typeof currentIndex == "undefined" ? 0 : currentIndex;
    if (i === elements.length - 1) {
        
        return function () {
            elements[i].style.display = "inherit";
            callback();
        };
    } else {
        
        var nextMethod = getFunctionToShowElements(elements, callback, i + 1);
        return function () {
            elements[i].style.display = "inherit";
            setTimeout(nextMethod, 1000);
        };
    }
}
.showme {
    background-color:red;
    display:none;
}
<button>Click me</button>
<div class="showme">Number 1</div>
<div class="showme">Number 2</div>
<div class="showme">Number 3</div>
<div class="showme">Number 4</div>