9

I realise that I probably need to declare the onclick event globally, but I am trying to avoid using the --bare tag when compiling.

This is the code I am trying to get working...

jQuery ->
  $('.tabs_image').click ->
    $(this).addClass('tabs_selected')
    $('.tabs_video').removeClass('tabs_selected')
    $('#image_upload_form').show()
    $('#video_upload_form').hide()
    return

  $('.tabs_video').click ->
    $(this).addClass('tabs_selected')
    $('.tabs_image').removeClass('tabs_selected')
    $('#image_upload_form').hide()
    $('#video_upload_form').show()
    return

  return

It works fine once the page is hard refreshed (refresh clicked) in the browser Chrome.

I have tried $ =>, $(document).ready ->, and $(document).ready =>.

ckhatton
  • 1,359
  • 1
  • 14
  • 43
  • 1
    "*It works fine once the page has refreshed in the browser Chrome.*" If the content is dynamic appended, [you'll have to use delegated events](http://stackoverflow.com/questions/6658752/jquery-click-event-doesnt-work-on-dynamically-generated-elements). – Jonathan Lonowski May 12 '14 at 13:15
  • @JonathanLonowski In this case the content already exists; it is not dynamically appended. I will try that though. This is in a Rails app, so I do not know if that would have an effect – ckhatton May 12 '14 at 13:19

3 Answers3

7

I found the crux of the problem - My Coffeescript was fine, it was because of a gem called Turbolinks that the code was not triggering. It keeps the current page instance alive and replaces only the body and the title in the head, which means you can't rely on DOMContentLoaded or jQuery.ready() to trigger your code. This is why the script would seem to work when the page was hard refreshed (refresh clicked).

For those who use Turbolinks

  • If you want to opt out specific links

Add data-no-turbolink to the parent container of the link(s) like so...

<a href="/">Home (via Turbolinks)</a>
<div id="some-div" data-no-turbolink>
  <a href="/">Home (without Turbolinks)</a>
</div>
  • If you have a lot of existing JavaScript that binds elements on jQuery.ready()

Using the event hook page:change, you can replace the jQuery.ready() with $(document).on 'page:change', -> or, even better $(document).on 'ready page:change', ->; better, because it means that even if turbolinks is not running (because of being on an old browser version maybe), the call will still trigger due to ready being there.

It is best to use page:change instead of page:load. The former event hook fires when the page is loaded from the server or from the client-side cache, whereas the latter event hook only fires when a new body element has been loaded into the DOM (source).

...or...

You can use the jquery-turbolinks gem.

Gemfile:

gem 'jquery-turbolinks'

bundle install and then add it to your JavaScript manifest file, in this order:

//= require jquery
//= require jquery.turbolinks
//= require jquery_ujs
//
// ... your other scripts here ...
//
//= require turbolinks
ckhatton
  • 1,359
  • 1
  • 14
  • 43
5

I'd argue that you should be using event delegation anyway.

Try something like this and see if you get better results:

$ ->
  $('body').on 'click', '.tabs_image', ->
    # do stuff
Nick Johnson
  • 190
  • 1
  • 12
  • *"I'd argue that you should be using event delegation anyway."* Why, given that *"In this case the content already exists; it is not dynamically appended."* – Kevin B May 12 '14 at 19:26
  • @nick Thank you, I have tried this, but does not help. I am getting the feeling I have found a bug in Rails – ckhatton May 13 '14 at 22:36
  • Now that I know it was because of [Turbolinks](https://github.com/rails/turbolinks), using the hook `page:load` works by replacing your `$ ->` with `$(document).on 'page:load', ->` or `$(document).on 'ready page:load', ->` – ckhatton May 14 '14 at 11:38
  • @KevinB because if there are multiple matching selectors, you are attaching the same event multiple times. It could result in memory leaks. Probably edge case for most apps, but there's nothing wrong with just using event delegation in general to combat these potential challenges. PPK touches on it here in the sentence just before "The focus problem": http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html – Nick Johnson May 15 '14 at 15:50
0

load the dom with $(document).on 'ready page:load', -> instead of jQuery -> you can read more on the Rails Documentation

Ori Lentz
  • 3,668
  • 6
  • 22
  • 28
Alex Onozor
  • 6,841
  • 1
  • 22
  • 26
  • It is best to use `page:change` than `page:load` ([source](https://github.com/turbolinks/turbolinks-classic#events)) – ckhatton Mar 06 '16 at 22:56