Skip to content

Instantly share code, notes, and snippets.

@coreyward
Last active September 7, 2018 17:14
  • Star 10 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save coreyward/1456815 to your computer and use it in GitHub Desktop.
<div id="modal">
<div class="content"></div>
</div>
// This partial should be @imported into your layout Sass file, or included via the Asset Pipeline
//
#modal {
width: 100%;
padding: 0 20px;
position: absolute;
left: 0;
right: 0;
opacity: 0;
display: none;
@include transition(opacity 0.3s);
&:before {
display: block;
content: '';
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.5);
z-index: 50;
}
.content {
background: #fff;
box-shadow: 0 2px 25px rgba(#111, 0.3);
padding: 30px;
margin: 0 auto;
max-width: 600px;
position: relative;
z-index: 51;
border-radius: 3px;
}
}
//= jquery
//= jquery_ujs
//= modals
# in your app controller, you'll want to set the layout to nil for XHR (ajax) requests
class ApplicationController < ActionController::Base
layout -> do
request.xhr? ? false : 'application'
end
end
<%= link_to 'New Post', new_post_path, remote: true %>
# This file should be "required" into your `application.js` via the Asset Pipeline.
#
$ ->
$modal = $('#modal')
$content = $modal.find('.content')
$window = $(window)
$(document).on 'click', (e) ->
if $(e.target).is $modal
$modal.hide()
$(document).on 'ajax:success', 'a[data-remote]', (xhr, data, status) ->
$content.html(data)
$modal.css opacity: 0, display: 'block'
docW = $window.width()
docH = $window.height()
mW = $modal.outerWidth()
mH = $modal.outerHeight()
x = (docW - mW) / 2
y = ((docH - mH) / 2) + $window.scrollTop()
$modal.css left: x, top: y, opacity: 1
@guillaumestevens
Copy link

Hello, thanks for this code. I've a problem using it. Modal Windows doesn't want to show.
I've got this trace :

Started GET "/users/1" for 10.100.2.68 at 2012-01-23 13:17:42 +0100
  Processing by UsersController#show as JS
  Parameters: {"id"=>"1"}
  User Load (0.2ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", "1"]]
Rendered users/show.html.erb (28.8ms)
Completed 200 OK in 34ms (Views: 31.7ms | ActiveRecord: 0.5ms)

I used scaffolding to generate Users.
The point I'm not sure to understand is where should I include _modal.html.erb. I put it in my app/layout/applications.html.erb using render. Does it correct ?

Thanks for your help.

PS : I'm a newbie in ror and javascritp.

@pjmorse
Copy link

pjmorse commented Nov 9, 2012

Really jazzed that you ran through all this on S.O. and here; it gets me about 95% there on my current feature. I'm getting stuck on one thing, which I think might be a Rails 3.2.x issue (where you have a 3.1.x adaptation here). I'm getting errors loading the modal.js.coffee file; in the console, the error is "Uncaught TypeError: Object function (e,t){return new v.fn.init(e,t,n)} has no method 'on' ". The Object in question is jQuery itself. Comments on this S.O. question made me question if it was a jQuery version incompatibility. I'm fiddling with it (ha) here to try and debug, and I'll ask on S.O. as well, but I'm commenting here in case you have feedback.

@pjmorse
Copy link

pjmorse commented Nov 9, 2012

@coreyward
Copy link
Author

Hey @pjmorse — glad this has helped so many people! I saw the problem you had on StackOverflow and it looks like someone has identified the issue. I've updated the Gist code to resolve that issue, too. Thanks for calling attention to it!

@pjmorse
Copy link

pjmorse commented Nov 9, 2012

@coreyward - thanks for the update, and for being willing to push up an update when random people turn up and start asking questions about code you wrote ten months ago. :) That does indeed make the error message go away.

Now, though, the on-ajax-success function simply isn't getting called at all, and I'm not sure how to debug why. No error messages. I can see that the action called by the xhr is returning the right markup (albeit with a 304 Not Modified response, not a 200 OK - maybe that's the problem?) it's just not tripping the function. Baffling. I'm going to chase it a bit longer and then I'll do the SO thing and come back here with any response I get.

@pjmorse
Copy link

pjmorse commented Nov 13, 2012

Just to update the above in case someone comes back to it: this is the Stack Overflow question about my latest bug. I don't think it's related to Corey's gist specifically; the ajax:success event doesn't seem to get tripped, which other SO question/answers I've found suggest may be more of an issue with the Ajax response than with anything included here.

@pjmorse
Copy link

pjmorse commented Nov 13, 2012

Aha. The answer is that Rails' rails.js doesn't trigger ajax:success if the response to the ajax request isn't text/json. This meant I had to adjust my controller to respond properly, from

format.js

to

format.js { render :json => { :html => render_to_string('templatename')}, :content_type => 'text/json' }

...and then alter modals.js.coffee to use .html(data.html) instead of just .html(data).

@boomer
Copy link

boomer commented Jan 30, 2013

Corey - this was super helpful. Have you thought about adding a function to close the modal if the user clicks outside it?

@mvandeloo
Copy link

In Rails 4 this line:

layout Proc.new { |controller| controller.request.xhr? ? nil : 'application' }

should be

layout Proc.new { |controller| controller.request.xhr? ? false : 'application' }

@coreyward
Copy link
Author

coreyward commented Jan 31, 2017

I've updated this Gist to work with Rails 5.

@crondaemon
Copy link

Hi, and thanks for the tutorial, it helped me a lot!

I'm having a problem on the very last step of the ajax stuff. In this line

https://gist.github.com/coreyward/1456815#file-modals-js-coffee-L13

data and status are undefined. Do I need to do something special in my method? I have

def new
  @model = Model.new
end

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment