MiniProfiler icon indicating copy to clipboard operation
MiniProfiler copied to clipboard

"Uncaught TypeError: Object has no method 'appendTo'" when trying to use with Rails and Turbolinks

Open denniskuczynski opened this issue 13 years ago • 5 comments

I noticed an issue when trying to use MiniProfiler with the new Rails Turbolinks gem: https://github.com/rails/turbolinks

Turbolinks makes AJAX requests for new pages and just replaces the body element. This causes a problem with miniprofiler because after swapping out the body, the $('#profilerTemplate') call return no matching elements.

I'm using the following workaround (Coffeescript) to reset the main MiniProfiler script each page change, but I'm not sure if there's a better way to do it.

(MiniProfiler is great by the way.)

resetMiniProfilerScript =->
  script = document.getElementById('mini-profiler')
  if script
    copy = document.createElement 'script'
    copy.setAttribute attr.name, attr.value for attr in script.attributes
    copy.appendChild document.createTextNode script.innerHTML
    { parentNode, nextSibling } = script
    parentNode.removeChild script
    parentNode.insertBefore copy, nextSibling

on_ready =->
  resetMiniProfilerScript()

# doc.ready init
$ ->
  on_ready()
  $(document).bind('page:change', on_ready)

denniskuczynski avatar Dec 12 '12 16:12 denniskuczynski

And so it begins :smile: I am not sure I want to get into the business of jumping through hoops to support turbolinks, however if you can think of a change that adds no additional lines of code and simply reorders stuff a bit I am open to it.

SamSaffron avatar Dec 14 '12 06:12 SamSaffron

Alright, I dug a little deeper into the code.

The only reason there's an issue is the body tags dynamically inserted: the results container div and the jquery template scripts, get clobbered by turbolinks update of the body.

Here's a script which makes everything work with turbolinks. It stores those tags in the window namespace, and drops them back into the body in after turbolinks has updated the page.

This can probably just exist as a separate script patch for now. The jquery templates might be able to be stored in the head always, but a special hook would be needed to deal with the container div.

# Store detached versions of body tags inserted by MiniProfiler when fetching a new page with Turbolinks
storeMiniProfileBodyTags =->
  if $('#mini-profiler').length and not window.MiniProfileBodyTags
    window.MiniProfileBodyTags = {}
    window.MiniProfileBodyTags.Container = $('.profiler-results').detach()
    window.MiniProfileBodyTags.Templates = $('script[type="text/x-jquery-tmpl"]').detach()

# Copy detached tags back into the body when changing pages with Turbolinks
migrateMiniProfileBodyTags =->
  if window.MiniProfileBodyTags
    $body = $('body')
    $body.append(window.MiniProfileBodyTags.Container)
    $body.append(window.MiniProfileBodyTags.Templates)

# doc.ready init
$ ->
  $(document).bind('page:change', migrateMiniProfileBodyTags)
  $(document).bind('page:fetch', storeMiniProfileBodyTags)

https://gist.github.com/4289111

denniskuczynski avatar Dec 14 '12 22:12 denniskuczynski

I am open to a patch in include.js that works around this issue, either that or a note in the readme

care to submit a PR

SamSaffron avatar Jul 30 '13 01:07 SamSaffron

I just spun up a quick Rails 3 test app, and didn't notice the error I saw previously. I no longer have the source code for the original app, but perhaps this is no longer an issue?

If you're still having reports of similar issues I can try digging around a bit more.

denniskuczynski avatar Aug 01 '13 01:08 denniskuczynski

I'm getting a similar error when I use AJAX to submit forms. (using a form_tag with remote:true). I'm also using turbolinks 3

Uncaught TypeError: result.appendTo is not a function

keyeh avatar Mar 11 '16 09:03 keyeh