Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery plugin initialization on browser back button for Turbolinks Rails 5

Whats a better solution for initializing jquery plugins on browser back button that aren't just transforming elements when using turbolinks in Rails 5 like masterslider (photo gallery) or slick (carousel), than reloading the page as I do below?

document.addEventListener 'turbolinks:load', ->
  slickElementsPresent = $('.event-card').find('div.slick-slide')[0]
  if slickElementsPresent?
    window.location.reload();
  else
    $('.event-card').each ->
      $(@).not('.slick-initialized').slick {
        infinite: false,
        nextArrow: $(@).find('.event-more-details-button'),
        prevArrow: $(@).find('.event-card-slide-back-button')
      }

To be clear, I check to see on 'turbolinks:load' if there are any html elements that would only be present if the plugin had been initialized, if so, then refresh the page because even though the elements are there, the plugin isn't initialized. And then I initialize the plugin on all the elements that have the class I want it on.

Some people encountered this problem here: https://github.com/turbolinks/turbolinks/issues/106 where someone points out

I just want to add for those having similar issues that making an initialization function idempotent is not necessarily the solution in some circumstances. Having done so with dataTables I am able to avoid duplicate elements. However, the cached versions of the elements on the page related to the plugin no longer function on a browser back click as it seems the plugin is not initialized in a cached page.

Reloading the page if the plugin has already changed the DOM because it's being retrieved from the cache when someone presses the back button just seems pretty bad, but its the best I've come up with so I'm turning to the world for more ideas!

UPDATE:

So some jquery plugins have great 'undo'/'destroy' methods and if that's the case it's better to add an event listener on "turbolinks:before-cache" and then call that method like so:

document.addEventListener "turbolinks:before-cache", ->
  $('.event-card').each ->
    $(@).slick('unslick');

but some jquery plugins do not have destroy functions or destroy functions that achieve this. Like masterslider has a $('your-slider-element').masterslider('destroy') function, but it doesn't 'undo' the javascript magic it applies to your html so much as just getting rid of it entirely, and so when you come back to the page from the browser back or forward button, the slider simply doesn't exist, because the html element it gets triggered on has been destroyed. That means for some plugins, the best answer I still have is to reload the page entirely when the page they are on is navigated to via the browser back and forward buttons.

like image 470
Sava Avatar asked Sep 21 '16 23:09

Sava


1 Answers

So the best answer I've come up with for dealing with 'Restoration' visits (as I have since learned browser back and forward button visits are called in the world of turbolinks) that involve jquery plugins that don't have an 'undo' method is to simply opt the page out of cache-ing. I implemented this by throwing:

<% if content_for?(:head) %>
  <%= yield(:head) %>
<% end %>

in the <head> section of my application.html.erb file and then at the top of the page I don't want turbolinks to include in it's cache, I put:

<% content_for :head do %>
  <meta name="turbolinks-cache-control" content="no-cache">
<% end %>

That way turbolinks fetches the page from the network and not the cache as would be the normal behavior for a 'restoration' visit. Just had to read the documentation very carefully and figure out how to implement it in rails which wasn't too bad.

like image 194
Sava Avatar answered Oct 04 '22 07:10

Sava