summaryrefslogtreecommitdiff
path: root/sites/all/modules/ctools/includes/modal.inc
blob: fc9901594b29e4a08a7b878ae8b3ce0058d4dd5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
<?php

/**
 * @file
 * Implement a modal form using AJAX.
 *
 * The modal form is implemented primarily from mc.js; this contains the
 * Drupal specific stuff to use it. The modal is fairly generic and can
 * be activated mostly by setting up the right classes, but if you are
 * using the modal you must include links to the images in settings,
 * because the javascript does not inherently know where the images are.
 *
 * You can accomplish this with this PHP code:
 * @code {
 *   ctools_include('modal');
 *   ctools_modal_add_js();
 * }
 *
 * You can have links and buttons bound to use the modal by adding the
 * class ctools-use-modal.
 *
 * For links, the href of the link will be the destination, with any
 * appearance of /nojs/ converted to /ajax/.
 *
 * For submit buttons, however, the URL is found a different, slightly
 * more complex way. The ID of the item is taken and -url is appended to
 * it to derive a class name. Then, all form elements that contain that
 * class name are founded and their values put together to form a URL.
 *
 * For example, let's say you have an 'add' button, and it has a select
 * form item that tells your system what widget it is adding. If the id
 * of the add button is edit-add, you would place a hidden input with
 * the base of your URL in the form and give it a class of 'edit-add-url'.
 * You would then add 'edit-add-url' as a class to the select widget
 * allowing you to convert this value to the form without posting.
 *
 * If no URL is found, the action of the form will be used and the entire
 * form posted to it.
 */

function ctools_modal_add_js() {
  // Provide a gate so we only do this once.
  static $done = FALSE;
  if ($done) {
    return;
  }

  $settings = array(
    'CToolsModal' => array(
      'loadingText' => t('Loading...'),
      'closeText' => t('Close Window'),
      'closeImage' => theme('image', array(
        'path' => ctools_image_path('icon-close-window.png'),
        'title' => t('Close window'),
        'alt' => t('Close window'),
      )),
      'throbber' => theme('image', array(
          'path' => ctools_image_path('throbber.gif'),
          'title' => t('Loading...'),
          'alt' => t('Loading'),
      )),
    ),
  );

  drupal_add_js($settings, 'setting');
  drupal_add_library('system', 'jquery.form');
  drupal_add_library('system', 'drupal.progress');
  drupal_add_library('system', 'drupal.ajax');
  drupal_add_library('system', 'ui');
  ctools_add_js('modal');

  ctools_add_css('modal');
  $done = TRUE;
}

/**
 * @todo this is deprecated
 */
function ctools_modal_add_plugin_js($plugins) {
  $css = array();
  $js = array(drupal_get_path('module', 'ctools') . '/js/dependent.js' => TRUE);
  foreach ($plugins as $subtype) {
    if (isset($subtype['js'])) {
      foreach ($subtype['js'] as $file) {
        if (file_exists($file)) {
          $js[$file] = TRUE;
        }
        else if (file(exists($subtype['path'] . '/' . $file))) {
          $js[$subtype['path'] . '/' . $file] = TRUE;
        }
      }
    }
    if (isset($subtype['css'])) {
      foreach ($subtype['css'] as $file) {
        if (file_exists($file)) {
          $css[$file] = TRUE;
        }
        else if (file(exists($subtype['path'] . '/' . $file))) {
          $css[$subtype['path'] . '/' . $file] = TRUE;
        }
      }
    }
  }

  foreach (array_keys($js) as $file) {
    drupal_add_js($file);
  }
  foreach (array_keys($css) as $file) {
    drupal_add_css($file);
  }
}

/**
 * Place HTML within the modal.
 *
 * @param $title
 *   The title of the modal.
 * @param $html
 *   The html to place within the modal.
 */
function ctools_modal_command_display($title, $html) {
  if (is_array($html)) {
    $html = drupal_render($html);
  }

  return array(
    'command' => 'modal_display',
    'title' => $title,
    'output' => $html,
  );
}

/**
 * Dismiss the modal.
 */
function ctools_modal_command_dismiss() {
  return array(
    'command' => 'modal_dismiss',
  );
}

/**
 * Display loading screen in the modal
 */
function ctools_modal_command_loading() {
  return array(
    'command' => 'modal_loading',
  );
}

/**
 * Render an image as a button link. This will automatically apply an AJAX class
 * to the link and add the appropriate javascript to make this happen.
 *
 * @param $image
 *   The path to an image to use that will be sent to theme('image') for rendering.
 * @param $dest
 *   The destination of the link.
 * @param $alt
 *   The alt text of the link.
 * @param $class
 *   Any class to apply to the link. @todo this should be a options array.
 */
function ctools_modal_image_button($image, $dest, $alt, $class = '') {
  return ctools_ajax_text_button(theme('image', array('path' => $image)), $dest, $alt, $class, 'ctools-use-modal');
}

/**
 * Render text as a link. This will automatically apply an AJAX class
 * to the link and add the appropriate javascript to make this happen.
 *
 * Note: 'html' => true so be sure any text is vetted! Chances are these kinds of buttons will
 * not use user input so this is a very minor concern.
 *
 * @param $text
 *   The text that will be displayed as the link.
 * @param $dest
 *   The destination of the link.
 * @param $alt
 *   The alt text of the link.
 * @param $class
 *   Any class to apply to the link. @todo this should be a options array.
 */
function ctools_modal_text_button($text, $dest, $alt, $class = '') {
  return ctools_ajax_text_button($text, $dest, $alt, $class, 'ctools-use-modal');
}

/**
 * Wrap a form so that we can use it properly with AJAX. Essentially if the
 * form wishes to render, it automatically does that, otherwise it returns
 * the render array so we can see submission results.

 * @param array $form
 *   An associative array containing the structure of the form.
 * @param array $form_state
 *   An associative array containing the current state of the form.
 *   If the 'reset_html_ids' key is set to TRUE, it will prevent HTML IDs in
 *   forms from being incremented.
 *
 * @return mixed
 *   The output of the form, if it was rendered. If $form_state['ajax']
 *   is set, this will use ctools_modal_form_render so it will be
 *   a $command object suitable for ajax_render already.
 *
 *   If the form was not rendered, the raw render array will be returned.
 *
 *   If ajax is set the form will never be redirected.
 */
function ctools_modal_form_wrapper($form_id, &$form_state) {
  // Since this will run again on form rebuild while still in the modal, prevent
  // form IDs from being incremented.
  // @todo https://drupal.org/node/1305882
  if (!empty($form_state['reset_html_ids']) && !empty($_POST['ajax_html_ids'])) {
    unset($_POST['ajax_html_ids']);
  }

  // This won't override settings already in.
  $form_state += array(
    're_render' => FALSE,
    'no_redirect' => !empty($form_state['ajax']),
  );

  $output = drupal_build_form($form_id, $form_state);
  if (!empty($form_state['ajax']) && (!$form_state['executed'] || $form_state['rebuild'])) {
     return ctools_modal_form_render($form_state, $output);
  }

  return $output;
}

/**
 * Render a form into an AJAX display.
 */
function ctools_modal_form_render($form_state, $output) {
  if (is_array($output)) {
    $output = drupal_render($output);
  }

  $title = empty($form_state['title']) ? drupal_get_title() : $form_state['title'];

  // If there are messages for the form, render them.
  if ($messages = theme('status_messages')) {
    $output = $messages . $output;
  }

  $commands = array();
  // If the form has not yet been rendered, render it.
  $commands[] = ctools_modal_command_display($title, $output);
  return $commands;
}

/**
 * Perform a simple modal render and immediately exit.
 *
 * This is primarily used for error displays, since usually modals will
 * contain forms.
 */
function ctools_modal_render($title, $output) {
  $commands = array();
  $commands[] = ctools_modal_command_display($title, $output);
  print ajax_render($commands);
}