How to clear window variables when using turbolinks

1k views Asked by At

Using ruby on rails, I have code that is triggered with the following coffee script;

$ = jQuery
$(document).on "turbolinks:load", ->
  if window.progress?
    // execute code on a div with an id of ```target```

On pages where the code is meant to trigger, I have a div with an id of target and a script tag which loads the progress parameter e.g.

<%= javascript_tag id: "window_vars" do %>
  window.progress = <%= raw graph.data.to_json %>
<% end -%>

If there is no turbolinks, then this works fine, the code triggers on the pages where it is meant to and does not trigger on the other pages. However, if I enable turbolinks 5.0.1 and I visit a page where the code is not meant trigger, then to a page where the code does trigger, and then back to the page where the code is not meant to trigger, the code triggers on the final page with an exception. It seems that turbolinks is not clearing the window.progress variable between page loads.

How do I make sure that the window variables loaded via a script are cleared between pages?

2

There are 2 answers

0
mroach On BEST ANSWER

I ran into this same issue today doing something similar. What I've surmised is that global variables persist between turbolinks visits. This actually makes sense since the page isn't reloaded; the content is just overwritten. My solution was to destroy the data before turbolinks renders a new page.

document.addEventListener('turbolinks:before-render', () => {
  delete window.progress;
})

Note that the delete method does not work with javascript variables declared with var, but does work for attributes assigned to window as in my case. If using var, you'll want to do var progress = null;

You have a lot of options for where to do this in the lifecycle of a request. I chose before-render to ensure data is only 'destroyed' if the request was successful.

0
Obromios On

A workaround is to not rely on the window.progress to detect if the graph is present, rather use the id e.g.

if $('#target').length > 0