Search code examples
ruby-on-railsturbolinks

Rails: turbolinks:load event is fired before body content changes


I'm building a code blog on a rails 5.1.6 app that uses turbolinks 5.2.0.

I want to do a really simple thing, which is highlight the code (using a js plugin) after the content is loaded, so I added this to the page:

coffee:
  $(document).on "turbolinks:load", ->
    Highlighter.init()

That works well on a fresh load. However, when you're in another page and you click a link to go there, the turbolinks:load event is fired before the content is updated, so the highlight doesn't work.

Do you know what's happening or how to fix this?

EDIT: I know turbolinks:load is fired before the content changes because I tried adding a debugger:

coffee:
  $(document).on "turbolinks:load", ->
    debugger # => This is called before new content is rendered
    Highlighter.init()

EDIT 2: This is the simple Highlighter.init():

class Highlighter
  @init: ->
    console.log "Trying to highlight"
    hljs.initHighlightingOnLoad()

Solution

  • The issue is that hljs.initHighlightingOnLoad() sets up the plugin to work on only DOMContentLoaded or load. These events are only called on the initial page load, so after that, they are never called again.

    Here's the order of relevant events:

    1. DOMContentLoaded
    2. turbolinks:load (your code sets up highlighter to be called on load)
    3. load (which initialises highlighting)
    4. Navigate to another page
    5. turbolinks:load (your code sets up highlighter to be called on load)
    6. That's it! load is not triggered again until a full page load

    To fix this you'll need to follow the Custom Initialization instructions and adapt them for Turbolinks:

    $(document).on('turbolinks:load', function() {
      $('pre code').each(function(i, block) {
        hljs.highlightBlock(block);
      });
    });
    

    I'd recommend that this is included in your main application JavaScript file. Adding event handlers in inline script tags in the <body> can often cause problems unless they are properly removed.