philippfrenzel / yii2fullcalendar

JQuery Fullcalendar Yii2 Extension
GNU General Public License v2.0
133 stars 97 forks source link

Calendar duplicates with Pjax + browser back button #36

Closed cicsolutions closed 8 years ago

cicsolutions commented 8 years ago

Hello,

I'm using your awesome fullcalendar widget in a view using Pjax, and I was having an issue where clicking the browser back button to go back to the view with the calendar would end up triggering the widget JS again and rendering the calendar twice.

I tried several ways to address the issue, and there probably are multiple ways to fix it, but in the end, what I was able to get working was I adjusted the registerPlugin method to first check if the calendar already exists before registering the javascript.

So in the registerPlugin() method, I made the following change:

//$js[] = "jQuery('#$id').fullCalendar($cleanOptions);";
$js[] = "if (jQuery('#$id').children().not('.fc-loading').length == 0) { jQuery('#$id').fullCalendar($cleanOptions); }";

This seems like a safe and helpful approach, so I thought I would share it in hopes it gets added to the core, or at least helps anyone else out that may be experiencing the same issue.

If there is a different and better way to do this, please let me know.

cicsolutions commented 8 years ago

Actually ... the above approach is not working properly. The calendar does not display twice (which is good), but now the calendar callback functions are not triggering.

If you have any suggestions, I'd very much appreciate your input. I'll keep thinking on my end too!

philippfrenzel commented 8 years ago

Hey, I'll take a look at this at the weekend - sorry to busy at work :/

cicsolutions commented 8 years ago

Awesome, thank you! The following resource looks like it could be helpful: https://github.com/defunkt/jquery-pjax/issues/152

This is probably more of a Pjax challenge than anything to do with your fullcalendar widget, but we may find a way to bake in a solution, which would be good :)

philippfrenzel commented 8 years ago

Hi, didn't forgett about you - did you solve it in the mean time? I think I'll have to undertand push states of the calendar... - need some more time ...

cicsolutions commented 8 years ago

Hey! Thanks so much for checking in! I spent a few days trying to find a solution, but was unsuccessful. I'll take another look too and let you know if I come up with anything fun :)

cicsolutions commented 8 years ago

Okay, so here's what I ended up doing to resolve the issue on my end. This is a complex matter. Since we're talking about using the fullcalendar along with pjax, it helped me to become as familiar as possible with the various js callbacks and the order in which they fire for both fullcalendar and pjax.

When the fullcalendar is initialized, the javascript basically looks for a container element with the calendar id and places the fullcalendar inside the container. Then, with pjax in the picture, if a user clicks the back browser button, the fullcalendar javascript fires again, thus duplicating the display of the fullcalendar. I ended up determining that we DO want the javascript to initialize again when the user clicks the back button, we just don't want the calendar to display twice.

Basically, what I did was to force a refresh of the calendar on every display. This effectively clears the calendar display before re-initializing the fullcalendar widget.

In the yii2fullcalendar.php file, I modified the registerPlugin method in the following way:

// Forcing a clean refresh of the calendar
var loading_container = jQuery('.fc-loading'); // take a backup of the loading container b/c we need to keep it
jQuery('#$id').fullCalendar('destroy').empty().append(loading_container); // destroy any existing calendar, empty the calendar container and append the loading container
jQuery('#$id').fullCalendar($cleanOptions);

I'm including the fullCalendar('destroy') event, but I'm not sure if it's really necessary. It doesn't seem to hurt anything, so I'm leaving it in for now :)

There are probably many ways to address this issue, which is certainly not a bug in anything you've coded, just a unique challenge when using fullcalendar with pjax.

Hopefully this helps others, and perhaps there's a cleaner better way to bake this into your fullcalendar yii2 extension.

I suppose, depending on how people are using the fullcalendar with pjax, this approach may not work for everyone. It probably needs more testing to be sure it's a safe fix for everyone. But it works for my specific build, so I'm happy!

Please let me know if you have any questions! And thanks for all you do for the yii community!

philippfrenzel commented 8 years ago

Hi, thank you so much for sharing your knowledge! If you agree and as I hope it doesn't crash the plugin, I will include it into the code! I would highly appreciate if you create a pull request for it and so people can see who finally figured out how it works ;)

+1+