summaryrefslogtreecommitdiff
path: root/modules/overlay/overlay.module
diff options
context:
space:
mode:
authorAngie Byron <webchick@24967.no-reply.drupal.org>2009-12-02 07:28:22 +0000
committerAngie Byron <webchick@24967.no-reply.drupal.org>2009-12-02 07:28:22 +0000
commitc912008307dd49b5e3e85c78069153f2f9f70411 (patch)
tree6e219858505bd38130a7d679488d3a41e689ce1d /modules/overlay/overlay.module
parentcfc96df9a7181526cb1c71cf4e39886026c668fe (diff)
downloadbrdo-c912008307dd49b5e3e85c78069153f2f9f70411.tar.gz
brdo-c912008307dd49b5e3e85c78069153f2f9f70411.tar.bz2
#610234 by Gábor Hojtsy, ksenzee, cwgordon7, David_Rothstein, seutje, marcvangend, sun, JoshuaRogers, markus_petrux, Bojhan, Rob Loach, Everett Zufelt, drifter, markboulton, leisareichelt, et al: Added Overlay module to core, which shows administrative pages in a JS overlay, retaining context on the front-end site.
Diffstat (limited to 'modules/overlay/overlay.module')
-rw-r--r--modules/overlay/overlay.module777
1 files changed, 777 insertions, 0 deletions
diff --git a/modules/overlay/overlay.module b/modules/overlay/overlay.module
new file mode 100644
index 000000000..101599009
--- /dev/null
+++ b/modules/overlay/overlay.module
@@ -0,0 +1,777 @@
+<?php
+// $Id$
+
+/**
+ * @file
+ * Displays the Drupal administration interface in an overlay.
+ */
+
+/**
+ * Implements hook_menu().
+ */
+function overlay_menu() {
+ $items['overlay-ajax/%'] = array(
+ 'title' => '',
+ 'page callback' => 'overlay_ajax_render_region',
+ 'page arguments' => array(1),
+ 'access arguments' => array('access overlay'),
+ 'type' => MENU_CALLBACK,
+ );
+ return $items;
+}
+
+/**
+ * Implements hook_permission().
+ */
+function overlay_permission() {
+ return array(
+ 'access overlay' => array(
+ 'title' => t('Access the administrative overlay'),
+ 'description' => t('View administrative pages in the overlay.'),
+ ),
+ );
+}
+
+/**
+ * Implements hook_init().
+ *
+ * Determine whether the current page request is destined to appear in the
+ * parent window or in the overlay window, and format the page accordingly.
+ *
+ * @see overlay_set_mode()
+ */
+function overlay_init() {
+ // @todo: custom_theme does not exist anymore.
+ global $custom_theme;
+ // Only act if the user has access to administration pages. Other modules can
+ // also enable the overlay directly for other uses of the JavaScript.
+ if (user_access('access overlay')) {
+ if (isset($_GET['render']) && $_GET['render'] == 'overlay') {
+ // If this page shouldn't be rendered here, redirect to the parent.
+ if (!path_is_admin($_GET['q'])) {
+ overlay_close_dialog();
+ }
+ // If system module did not switch the theme yet (i.e. this is not an
+ // admin page, per se), we should switch the theme here.
+ $admin_theme = variable_get('admin_theme', 0);
+ if ($custom_theme != $admin_theme) {
+ $custom_theme = $admin_theme;
+ drupal_add_css(drupal_get_path('module', 'system') . '/admin.css');
+ }
+ // Indicate that we are viewing an overlay child page.
+ overlay_set_mode('child');
+ }
+ else {
+ // Otherwise add overlay parent code and our behavior.
+ overlay_set_mode('parent');
+ }
+ }
+}
+
+/**
+ * Implements hook_exit().
+ *
+ * When viewing an overlay child page, check if we need to trigger a refresh of
+ * the supplemental regions of the overlay on the next page request.
+ */
+function overlay_exit() {
+ // Check that we are in an overlay child page. Note that this should never
+ // return TRUE on a cached page view, since the child mode is not set until
+ // overlay_init() is called.
+ if (overlay_get_mode() == 'child') {
+ // Load any markup that was stored earlier in the page request, via calls
+ // to overlay_store_rendered_content(). If none was stored, this is not a
+ // page request where we expect any changes to the overlay supplemental
+ // regions to have occurred, so we do not need to proceed any further.
+ $original_markup = overlay_get_rendered_content();
+ if (!empty($original_markup)) {
+ // Compare the original markup to the current markup that we get from
+ // rendering each overlay supplemental region now. If they don't match,
+ // something must have changed, so we request a refresh of that region
+ // within the parent window on the next page request.
+ foreach (overlay_supplemental_regions() as $region) {
+ if (!isset($original_markup[$region]) || $original_markup[$region] != overlay_render_region($region)) {
+ overlay_request_refresh($region);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Implements hook_element_info_alter().
+ */
+function overlay_element_info_alter(&$types) {
+ foreach (array('submit', 'button', 'image_button', 'form') as $type) {
+ $types[$type]['#after_build'][] = 'overlay_form_after_build';
+ }
+}
+
+/**
+ * Implements hook_library().
+ */
+function overlay_library() {
+ $module_path = drupal_get_path('module', 'overlay');
+
+ // Overlay parent.
+ $libraries['parent'] = array(
+ 'title' => 'Overlay: Parent',
+ 'website' => 'http://drupal.org/node/517688',
+ 'version' => '1.0',
+ 'js' => array(
+ $module_path . '/overlay-parent.js' => array(),
+ ),
+ 'css' => array(
+ $module_path . '/overlay-parent.css' => array(),
+ ),
+ 'dependencies' => array(
+ array('system', 'ui.dialog'),
+ array('system', 'jquery-bbq'),
+ ),
+ );
+ // Overlay child.
+ $libraries['child'] = array(
+ 'title' => 'Overlay: Child',
+ 'website' => 'http://drupal.org/node/517688',
+ 'version' => '1.0',
+ 'js' => array(
+ $module_path . '/overlay-child.js' => array(),
+ ),
+ 'dependencies' => array(
+ array('system', 'ui'),
+ ),
+ );
+
+ return $libraries;
+}
+
+/**
+ * Implements hook_form_alter().
+ *
+ * For forms displayed in the overlay, add a hidden form field that lets us pass
+ * the parent window's URL into the form.
+ */
+function overlay_form_alter(&$form, &$form_state, $form_id) {
+ if (overlay_get_mode() == 'child') {
+ $form['overlay_parent_url'] = array(
+ '#type' => 'hidden',
+ );
+ }
+}
+
+/**
+ * Implements hook_drupal_goto_alter().
+ *
+ * If the current page request is inside the overlay, add ?render=overlay to
+ * the new path, so that it appears correctly inside the overlay.
+ *
+ * @see overlay_get_mode()
+ */
+function overlay_drupal_goto_alter(&$path, &$options, &$http_response_code) {
+ if (overlay_get_mode() == 'child') {
+ if (isset($options['query'])) {
+ $options['query'] += array('render' => 'overlay');
+ }
+ else {
+ $options['query'] = array('render' => 'overlay');
+ }
+ }
+}
+
+/**
+ * Implements hook_batch_alter().
+ *
+ * If the current page request is inside the overlay, add ?render=overlay to
+ * the success callback URL, so that it appears correctly within the overlay.
+ *
+ * @see overlay_get_mode()
+ */
+function overlay_batch_alter(&$batch) {
+ if (overlay_get_mode() == 'child') {
+ if (isset($batch['url_options']['query'])) {
+ $batch['url_options']['query']['render'] = 'overlay';
+ }
+ else {
+ $batch['url_options']['query'] = array('render' => 'overlay');
+ }
+ }
+}
+
+/**
+ * Implements hook_page_alter().
+ */
+function overlay_page_alter(&$page) {
+ // If we are limiting rendering to a subset of page regions, deny access to
+ // all other regions so that they will not be processed.
+ if ($regions_to_render = overlay_get_regions_to_render()) {
+ $skipped_regions = array_diff(element_children($page), $regions_to_render);
+ foreach ($skipped_regions as $skipped_region) {
+ $page[$skipped_region]['#access'] = FALSE;
+ }
+ }
+}
+
+/**
+ * Implements hook_block_info_alter().
+ */
+function overlay_block_info_alter(&$blocks) {
+ // If we are limiting rendering to a subset of page regions, hide all blocks
+ // which appear in regions not on that list. Note that overlay_page_alter()
+ // does a more comprehensive job of preventing unwanted regions from being
+ // displayed (regardless of whether they contain blocks or not), but the
+ // reason for duplicating effort here is performance; we do not even want
+ // these blocks to be built if they are not going to be displayed.
+ if ($regions_to_render = overlay_get_regions_to_render()) {
+ foreach ($blocks as $bid => $block) {
+ if (!in_array($block->region, $regions_to_render)) {
+ unset($blocks[$bid]);
+ }
+ }
+ }
+}
+
+/**
+ * Implements hook_system_info_alter().
+ *
+ * Add default regions for the overlay.
+ */
+function overlay_system_info_alter(&$info, $file, $type) {
+ if ($type == 'theme') {
+ $info['overlay_regions'][] = 'content';
+ $info['overlay_regions'][] = 'help';
+ }
+}
+
+/**
+ * Preprocess template variables for html.tpl.php.
+ *
+ * If the current page request is inside the overlay, add appropriate classes
+ * to the <body> element, and simplify the page title.
+ *
+ * @see overlay_get_mode()
+ */
+function overlay_preprocess_html(&$variables) {
+ if (overlay_get_mode() == 'child') {
+ // Add overlay class, so themes can react to being displayed in the overlay.
+ $variables['classes_array'][] = 'overlay';
+ // Do not include site name or slogan in the overlay title.
+ $variables['head_title'] = drupal_get_title();
+ }
+}
+
+/**
+ * Preprocess template variables for page.tpl.php.
+ *
+ * Display breadcrumbs correctly inside the overlay.
+ *
+ * @see overlay_get_mode()
+ */
+function overlay_preprocess_page(&$variables) {
+ if (overlay_get_mode() == 'child') {
+ // Remove 'Home' from the breadcrumbs.
+ $overlay_breadcrumb = drupal_get_breadcrumb();
+ array_shift($overlay_breadcrumb);
+ $variables['breadcrumb'] = theme('breadcrumb', array('breadcrumb' => $overlay_breadcrumb));
+ }
+}
+
+/**
+ * Preprocess template variables for toolbar.tpl.php.
+ *
+ * Adding the 'overlay-displace-top' class to the toolbar pushes the overlay
+ * down, so it appears below the toolbar.
+ */
+function overlay_preprocess_toolbar(&$variables) {
+ $variables['classes_array'][] = "overlay-displace-top";
+}
+
+/**
+ * Form after_build callback.
+ *
+ * After all hook_form_alter() implementations have been processed, we look at
+ * the list of submit handlers and add our own at the end. The added handler
+ * determines whether or not the user is redirected done at the end of form
+ * processing, so that it's possible to close the overlay after submitting
+ * a form.
+ *
+ * @see _form_builder_handle_input_element()
+ * @see _form_builder_ie_cleanup()
+ * @see form_execute_handlers()
+ * @see form_builder()
+ * @see overlay_form_submit()
+ *
+ * @ingroup forms
+ */
+function overlay_form_after_build($form, &$form_state) {
+ if (isset($_GET['render']) && $_GET['render'] == 'overlay') {
+ // Form API may have already captured submit handlers from the submitted
+ // button before after_build callback is invoked. This may have been done
+ // by _form_builder_handle_input_element(). If so, the list of submit
+ // handlers is stored in the $form_state array, which is something we can
+ // also alter from here, luckily. Rememeber: our goal here is to set
+ // $form_state['redirect'] to FALSE if the API function
+ // overlay_request_dialog_close() has been invoked. That's because we want
+ // to tell the parent window to close the overlay.
+ if (!empty($form_state['submit_handlers']) && !in_array('overlay_form_submit', $form_state['submit_handlers'])) {
+ $form_state['submit_handlers'][] = 'overlay_form_submit';
+ }
+ // If this element has submit handlers, then append our own.
+ if (isset($form['#submit'])) {
+ $form['#submit'][] = 'overlay_form_submit';
+ }
+ }
+ return $form;
+}
+
+/**
+ * Generic form submit handler.
+ *
+ * When we are requested to close an overlay, we don't want Form API to
+ * perform any redirection once the submitted form has been processed.
+ *
+ * When $form_state['redirect'] is set to FALSE, then Form API will simply
+ * re-render the form with the values still in its fields. And this is all
+ * we need to output the JavaScript that will tell the parent window to close
+ * the child dialog.
+ *
+ * @see overlay_get_mode()
+ * @ingroup forms
+ */
+function overlay_form_submit($form, &$form_state) {
+ $settings = &drupal_static(__FUNCTION__);
+
+ // Check if we have a request to close the overlay.
+ $args = overlay_request_dialog_close();
+
+ // Close the overlay if the overlay module has been disabled
+ if (!module_exists('overlay')) {
+ $args = overlay_request_dialog_close(TRUE);
+ }
+
+ // If there is a form redirect to a non-admin page, close the overlay.
+ if (isset($form_state['redirect'])) {
+ // A destination set in the URL trumps $form_state['redirect'].
+ if (isset($_GET['destination'])) {
+ $url = $_GET['destination'];
+ $url_settings = array();
+ }
+ elseif (is_array($form_state['redirect'])) {
+ $url = $form_state['redirect'][0];
+ $url_settings = $form_state['redirect'][1];
+ }
+ else {
+ $url = $form_state['redirect'];
+ $url_settings = array();
+ }
+ if (!path_is_admin($url)) {
+ $args = overlay_request_dialog_close(TRUE);
+ }
+ }
+
+ // If the overlay is to be closed, pass that information through JavaScript.
+ if ($args !== FALSE) {
+ if (!isset($settings)) {
+ $settings = array(
+ 'overlayChild' => array(
+ 'closeOverlay' => TRUE,
+ 'statusMessages' => theme('status_messages'),
+ 'args' => $args,
+ ),
+ );
+ // Tell the child window to perform the redirection when requested to.
+ if (!empty($form_state['redirect'])) {
+ $settings['overlayChild']['redirect'] = url($url, $settings);
+ }
+ // If the redirect destination is the same as the parent window, just
+ // close the overlay without redirecting the parent.
+ if (url($form['overlay_parent_url']['#value']) == $settings['overlayChild']['redirect']) {
+ unset($settings['overlayChild']['redirect']);
+ }
+ drupal_add_js($settings, array('type' => 'setting'));
+ }
+ // Tell FAPI to redraw the form without redirection after all submit
+ // callbacks have been processed.
+ $form_state['redirect'] = FALSE;
+ }
+}
+
+/**
+ * Get the current overlay mode.
+ *
+ * @see overlay_set_mode()
+ */
+function overlay_get_mode() {
+ return overlay_set_mode(NULL);
+}
+
+/**
+ * Set overlay mode and add proper JavaScript and styles to the page.
+ *
+ * @param $mode
+ * To set the mode, pass in either 'parent' or 'child'. 'parent' is used in
+ * the context of a parent window (a regular browser window), and JavaScript
+ * is added so that administrative links in the parent window will open in
+ * an overlay. 'child' is used in the context of the child overlay window (the
+ * page actually appearing within the overlay iframe) and JavaScript and CSS
+ * are added so that Drupal behaves nicely from within the overlay.
+ *
+ * This parameter is optional, and if omitted, the current mode will be
+ * returned with no action taken.
+ *
+ * @return
+ * The current mode, if any has been set, or NULL if no mode has been set.
+ *
+ * @ingroup overlay_api
+ */
+function overlay_set_mode($mode = NULL) {
+ global $base_path;
+ $overlay_mode = &drupal_static(__FUNCTION__);
+
+ // Make sure external resources are not included more than once. Also return
+ // the current mode, if no mode was specified.
+ if (isset($overlay_mode) || !isset($mode)) {
+ return $overlay_mode;
+ }
+ $overlay_mode = $mode;
+
+ switch ($overlay_mode) {
+ case 'parent':
+ drupal_add_library('overlay', 'parent');
+ drupal_add_library('overlay', 'jquery-bbq');
+
+ // Allow modules to act upon overlay events.
+ module_invoke_all('overlay_parent_initialize');
+ break;
+
+ case 'child':
+ drupal_add_library('overlay', 'child');
+
+ // Allow modules to act upon overlay events.
+ module_invoke_all('overlay_child_initialize');
+ break;
+ }
+ return $overlay_mode;
+}
+
+/**
+ * Implements hook_overlay_parent_initialize().
+ */
+function overlay_overlay_parent_initialize() {
+ // Let the client side know which paths are administrative.
+ $paths = path_get_admin_paths();
+ foreach ($paths as &$type) {
+ $type = str_replace('<front>', variable_get('site_frontpage', 'node'), $type);
+ }
+ drupal_add_js(array('overlay' => array('paths' => $paths)), 'setting');
+ // Pass along the AJAX callback for rerendering sections of the parent window.
+ drupal_add_js(array('overlay' => array('ajaxCallback' => 'overlay-ajax')), 'setting');
+}
+
+/**
+ * Implements hook_overlay_child_initialize().
+ */
+function overlay_overlay_child_initialize() {
+ // Check if the parent window needs to refresh any page regions on this page
+ // request.
+ overlay_trigger_regions_to_refresh();
+ // If this is a POST request, or a GET request with a token parameter, we
+ // have an indication that something in the supplemental regions of the
+ // overlay might change during the current page request. We therefore store
+ // the initial rendered content of those regions here, so that we can compare
+ // it to the same content rendered in overlay_exit(), at the end of the page
+ // request. This allows us to check if anything actually did change, and, if
+ // so, trigger an AJAX refresh of the parent window.
+ if (!empty($_POST) || isset($_GET['token'])) {
+ foreach (overlay_supplemental_regions() as $region) {
+ overlay_store_rendered_content($region, overlay_render_region($region));
+ }
+ }
+ // Indicate that when the main page rendering occurs later in the page
+ // request, only the regions that appear within the overlay should be
+ // rendered.
+ overlay_set_regions_to_render(overlay_regions());
+}
+
+/**
+ * Callback to request that the overlay close on the next page load.
+ *
+ * @param $value
+ * By default, the dialog will not close. Set to TRUE or a value evaluating to
+ * TRUE to request the dialog to close. Use FALSE to disable closing the
+ * dialog (if it was previously enabled). The value passed will be forwarded
+ * to the onOverlayClose callback of the overlay.
+ *
+ * @return
+ * The current overlay close dialog mode, a value evaluating to TRUE if the
+ * overlay should close or FALSE if it should not (default).
+ */
+function overlay_request_dialog_close($value = NULL) {
+ $close = &drupal_static(__FUNCTION__, FALSE);
+ if (isset($value)) {
+ $close = $value;
+ }
+ return $close;
+}
+
+/**
+ * Close the overlay and redirect the parent window to a new path.
+ *
+ * @param $redirect
+ * The path that should open in the parent window after the overlay closes.
+ */
+function overlay_close_dialog($redirect = NULL) {
+ if (empty($redirect)) {
+ $path = $_GET['q'];
+ }
+ $settings = array(
+ 'overlayChild' => array(
+ 'closeOverlay' => TRUE,
+ 'statusMessages' => theme('status_messages'),
+ 'args' => $args,
+ 'redirect' => url($redirect),
+ ),
+ );
+ drupal_add_js($settings, array('type' => 'setting'));
+ return $settings;
+}
+
+/**
+ * Returns a list of page regions that appear in the overlay.
+ *
+ * Overlay regions correspond to the entire contents of the overlay child
+ * window and are refreshed each time a new page request is made within the
+ * overlay.
+ *
+ * @return
+ * An array of region names that correspond to those which appear in the
+ * overlay, within the theme that is being used to display the current page.
+ *
+ * @see overlay_supplemental_regions()
+ */
+function overlay_regions() {
+ return _overlay_region_list('overlay_regions');
+}
+
+/**
+ * Returns a list of supplemental page regions for the overlay.
+ *
+ * Supplemental overlay regions are those which are technically part of the
+ * parent window, but appear to the user as being related to the overlay
+ * (usually because they are displayed next to, rather than underneath, the
+ * main overlay regions) and therefore need to be dynamically refreshed if any
+ * administrative actions taken within the overlay change their contents.
+ *
+ * An example of a typical overlay supplemental region would be the 'page_top'
+ * region, in the case where a toolbar is being displayed there.
+ *
+ * @return
+ * An array of region names that correspond to supplemental overlay regions,
+ * within the theme that is being used to display the current page.
+ *
+ * @see overlay_regions()
+ */
+function overlay_supplemental_regions() {
+ return _overlay_region_list('overlay_supplemental_regions');
+}
+
+/**
+ * Helper function for returning a list of page regions related to the overlay.
+ *
+ * @param $type
+ * The type of regions to return. This can either be 'overlay_regions' or
+ * 'overlay_supplemental_regions'.
+ *
+ * @return
+ * An array of region names of the given type, within the theme that is being
+ * used to display the current page.
+ *
+ * @see overlay_regions()
+ * @see overlay_supplemental_regions()
+ */
+function _overlay_region_list($type) {
+ // Obtain the current theme. We need to first make sure the theme system is
+ // initialized, since this function can be called early in the page request.
+ drupal_theme_initialize();
+ $themes = list_themes();
+ $theme = $themes[$GLOBALS['theme']];
+ // Return the list of regions stored within the theme's info array, or an
+ // empty array if no regions of the appropriate type are defined.
+ return !empty($theme->info[$type]) ? $theme->info[$type] : array();
+}
+
+/**
+ * Returns a list of page regions that rendering should be limited to.
+ *
+ * @return
+ * An array containing the names of the regions that will be rendered when
+ * drupal_render_page() is called. If empty, then no limits will be imposed,
+ * and all regions of the page will be rendered.
+ *
+ * @see overlay_page_alter()
+ * @see overlay_block_info_alter()
+ * @see overlay_set_regions_to_render()
+ */
+function overlay_get_regions_to_render() {
+ return overlay_set_regions_to_render();
+}
+
+/**
+ * Sets the regions of the page that rendering will be limited to.
+ *
+ * @param $regions
+ * (Optional) An array containing the names of the regions that should be
+ * rendered when drupal_render_page() is called. Pass in an empty array to
+ * remove all limits and cause drupal_render_page() to render all page
+ * regions (the default behavior). If this parameter is omitted, no change
+ * will be made to the current list of regions to render.
+ *
+ * @return
+ * The current list of regions to render, or an empty array if the regions
+ * are not being limited.
+ *
+ * @see overlay_page_alter()
+ * @see overlay_block_info_alter()
+ * @see overlay_get_regions_to_render()
+ */
+function overlay_set_regions_to_render($regions = NULL) {
+ $regions_to_render = &drupal_static(__FUNCTION__, array());
+ if (isset($regions)) {
+ $regions_to_render = $regions;
+ }
+ return $regions_to_render;
+}
+
+/**
+ * Renders an individual page region.
+ *
+ * This function is primarily intended to be used for checking the content of
+ * supplemental overlay regions (e.g., a region containing a toolbar). Passing
+ * in a region that is intended to display the main page content is not
+ * supported; the region will be rendered by this function, but the main page
+ * content will not appear in it.
+ *
+ * @param $region
+ * The name of the page region that should be rendered.
+ *
+ * @return
+ * The rendered HTML of the provided region.
+ */
+function overlay_render_region($region) {
+ // Indicate the region that we will be rendering, so that other regions will
+ // be hidden by overlay_page_alter() and overlay_block_info_alter().
+ overlay_set_regions_to_render(array($region));
+ // Do what is necessary to force drupal_render_page() to only display HTML
+ // from the requested region. Specifically, declare that the main page
+ // content does not need to automatically be added to the page, and pass in
+ // a page array that has all theme functions removed (so that overall HTML
+ // for the page will not be added either).
+ $system_main_content_added = &drupal_static('system_main_content_added');
+ $system_main_content_added = TRUE;
+ $page = array(
+ '#type' => 'page',
+ '#theme' => NULL,
+ '#theme_wrappers' => array(),
+ );
+ $markup = drupal_render_page($page);
+ // Indicate that the main page content has not, in fact, been displayed, so
+ // that future calls to drupal_render_page() will be able to render it
+ // correctly.
+ $system_main_content_added = FALSE;
+ // Restore the original behavior of rendering all regions for the next time
+ // drupal_render_page() is called.
+ overlay_set_regions_to_render(array());
+ return $markup;
+}
+
+/**
+ * Returns any rendered content that was stored earlier in the page request.
+ *
+ * @return
+ * An array of all rendered HTML that was stored earlier in the page request,
+ * keyed by the identifier with which it was stored. If no content was
+ * stored, an empty array is returned.
+ *
+ * @see overlay_store_rendered_content()
+ */
+function overlay_get_rendered_content() {
+ return overlay_store_rendered_content();
+}
+
+/**
+ * Stores strings representing rendered HTML content.
+ *
+ * This function is used to keep a static cache of rendered content that can be
+ * referred to later in the page request.
+ *
+ * @param $id
+ * (Optional) An identifier for the content which is being stored, which will
+ * be used as an array key in the returned array. If omitted, no change will
+ * be made to the current stored data.
+ * @param $content
+ * (Optional) A string representing the rendered data to store. This only has
+ * an effect if $id is also provided.
+ *
+ * @return
+ * An array representing all data that is currently being stored, or an empty
+ * array if there is none.
+ *
+ * @see overlay_get_rendered_content()
+ */
+function overlay_store_rendered_content($id = NULL, $content = NULL) {
+ $rendered_content = &drupal_static(__FUNCTION__, array());
+ if (isset($id)) {
+ $rendered_content[$id] = $content;
+ }
+ return $rendered_content;
+}
+
+/**
+ * Request that the parent window refresh a particular page region.
+ *
+ * @param $region
+ * The name of the page region to refresh. The parent window will trigger a
+ * refresh of this region on the next page load.
+ *
+ * @see overlay_trigger_regions_to_refresh()
+ * @see Drupal.overlay.refreshRegions()
+ */
+function overlay_request_refresh($region) {
+ $class = drupal_region_class($region);
+ $_SESSION['overlay_regions_to_refresh'][] = array($class => $region);
+}
+
+/**
+ * Check if the parent window needs to refresh any regions on this page load.
+ *
+ * If the previous page load requested that any page regions be refreshed, pass
+ * that request via JavaScript to the child window, so it can in turn pass the
+ * request to the parent window.
+ *
+ * @see overlay_request_refresh()
+ * @see Drupal.overlay.refreshRegions()
+ */
+function overlay_trigger_regions_to_refresh() {
+ if (!empty($_SESSION['overlay_regions_to_refresh'])) {
+ $settings = array(
+ 'overlayChild' => array(
+ 'refreshRegions' => $_SESSION['overlay_regions_to_refresh'],
+ ),
+ );
+ drupal_add_js($settings, array('type' => 'setting'));
+ unset($_SESSION['overlay_regions_to_refresh']);
+ }
+}
+
+/**
+ * Prints the markup obtained by rendering a single region of the page.
+ *
+ * This function is intended to be called via AJAX.
+ *
+ * @param $region
+ * The name of the page region to render.
+ *
+ * @see Drupal.overlay.refreshRegions()
+ */
+function overlay_ajax_render_region($region) {
+ print overlay_render_region($region);
+}