diff --git admin_menu.js admin_menu.js
index f8c730a..ddadb52 100644
--- admin_menu.js
+++ admin_menu.js
@@ -35,7 +35,12 @@ Drupal.behaviors.adminMenu = {
if (!$adminMenu.length && settings.admin_menu.hash) {
Drupal.admin.getCache(settings.admin_menu.hash, function (response) {
if (typeof response == 'string' && response.length > 0) {
- $('body', context).prepend(response);
+ // Insert this in the same location and with the same markup that
+ // it would have had if it had been placed on the page by the
+ // server-side code.
+ // @todo: Ideally the wrapping markup should be returned as part of
+ // the AJAX response.
+ $('body', context).append('
' + response + '
');
}
var $adminMenu = $('#admin-menu:not(.admin-menu-processed)', context);
// Apply our behaviors.
diff --git admin_menu.module admin_menu.module
index 6fa85f2..3abd24c 100644
--- admin_menu.module
+++ admin_menu.module
@@ -116,6 +116,10 @@ function admin_menu_menu_alter(&$items) {
* like chameleon load and output scripts and stylesheets in front of
* theme_closure(), so we ensure Admin menu's styles and scripts are loaded on
* all pages via hook_init().
+ *
+ * See also admin_menu_page_build(), where additional scripts are attached to
+ * regions of the $page array (so that they only are added to the page when
+ * those regions are actually rendered).
*/
function admin_menu_init() {
if (!user_access('access administration menu') || admin_menu_suppress(FALSE)) {
@@ -202,12 +206,39 @@ function admin_menu_suppress($set = TRUE) {
}
/**
- * Implements hook_page_alter().
+ * Implements hook_page_build().
*/
-function admin_menu_page_alter(&$page) {
+function admin_menu_page_build(&$page) {
$page['page_bottom']['admin_menu'] = array(
'#markup' => admin_menu_output(),
);
+
+ // Attach the administration menu JavaScript to the same part of the $page
+ // array as the menu itself. This ensures that when this region of the page
+ // is not intended to be rendered (for example, inside the Overlay), the
+ // JavaScript won't be added either. (If the JavaScript were added, the
+ // client-side code would add the menu to the page even when it isn't
+ // supposed to be there.)
+ // @todo: Should all the JavaScript added in admin_menu_init() move here too,
+ // rather than just this file?
+ if (user_access('access administration menu') && !admin_menu_suppress(FALSE)) {
+ $js_file = drupal_get_path('module', 'admin_menu') . '/admin_menu.js';
+ // Performance: Defer execution.
+ $page['page_bottom']['admin_menu']['#attached']['js'][$js_file] = array('defer' => TRUE);
+ }
+}
+
+/**
+ * Implements hook_system_info_alter().
+ *
+ * Indicate that the 'page_bottom' region (in which the administration menu
+ * is displayed) is an overlay supplemental region that should be refreshed
+ * whenever its content is updated.
+ */
+function admin_menu_system_info_alter(&$info, $file, $type) {
+ if ($type == 'theme') {
+ $info['overlay_supplemental_regions'][] = 'page_bottom';
+ }
}
/**
@@ -236,7 +267,7 @@ function admin_menu_js() {
* The cache ID of the data to retrieve.
*/
function admin_menu_cache_get($cid) {
- static $cache = array();
+ $cache = &drupal_static(__FUNCTION__, array());
if (!variable_get('admin_menu_cache_client', TRUE)) {
return FALSE;
@@ -375,12 +406,13 @@ function admin_menu_output() {
$cid = 'admin_menu:' . $user->uid . ':' . $language->language;
// Do nothing at all here if the client supports client-side caching, the user
- // has a hash, and is NOT requesting the cache update path. Consult the hash
- // cache last, since it requires a DB request.
+ // has a hash, and is NOT requesting either the cache update path or the
+ // Overlay module's AJAX update path. Consult the hash cache last, since it
+ // requires a DB request.
// @todo Implement a sanity-check to prevent permanent double requests; i.e.
// what if the client-side cache fails for any reason and performs a second
// request on every page?
- if (!empty($_COOKIE['has_js']) && strpos($_GET['q'], 'js/admin_menu/cache') !== 0) {
+ if (!empty($_COOKIE['has_js']) && strpos($_GET['q'], 'js/admin_menu/cache') !== 0 && strpos($_GET['q'], 'overlay-ajax/') !== 0) {
if (admin_menu_cache_get($cid)) {
return;
}
@@ -474,7 +506,7 @@ function theme_admin_menu_links($variables) {
'#options' => array(),
);
// Render children to determine whether this link is expandable.
- if (isset($elements[$path]['#type']) || isset($elements[$path]['#theme'])) {
+ if (isset($elements[$path]['#type']) || isset($elements[$path]['#theme']) || isset($elements[$path]['#pre_render'])) {
$elements[$path]['#admin_menu_depth'] = $depth_child;
$elements[$path]['#children'] = drupal_render($elements[$path]);
}
@@ -577,6 +609,7 @@ function admin_menu_flush_caches() {
// Flush cached output of admin_menu.
cache_clear_all('admin_menu:', 'cache_menu', TRUE);
// Flush client-side cache hashes.
+ drupal_static_reset('admin_menu_cache_get');
// db_table_exists() required for SimpleTest.
if (db_table_exists('cache_admin_menu')) {
cache_clear_all('*', 'cache_admin_menu', TRUE);
@@ -593,6 +626,33 @@ function admin_menu_form_system_clean_url_settings_alter(&$form, $form_state) {
}
/**
+ * Implements hook_menu_link_insert().
+ */
+function admin_menu_menu_link_insert($link) {
+ // Flush the admin menu cache so it can take into account the changed menu
+ // links.
+ admin_menu_flush_caches();
+}
+
+/**
+ * Implements hook_menu_link_update().
+ */
+function admin_menu_menu_link_update($link) {
+ // Flush the admin menu cache so it can take into account the changed menu
+ // links.
+ admin_menu_flush_caches();
+}
+
+/**
+ * Implements hook_menu_link_delete().
+ */
+function admin_menu_menu_link_delete($link) {
+ // Flush the admin menu cache so it can take into account the changed menu
+ // links.
+ admin_menu_flush_caches();
+}
+
+/**
* Implements hook_form_FORM_ID_alter().
*
* Extends Devel module with Administration menu developer settings.
diff --git admin_menu_toolbar/admin_menu_toolbar.css admin_menu_toolbar/admin_menu_toolbar.css
index 85c7d8e..4c16d7c 100644
--- admin_menu_toolbar/admin_menu_toolbar.css
+++ admin_menu_toolbar/admin_menu_toolbar.css
@@ -13,6 +13,9 @@
html body.admin-menu {
margin-top: 29px !important;
}
+html body.admin-menu-with-shortcuts {
+ margin-top: 62px !important;
+}
body div#toolbar {
top: 30px;
}
@@ -116,21 +119,21 @@ body div#toolbar {
#admin-menu li.admin-menu-shortcuts-active span.toggle:hover {
background-position: -75px -20px;
}
-
-/**
- * Shortcuts widget.
- */
+/* Override the standard admin menu hover behavior with our own */
+#admin-menu li.admin-menu-shortcuts-inactive ul {
+ display: none !important;
+ left: -999em !important;
+}
#admin-menu li.admin-menu-shortcuts-active ul {
display: block !important;
left: 20px !important;
- right: 20px;
- width: auto;
}
+
+/**
+ * Shortcuts widget.
+ */
+/* General styling that applies to the entire widget and all shortcuts in it */
#admin-menu li.admin-menu-shortcuts ul {
- background-color: #666;
- left: 20px !important;
- padding: 5px 10px;
- right: 20px;
width: auto;
}
#admin-menu li.admin-menu-shortcuts ul li {
@@ -146,10 +149,42 @@ body div#toolbar {
padding: 5px 10px 5px 5px;
margin-right: 5px;
}
-#admin-menu li.admin-menu-shortcuts ul li a:hover {
+
+/* Styling that applies to the wrapper list but not the shortcuts themselves */
+#admin-menu li.admin-menu-shortcuts > ul {
+ background-color: #666;
+ padding: 5px 10px;
+ right: 20px;
+}
+#admin-menu li.admin-menu-shortcuts > ul > li {
+ width: 100%;
+}
+
+/* Styling that applies to the actual shortcuts but not to "Edit shortcuts" */
+#admin-menu li.admin-menu-shortcuts .toolbar-shortcuts ul li a:hover {
background: #555;
}
-#admin-menu li.admin-menu-shortcuts ul li a.active:hover,
-#admin-menu li.admin-menu-shortcuts ul li a.active {
- background: url(toolbar.png) 0 -20px repeat-x;
+
+/* Styling that applies to the "Edit shortcuts" link only */
+#admin-menu a#edit-shortcuts {
+ float: right;
+ padding: 5px 10px 5px 5px;
+ color: #fefefe;
+}
+#admin-menu a#edit-shortcuts:focus,
+#admin-menu a#edit-shortcuts:hover,
+#admin-menu a#edit-shortcuts.active {
+ color: #fff;
+ text-decoration: underline;
}
+
+/* Drop shadow on shortcut bar */
+html body.admin-menu-with-shortcuts #admin-menu li.admin-menu-shortcuts > ul {
+ -moz-box-shadow: 0 3px 20px #000;
+ -webkit-box-shadow: 0 3px 20px #000;
+ box-shadow: 0 3px 20px #000;
+ filter: progid:DXImageTransform.Microsoft.Shadow(color=#000000, direction='180', strength='10');
+ -ms-filter: "progid:DXImageTransform.Microsoft.Shadow(color=#000000, direction='180', strength='10')";
+ z-index: -1;
+}
+
diff --git admin_menu_toolbar/admin_menu_toolbar.js admin_menu_toolbar/admin_menu_toolbar.js
index 28f8448..c4c09a7 100644
--- admin_menu_toolbar/admin_menu_toolbar.js
+++ admin_menu_toolbar/admin_menu_toolbar.js
@@ -4,6 +4,19 @@ Drupal.admin = Drupal.admin || {};
Drupal.admin.behaviors = Drupal.admin.behaviors || {};
/**
+ * Apply margin to page, taking into account the shortcuts.
+ *
+ * @see Drupal.behaviors.adminMenuMarginTop()
+ */
+Drupal.behaviors.adminMenuMarginTopShortcuts = {
+ attach: function (context, settings) {
+ if (!settings.admin_menu.suppress && settings.admin_menu.toolbar.margin_top_shortcuts) {
+ $('body:not(.admin-menu-with-shortcuts)', context).addClass('admin-menu-with-shortcuts');
+ }
+ }
+};
+
+/**
* @ingroup admin_behaviors
* @{
*/
@@ -20,6 +33,27 @@ Drupal.admin.behaviors.toolbarActiveTrail = function (context, settings, $adminM
};
/**
+ * Toggle the shortcut drawer.
+ */
+Drupal.admin.behaviors.toggleShortcutDrawer = function (context, settings, $adminMenu) {
+ var $body = $('body', context);
+ var $shortcuts = $('li.admin-menu-shortcuts', $adminMenu);
+ var $toggle = $('.toggle', $shortcuts);
+ $toggle.toggle(
+ function () {
+ $shortcuts.addClass('admin-menu-shortcuts-inactive').removeClass('admin-menu-shortcuts-active');
+ $body.removeClass('admin-menu-with-shortcuts');
+ return false;
+ },
+ function () {
+ $shortcuts.addClass('admin-menu-shortcuts-active').removeClass('admin-menu-shortcuts-inactive');
+ $body.addClass('admin-menu-with-shortcuts');
+ return false;
+ }
+ );
+};
+
+/**
* @} End of "defgroup admin_behaviors".
*/
diff --git admin_menu_toolbar/admin_menu_toolbar.module admin_menu_toolbar/admin_menu_toolbar.module
index 577bc8c..93b8428 100644
--- admin_menu_toolbar/admin_menu_toolbar.module
+++ admin_menu_toolbar/admin_menu_toolbar.module
@@ -35,6 +35,12 @@ function admin_menu_toolbar_init() {
elseif (drupal_is_front_page()) {
$settings['activeTrail'] = url('');
}
+
+ // Adjust top margin for the shortcut bar.
+ if (module_exists('shortcut') && ($setting = variable_get('admin_menu_margin_top', 1))) {
+ $settings['margin_top_shortcuts'] = $setting;
+ }
+
drupal_add_js(array('admin_menu' => array('toolbar' => $settings)), 'setting');
}
@@ -58,27 +64,20 @@ function admin_menu_toolbar_admin_menu_output_alter(&$content) {
// Add shortcuts menu.
$content['shortcuts'] = array(
+ '#access' => module_exists('shortcut'),
'#theme' => 'admin_menu_links',
'#weight' => -200,
);
$content['shortcuts']['shortcuts'] = array(
'#title' => t('Show shortcuts'),
// @todo How do we want to trigger/store state?
- '#attributes' => array('class' => array('admin-menu-shortcuts')),
- //'#attributes' => array('class' => array('admin-menu-shortcuts', 'admin-menu-shortcuts-active')),
+ '#attributes' => array('class' => array('admin-menu-shortcuts', 'admin-menu-shortcuts-active')),
'#options' => array(
'attributes' => array('class' => 'toggle'),
),
);
- // @todo *Move* this from $content['menu'] instead.
- $content['shortcuts']['shortcuts']['node-add'] = array(
- '#title' => t('Add content'),
- '#href' => 'node/add',
- );
- $content['shortcuts']['shortcuts']['admin-content-node'] = array(
- '#title' => t('Find content'),
- '#href' => 'admin/content/node',
- '#access' => user_access('administer nodes'),
+ $content['shortcuts']['shortcuts']['shortcuts'] = array(
+ '#pre_render' => array('shortcut_toolbar_pre_render'),
);
}