From ba8ac204a12de2dee68988d88febee49a0ccb4a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?"J.=20Rene=CC=81e=20Beach"?= Date: Fri, 14 Dec 2012 15:37:33 -0500 Subject: [PATCH] Issue #1847198 from 27 to 38 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit 271a5fb24b42694aacac07f376660702819a2293 Author: J. Renée Beach Date: Fri Dec 14 15:27:53 2012 -0500 Fixed toolbar tests. Signed-off-by: J. Renée Beach commit dea4160d2eef387abfd33a1d559898e7ffe312e5 Author: J. Renée Beach Date: Fri Dec 14 14:48:54 2012 -0500 Moved toolbar attrs to hook_element_info(). Signed-off-by: J. Renée Beach commit 82b998d4cb3d46ab33b18c9231f0cf6feeb4fd0c Author: J. Renée Beach Date: Fri Dec 14 13:17:26 2012 -0500 Updated toolbar.api.php Signed-off-by: J. Renée Beach commit 6eae21e8fac0eb248ceba89f82323a8b877bff76 Author: J. Renée Beach Date: Fri Dec 14 13:10:31 2012 -0500 fixed a small bug with $element['attributes'] Signed-off-by: J. Renée Beach commit 8915df54643921f9ceffd6016adab1e8d93df5cc Author: J. Renée Beach Date: Fri Dec 14 12:53:53 2012 -0500 Changes from implementing the Countcount module. Signed-off-by: J. Renée Beach commit bd2727e102cee3feb8ec0a01ba7a6c82b6f9384c Author: J. Renée Beach Date: Fri Dec 14 12:20:45 2012 -0500 Further toolbar.module cleanups. Signed-off-by: J. Renée Beach commit a2bbfbda61079313377d900039f01535a109d489 Author: J. Renée Beach Date: Fri Dec 14 11:33:30 2012 -0500 Almost working again. Just need to clean up the code. Signed-off-by: J. Renée Beach commit 1b1bea609f3ae868abf929cec80410ac8af33efc Author: J. Renée Beach Date: Fri Dec 14 11:15:08 2012 -0500 New render paradigm is in place. Signed-off-by: J. Renée Beach commit 46400ab4ce5549ebab9018edd5505951e9a44876 Author: J. Renée Beach Date: Thu Dec 13 19:52:16 2012 -0500 Getting to a sane point. Signed-off-by: J. Renée Beach commit 00d24962750ee0cc88b1db90217232025d90f431 Author: J. Renée Beach Date: Thu Dec 13 19:08:30 2012 -0500 Toolbar trays are actually kind of working. Signed-off-by: J. Renée Beach commit 319636083d4aee97bd5d6e56c9c24e435db4f26b Author: J. Renée Beach Date: Tue Dec 11 16:48:30 2012 -0500 patch 27 Signed-off-by: J. Renée Beach --- core/modules/shortcut/shortcut.module | 52 +-- core/modules/toolbar/css/toolbar.base.css | 10 +- core/modules/toolbar/css/toolbar.theme.css | 14 +- core/modules/toolbar/js/toolbar.js | 7 +- core/modules/toolbar/templates/toolbar.twig | 39 -- .../tests/modules/toolbar_test/toolbar_test.module | 31 +- core/modules/toolbar/toolbar.api.php | 128 +++++-- core/modules/toolbar/toolbar.module | 397 +++++++++++++------- core/modules/user/user.module | 31 +- 9 files changed, 430 insertions(+), 279 deletions(-) delete mode 100644 core/modules/toolbar/templates/toolbar.twig diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index 8677c72..9cf12d4 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -716,13 +716,8 @@ function shortcut_preprocess_page(&$variables) { * Implements hook_toolbar(). */ function shortcut_toolbar() { + $items = array(); $links = shortcut_renderable_links(); - $links['#attached'] = array( - 'css' => array( - drupal_get_path('module', 'shortcut') . '/shortcut.base.css', - drupal_get_path('module', 'shortcut') . '/shortcut.theme.css', - ), - ); $shortcut_set = shortcut_current_displayed_set(); $configure_link = NULL; if (shortcut_set_edit_access($shortcut_set)) { @@ -733,26 +728,33 @@ function shortcut_toolbar() { '#options' => array('attributes' => array('class' => array('edit-shortcuts'))), ); } - - $links_tray = array( - '#heading' => t('User-defined shortcuts'), - 'shortcuts' => $links, - 'configure' => $configure_link, - ); - - $items['shortcuts'] = array( - 'tab' => array( - 'title' => t('Shortcuts'), - 'href' => 'admin/config/user-interface/shortcut', - 'html' => FALSE, - 'attributes' => array( - 'title' => t('Shortcuts'), - 'class' => array('icon', 'icon-shortcut'), + if (!empty($links) || !empty($configure_link)) { + $items['shortcuts'] = array( + '#type' => 'toolbar_item', + '#text' => t('Shortcuts'), + '#path' => 'admin/config/user-interface/shortcut', + '#options' => array( + 'html' => FALSE, + 'attributes' => array( + 'title' => t('Shortcuts'), + 'class' => array('icon', 'icon-shortcut'), + ), ), - ), - 'tray' => $links_tray, - 'weight' => -10, - ); + 'tray' => array( + '#heading' => t('User-defined shortcuts'), + 'shortcuts' => $links, + 'configure' => $configure_link, + ), + '#weight' => -10, + '#attached' => array( + 'css' => array( + drupal_get_path('module', 'shortcut') . '/shortcut.base.css', + drupal_get_path('module', 'shortcut') . '/shortcut.theme.css', + ), + ), + ); + } + return $items; } diff --git a/core/modules/toolbar/css/toolbar.base.css b/core/modules/toolbar/css/toolbar.base.css index cbdf153..e6cf95a 100644 --- a/core/modules/toolbar/css/toolbar.base.css +++ b/core/modules/toolbar/css/toolbar.base.css @@ -39,12 +39,12 @@ html.js .toolbar { .toolbar .menu li { padding-top: 0; } -.js .toolbar .bar li, +.js .toolbar .bar .tab, .js .toolbar .menu li { display: block; } -.js .toolbar .bar li, -.js .toolbar .horizontal li { +.js .toolbar .bar .tab, +.js .toolbar .horizontal .tab { float: left; /* LTR */ } .js .toolbar a { @@ -62,13 +62,13 @@ html.js .toolbar { width: 100%; } @media only screen { - .js .toolbar .bar li, + .js .toolbar .bar .tab, .js .toolbar .tray li { float: none; /* LTR */ } } @media only screen and (min-width: 16.5em) { - .js .toolbar .bar li, + .js .toolbar .bar .tab, .js .toolbar .horizontal li { float: left; /* LTR */ } diff --git a/core/modules/toolbar/css/toolbar.theme.css b/core/modules/toolbar/css/toolbar.theme.css index 08a573c..c1317e5 100644 --- a/core/modules/toolbar/css/toolbar.theme.css +++ b/core/modules/toolbar/css/toolbar.theme.css @@ -31,19 +31,21 @@ box-shadow: 0 0 3px 1px rgba(0, 0, 0, 0.3333); color: #dddddd; } -.toolbar .bar a:hover { +.toolbar .bar a { + color: #ffffff; +} +.toolbar .bar .tab > a { + font-weight: bold; +} +.toolbar .bar .tab > a:hover { background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.125) 20%, transparent 200%); background-image: linear-gradient(rgba(255, 255, 255, 0.125) 20%, transparent 200%); text-decoration: none; } -.toolbar .bar a.active { +.toolbar .bar .tab > a.active { background-image: -webkit-linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%); background-image: linear-gradient(rgba(255, 255, 255, 0.25) 20%, transparent 200%); } -.toolbar .bar a { - color: #ffffff; - font-weight: bold; -} /** * Toolbar tray. diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js index 08a68d2..de62afe 100644 --- a/core/modules/toolbar/js/toolbar.js +++ b/core/modules/toolbar/js/toolbar.js @@ -61,8 +61,11 @@ Drupal.behaviors.toolbar = { // readers. $messages = $(Drupal.theme('toolbarMessageBox')).appendTo($toolbar); // Store the trays in a scoped variable. + $trays = $toolbar.find('.tray'); $trays + // Move the trays outside of the bar. + .insertAfter($toolbar.find('.bar')) // Add the tray orientation toggles. .find('.lining') .append(Drupal.theme('toolbarOrientationToggle')); @@ -78,7 +81,7 @@ Drupal.behaviors.toolbar = { // query application decide the orientation. changeOrientation((locked) ? 'vertical' : ((mql.wide.matches) ? 'horizontal' : 'vertical'), locked); // Render the main menu as a nested, collapsible accordion. - $toolbar.find('.administration.tray .toolbar-menu > .menu').toolbarMenu(); + $toolbar.find('.toolbar-menu-administration > .menu').toolbarMenu(); // Call setHeight on screen resize. Wrap it in debounce to prevent // setHeight from being called too frequently. var setHeight = Drupal.debounce(Drupal.toolbar.setHeight, 200); @@ -150,7 +153,7 @@ Drupal.toolbar.toggleTray = function (event) { localStorage.removeItem('Drupal.toolbar.activeTab'); } // Disable non-selected tabs and trays. - $toolbar.find('.bar a') + $toolbar.find('.bar .trigger') .not($tab) .removeClass('active') // Set aria-pressed to false. diff --git a/core/modules/toolbar/templates/toolbar.twig b/core/modules/toolbar/templates/toolbar.twig deleted file mode 100644 index c2181df..0000000 --- a/core/modules/toolbar/templates/toolbar.twig +++ /dev/null @@ -1,39 +0,0 @@ -{# -/** - * @file - * Default template for admin toolbar. - * - * Available variables: - * - * - tabs: Themed links for the top level tabs. - * - trays: An array of trays. It contains: - * - content: The themed tray content. - * - attributes: HTML attributes for the surrounding element. It includes: - * - id: The unique id of the tray. This corresponds to the module name - * registered the tray. - * - class: A list of classes to target the trays for styling. - * - attributes: HTML attributes for the surrounding element. It includes: - * - id: The unique id of the toolbar. - * - class: A list of classes to target the toolbar for styling. - * - * @see template_preprocess() - * @see template_preprocess_toolbar() - * - * @ingroup themeable - */ -#} - - diff --git a/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module index cadddc9..833002e 100644 --- a/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module +++ b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module @@ -6,34 +6,39 @@ */ /** - * Um + * Implements hook_toolbar(). */ function toolbar_test_toolbar() { - $tray_items = array( - l('link 1', ''), - l('link 2', ''), - l('link 3', ''), - ); - $items['testing'] = array( - 'tab' => array( - 'title' => t('Test tab'), - 'href' => '', + + $items['testing'] = array( + "#type" => 'toolbar_item', + '#text' => t('Test tab'), + '#path' => '', + '#options' => array( 'html' => FALSE, 'attributes' => array( + 'id' => 'toolbar-tab-testing', 'title' => t('Test tab'), ), ), 'tray' => array( - '#heading' => t('Test tray'), + '#wrapper_attributes' => array( + 'id' => 'toolbar-tray-testing', + ), 'content' => array( '#theme' => 'item_list', - '#items' => $tray_items, + '#items' => array( + l(t('link 1'), ''), + l(t('link 2'), ''), + l(t('link 3'), ''), + ), + '#prefix' => '

' . t('Test tray') . '

', '#attributes' => array( 'class' => array('menu'), ), ), ), - 'weight' => 50, + '#weight' => 50, ); return $items; diff --git a/core/modules/toolbar/toolbar.api.php b/core/modules/toolbar/toolbar.api.php index 42ca3fe..4988814 100644 --- a/core/modules/toolbar/toolbar.api.php +++ b/core/modules/toolbar/toolbar.api.php @@ -2,7 +2,7 @@ /** * @file - * Hooks provided by the Toolbar module. + * Hooks provided by the toolbar module. */ /** @@ -11,62 +11,90 @@ */ /** - * Add items to the Toolbar menu. + * Add items to the toolbar menu. * - * The Toolbar has two parts. The tabs are menu links, rendered by - * theme_links(), that are displayed if the module is enabled and the user has - * the 'access toolbar' permission. The trays are render elements, usually lists - * of links, and each tray corresponds to a tab. When a tab is activated, the - * corresponding tray is displayed; only one tab can be activated at a time. If - * a tab does not have a corresponding tray, or if javascript is disabled, then - * the tab is simply a link. + * The toolbar is a container for adminstrative and site-global interactive + * components. * - * This hook is invoked in toolbar_view(). + * The toolbar provides a common styling for items denoted by the .tab class. + * The theme wrapper toolbar_tab_wrapper is provided to wrap a toolbar item + * with the appropriate markup to apply the styling. + * + * The toolbar provides a construct called a 'tray'. The tray is a container + * for content. The tray may be associated with a toggle in the adminstration + * bar. The toggle shows or hides the tray and is optimized for small and + * large screens. To create this association, declare the '#type' of a + * renderable array as 'toolbar_item' and provide renderable content in a 'tray' + * property of that item. + * + * The following properties are available: + * - 'tray': Optional. A renderable array. + * - '#weight': Optional. Integer weight used for sorting toolbar items in + * adminstration bar area. + * + * This hook is invoked in toolbar_pre_render(). * * @return * An array of toolbar items, keyed by unique identifiers such as 'home' or * 'administration', or the short name of the module implementing the hook. - * The corresponding value is an associative array that may contain the - * following key-value pairs: - * - 'tab': Required, unless the item is adding links to an existing tab. An - * array with keys 'title', 'href', 'html', and 'attributes', as used by - * theme_links(). The 'href' value is ignored unless 'tray' (below) is - * omitted, or if javascript is disabled. - * - 'tray': Optional. A render element that is displayed when the tab is - * activated. - * - 'weight': Optional. Integer weight used for sorting tabs. + * The corresponding value is an associative array of renderable content. * - * @see toolbar_view() + * @see toolbar_pre_render() * @ingroup toolbar_tabs */ function hook_toolbar() { $items = array(); - // The 'Home' tab is a simple link, with no corresponding tray. + // Add a search field to the toolbar. The search field employs no toolbar + // module themeing functions. + $items['global_search'] = array( + '#type' => 'search', + '#attributes' => array( + 'placeholder' => t('Search the site'), + 'class' => array('search-global'), + ), + '#weight' => 200, + // Custom CSS, JS or a library can be associated with the toolbar item. + '#attached' => array( + 'css' => array( + drupal_get_path('module', 'search') . '/css/search.base.css', + ), + ), + ); + + /** + * The 'Home' tab is a simple link, that is wrapped in markup associated + * with a visual tab styling. + */ $items['home'] = array( - 'tab' => array( - 'title' => t('Home'), - 'href' => '', + '#type' => 'toolbar_item', + '#text' => t('Home'), + '#path' => '', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('Home page'), + 'class' => array('icon', 'icon-home'), ), ), - 'weight' => -10, + '#weight' => -20, ); /** - * A tab may be associated with a tray. + * A tray may be associated with a tab. + * + * When the tab is activated, the tray will become visible, either in a + * horizontal or vertical orientation on the screen. * * The tray should contain a renderable array. An option #heading property * can be passed. The text is written to a heading tag in the tray as a - * landmark for accessibility. A default heading will be created if one is not - * passed. + * landmark for accessibility. */ $items['commerce'] = array( - 'tab' => array( - 'title' => t('Shopping cart'), - 'href' => '', + "#type" => 'toolbar_item', + '#text' => t('Shopping cart'), + '#path' => '/cart', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('Shopping cart'), @@ -74,19 +102,47 @@ function hook_toolbar() { ), 'tray' => array( '#heading' => t('Shopping cart actions'), - 'content' => array( + 'shopping_cart' => array( '#theme' => 'item_list', '#items' => array( /* An item list renderable array */ ), ), ), - 'weight' => 50, + '#weight' => 150, + ); + + /** + * The #tray can be used to render arbritrary content. + * + * A renderable array passed to the 'tray' property will be rendered outside + * the administration bar but within the containing toolbar element. + * + * If the default behavior and styling of a toolbar tray is not desired, one + * can render content to the toolbar element and apply custom themeing and + * behaviors. + */ + $items['user_messages'] = array( + // Include the toolbar_tab_wrapper to style the link like a toolbar tab. + // Exclude the theme wrapper if custom styling is desired. + "#type" => 'toolbar_item', + '#theme' => 'user_message_toolbar_tab', + '#theme_wrappers' => array(), + '#text' => t('Messages'), + '#path' => '/user/messages', + '#options' => array( + 'html' => FALSE, + 'attributes' => array( + 'title' => t('Messages'), + ), + ), + 'tray' => array(/* renderable content */), + '#weight' => 125, ); return $items; } /** - * Alter the Toolbar menu after hook_toolbar() is invoked. + * Alter the toolbar menu after hook_toolbar() is invoked. * * This hook is invoked by toolbar_view() immediately after hook_toolbar(). The * toolbar definitions are passed in by reference. Each element of the $items @@ -94,11 +150,11 @@ function hook_toolbar() { * may be added, or existing items altered. * * @param $items - * Associative array of Toolbar menu definitions returned from hook_toolbar(). + * Associative array of toolbar menu definitions returned from hook_toolbar(). */ function hook_toolbar_alter(&$items) { // Move the User tab to the right. - $items['commerce']['weight'] = 5; + $items['commerce']['#weight'] = 5; } /** diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index e543326..4e16671 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -41,13 +41,79 @@ function toolbar_permission() { */ function toolbar_theme($existing, $type, $theme, $path) { $items['toolbar'] = array( - 'render element' => 'toolbar', - 'template' => 'toolbar', + 'render element' => 'element', + ); + $items['toolbar_tab'] = array( + 'render element' => 'element', + ); + $items['toolbar_tab_wrapper'] = array( + 'render element' => 'element', + ); + $items['toolbar_tray_wrapper'] = array( + 'render element' => 'element', ); return $items; } /** + * Implements hook_element_info(). + */ +function toolbar_element_info() { + $elements = array(); + + $elements['toolbar'] = array( + // Do not build the toolbar if the user does not have access. + '#access' => user_access('access toolbar'), + '#pre_render' => array('toolbar_pre_render'), + '#theme' => 'toolbar', + '#attached' => array( + 'library' => array( + array('toolbar', 'toolbar'), + ), + ), + // Metadata for the toolbar wrapping element. + '#attributes' => array( + // The id cannot be simply "toolbar" or it will clash with the simpletest + // tests listing which produces a checkbox with attribute id="toolbar" + 'id' => 'toolbar-administration', + // The 'overlay-displace-top' class pushes the overlay down, so it appears + // below the toolbar. + 'class' => array('toolbar', 'overlay-displace-top'), + 'role' => 'navigation', + ), + // Metadata for the administration bar. + '#bar' => array( + '#attributes' => array( + 'id' => 'toolbar-bar', + 'class' => array('bar', 'overlay-displace-top', 'clearfix'), + ), + ), + ); + + // A toolbar item is wrapped in markup for common styling. The 'tray' + // property contains a renderable array. theme_toolbar_tab() is a light + // wrapper around the l() function. The contents of tray are rendered in + // theme_toolbar_tab(). + $elements['toolbar_item'] = array( + '#pre_render' => array('toolbar_pre_render_item'), + // A light wrapper for the l() function. + '#theme' => 'toolbar_tab', + '#theme_wrappers' => array('toolbar_tab_wrapper'), + '#text' => NULL, + '#path' => '', + // Standardize element attributes on the #attributes property. + '#attributes' => array(), + // l() takes an #options parameter. + '#options' => array( + 'html' => FALSE, + 'attributes' => array(), + ), + 'tray' => array(), + ); + return $elements; +} + +/** * Implements hook_menu(). */ function toolbar_menu() { @@ -130,60 +196,199 @@ function _toolbar_initialize_page_cache() { */ function toolbar_page_build(&$page) { $page['page_top']['toolbar'] = array( - '#pre_render' => array('toolbar_pre_render'), - '#access' => user_access('access toolbar'), + '#type' => 'toolbar', ); } /** - * Provides pre_render function for the toolbar. + * Builds the Toolbar as a structured array ready for drupal_render(). * * Since building the toolbar takes some time, it is done just prior to * rendering to ensure that it is built only if it will be displayed. * + * @param array $element + * A renderable array. + * + * @return + * A renderable array. + * * @see toolbar_page_build(). */ -function toolbar_pre_render($toolbar) { - $toolbar = array_merge($toolbar, toolbar_view()); - return $toolbar; +function toolbar_pre_render($element) { + + // Get the configured breakpoints to switch from vertical to horizontal + // toolbar presentation. + $breakpoints = entity_load('breakpoint_group', 'module.toolbar.toolbar'); + if (!empty($breakpoints)) { + $media_queries = array(); + $media_queries['toolbar']['breakpoints'] = array_map( + function ($object) { + return $object->mediaQuery; + }, + $breakpoints->breakpoints + ); + + $element['#attached']['js'][] = array( + 'data' => $media_queries, + 'type' => 'setting', + ); + } + + // Get toolbar items from all modules that implement hook_toolbar(). + $items = module_invoke_all('toolbar'); + // Allow for altering of hook_toolbar(). + drupal_alter('toolbar', $items); + // Sort the children. + uasort($items, 'element_sort'); + + // Merge in the original toolbar values. + $element = array_merge($element, $items); + + // Render the children. + $element['#children'] = drupal_render_children($element); + + return $element; } /** - * Implements template_preprocess_HOOK(). + * Returns HTML that wraps the administration toolbar. + * + * @param array $variables + * An associative array containing: + * - element: An associative array containing the properties and children of + * the tray. Properties used: #children, #attributes and #bar. */ -function template_preprocess_toolbar(&$variables) { - // Metadata for the toolbar wrapping element. - $variables['attributes'] = new Attribute(array( - // The id cannot be simply "toolbar" or it will clash with the simpletest - // tests listing which produces a checkbox with attribute id="toolbar" - 'id' => 'toolbar-administration', - // The 'overlay-displace-top' class pushes the overlay down, so it appears - // below the toolbar. - 'class' => array('toolbar', 'overlay-displace-top'), - 'role' => 'navigation' - )); - - // Provide a convenience variable for the themed tabs. - $variables['toolbar']['tabs']['#attributes']['class'][] = 'overlay-displace-top'; - $variables['tabs'] = $variables['toolbar']['tabs']; - - // Place the tabs in a top-level variable so that attribute information - // can be associated with each one. - foreach ($variables['toolbar']['trays'] as $key => $tray) { - // Create tray heading text. Prefer the provided heading text if it exists. - $heading = isset($tray['#heading']) ? $tray['#heading'] : t('@group actions', array('@group' => $key)); - - $variables['trays'][$key] = array( - 'heading' => $heading, - 'content' => $variables['toolbar']['trays'][$key], - 'attributes' => new Attribute(array( - 'id' => 'toolbar-tray-' . $key, - 'class' => array('tray', 'overlay-displace-top', $key), - 'data-toolbar-tray' => $key, - 'aria-owned-by' => 'toolbar-tab-' . $key, - ) - ), +function theme_toolbar(&$variables) { + if (!empty($variables['element']['#children'])) { + $element = $variables['element']; + return '' . '' . $element['#children'] . ''; + } +} + +/** + * Provides markup for associating a tray trigger with a tray element. + * + * A tray is a responsive container that wraps renderable content. Trays present + * content well on small and large screens alike. + * + * @param array $element + * A renderable array. + * + * @return + * A renderable array. + */ +function toolbar_pre_render_item($element) { + + // Attributes are nested in the #options property passed to l(). + // To make the return structure of toolbar_pre_render_item() uniform, + // attributes will always be returned in the #attributes property. These + // properties will be included in the #options parameter passed to l() in + // theme_toolbar_tab(). + $element['#attributes'] = $element['#options']['attributes']; + + // If tray content is present, markup the tray and its associated trigger. + if (!empty($element['tray'])) { + + // Trays are associated with their trigger by a unique ID. + $id = drupal_html_id('toolbar-tray'); + $element['#tray_id'] = $id; + + // Provide attributes for a tray trigger. + $attributes = array( + 'id' => 'toolbar-tab-' . $id, + 'data-toolbar-tray' => $id, + 'aria-owns' => $id, + 'role' => 'button', + 'aria-pressed' => 'false', ); + // Merge in module-provided attributes. + $element['#attributes'] = array_merge($attributes, $element['#attributes']); + $element['#attributes']['class'][] = 'trigger'; + + // Provide attributes for the tray theme wrapper. + $attributes = array( + 'id' => $id, + 'class' => array('tray', 'overlay-displace-top',), + 'data-toolbar-tray' => $id, + 'aria-owned-by' => 'toolbar-tab-' . $id, + ); + // Merge in module-provided attributes. + if (!isset($element['tray']['#wrapper_attributes'])) { + $element['tray']['#wrapper_attributes'] = array(); + } + $element['tray']['#wrapper_attributes'] = array_merge($attributes, $element['tray']['#wrapper_attributes']); + + if (!isset($element['tray']['#theme_wrappers'])) { + $element['tray']['#theme_wrappers'] = array(); + } + + array_unshift($element['tray']['#theme_wrappers'], 'toolbar_tray_wrapper'); + } + + return $element; +} + +/** + * Implements template_preprocess_HOOK(). + */ +function template_preprocess_toolbar_tab_wrapper(&$variables) { + if (!isset($variables['element']['#wrapper_attributes'])) { + $variables['element']['#wrapper_attributes'] = array(); + } + $variables['element']['#wrapper_attributes']['class'][] = 'tab'; +} + +/** + * Returns HTML for wrapping a toolbar tab. + * + * Toolbar tabs have a common styling and placement with the toolbar's bar area. + * + * @param array $variables + * An associative array containing: + * - element: An associative array containing the properties and children of + * the tray. Properties used: #children and #attributes. + */ +function theme_toolbar_tab_wrapper(&$variables) { + if (!empty($variables['element']['#children'])) { + $element = $variables['element']; + return '' . $element['#children'] . ''; + } +} + +/** + * Returns HTML for toolbar tab that opens and closes a tray. + * + * Use in combination with theme_toolbar_tray_wrapper to create an + * association between a link tag in the administration bar and a tray. + * + * @param $variables + * An associative array containing the keys 'text', 'path', and 'options'. See + * the l() function for information about these variables. + * + * @see l() + */ +function theme_toolbar_tab($variables) { + $element = $variables['element']; + $element['#options']['attributes'] = $element['#attributes']; + return l($element['#text'], $element['#path'], $element['#options']) . drupal_render_children($element); +} + +/** + * Returns HTML for wrapping a toolbar tray. + * + * Used in combination with theme_toolbar_tab() to create an + * association between a link tag in the administration bar and a tray. + * + * @param array $variables + * An associative array containing: + * - element: An associative array containing the properties and children of + * the tray. Properties used: #children, #toolbar_identifier and + * #attributes. + */ +function theme_toolbar_tray_wrapper(&$variables) { + if (!empty($variables['element']['#children'])) { + $element = $variables['element']; + return '
' . $element['#children'] . '
'; } } @@ -211,16 +416,17 @@ function toolbar_toolbar() { // The 'Home' tab is a simple link, with no corresponding tray. $items['home'] = array( - 'tab' => array( - 'title' => t('Home'), - 'href' => '', + '#type' => 'toolbar_item', + '#text' => t('Home'), + '#path' => '', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('Home page'), 'class' => array('icon', 'icon-home'), ), ), - 'weight' => -20, + '#weight' => -20, ); // Retrieve the administration menu from the database. @@ -232,12 +438,12 @@ function toolbar_toolbar() { $menu = array( 'toolbar_administration' => array( '#type' => 'container', + '#prefix' => '

' . t('Administration menu') . '

', '#attributes' => array( - 'class' => array('toolbar-menu',), + 'class' => array('toolbar-menu', 'toolbar-menu-administration'), ), 'administration_menu' => menu_tree_output($tree), ), - '#heading' => t('Administration menu'), ); // To conserve bandwidth, we only include the top-level links in the HTML. @@ -247,10 +453,13 @@ function toolbar_toolbar() { // @see toolbar_subtrees_jsonp() $menu['toolbar_administration']['#attached']['js'][url('toolbar/subtrees/' . _toolbar_get_subtree_hash())] = array('type' => 'external'); + // The administration element has a link that is themed to correspond to + // a toolbar tray. The tray contains the full administrative menu of the site. $items['administration'] = array( - 'tab' => array( - 'title' => t('Menu'), - 'href' => 'admin', + '#type' => 'toolbar_item', + '#text' => t('Menu'), + '#path' => 'admin', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('Admin menu'), @@ -258,99 +467,13 @@ function toolbar_toolbar() { ), ), 'tray' => $menu, - 'weight' => -15, + '#weight' => -15, ); return $items; } /** - * Builds the Toolbar as a structured array ready for drupal_render(). - * - * @return - * A renderable arrray, with two children: - * - 'tabs': an array of links, rendered by theme('links'). - * - 'trays': an array of render elements displayed when the corresponding tab - * is activated. - */ -function toolbar_view() { - - $build = array('#theme' => 'toolbar'); - $build['#attached']['library'][] = array('toolbar', 'toolbar'); - - // Get the configured breakpoint to switch from vertical to horizontal - // toolbar presentation. - $breakpoints = entity_load('breakpoint_group', 'module.toolbar.toolbar'); - if (!empty($breakpoints)) { - $media_queries = array(); - $media_queries['toolbar']['breakpoints'] = array_map( - function($object) {return $object->mediaQuery;}, - $breakpoints->breakpoints); - - $build['#attached']['js'][] = array( - 'data' => $media_queries, - 'type' => 'setting', - ); - // // Load the breakpoints for toolbar. - foreach ($breakpoints->breakpoints as $key => $breakpoint) { - $build['#attached']['js'][0]['data']['toolbar']['breakpoints'][$key] = $breakpoint->mediaQuery; - } - } - - // Get toolbar items from all modules that implement hook_toolbar() or - // hook_toolbar_alter(). - $toolbar_groups = module_invoke_all('toolbar'); - drupal_alter('toolbar', $toolbar_groups); - uasort($toolbar_groups, 'drupal_sort_weight'); - - // Build the tabs and trays from the toolbar groups. - $build['trays'] = array(); - $build['tabs'] = array( - '#theme' => 'links', - '#links' => array(), - '#attributes' => array( - 'class' => array('bar', 'clearfix'), - ), - '#heading' => array('text' => t('Toolbar'), 'level' => 'h2', 'class' => 'element-invisible'), - ); - $tab_defaults = array( - 'title' => '', - 'href' => '', - 'html' => FALSE, - 'attributes' => new Attribute(), - ); - - foreach ($toolbar_groups as $group => $items) { - if ($tab = $items['tab']) { - // Merge in the defaults. - $tab += $tab_defaults; - } - // Register a tray if one is associated with this tab. - if (!empty($items['tray'])) { - // Provide an id, a data attribute linking each tab to the corresponding - // tray and aria information. - $tab['attributes']['id'] = 'toolbar-tab-' . $group; - $tab['attributes']['data-toolbar-tray'] = $group; - $tab['attributes']['aria-owns'] = 'toolbar-tray-' . $group; - $tab['attributes']['role'] = 'button'; - $tab['attributes']['aria-pressed'] = 'false'; - - if (array_key_exists($group, $build['trays'])) { - array_merge($build['trays'][$group], $items['tray']); - } - else { - // Assign the tray to the build. - $build['trays'][$group] = $items['tray']; - } - } - // Assign the tabs to the build. - $build['tabs']['#links'][$group] = $tab; - } - - return $build; -} - -/** * Gets only the top level items below the 'admin' path. * * @return diff --git a/core/modules/user/user.module b/core/modules/user/user.module index ac8f7e8..e1a7b9d 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -2931,29 +2931,28 @@ function user_toolbar() { ); } - $user_tray = array( - '#heading' => t('User account actions'), - 'content' => array( - '#theme' => 'links__toolbar_user', - '#links' => $links, - '#attributes' => array( - 'class' => array('menu',), - ), - ), - ); - $items['user'] = array( - 'tab' => array( - 'title' => user_format_name($user), - 'href' => 'user', + '#type' => 'toolbar_item', + '#text' => user_format_name($user), + '#path' => 'user', + '#options' => array( 'html' => FALSE, 'attributes' => array( 'title' => t('My account'), 'class' => array('icon', 'icon-user'), ), ), - 'tray' => $user_tray, - 'weight' => 100, + 'tray' => array( + '#heading' => t('User account actions'), + 'user_links' => array( + '#theme' => 'links__toolbar_user', + '#links' => $links, + '#attributes' => array( + 'class' => array('menu',), + ), + ), + ), + '#weight' => 100, ); return $items; -- 1.7.10.4