Search code examples
javascriptjqueryhtmlflexslider

Second jQuery function failing to run


I have created two user-defined functions within the "head" section of an HTML page and I am calling them with a script just before the closing "body" tag. The trouble is that the second function is not working, unless I include an "alert" statement in the first function (which halts the execution until I dismiss the alert).

I am guessing it is caused by the first function not actually finishing completely before the second one starts and by having my alert statement it gives the first function time to finish.

Function one is to build a list of images in DIV tags. Function two implements FlexSlider to initiate a slideshow of the images.

Calling the below as it is will render a page with all images shown. If I uncomment the alert box and run it again, the screen is rendered with my images, I dismiss the alert box, and then FlexSlider kicks in and starts the slideshow.

Here are the two functions defined in the "head" section.

<script type="text/javascript">
        var buildslider = function () {
            $.ajax({
                type: "GET",
                url: "/myImages/homepageslider/PhotoGallery.xml",
                dataType: "xml",
                success: function(xml) {
                    $(xml).find('img').each(function() {
                        var location = '/myImages/homepageslider/';
                        var url = $(this).attr('src');
                        var alt = $(this).attr('alt');
                        $('<div class="slide-group"></div>').html('<img src="'+location+''+url+'" alt="'+alt+'"/>').appendTo('.slides');
                    });
                }
            });
        //alert("buildslider finished");
        };

        var runslider = function() {
            $('.flexslider').flexslider({
                selector: '.slides > .slide-group',
                controlNav: false,
                directionNav: false
            });
        };
    </script>

And here is the code near the closing "body" tag.

   <script>
        $(document).ready(function() {
            buildslider();
            runslider();
            });
    </script>

What am I doing wrong and how do I correct this so it can be done properly?

Thank you in advance. David.


Solution

  • Return the ajax() returned object from the first function. This is a jQuery "promise" object which will then expose done and fail methods. These methods take a function, so you can just insert your second function into done. See example below:

    <script type="text/javascript">
            var buildslider = function () {
                return $.ajax({
                    type: "GET",
                    url: "/myImages/homepageslider/PhotoGallery.xml",
                    dataType: "xml",
                    success: function(xml) {
                        $(xml).find('img').each(function() {
                            var location = '/myImages/homepageslider/';
                            var url = $(this).attr('src');
                            var alt = $(this).attr('alt');
                            $('<div class="slide-group"></div>').html('<img src="'+location+''+url+'" alt="'+alt+'"/>').appendTo('.slides');
                        });
                    }
                });
            };
    
            var runslider = function() {
                $('.flexslider').flexslider({
                    selector: '.slides > .slide-group',
                    controlNav: false,
                    directionNav: false
                });
            };
        </script>
    

    Then run with:

    <script>
        $(document).ready(function() {
            buildslider().done(runslider);
            });
    </script>
    

    It also makes it easier to handle failures in a more general way:

    <script>
        $(document).ready(function() {
            buildslider().done(runslider).fail(function(){
               alert("#%&£ happens!");
            });
        });
    </script>
    

    Using promises is far more flexible than using callbacks, and supports multiple done() functions, so is now the preferred way to do this.

    Note: A simpler shortcut for DOM ready is $(function(){ your code here }); or if you want it to have a locally scoped $ use jQuery(function($){ your code here }); which acts as both a DOM ready handler and provides a locally scoped $ to avoid clashes (e.g. with other plugins).