One Time Modal Windows With Rails and Fancybox

Let’s say that you have a situation that you want to have a modal window show up only once for each user. It’s actually not that difficult although lots of Googling around got me nowhere. I am choosing to use FancyBox for my modal window, but feel free to use your modal framework of choice. So let’s get down to business.

First thing you’ll need to do is download FancyBox and copy the stylesheets, images, and Javascript files to their proper/desired location in your Rails app. Style the window according to your likings.

Whether it is right or wrong, I did this entirely in the view, without even pulling the Javascript out into the application.js (or even another Javascript file for that matter). My reason was that I only want the modal window showing up on this page. If you want your modal window to show up somewhere else (or on every page), then put the code in your layout. But remember that this call will be executed every time the page loads. I put mine in a profile page which doesn’t get accessed that often so the conditional is not checked quite as frequently.

My application uses Facebook Connect and grabs the users Facebook Proxy email address (FB app developers will know what this is). So I check if that’s the email I have for the user. If yes, then I pop up a modal window on page load only once to get their regular email address and possibly a password so they can login to their account without Facebook Connect if they want. When the modal window is shown, a variable is set in the cookie (note that this cookie is shared with authlogic for sessions) to ensure that the modal window isn’t shown again.

The explanation of the code is below with comments in the code.

The code that goes in the view is as follows:

# Check the user's email and see if they have a facebook proxy email address
# Check the user's cookie to see if they have already seen the Facebook modal window
< % if @user.email.match(/^.+proxymail.facebook.com$/) and (cookies[:facebook_email_modal_shown] != "1") %>
    # Include the JS and stylesheets
    < %= javascript_include_tag 'jquery.fancybox-1.2.3' %>
    < %= stylesheet_link_tag 'jquery.fancybox' %>
    <script type="text/javascript" charset="utf-8">
            /* Function to load the modal window by clicking the "invisible" link */
        var modalLoadFunction = function() {
            jQuery("a.modalGroup").click();
            clearInterval(globalInterval);
        }

        /* Hide the div on load  and set the modal window options */
        jQuery(document).ready(function() {
            jQuery('#modalFacebookEmail').hide();

            /* Check out the FancyBox site for more information on the options */
            jQuery("a.modalGroup").fancybox({
                'zoomSpeedIn': 200,
                'zoomSpeedOut': 250,
                'overlayShow': true,
                'overlayOpacity': 0.6,
                'enableEscapeButton': true,
                'hideOnContentClick': false,
                'hideOnOverlayClick': false,
                'centerOnScroll': true
                });
                           
            /* Kickoff the modal window as soon as possible */
            globalInterval = setInterval(modalLoadFunction, 50)
        });
    </script>

    # Invisible link for the JS to click()
    <a id="inline" href="#modalFacebookEmail" class="modalGroup" id="modalFunction"></a>
    <div style="display:none" id='modalFacebookEmail'>
        # Change the value in the cookie so the modal window is only shown once
        < % cookies[:facebook_email_modal_shown] = 1 %>
        < % form_for( @user ) do |f| %>
        < %= f.error_messages %>
            <h3>Facebook Email Address</h3>
            <p>If you want to login into the website when not logged into Facebook, please provide your email address and a password.</p>
            <br />
            <p><strong>Email Address</strong><br />< %= f.text_field :email %></p>
            <p><strong>Password</strong><br />< %= f.password_field :password %></p>
            <p><strong>Password Confirmation</strong><br />< %= f.password_field :password_confirmation %></p>
            <p>&nbsp;</p>
            # Note the method for closing the modal window
            <p>< %= f.submit 'Update' %> | <a onClick="jQuery('a.modalGroup').fancybox.close()" href="#">Cancel</a></p>
        < % end %>
    </div>
< % end %>

Now you have a modal window that is only shown once.