codedance / jquery.AreYouSure

A light-weight jQuery "dirty forms" Plugin - it monitors html forms and alerts users to unsaved changes if they attempt to close the browser or navigate away from the page. (Are you sure?)
507 stars 145 forks source link

Conflict with Ruby on Rails' UJS library if using "javascript at bottom" design #90

Open lucas-nelson opened 8 years ago

lucas-nelson commented 8 years ago

Thanks to Ruby on Rails' "unobtrusive" (ha!) JS library (UJS), every form that has a authenticity_token field in it (which is all forms not marked as 'remote', assuming CSRF protection has not been disabled) will stay dirty after a change, even if you revert your change. This is because AreYouSure has marked the authenticity_token field as dirty because UJS changes it.

I was curious why I seemed to be the only person with the problem, but it dawned on me that the use of the "put your JavaScript at the end of and use inline, not ready()" design is probably not widespread enough to catch others out.

If you use the equivalent of:

$(function() { $('form').areYouSure(); });

to load this plugin, everything seems to work fine. But I have a nagging feeling it's a bit of an accident of the order in which I've included my JavaScript files.

If you use plain old inline:

$('form').areYouSure();

All the forms get stuck in a dirty state after the first change.

Two easy workarounds in the JavaScript:

  1. Use the ready()-style call to delay the plugin initialisation until after, hopefully, UJS has stuck it's obnoxious nose in.
  2. Use the inline style, but just before, run this:
$('input[type="hidden"][name="authenticity_token"]').attr('data-ays-ignore', 'true');

To add the ignore marker to the input field.

Rails provides no pre-canned customisation of the authenticity_token input element, so the only option server side would be to monkey-patch the ActionView::Helpers::UrlHelper module, which seemed … overkill.

I suggest something be added to the README.md about this as it can effect a default Rails app depending on how you add the JavaScript to initialise the AreYourSure plugin.

PS: and it took me ages in the JS debugger trying to work out what was changing the authenticity_token field value, so even if there's just a history here in this issue, hopefully it will help someone someday!

codedance commented 8 years ago

That's a great reference. Thanks for doing the investigation. The only more elegant solution I can come up with would be to maybe have a configuration option that can be passed into the areYouSure(...) options list. Maybe a new option which is a list of fields by ID/name that should be ignore irrespective of if it has an ays-ignore annotation or not. This however is a bit of a hack for just this case. Your inline JS might be the best option.

I'm thinking about adding an integrations section to the README. We have a few submitted sitting in issues such as this https://github.com/codedance/jquery.AreYouSure/issues/62

Happy to accept a pull request and/or take some advise on how to structure these notes. I'm sure this will not be the last - the joys of JS and the web ;-)

Thanks for the time to share the findings. That's what community is all about!