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..4a6ec01 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,31 @@ 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; } 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'), ); }