HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

jQuery Delay slideDown using Queue

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
slidedowndelayjqueryusingqueue

Problem

I have the task to create a function that adds some messages to the page and another to show them in last to first order with a jQuery slideDown() effect.

jsFiddle

jQuery("#input1").click(function()
{
    //Represents the first function to add the messages
    jQuery.each(["1", "2", "3"],
        function(index, item)
        {
            var jDiv =jQuery(item);
            jDiv.hide();
            jQuery(".parent").prepend(jDiv);
        });

    //represents the second function to show them.
    var jParent = jQuery(".parent");
    jParent.children().reverse().each(function()
    {
        var jThis= jQuery(this);
        jParent.queue( function()
       {
           jThis.slideDown(function()
           {
               jParent.dequeue();
           });

       });
    }); 
});


(reverse from this answer)

jQuery.fn.reverse = [].reverse;


This seems to be an awful bunch of code just to show them one after another. Is there any way to clean up/remove redundant code?

Solution

I would use function recursion in place of a jQuery queue.

The central piece is the displayNextHiddenMessagesIn function. As the name implies, it grabs the next hidden message and displays it. After the message is displayed, it calls this function again... looping until all messages are visible.

To me, this seems much more readable and easier to maintain. Also, it would be trivial to have a another message parent and reuse this same code (i.e. error messages and information messages).

(function($) {

    function createMessageFor(parent, contents) {
        var $parent = $(parent);
        
        for(var content in contents) {
            var $message = newMessage(contents[content]);
    
            $parent.prepend($message);
        }
   
        function newMessage(text) {
            return $("").text(text).hide();
        };
    }
    
    var displayNextHiddenMessagesIn = function(parent) {
        var $parent = $(parent);

        $parent.find('div:hidden:last').slideDown(function() {
            displayNextHiddenMessagesIn($parent);                             
        });
    };

    $("#input1").click(function()
    {
        createMessageFor('.parent', [1,2,3]);
        displayNextHiddenMessagesIn('.parent');
    });
        
})(jQuery);


see it in action: http://jsfiddle.net/natedavisolds/TP66b/6/
Update

Here's what it looks like as a plugin:

(function($) {
    $.fn.fanDownHiddens = function() {
        return this.each(function() {            
            var $parent = $(this);
        
            $parent.find('div:hidden:last').slideDown(function() {
                $parent.fanDownHiddens();                             
            });
        });
    }            
})(jQuery);


And then the onload with the test data.

(function($) {
    
    $(function() {
        $("#input1").click(function() {
           setupTestMessages('.parent');
           $('.parent').fanDownHiddens();
        });
    });
    
     function setupTestMessages(parent) {
        var $parent = $(parent),
            testData = [1,2,3];
        
        for(var content in testData) {
            var $message = newMessage(testData[content]);
            
            $parent.prepend($message);
        }
        
        function newMessage(text) {
            return $("").text(text).hide();
        };
    }
})(jQuery);


Here's the plugin working: http://jsfiddle.net/natedavisolds/TP66b/12/

Code Snippets

(function($) {

    function createMessageFor(parent, contents) {
        var $parent = $(parent);
        
        for(var content in contents) {
            var $message = newMessage(contents[content]);
    
            $parent.prepend($message);
        }
   
        function newMessage(text) {
            return $("<div />").text(text).hide();
        };
    }
    
    var displayNextHiddenMessagesIn = function(parent) {
        var $parent = $(parent);

        $parent.find('div:hidden:last').slideDown(function() {
            displayNextHiddenMessagesIn($parent);                             
        });
    };

    $("#input1").click(function()
    {
        createMessageFor('.parent', [1,2,3]);
        displayNextHiddenMessagesIn('.parent');
    });
        
})(jQuery);
(function($) {
    $.fn.fanDownHiddens = function() {
        return this.each(function() {            
            var $parent = $(this);
        
            $parent.find('div:hidden:last').slideDown(function() {
                $parent.fanDownHiddens();                             
            });
        });
    }            
})(jQuery);
(function($) {
    
    $(function() {
        $("#input1").click(function() {
           setupTestMessages('.parent');
           $('.parent').fanDownHiddens();
        });
    });
    
     function setupTestMessages(parent) {
        var $parent = $(parent),
            testData = [1,2,3];
        
        for(var content in testData) {
            var $message = newMessage(testData[content]);
            
            $parent.prepend($message);
        }
        
        function newMessage(text) {
            return $("<div />").text(text).hide();
        };
    }
})(jQuery);

Context

StackExchange Code Review Q#2223, answer score: 2

Revisions (0)

No revisions yet.