Search code examples
jqueryruby-on-railsinitializationfullcalendarpartial-views

FullCalendar only appears on reload


So I've been going crazy here. I'm pretty new to coding and have no idea how to fix this.

I'm making a rails 4 app using ruby 2 and arshaw's FullCalendar.

The correct scripts are appearing in the head. The JQuery script that calls the calendar is in the head. The calendar is working. The issue is that the calendar is in a different view that the user navigates to from a link in the header. The calendar does not appear but appears upon refreshing the page.

I have no idea why this is happening but I think it has something to do with the initializing script in the head requiring the existence of a div id='calendar'. It does not have this until the later view is called, whereupon I recall the script in the head and everything works.

I'll patch in as much code as I can here and the full code is available on:

https://github.com/joesus/MtgCal

So far I've tried using the controller to refresh the page but I can't figure out how to do this without it sending me into an infinite loop, also it only refreshes that part of the view so it doesn't help anyway.

I've tried using a js timeout but again that only seems to refresh part of the view and not the full page so it didn't work.

Here's my layout: application.html.erb

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= content_for?(:title) ? yield(:title) : "1311 York St" %></title>
<%= csrf_meta_tags %>
<%= render 'layouts/shim' %>   
<%= stylesheet_link_tag "application", :media => "all" %>
<%= render 'layouts/device_specific' %>
<%= javascript_include_tag "application" %>
<!-- Tried calling the script from partial _cal.html.erb instead of a .js file with the same info,
 didn't fix anything, not sure why I thought it might. -->
</head>

<body>

  <!-- <div id='calendar' style='display: none'></div> 
  Thought I could initialize it in the layout
  then call it again in the schedule view. Didn't work. -->

<%= render 'layouts/header' %>
<p id="bodytop"></p>
      <%= bootstrap_flash %>
      <%= yield %>


<%= render 'layouts/footer' %>

</div>

</body>
</html>

Here's my script where I initalize the calendar: /assets/javascripts/initialize.js

$(document).ready(function() {

// page is now ready, initialize the calendar...
// 

$('#calendar').fullCalendar({
   events: 'http://www.google.com/calendar/feeds/.../public/basic', 

      weekMode: 'liquid',

      height: 600,

      defaultView: 'agendaWeek',

      allDaySlot: false,

        header: {
                  left: 'title',
                  center: 'agendaDay,agendaWeek,month',
                  right: 'today prev,next'
        }


    });
});

This appears in local host in the head as:

<script src="/assets/jquery-ui-1.10.3.custom.min.js?body=1"></script>

And this is where I call the Calendar into existence: /views/layouts/static_pages/schedule.html.erb

<h1>Meetings</h1>
<div id='calendar'></div>

Basically I need to figure out someway to refresh the information in the head when I navigate to a view that renders in the main layout.

Any advice would be greatly appreciated. Again, whole thing is on github so maybe there's something I broke somewhere else that explains this.

Thanks, Joe

Update:

I implemented Erowlin's solution and now my initalize.js looks like this:

$(document).on('ready page:load', function(){

$('#calendar').fullCalendar({

   events: 'http://www.google.com/calendar/feeds/..../public/basic', 

      weekMode: 'liquid',

      height: 600,

      defaultView: 'agendaWeek',

      allDaySlot: false,

        header: {
                  left: 'title',
                  center: 'agendaDay,agendaWeek,month',
                  right: 'today prev,next'
        },

    windowResize: function(view) {
      if ($(window).width() < 514){
        $('#calendar').fullCalendar( 'changeView', 'agendaDay' );
      } else {
        $('#calendar').fullCalendar( 'changeView', 'agendaWeek' );
      }
    }
  });
});

It works beautifully and allows me to leave my schedule.html.erb view looking clean and beautiful.

<h1>Meetings</h1>
<div id='calendar'></div>

The windowResize callback was used to solve a different issue. More information here: How Can I get Adam Shaw's fullCalendar to display responsively in a rails 4 app

Thanks again for the help.


Solution

  • Short answer : TurboLink preloads each page so the ready event is not fired. Instead you have to add "page:load" even to your javascript, like this :

    Coffeescript solution:

    $(document).on 'ready page:load', ->
         // Your coffee script stuff
    

    JQuery Solution :

    $(document).on('ready page:load', function(){
         // Your stuff
    }
    

    Long answer : Turbolink doesn't care about JQuery ready event and add new event. Here is a list of turbolink's events. Turbolink preloads each page and the ready event is not fired. If you have a lot of javascript, you can use this library to add the "page:load" on all your JQuery stuff.