summaryrefslogtreecommitdiffstats
path: root/dialog.module
blob: 6b11ffe3e23b655b5b0938ddf299a7721e73ef8f (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
<?php

/**
 * @file
 * The Dialog module provides an API for displaying and interacting with
 * jQuery UI Dialog modals.
 *
 * This API is an integration with Drupal's AJAX Framework.  Using the
 * ajax "commands" provided, dialogs can be displayed, modified, and
 * closed.
 *
 * @link
 *   http://api.drupal.org/api/group/ajax/7
 *   Drupal AJAX framework documentation.
 */

/**
 * Implementation of hook_page_alter().
 */
function dialog_page_alter(&$page) {
  // Alter the current page to display as a dialog box if desired.
  if ($options = dialog_display()) {
    // Construct the contents of the dialog box.
    $content = render(drupal_set_page_content());

    // Cleanse the dialog options.
    if (!isset($options['title'])) {
      $options['title'] = drupal_get_title();
    }

    // Send over the commands.
    $commands = array();
    $commands[] = dialog_command_display($content, $options);
    ajax_render($commands);
  }
}

/**
 * Provides an easy way of representing the current page context as a dialog.
 *
 * @param $options
 *   (optional) If set, will become the options that are used when displaying the dialog
 *   to the user. See the jQuery UI Dialog options documentation for more
 *   information on this: http://jqueryui.com/demos/dialog/ .
 *
 * @return
 *   FALSE if the page is not to become a dialog box. Otherwise, will be an
 *   array of options that were previously set through the call to
 *   dialog_display. These options define how the resulting dialog box should
 *   be displayed.
 */
function dialog_display($options = NULL) {
  $dialog = &drupal_static(__FUNCTION__, FALSE);
  if (isset($options)) {
    // Make sure that an array is passed in as the options.
    $dialog = is_array($options) ? $options : array('dialogClass' => drupal_html_class($_GET['q']));
  }
  return $dialog;
}

/**
 * Implement hook_library().
 */
function dialog_library() {
  $path = drupal_get_path('module', 'dialog');

  $libraries['dialog'] = array(
    'title' => 'Dialog',
    'website' => 'http://drupal.org/project/dialog',
    'version' => '7.x',
    'js' => array(
      $path . '/jquery.xLazyLoader.js' => array('group' => JS_LIBRARY),
      $path . '/dialog.js' => array('weight' => 5),
    ),
    'dependencies' => array(
      array('system', 'drupal.ajax'),
      array('system', 'jquery.form'),
      array('system', 'ui.dialog'),
    ),
  );

  return $libraries;
}

/**
 * Check to see if the incoming menu item is able to use dialogs.
 *
 * @TODO: Move this to Drupal core?
 */
function dialog_js_load($js = 'nojs') {
  if ($js == 'ajax') {
    return TRUE;
  }
  return 0;
}

/**
 * Implement hook_ajax_render_alter().
 *
 * Using the xLazyLoader library and command, load additional css and
 * javascript into the page.
 *
 * TODO: Deal with overloading one theme's css onto another.
 */
function dialog_ajax_render_alter(&$commands) {
  if (dialog_display()) {
    $loader = array();
    $allowed_media = array('all', 'screen');
    // Inject additional JavaScript and CSS to the browser's client.
    $css = drupal_add_css();
    drupal_alter('css', $css);
    foreach ($css as $data => $options) {
      if ($options['type'] == 'file' && in_array($options['media'], $allowed_media)) {
        $loader['css'][] = base_path() . $options['data'];
      }
    }
    $scripts = drupal_add_js();
    drupal_alter('js', $scripts);
    foreach ($scripts as $data => $options) {
      if ($options['type'] == 'file') {
        $loader['js'][] = base_path() . $options['data'];
      }
    }
    if (!empty($loader)) {
      array_unshift($commands, dialog_command_xlazyloader($loader));
    }

    // Prepend status messages to the dialog content.
    $commands[] = ajax_command_prepend('#dialog', theme('status_messages'));
  }
}

/**
 * Process a form and prepare it for the dialog.
 */
function dialog_process_ajax_form($element) {
  dialog_fix_element_id($element);
  return $element;
}

/**
 * Fix element and its chilren's id's so they are unique in the page.
 */
function dialog_fix_element_id(&$element) {
  if (!isset($element['#id'])) {
    $element['#id'] = drupal_html_id('edit-' . implode('-', $element['#parents']));
  }
  $element['#id'] .= '-dialog';
  foreach (element_children($element) as $child) {
    // Don't squash an existing tree value.
    if (!isset($element[$child]['#tree'])) {
      $element[$child]['#tree'] = $element['#tree'];
    }

    // Don't squash existing parents value.
    if (!isset($element[$child]['#parents'])) {
      // Check to see if a tree of child elements is present. If so,
      // continue down the tree if required.
      $element[$child]['#parents'] = $element[$child]['#tree'] && $element['#tree'] ? array_merge($element['#parents'], array($child)) : array($child);
    }

    dialog_fix_element_id($element[$child]);
  }
}

/**
 * Creates a Drupal AJAX command to open the modal with a loading animation.
 */
function dialog_command_loading() {
  return array(
    'command' => 'dialog_loading',
  );
}

/**
 * Creates a Drupal AJAX command to place HTML within the modal and open it.
 *
 * @param $content
 *   The contents of the dialog box. This can be either straight HTML, or a
 *   renderable array.
 * @param $options
 *   An array of ui.dialog options. See the
 *   {@link http://jqueryui.com/demos/dialog/ jQuery UI Dialog} documentation
 *   for available options.
 */
function dialog_command_display($content, $options = array()) {
  return array(
    'command' => 'dialog_display',
    'content' => render($content),
    'options' => $options,
  );
}

/**
 * Creates a Drupal AJAX command to close the modal.
 */
function dialog_command_dismiss() {
  return array(
    'command' => 'dialog_dismiss',
  );
}

/**
 * Force a client-side redirect.
 *
 * @param $path
 *   The url to be redirected to.
 * @param $options
 *   Any additional options for the URL.
 */
function dialog_command_redirect($path, $options = array()) {
  $options['absolute'] = TRUE;
  return array(
    'command' => 'dialog_redirect',
    'url' => url($path, $options),
  );
}

/**
 * Force a client-side reload.
 */
function dialog_command_reload() {
  return array(
    'command' => 'dialog_reload',
  );
}

/**
 * Creates a Drupal AJAX 'xLazyLoader' command.
 *
 * The 'xLazyLoader' command loads additional JavaScript, CSS and images through
 * the xLazyLoader library (http://code.google.com/p/ajaxsoft/wiki/xLazyLoader).
 *
 * This command is implemented by Drupal.ajax.prototype.commands.xlazyloader()
 * defined in dialog.js.
 *
 * @param $options
 *   An associative of what JavaScript, CSS or images the client should load.
 *   - "js": An array of JavaScript files to load.
 *   - "css": An array of CSS files to load.
 *   - "img": An array of images to load.
 *
 * @return
 *   An array suitable for use with the ajax_render() function.
 */
function dialog_command_xlazyloader($options = array()) {
  return array(
    'command' => 'xlazyloader',
    'options' => $options,
  );
}