reed / turbolinks-compatibility

A collection of tutorials for how to get your favorite javascript libraries, plugins, and snippets working with Turbolinks.
reed.github.io/turbolinks-compatibility
MIT License
147 stars 35 forks source link

Github embedded gists do not work with turbolinks #18

Open nickjj opened 10 years ago

nickjj commented 10 years ago

Have you guys figured out a solution to this? They load normally but when accessed through turbolinks they do not show up.

Embedded gists have special needs too. Often times you'll embed 5 different files one at a time per gist in a typical blog article and there might be hundreds of distinct gist URLs across many articles.

reed commented 10 years ago

How are you embedding gists?

nickjj commented 10 years ago

@reed,

For full gists: [script src="https://gist.github.com/username/gist_id.js"][/script]

For specific files in a gist: [script src="https://gist.github.com/username/gist_id.js?file=file_name"][/script]

reed commented 10 years ago

Stealing a bit from this post, I put together a solution that seems to work for me.

First, change all of your gist script tags into divs with a gist class and data attributes for the URL and the file name. Also, use the .json extension instead of .js. Like this:

<!-- before -->
<script src="https://gist.github.com/username/gist_id.js"></script>
<script src="https://gist.github.com/username/gist_id.js?file=file_name"></script>

<!-- after -->
<div class="gist" data-src="https://gist.github.com/username/gist_id.json"></div>
<div class="gist" data-src="https://gist.github.com/username/gist_id.json" data-file="file_name"></div>

Then add this to your application's js:

$ ->
  loadGists()
  $(document).on 'page:load', loadGists

loadGists = ->
  $('.gist').each ->
    loadGist $(this)

loadGist = ($gist) ->
  callbackName = 'c' + Math.random().toString(36).substring(7)

  window[callbackName] = (gistData) ->
    delete window[callbackName]
    html = '<link rel="stylesheet" href="https://gist.github.com' + encodeURI(gistData.stylesheet) + '"></link>'
    html += gistData.div
    $gist.html html
    script.parentNode.removeChild script

  script = document.createElement 'script'
  script.setAttribute 'src', [
    $gist.data('src'), 
    $.param(
      callback: callbackName
      file: $gist.data('file') || ''
    )
  ].join '?'
  document.body.appendChild script

Try that out and let me know if it works for you.

nickjj commented 10 years ago

@reed,

Great start, so far it works in most browsers but it won't load on IE8.

So far here's a list of browsers that do work for both regular page loads and turbolinks:

Windows 7 - Opera 12.x Windows 7 - Chrome latest stable Windows 7 - Firefox 18.x Windows 7 - Firefox latest stable Ubuntu 12.04 - Chrome latest stable

Here's a slightly re-factored version to clean a few things up:

GistTurbolinks =
  get_gist: ($gist) ->
    callback_name = "c#{Math.random().toString(36).substring(7)}"

    window[callback_name] = (gist_data) ->
      delete window[callback_name]
      html = '<link rel="stylesheet" href="https://gist.github.com' + encodeURI(gist_data.stylesheet) + '"></link>'
      html += gist_data.div
      $gist.html html
      script.parentNode.removeChild script

    script = document.createElement "script"
    script.setAttribute "src", [
      $gist.data("src"),
      $.param(
        callback: callback_name
        file: $gist.data("file") || ""
      )
    ].join "?"

    document.body.appendChild script

  load: ->
    $this = @
    $(".gist").each ->
      $this.get_gist $(@)

IE8 fails on the line file: $gist.data("file") || ""

Usage:

$(document).ready ->
  GistTurbolinks.load()

$(document).on 'page:load', ->
  GistTurbolinks.load()
reed commented 10 years ago

I don't have a copy of IE8 to test it on. How does it fail? Does the console show an error message?

nickjj commented 10 years ago

@reed,

Here's what IE8's errors have to say:

Message: Object doesn't support this action Line: 44 Char: 9

That line is where it does .join "?" but to my knowledge IE8 supports array join so maybe it has to do with that block of code in general?


Message: Object doesn't support this property or method Line: 1 Char: 1 Code: 0 URI: https://gist.github.com/username/some_gist.json?callback=c0gfpni1&file=

I'm not really sure what's going on here but that's all the info it says the error occurs in the actual .json file though, so in this case it would be an error in some_gist.json.

reed commented 10 years ago

In IE10, I switched the browser mode to IE8 and got the same error, but it was on the delete window[callback_name] line. I changed it to the following and it worked:

window[callback_name] = undefined
try
  delete window[callback_name]
catch e

Are you checking line 44 of the coffeescript, or line 44 of the compiled javascript? Because that may be the reason we're seeing errors on different lines.

nickjj commented 10 years ago

The line numbers were including my entire script and it was the compiled result oops.

Your fix worked here on IE8 too btw. Nice one. You may want to add it to your official list.

The snippet now looks like:

    window[callback_name] = (gist_data) ->
      window[callback_name] = undefined
      try
        delete window[callback_name]
      catch e

      ...
dylanjhunt commented 7 years ago

I tried the code above and it wasn't working until I modified the top line to fire on turbolinks:load instead of page load. Hope that helps

$ ->
  loadGists()
  $(document).on 'turbolinks:load', loadGists