summaryrefslogtreecommitdiff
path: root/modules/overlay
diff options
context:
space:
mode:
authorDries Buytaert <dries@buytaert.net>2010-11-06 00:18:24 +0000
committerDries Buytaert <dries@buytaert.net>2010-11-06 00:18:24 +0000
commit755bf9cd70be27fafb1c2fd28920559e2d5f055c (patch)
treead22554ff2da32a3b4b2fe551000c16e9237762d /modules/overlay
parent7ab426ecae5e383ee1c662756e89320207f91cbd (diff)
downloadbrdo-755bf9cd70be27fafb1c2fd28920559e2d5f055c.tar.gz
brdo-755bf9cd70be27fafb1c2fd28920559e2d5f055c.tar.bz2
- Patch #896364 by frega, effulgentsia, Jacine, sun, David_Rothstein, Jeff Burnz, james.elliott, casey, mgifford: screen reader users and some keyboard only users need a clear, quick way to disable the overlay.
Diffstat (limited to 'modules/overlay')
-rw-r--r--modules/overlay/overlay-child.css25
-rw-r--r--modules/overlay/overlay-child.js13
-rw-r--r--modules/overlay/overlay-parent.css14
-rw-r--r--modules/overlay/overlay-parent.js10
-rw-r--r--modules/overlay/overlay.module147
-rw-r--r--modules/overlay/overlay.tpl.php1
6 files changed, 204 insertions, 6 deletions
diff --git a/modules/overlay/overlay-child.css b/modules/overlay/overlay-child.css
index 0a2d4a099..c50e911f1 100644
--- a/modules/overlay/overlay-child.css
+++ b/modules/overlay/overlay-child.css
@@ -6,6 +6,8 @@ html.js {
}
html.js body {
background: transparent !important;
+ margin-left: 0;
+ margin-right: 0;
padding: 20px 0;
}
@@ -138,3 +140,26 @@ html.js body {
* html #overlay-close:hover {
position: absolute;
}
+
+/**
+ * Disable message.
+ */
+#overlay-disable-message {
+ background-color: #fff;
+ margin: -20px auto 20px;
+ width: 80%;
+ -moz-border-radius: 0 0 8px 8px;
+ -webkit-border-bottom-left-radius: 8px;
+ -webkit-border-bottom-right-radius: 8px;
+ border-radius: 0 0 8px 8px;
+}
+.overlay-disable-message-focused {
+ padding: 0.5em;
+}
+.overlay-disable-message-focused a {
+ display: block;
+ float: left;
+}
+.overlay-disable-message-focused #overlay-dismiss-message {
+ float: right;
+}
diff --git a/modules/overlay/overlay-child.js b/modules/overlay/overlay-child.js
index d0e4b8df8..4c2666cd9 100644
--- a/modules/overlay/overlay-child.js
+++ b/modules/overlay/overlay-child.js
@@ -57,6 +57,19 @@ Drupal.behaviors.overlayChild = {
// Attach child related behaviors to the iframe document.
Drupal.overlayChild.attachBehaviors(context, settings);
+
+ // There are two links within the message that informs people about the
+ // overlay and how to disable it. Make sure both links are visible when
+ // either one has focus and add a class to the wrapper for styling purposes.
+ $('#overlay-disable-message', context)
+ .focusin(function () {
+ $(this).addClass('overlay-disable-message-focused');
+ $('a.element-focusable', this).removeClass('element-invisible');
+ })
+ .focusout(function () {
+ $(this).removeClass('overlay-disable-message-focused');
+ $('a.element-focusable', this).addClass('element-invisible');
+ });
}
};
diff --git a/modules/overlay/overlay-parent.css b/modules/overlay/overlay-parent.css
index 50e8e364e..196ca177e 100644
--- a/modules/overlay/overlay-parent.css
+++ b/modules/overlay/overlay-parent.css
@@ -35,3 +35,17 @@ html.overlay-open .displace-top,
html.overlay-open .displace-bottom {
z-index: 600;
}
+
+/**
+ * Within the overlay parent, the message about disabling the overlay is for
+ * screen-reader users only. It is always kept invisible with the
+ * element-invisible class, and removed from the tab order. Overlay-child.css
+ * contains styling for the same message appearing within the overlay, and
+ * intended for sighted users.
+ */
+#overlay-disable-message {
+ display: none;
+}
+html.overlay-open #overlay-disable-message {
+ display: block;
+}
diff --git a/modules/overlay/overlay-parent.js b/modules/overlay/overlay-parent.js
index a4eb5aaa2..d176234cf 100644
--- a/modules/overlay/overlay-parent.js
+++ b/modules/overlay/overlay-parent.js
@@ -825,9 +825,15 @@ Drupal.overlay.getDisplacement = function (region) {
* the entire page.
*/
Drupal.overlay.makeDocumentUntabbable = function (context) {
- // Manipulating tabindexes is unacceptably slow in IE6 and IE7, so in those
- // browsers, the underlying page will still be reachable via the tab key.
+ // Manipulating tabindexes for the entire document is unacceptably slow in IE6
+ // and IE7, so in those browsers, the underlying page will still be reachable
+ // via the tab key. However, we still make the links within the Disable
+ // message unreachable, because the same message also exists within the
+ // child document. The duplicate copy in the underlying document is only for
+ // assisting screen-reader users navigating the document with reading commands
+ // that follow markup order rather than tab order.
if (jQuery.browser.msie && parseInt(jQuery.browser.version, 10) < 8) {
+ $('#overlay-disable-message a', context).attr('tabindex', -1);
return;
}
diff --git a/modules/overlay/overlay.module b/modules/overlay/overlay.module
index 5172809b7..aa78f2123 100644
--- a/modules/overlay/overlay.module
+++ b/modules/overlay/overlay.module
@@ -30,10 +30,29 @@ function overlay_menu() {
'access arguments' => array('access overlay'),
'type' => MENU_CALLBACK,
);
+ $items['overlay/dismiss-message'] = array(
+ 'title' => '',
+ 'page callback' => 'overlay_user_dismiss_message',
+ 'access arguments' => array('access overlay'),
+ 'type' => MENU_CALLBACK,
+ );
return $items;
}
/**
+ * Implements hook_admin_paths().
+ */
+function overlay_admin_paths() {
+ $paths = array(
+ // This is marked as an administrative path so that if it is visited from
+ // within the overlay, the user will stay within the overlay while the
+ // callback is being processed.
+ 'overlay/dismiss-message' => TRUE,
+ );
+ return $paths;
+}
+
+/**
* Implements hook_permission().
*/
function overlay_permission() {
@@ -54,6 +73,9 @@ function overlay_theme() {
'render element' => 'page',
'template' => 'overlay',
),
+ 'overlay_disable_message' => array(
+ 'render element' => 'element',
+ ),
);
}
@@ -254,10 +276,127 @@ function overlay_page_alter(&$page) {
}
}
- if (overlay_get_mode() == 'child') {
+ $mode = overlay_get_mode();
+ if ($mode == 'child') {
// Add the overlay wrapper before the html wrapper.
array_unshift($page['#theme_wrappers'], 'overlay');
}
+ elseif ($mode == 'parent' && ($message = overlay_disable_message())) {
+ $page['page_top']['disable_overlay'] = $message;
+ }
+}
+
+/**
+ * Menu callback; dismisses the overlay accessibility message for this user.
+ */
+function overlay_user_dismiss_message() {
+ global $user;
+ // It's unlikely, but possible that "access overlay" permission is granted to
+ // the anonymous role. In this case, we do not display the message to disable
+ // the overlay, so there is nothing to dismiss. Also, protect against
+ // cross-site request forgeries by validating a token.
+ if (empty($user->uid) || !isset($_GET['token']) || !drupal_valid_token($_GET['token'], 'overlay')) {
+ return MENU_ACCESS_DENIED;
+ }
+ else {
+ user_save(user_load($user->uid), array('data' => array('overlay_message_dismissed' => 1)));
+ drupal_set_message(t('The message has been dismissed. You can change your overlay settings at any time by visiting your profile page.'));
+ // Destination is normally given. Go to the user profile as a fallback.
+ drupal_goto('user/' . $user->uid . '/edit');
+ }
+}
+
+/**
+ * Returns a renderable array representing a message for disabling the overlay.
+ *
+ * If the current user can access the overlay and has not previously indicated
+ * that this message should be dismissed, this function returns a message
+ * containing a link to disable the overlay. Nothing is returned for anonymous
+ * users, because the links control per-user settings. Therefore, because some
+ * screen readers are unable to properly read overlay contents, site builders
+ * are discouraged from granting the "access overlay" permission to the
+ * anonymous role. See http://drupal.org/node/890284.
+ */
+function overlay_disable_message() {
+ global $user;
+
+ if (!empty($user->uid) && empty($user->data['overlay_message_dismissed']) && (!isset($user->data['overlay']) || $user->data['overlay']) && user_access('access overlay')) {
+ $build = array(
+ '#theme' => 'overlay_disable_message',
+ '#weight' => -99,
+ // Link to the user's profile page, where the overlay can be disabled.
+ 'profile_link' => array(
+ '#type' => 'link',
+ '#title' => t('If you have problems accessing administrative pages on this site, disable the overlay on your profile page.'),
+ '#href' => 'user/' . $user->uid . '/edit',
+ '#options' => array(
+ 'query' => drupal_get_destination(),
+ 'fragment' => 'edit-overlay-control',
+ 'attributes' => array(
+ 'id' => 'overlay-profile-link',
+ // Prevent the target page from being opened in the overlay.
+ 'class' => array('overlay-exclude'),
+ ),
+ ),
+ ),
+ // Link to a menu callback that allows this message to be permanently
+ // dismissed for the current user.
+ 'dismiss_message_link' => array(
+ '#type' => 'link',
+ '#title' => t('Dismiss this message.'),
+ '#href' => 'overlay/dismiss-message',
+ '#options' => array(
+ 'query' => drupal_get_destination() + array(
+ // Add a token to protect against cross-site request forgeries.
+ 'token' => drupal_get_token('overlay'),
+ ),
+ 'attributes' => array(
+ 'id' => 'overlay-dismiss-message',
+ // If this message is being displayed outside the overlay, prevent
+ // this link from opening the overlay.
+ 'class' => (overlay_get_mode() == 'parent') ? array('overlay-exclude') : array(),
+ ),
+ ),
+ )
+ );
+ }
+ else {
+ $build = array();
+ }
+
+ return $build;
+}
+
+/**
+ * Returns the HTML for the message about how to disable the overlay.
+ *
+ * @see overlay_disable_message()
+ */
+function theme_overlay_disable_message($variables) {
+ $element = $variables['element'];
+
+ // Add CSS classes to hide the links from most sighted users, while keeping
+ // them accessible to screen-reader users and keyboard-only users. To assist
+ // screen-reader users, this message appears in both the parent and child
+ // documents, but only the one in the child document is part of the tab order.
+ foreach (array('profile_link', 'dismiss_message_link') as $key) {
+ $element[$key]['#options']['attributes']['class'][] = 'element-invisible';
+ if (overlay_get_mode() == 'child') {
+ $element[$key]['#options']['attributes']['class'][] = 'element-focusable';
+ }
+ }
+
+ // Render the links.
+ $output = drupal_render($element['profile_link']) . ' ' . drupal_render($element['dismiss_message_link']);
+
+ // Add a heading for screen-reader users. The heading doesn't need to be seen
+ // by sighted users.
+ $output = '<h3 class="element-invisible">' . t('Options for the administrative overlay') . '</h3>' . $output;
+
+ // Wrap in a container for styling.
+ $output = '<div id="overlay-disable-message" class="clearfix">' . $output . '</div>';
+
+ return $output;
}
/**
@@ -324,9 +463,9 @@ function overlay_preprocess_maintenance_page(&$variables) {
* @see overlay.tpl.php
*/
function template_preprocess_overlay(&$variables) {
- $variables['tabs'] = menu_primary_local_tasks();
- $variables['title'] = drupal_get_title();
-
+ $variables['tabs'] = menu_primary_local_tasks();
+ $variables['title'] = drupal_get_title();
+ $variables['disable_overlay'] = overlay_disable_message();
$variables['content_attributes_array']['class'][] = 'clearfix';
}
diff --git a/modules/overlay/overlay.tpl.php b/modules/overlay/overlay.tpl.php
index d6d9e1c59..5dfcade9b 100644
--- a/modules/overlay/overlay.tpl.php
+++ b/modules/overlay/overlay.tpl.php
@@ -21,6 +21,7 @@
*/
?>
+<?php print render($disable_overlay); ?>
<div id="overlay" <?php print $attributes; ?>>
<div id="overlay-titlebar" class="clearfix">
<div id="overlay-title-wrapper" class="clearfix">