1

I'm using the Bootstrap Carousel feature. On initial load of the page the Carousel next/prev controls work perfectly however when I simpy reload the page these controls no longer respond to clicks even though the interval for "auto" rotating the slides that I've configured continues to work.

I've done alot of research trying to troubleshoot this problems..including reviewing probably 30+ stackoverflow postings on Bootstrap Carousel but none of them offered any solutions for me. After two days of researching this problem I'm still stumped.

Environment/setup:

  1. My browser is Chrome
  2. Libraries included in the following order: a)jQuery 2.1.3, b)Bootstrap CSS 3.3.5, c)Bootsrap JS 3.3.5
  3. Running in Ruby on Rails 4.2 environment
  4. My solution is a pure bootstrap solution (e.g., no special JS other than including variants of $('#carousel-generic-example).carousel() type statement per examples I've seen online..apparently no change in behavior with or without this statement).

I'm a bit puzzled as to why it works properly on initial load but not on subsequent reloads. Perhaps something isn't being loaded properly when I do a re-load of the web page??? Maybe there is some behavior within Rails that is causing this behavior?

If anyone has any theories as to what might be causing this behavior I'd love to hear it (even if you don't have time to dig into the code). Or if you have any specific ideas on what I might be able to do troubleshoot this problem.

There is a lot of relevant code associated with my solution...rather than trying to copy and paste it all in this post I think the most effective and efficient way of "sharing" it with you is to point you to my public Github account where the code is located and provide a map to the relevant files within the project.

First the full set of code can be found on my Github account at: gitHub site Within this project here is where you can find the relevant sections of code:

  • app/views/application.html.erb : List of external libraries (e.g., jQuery, bootstrap files, etc.)
  • app/views/portfolio_items/show.html.erb : HTML for page including Carousel
  • app/assets/javascripts/jet.js : see what I tried lines 17-20, 199-202. I'm not sure if I really need to include javascript as it didn't really seem to affect the behavior of the solution. So I ultimately commented it out.
  • app/assets/stylesheets/jet.css.erb : Lines 2332-2354

Note 1: you'll see that in my javascript file I'm using both $(window).load(function ()... and `$(document).ready(function() {' functions. I have to admit that I'm a bit fuzzy on what these two functions do other than generally make sure that the items on the page load before the javascript starts to run. I leveraged parts of my template from a theme and I noticed that they used both of these functions in their theme so I don't think this is the cause of my issues...but thought I would reference it just in case.

Note 2: I'm not sure it is relevant but I'm also using another Carousel solution (caroufredsel) on the same page with the Bootstrap Carousel. I don't think there is any conflict as the theme I borrowed from did the same thing...but I thought I would mention it.

UPDATE: I've continued to try and resolve my issue (i.e., Bootstrap Carousel next/prev buttons don't advance images) and stumbled upon something interesting that could be the key to fixing my issue. Specifically

When I "close" the $(document).ready" statement immediately as follows:

  • '$(document).ready(function() {});'

in my javascript "app/assets/javascripts/jet.js" the Bootstrap Carousel behaves as I would expect (prev/next controls advance images when clicked on).

Unfortunately making the change breaks the other carousel functionality (caroufredsel) at the bottom of the web page (i.e., instead of only showing 3 elements at a time in caroufredsel it shows all of the items and the controls for caroufredsel then don't work). I really need to wrap other jQuery code in the $(document).ready functionality...but when I do the Bootstrap prev/next controls don't work properly.

Anybody have any suggestions on what is going on here and how I could fix it? Here is the full version of the jet.js file:

function scroll_to(clicked_link, nav_height) {
    var element_class = clicked_link.attr('href').replace('#', '.');
    var scroll_to = 0;
    if(element_class != '.top-content') {
        element_class += '-container';
        scroll_to = $(element_class).offset().top - nav_height;
    }
    if($(window).scrollTop() != scroll_to) {
        $('html, body').stop().animate({scrollTop: scroll_to}, 1000);
    }
}


$(document).ready(function() {
// Bootstrap Carousel -- Tried each of the following lines but neither of them helped
// $('#carousel-generic-example').carousel()
// $('.carousel').carousel()
// $('#carousel-generic-example').carousel()});
// {
    // 'prev'
    // 'next'
    // pause: true,
    // interval: false,
    // keyboard: true
// }

// jQuery('#carousel-generic-example').carousel();

// Pretty photo script
$("a[data-rel^='prettyPhoto']").prettyPhoto({
        theme: 'light_square',
        social_tools: false,
        hook: 'data-rel'
});


// ------------------------------------------------------------------------------------------
  // Code below attempted to dynamically change glyphicons used on web page separator
  // to avoid having to distinct CSS code for every separator (e.g., blog-separator, project-separator, etc)
  // Unfortunately I couldn't get this to work...this code displays the character string
  // for the blog glyphicon (i.e., e043) rather than the actual glyphicon. StackOverflow (http://stackoverflow.com/questions/5041494/manipulating-css-pseudo-elements-such-as-before-and-after-using-jquery?lq=1) from Blazemonger (#3) suggest it may only work for strings (maybe not hex values)
  // So I'm assuming i can't dynamically insert glyphicons.
// ------------------------------------------------------------------------------------------
  // var regExp = /\#([a-z]+)/;
  //
  //  $(".menu-items a").on('click', function () {
  //     var href = $(this).attr('href');
  //     var matches = regExp.exec(href);
  //     switch(matches[1]) {
  //       case "home":
  //         alert(href);
  //
  //         break;
  //       case "about":
  //         alert(href);
  //         break;
  //       case "projects":
  //         alert(href);
  //         break;
  //       case "blog":
  //         $('.separator-line').attr('data-content', '\e043');
  //         // $(this).attr('data-content', '\e043');
  //         // $(".separator-line::after.content").attr('glyphicon-code',"\e043");
  //         var separatorCode = $(this).attr('data-content', '\e043').val();
  //         alert(separatorCode);
  //         break;
  //       case "contact":
  //         alert(href)
  //         break;
  //     }
  //    });
// -------------------------------------------------------------------------------

// Portfolio Javascript to load images

// var $container = $('.container');
//
// $container.imagesLoaded( function() {
//   $container.masonry({
//     itemSelector        : '.post-box',
//     columnWidth         : '.post-box',
//     transitionDuration  : 0
//   });
// });

$(".truncateIt").dotdotdot({
        // configuration goes here
        /*  The text to add as ellipsis. */
    ellipsis    : '... ',

    /*  How to cut off the text/html: 'word'/'letter'/'children' */
    wrap        : 'word',

    /*  Wrap-option fallback to 'letter' for long words */
    fallbackToLetter: true,

    /*  jQuery-selector for the element to keep and put after the ellipsis. */
    after       : 'a.next',

    /*  Whether to update the ellipsis: true/'window' */
    watch       : false,

    /*  Optionally set a max-height, if null, the height will be measured. */
    height      : 60,

    /*  Deviation for the height-option. */
    tolerance   : 0,

    /*  Callback function that is fired after the ellipsis is added,
        receives two parameters: isTruncated(boolean), orgContent(string). */
    callback    : function( isTruncated, orgContent ) {},

    lastCharacter   : {

        /*  Remove these characters from the end of the truncated text. */
        remove      : [ ' ', ',', ';', '.', '!', '?' ],

        /*  Don't add an ellipsis if this array contains
            the last character of the truncated text. */
        noEllipsis  : []
    }
});

// Scroll location for buttons on banner page

$('a.scroll-link').on('click', function(e) {
  e.preventDefault();
  scroll_to($(this), $('nav').outerHeight());
});

// Link and activate WOW.js
new WOW().init();

$(".nav a").on("click", function(){
   $(".nav").find(".active").removeClass("active");
   $(this).parent().addClass("active");
});

// Smooth scrolling logic

  $('a[href*=#]:not([href=#])').click(function() {
      if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'')
          || location.hostname == this.hostname) {

          var target = $(this.hash);
          target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
             if (target.length) {
               $('html,body').animate({
                   scrollTop: target.offset().top
              }, 1000);
              return false;
          }
      }
  });


    $(".cnbox").each(function () {
        var nheight = $(this).find(".nbox").height();
        $(this).find(".cbox").css("height", nheight + 50);
    });

}); // /document.ready()

var caroufredsel = function () {
        $('#caroufredsel-portfolio-container').carouFredSel({
            responsive: true,
            scroll: 1,
            circular: false,
            infinite: false,
            items: {
                    visible: {
                            min: 1,
                            max: 3
                    }
            },
            prev: '#portfolio-prev',
            next: '#portfolio-next',
            auto: {
                    play: false
            }
    });


    $('#caroufredsel-blog-posts-container').carouFredSel({
        responsive: true,
        scroll: 1,
        circular: false,
        infinite: false,
        items: {
            visible: {
                    min: 1,
                    max: 3
                }
        },
        prev: '#blog-posts-prev',
        next: '#blog-posts-next',
        auto: {
                play: false
        }
    });
};


// Isotope Portfolio
var $container = $('.portfolio-container');
var $blogcontainer = $('.posts-wrap');
var $filter = $('.portfolio-filter');

$(window).load(function () {
        // Bootstrap Carousel -- Tried each of the following lines but neither of them helped
        // jQuery('.carousel').carousel();
        // jQuery('#carousel-generic-example').carousel();

        caroufredsel();
        // Initialize Isotope
        $container.isotope({
                itemSelector: '.portfolio-item-wrapper'
        });

        $blogcontainer.isotope({
                itemSelector: '.article-wrap'
        });

        $('.portfolio-filter a').click(function () {
                var selector = $(this).attr('data-filter');
                $container.isotope({ filter: selector });
                return false;
        });
        $filter.find('a').click(function () {
                $filter.find('a').parent().removeClass('active');
                $(this).parent().addClass('active');
        });
    });

    $(window).smartresize(function () {
        $container.isotope('reLayout');
        $blogcontainer.isotope('reLayout');
    });

    $(window).resize(function () {
        caroufredsel();
    });

Cheers.

user2101068
  • 617
  • 1
  • 8
  • 23
  • I'm not 100% sure of this, but you might try turning off turbolinks (comment it out) in your gemfile and run again. If it works after that, the solution is simple. – Mark Swardstrom Aug 20 '15 at 18:49
  • Swards, thanks for the suggestion...as per your suggestion I commented out turbolinks (and commented out "references" to it in app/views/layouts/application.html.erb file and restarted my Rails server. It did have an effect but unfortunately now the prev/next controls don't work on initial load or reload.....but i think my problem is probably something like this...i.e., Rails specific. That being said turning off turbolinks does allow my other carosel (caroufredsel) to work properly on first load (previously it only worked properly when I reloaded the web page). Further thoughts? – user2101068 Aug 20 '15 at 19:16
  • You can search on this more - but essentially you don't want to use $(document).ready with turbolinks. To get you started http://stackoverflow.com/questions/18770517/rails-4-how-to-use-document-ready-with-turbo-links – Mark Swardstrom Aug 20 '15 at 19:20
  • Swards, thanks...I will research this...maybe it's also time for me to better understand $(document).ready vs $(window).load(function()). I suspect my problem is being caused by Rails...maybe following the thread you provided will lead me to a solution. Thanks again for responding! – user2101068 Aug 20 '15 at 19:26
  • Does anyone know if the Bootsrap Carousel requires that you use any jquery to make the controls work properly? (e.g., $('#carousel-generic-example).carousel()). – user2101068 Aug 20 '15 at 22:18
  • Answering my own comment...It appears that you don't need to include $('#carousel-generic-example).carousel()) based on my experience. – user2101068 Aug 22 '15 at 05:07

2 Answers2

1

After much trial and error I found the solution through trial and error. As it turns out the $(document).ready(function() { had to be closed (i.e., }); immediately before the Smooth Scrolling logic (i.e., code that starts with $('a[href*=#]:not([href=#])').click(function() {).

I'm not completely sure why the "close" has to be placed there and not after the Smooth scrolling logic.

If anyone has an explanation I'd love to hear why...As I mentioned I discovered the solution largely by trial and error.

user2101068
  • 617
  • 1
  • 8
  • 23
0

Bootstrap needs normally a JQuery file to overcome this error. So, better embed it in your file and it works when online.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>