thoughtbot/refills

Modal closing mechanics break Rails' UJS

cdale77 opened this issue · 4 comments

The Refills pattern for a modal involves an outer div.modal-fade-screen and an inner div.modal-inner. There is a click event handler attached to div.modal-fade-screen that will close the modal when the user clicks that element. To make that work, another click event handler is attached to the inner div.modal-inner which stops the event propagation so that un-handled clicks to the modal content don't propagate up and trigger the handler attached to div.modal-face-screen, which would close the modal.

This is the relevant code from the Refills web page:

  $(".modal-fade-screen, .modal-close").on("click", function() {
    $(".modal-state:checked").prop("checked", false).change();
  });

  $(".modal-inner").on("click", function(e) {
    e.stopPropagation();
  });

This stops Rails' UJS from working with elements inside the inner modal. For example, the following code placed in a div.modal-inner will produce an html request and redirect, not the AJAX request as expected (haml):

= link_to "My Ajax Thing", some_thing_path, remote: true

Removing ".modal-fade-screen" class from the closing click handler, and allowing event propagation from div.modal-inner fixed things for me, though users cannot click on the fade screen to close the modal (they must click on the close icon).

I'm not sure the best way to address this. My approach fixes UJS, but most people expect a modal to disappear when clicking outside of it. I'd be happy to submit a PR using my approach, or if others have a better idea let me know. I'm not familiar enough with the mechanics of UJS to see a better way.

I had a related issue, where I could close the modal by clicking outside of it, but not by clicking the close button.

I resolved it by separating the .modal-close function and the .modal-fade-screen functions. They are still identical otherwise. It is unclear why this worked, but googling seems to show that this is an issue that has occurred before (issue #288).

I believe I found a solution that works here

I removed the click event stopping propagation and changed the first click event to this:

  $(".modal-fade-screen, .modal-close").on("click", function(e) {
    if (e.target === this) {
      $(".modal-state:checked").prop("checked", false).change();
    }
  });

Now everything appears to work.

I’m closing this as we are focusing our efforts on a new, rewritten Refills library with a focus on accessibility and removal of grid and visual opinion for components. You can see a preview of the work here: http://refills.netlify.com/

Existing components and patterns from the 0.2.0 release will be provided as-is (no longer maintained) until the new version is released.

Thanks for the response and for your work on refills @tysongach !! Very excited for a new version!