In Part I, I explained how to use JQuery UI's .dialog method to script a modal message in Drupal. In part two, I show how to customize what the message looks like and how often it appears in the browser (using cookies).
In this case, the dialog is a terms of service message that hides a publicly-accessible member directory. Before proceeding to the directory, the user must click a button in the dialog indicating agreement with the terms.
If you want to see the finished file before or while reading the explanation, you can download it here: modal.js.
Hiding the "X" in the Modal Dialog
Here's a problem: JQuery UI's default dialog method allows the user to close our "terms of service" dialog without clicking the "I accept the terms" button. The user can just click "X" to close the window instead of "I agree." This isn't a binding legal document, but it is very important to the client that the user directly click "I agree" before gaining access to the directory.
Getting rid of this "X" (circled in red in the image) is actually pretty easy. I took a peak at the "Theming" tab for the .dialog method on the JQuery UI site and found that the "X" is styled with CSS using the following class: .ui-dialog-titlebar-close. I also looked at the "Events" tab and found the syntax for coding a function that occurs right when the modal dialog opens. Putting this information together, I inserted the following code inside my modal.js file:
open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); },
I reloaded the theme again (see Part I) and refreshed the page. The dialog opened automatically, but this time there was no "X". Mission accomplished.
A Dialog Dilemma
Still, the dialog box now appears every time the page loads. Every time. This seemed like the desired behavior at first, but it’s not. The page refreshes whenever the user sorts the directory or advances to the next page in the list of therapists. Each time the page refreshes for this or any other reason, the modal dialog pops up to annoy the user all over again. The user should only have to agree to the terms of service once per visit to the site (or some other interval, like once every few days).
To keep track of whether the user has agreed to the terms of service, we need to pass a cookie to the browser when the "I agree" button is clicked. If the user has clicked the button, the modal dialog should only appear again after the user quits the browser (not just when the page is refreshed).
Installing JQuery Cookie
Rather than writing the Javascript to set and unset cookies on my own, I downloaded Klaus Hartl's JQuery Cookie script from Github (a popular site for archiving and sharing code).
To make use of Hartl's code in my own modal.js file, I had to take the following steps:
- Download the jquery.cookie.js file from Github.
- Upload the file to my drupal site in the same directory as my theme.
- Edit the [nameofyourtheme].info file, adding the following line of code:
scripts[] = "jquery.cookie.js"
- Reload the Theme. Go back to the theme administration page and save the theme choices again (even if you are not making any changes) for the changes you made to the files to take effect. If the changes still don't show up, I recommend flushing the caches of your drupal site.
- Read the documentation for JQuery Cookie on Github so I know how to use the new methods that it makes available.
Setting A Session Cookie On Accept
Using the methods provided by JQuery Cookie, setting a cookie in response to a user action was pretty simple. First, I needed to write a function for passing the cookie:
function setCookie(evt){ $.cookie("accept", 1); }
I gave the function the name "setCookie" and set the two required parameters inside the parens: the cookie passed to the user will be named "accept" and will be assigned the number "1". I could've set a third parameter, indicating when the cookie should expire (7 days from now, for example), but I didn't do that. When the that last parameter isn't set, JQuery Cookie assumes that the cookie being created will be a session cookie; in this case, that's exactly what I want.
I've written a function, but as any programmer will tell you, that doesn't do anything useful on its own. I have to call the function in order to activate it. I don't want the function to be called automatically, but only in response to the user clicking the "I accept the terms" button.
Taking another look at the documentation for JQuery UI's .dialog function, I found that the CSS class for the button in my modal dialog was .ui-dialog-buttonpane. Adding the following bit of code tells JQuery to call the "setCookie" function when the user clicks the button.
$(".ui-dialog-buttonpane").click(setCookie);
If . . . Else
Now, we're most of the way there. Whenever the user clicks on the "I accept the terms" button, a cookie named "accept" with a value of "1" is passed to her browser. But so what? So far, modal.js doesn't pay any attention to the "accept" (or any other) cookie.
The final step is to take the block of code for the modal dialog and enclose it in an "if . . . else" statement. The is essentially an either/or statement. In plain language, we might describe it like this:
If our script does not find a cookie called "accept" with a value of "1" in the user's browser, then it knows that the user hasn't accepted the terms of service yet (at least not during this session). The script should display the modal dialog with the terms of service.
In any other case (Else), the script will not show the modal dialog. It will, however, hide the text that's supposed to go into that dialog so that it doesn't show up as part of the page's footer (see Part I, where we put the text of the terms of use in its own div in the footer of the page for the .dialog function to grab).
In JQuery, that statement looks like this (placed inside the "document ready" function):
if ($.cookie("accept") !=1) { [the .dialog function] }else{ $("#dialog").hide(); }
In the "if" part of the function, we're asking JQuery to check the value of the "accept" cookie. If the value of that cookie is not "1" (!=1), then it should run the .dialog function. If the user doesn't have the "accept" cookie at all, then it can't be equal to 1; the script brings up the modal dialog with the terms of service.
In the "else" part of the function, #dialog is simply the id assigned to the div that contains the text of the terms of service. JQuery hides that text if it is not going to be used in the modal dialog. That way this div and its text isn't just tacked on to the end of the page as if it were part of the page's content.
Download the File
The best way to see how this script fits together is to download modal.js. I've provided a few comments in the file itself to clarify things. I hope this article and the code can help another developer with a similar use case.
Going Further
To learn how to use JQuery and JQuery UI in your own projects, check out lynda.com's JQuery Essential Training. You can learn how to modify Drupal themes and how to create your own with the Creating and Editing Custom Themes course.