5 * Implement a modal form using AJAX.
7 * The modal form is implemented primarily from mc.js; this contains the
8 * Drupal specific stuff to use it. The modal is fairly generic and can
9 * be activated mostly by setting up the right classes, but if you are
10 * using the modal you must include links to the images in settings,
11 * because the javascript does not inherently know where the images are.
13 * You can accomplish this with this PHP code:
15 * ctools_include('modal');
16 * ctools_modal_add_js();
19 * You can have links and buttons bound to use the modal by adding the
20 * class ctools-use-modal.
22 * For links, the href of the link will be the destination, with any
23 * appearance of /nojs/ converted to /ajax/.
25 * For submit buttons, however, the URL is found a different, slightly
26 * more complex way. The ID of the item is taken and -url is appended to
27 * it to derive a class name. Then, all form elements that contain that
28 * class name are founded and their values put together to form a URL.
30 * For example, let's say you have an 'add' button, and it has a select
31 * form item that tells your system what widget it is adding. If the id
32 * of the add button is edit-add, you would place a hidden input with
33 * the base of your URL in the form and give it a class of 'edit-add-url'.
34 * You would then add 'edit-add-url' as a class to the select widget
35 * allowing you to convert this value to the form without posting.
37 * If no URL is found, the action of the form will be used and the entire
41 function ctools_modal_add_js() {
42 // Provide a gate so we only do this once.
49 'CToolsModal' => array(
50 'loadingText' => t('Loading...'),
51 'closeText' => t('Close Window'),
52 'closeImage' => theme('image', array(
53 'path' => ctools_image_path('icon-close-window.png'),
54 'title' => t('Close window'),
55 'alt' => t('Close window'),
57 'throbber' => theme('image', array(
58 'path' => ctools_image_path('throbber.gif'),
59 'title' => t('Loading...'),
60 'alt' => t('Loading'),
65 drupal_add_js($settings, 'setting');
66 drupal_add_library('system', 'jquery.form');
67 drupal_add_library('system', 'drupal.progress');
68 drupal_add_library('system', 'drupal.ajax');
69 drupal_add_library('system', 'ui');
70 ctools_add_js('modal');
72 ctools_add_css('modal');
77 * @todo this is deprecated
79 function ctools_modal_add_plugin_js($plugins) {
81 $js = array(drupal_get_path('module', 'ctools') . '/js/dependent.js' => TRUE);
82 foreach ($plugins as $subtype) {
83 if (isset($subtype['js'])) {
84 foreach ($subtype['js'] as $file) {
85 if (file_exists($file)) {
88 else if (file(exists($subtype['path'] . '/' . $file))) {
89 $js[$subtype['path'] . '/' . $file] = TRUE;
93 if (isset($subtype['css'])) {
94 foreach ($subtype['css'] as $file) {
95 if (file_exists($file)) {
98 else if (file(exists($subtype['path'] . '/' . $file))) {
99 $css[$subtype['path'] . '/' . $file] = TRUE;
105 foreach (array_keys($js) as $file) {
106 drupal_add_js($file);
108 foreach (array_keys($css) as $file) {
109 drupal_add_css($file);
114 * Place HTML within the modal.
117 * The title of the modal.
119 * The html to place within the modal.
121 function ctools_modal_command_display($title, $html) {
122 if (is_array($html)) {
123 $html = drupal_render($html);
127 'command' => 'modal_display',
136 function ctools_modal_command_dismiss() {
138 'command' => 'modal_dismiss',
143 * Display loading screen in the modal
145 function ctools_modal_command_loading() {
147 'command' => 'modal_loading',
152 * Render an image as a button link. This will automatically apply an AJAX class
153 * to the link and add the appropriate javascript to make this happen.
156 * The path to an image to use that will be sent to theme('image') for rendering.
158 * The destination of the link.
160 * The alt text of the link.
162 * Any class to apply to the link. @todo this should be a options array.
164 function ctools_modal_image_button($image, $dest, $alt, $class = '') {
165 return ctools_ajax_text_button(theme('image', array('path' => $image)), $dest, $alt, $class, 'ctools-use-modal');
169 * Render text as a link. This will automatically apply an AJAX class
170 * to the link and add the appropriate javascript to make this happen.
172 * Note: 'html' => true so be sure any text is vetted! Chances are these kinds of buttons will
173 * not use user input so this is a very minor concern.
176 * The text that will be displayed as the link.
178 * The destination of the link.
180 * The alt text of the link.
182 * Any class to apply to the link. @todo this should be a options array.
184 function ctools_modal_text_button($text, $dest, $alt, $class = '') {
185 return ctools_ajax_text_button($text, $dest, $alt, $class, 'ctools-use-modal');
189 * Wrap a form so that we can use it properly with AJAX. Essentially if the
190 * form wishes to render, it automatically does that, otherwise it returns
191 * the render array so we can see submission results.
194 * An associative array containing the structure of the form.
195 * @param array $form_state
196 * An associative array containing the current state of the form.
197 * If the 'reset_html_ids' key is set to TRUE, it will prevent HTML IDs in
198 * forms from being incremented.
201 * The output of the form, if it was rendered. If $form_state['ajax']
202 * is set, this will use ctools_modal_form_render so it will be
203 * a $command object suitable for ajax_render already.
205 * If the form was not rendered, the raw render array will be returned.
207 * If ajax is set the form will never be redirected.
209 function ctools_modal_form_wrapper($form_id, &$form_state) {
210 // Since this will run again on form rebuild while still in the modal, prevent
211 // form IDs from being incremented.
212 // @todo https://drupal.org/node/1305882
213 if (!empty($form_state['reset_html_ids']) && !empty($_POST['ajax_html_ids'])) {
214 unset($_POST['ajax_html_ids']);
217 // This won't override settings already in.
218 $form_state += array(
219 're_render' => FALSE,
220 'no_redirect' => !empty($form_state['ajax']),
223 $output = drupal_build_form($form_id, $form_state);
224 if (!empty($form_state['ajax']) && (!$form_state['executed'] || $form_state['rebuild'])) {
225 return ctools_modal_form_render($form_state, $output);
232 * Render a form into an AJAX display.
234 function ctools_modal_form_render($form_state, $output) {
235 if (is_array($output)) {
236 $output = drupal_render($output);
239 $title = empty($form_state['title']) ? drupal_get_title() : $form_state['title'];
241 // If there are messages for the form, render them.
242 if ($messages = theme('status_messages')) {
243 $output = $messages . $output;
247 // If the form has not yet been rendered, render it.
248 $commands[] = ctools_modal_command_display($title, $output);
253 * Perform a simple modal render and immediately exit.
255 * This is primarily used for error displays, since usually modals will
258 function ctools_modal_render($title, $output) {
260 $commands[] = ctools_modal_command_display($title, $output);
261 print ajax_render($commands);