diff --git a/core/misc/debounce.js b/core/misc/debounce.js new file mode 100644 index 0000000000000000000000000000000000000000..338a50dbc4e931a676791436a97096b24e22b2be --- /dev/null +++ b/core/misc/debounce.js @@ -0,0 +1,36 @@ +/** + * Limits the invocations of a function in a given time frame. + * + * The debounce function wrapper should be used sparingly. One clear use case + * is limiting the invocation of a callback attached to the window resize event. + * + * Before using the debounce function wrapper, consider first whether the + * callback could be attache to an event that fires less frequently or if the + * function can be written in such a way that it is only invoked under specific + * conditions. + * + * @param {Function} callback + * The function to be invoked. + * + * @param {Number} wait + * The time period within which the callback function should only be + * invoked once. For example if the wait period is 250ms, then the callback + * will only be called at most 4 times per second. + */ +Drupal.debounce = function (callback, wait) { + + "use strict"; + + var timeout, result; + return function () { + var context = this; + var args = arguments; + var later = function () { + timeout = null; + result = callback.apply(context, args); + }; + window.clearTimeout(timeout); + timeout = window.setTimeout(later, wait); + return result; + }; +}; diff --git a/core/modules/overlay/overlay-parent.js b/core/modules/overlay/overlay-parent.js index 1f38f2f8dc54808ddda5036cf9f8eff1b9fca491..caf9336db3e7ace393783daaeba550ed8f35755a 100644 --- a/core/modules/overlay/overlay-parent.js +++ b/core/modules/overlay/overlay-parent.js @@ -881,9 +881,9 @@ Drupal.overlay.getPath = function (link) { */ Drupal.overlay.getDisplacement = function (region) { var displacement = 0; - var lastDisplaced = $('.overlay-displace-' + region + ':last'); + var lastDisplaced = $('[data-offset-' + region + ']'); if (lastDisplaced.length) { - displacement = lastDisplaced.offset().top + lastDisplaced.outerHeight(); + displacement = parseInt(lastDisplaced.attr('data-offset-' + region)); } return displacement; }; diff --git a/core/modules/shortcut/images/shortcut-active.png b/core/modules/shortcut/images/shortcut-active.png new file mode 100644 index 0000000000000000000000000000000000000000..214bd30636b1114885ddc1322090479bfbcc799b --- /dev/null +++ b/core/modules/shortcut/images/shortcut-active.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������Ä´l;���tEXtSoftware�Adobe ImageReadyqÉe<���ŸIDATxÚbd@ÿÿÿw�R䃌ŒŒ@4 ¡õ”Lƒ.f 5»Áÿþý ŠÑÈ ã•*6�q�13¡»¾�”6 ÒŽ@þ\jI1¸QTTd(Èp }�(f'×`Šbbb èÞŠ}�‰C-¸@¬Á€¸P\\܈àG ü ^Õ—0�M×Èý}\¸Y����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/shortcut/images/shortcut.png b/core/modules/shortcut/images/shortcut.png new file mode 100644 index 0000000000000000000000000000000000000000..739a8d0e049227bdc8f1e9dcb726131c1047aa70 --- /dev/null +++ b/core/modules/shortcut/images/shortcut.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������Ä´l;���tEXtSoftware�Adobe ImageReadyqÉe<���²IDATxÚbd@gÎœq�Räƒ&&&@4 ¡õ”LƒÿýûÇ@-@ƒÿþý;Ä\<Æ£A1#-(6�q�13¡»¾ðÿÿÃÈÈÈ@ íä?À¥–ƒ£££ £¢¢.€Ô�é@1C8у‚†Š@(ÆÆÆ6 {(ö$²�¨ö²>|‘÷‘‘±1!!a¡pŒùÂpþüùÀ B©+�´éÊ"Ôòµ����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/shortcut/shortcut.base-rtl.css b/core/modules/shortcut/shortcut.base-rtl.css index c236f47ea511e02734cf69ef1d962b9457ff1024..ed903a7d37b85e53d27b6a59e7a6ea48a09eac73 100644 --- a/core/modules/shortcut/shortcut.base-rtl.css +++ b/core/modules/shortcut/shortcut.base-rtl.css @@ -4,21 +4,6 @@ * Generic RTL base styles for shortcut module. */ -/** - * Toolbar. - */ -#edit-shortcuts { - left: 0; - position: absolute; - top: 0; -} -#shortcut-toolbar ul { - float: none; -} -#shortcut-toolbar .icon { - float: right; -} - /** * Add/remove links. */ diff --git a/core/modules/shortcut/shortcut.base.css b/core/modules/shortcut/shortcut.base.css index 90a1046f38df3de1a61f26b80d515bcbaad1b03d..aca7807461be3399251baf8d3c8d380e88ce90f7 100644 --- a/core/modules/shortcut/shortcut.base.css +++ b/core/modules/shortcut/shortcut.base.css @@ -1,22 +1,8 @@ - /** * @file * Generic base styles for shortcut module. */ -/** - * Toolbar. - */ -#edit-shortcuts { - float: right; /* LTR */ -} -#shortcut-toolbar ul { - float: left; /* LTR */ -} -#shortcut-toolbar .icon { - float: left; /* LTR */ -} - /** * Add/remove links. */ diff --git a/core/modules/shortcut/shortcut.module b/core/modules/shortcut/shortcut.module index 2a079898faf08372c4f6ce35efa8547c745d0771..8677c722fa685571e2dfccdc25c935e9f3da42b6 100644 --- a/core/modules/shortcut/shortcut.module +++ b/core/modules/shortcut/shortcut.module @@ -713,20 +713,9 @@ function shortcut_preprocess_page(&$variables) { } /** - * Implements hook_page_alter(). + * Implements hook_toolbar(). */ -function shortcut_page_alter(&$page) { - if (isset($page['page_top']['toolbar'])) { - // If the toolbar is available, add a pre-render function to display the - // current shortcuts in the toolbar drawer. - $page['page_top']['toolbar']['#pre_render'][] = 'shortcut_toolbar_pre_render'; - } -} - -/** - * Pre-render function for adding shortcuts to the toolbar drawer. - */ -function shortcut_toolbar_pre_render($toolbar) { +function shortcut_toolbar() { $links = shortcut_renderable_links(); $links['#attached'] = array( 'css' => array( @@ -734,8 +723,6 @@ function shortcut_toolbar_pre_render($toolbar) { drupal_get_path('module', 'shortcut') . '/shortcut.theme.css', ), ); - $links['#prefix'] = '<div id="shortcut-toolbar">'; - $links['#suffix'] = '</div>'; $shortcut_set = shortcut_current_displayed_set(); $configure_link = NULL; if (shortcut_set_edit_access($shortcut_set)) { @@ -743,17 +730,30 @@ function shortcut_toolbar_pre_render($toolbar) { '#type' => 'link', '#title' => t('Edit shortcuts'), '#href' => 'admin/config/user-interface/shortcut/' . $shortcut_set->set_name, - '#options' => array('attributes' => array('id' => 'edit-shortcuts')), + '#options' => array('attributes' => array('class' => array('edit-shortcuts'))), ); } - $drawer = array( + $links_tray = array( + '#heading' => t('User-defined shortcuts'), 'shortcuts' => $links, 'configure' => $configure_link, ); - $toolbar['toolbar_drawer'][] = $drawer; - return $toolbar; + $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'), + ), + ), + 'tray' => $links_tray, + 'weight' => -10, + ); + return $items; } /** diff --git a/core/modules/shortcut/shortcut.theme-rtl.css b/core/modules/shortcut/shortcut.theme-rtl.css index 424f38fb092862b910f5c3735ae4b1535a5686c6..8a687d9e83d36074955ff392c2b29c44691e618e 100644 --- a/core/modules/shortcut/shortcut.theme-rtl.css +++ b/core/modules/shortcut/shortcut.theme-rtl.css @@ -4,22 +4,6 @@ * RTL styling for the shortcut module. */ -/** - * Toolbar. - */ -#shortcut-toolbar ul { - margin-left: 0; - margin-right: 5px; -} -#shortcut-toolbar a { - margin-left: 5px; - margin-right: 0; -} -#shortcut-toolbar .icon { - margin-left: 5px; - margin-right: 0; -} - /** * Add/remove links. */ @@ -42,3 +26,16 @@ .add-or-remove-shortcuts a:hover .text { border-radius: 5px 0 0 5px; } + +/** + * Toolbar. + */ +.toolbar-js .horizontal #edit-shortcuts { + border-left: 0 none; + border-right: 1px solid #d9d9d9; + float: right; + margin-left: 0; + margin-right: 0.3333em; + padding-left: 0.3333em; + padding-right: 0.6667em; +} diff --git a/core/modules/shortcut/shortcut.theme.css b/core/modules/shortcut/shortcut.theme.css index 9e2dc69007730e035202d735e99d82c1d8da3ed8..727289bf3869b83be7b64bb036adb46e3bfd1985 100644 --- a/core/modules/shortcut/shortcut.theme.css +++ b/core/modules/shortcut/shortcut.theme.css @@ -1,4 +1,3 @@ - /** * @file * Styling for the shortcut module. @@ -7,40 +6,25 @@ /** * Toolbar. */ -.toolbar #edit-shortcuts { - line-height: 24px; - padding: 5px 10px; -} -#edit-shortcuts:focus, -#edit-shortcuts:hover, -#edit-shortcuts.active { - text-decoration: underline; +.icon-shortcut:before { + background-image: url("images/shortcut.png"); } -#shortcut-toolbar ul { - line-height: 24px; - margin-left: 5px; /* LTR */ - padding: 5px 0; +.icon-shortcut:active:before, +.icon-shortcut.active:before { + background-image: url("images/shortcut-active.png"); } -#shortcut-toolbar a { - border-radius: 5px; - margin-right: 5px; /* LTR */ - padding: 0 5px; +.toolbar .tray.horizontal.shortcuts .menu { + float: left; } -#shortcut-toolbar a:focus, -#shortcut-toolbar a:hover, -#shortcut-toolbar a.active:focus { - background: #555; +.edit-shortcuts { + display: block; } -#shortcut-toolbar a.active:hover, -#shortcut-toolbar a.active { - background-color: #000; +.toolbar .vertical .edit-shortcuts { + text-align: right; + padding: 1em; } -#shortcut-toolbar .icon { - background-color: #444; - border-radius: 5px; - height: 30px; - margin-right: 5px; /* LTR */ - width: 30px; +.toolbar .horizontal .edit-shortcuts { + float: left; /* LTR */ } /** @@ -65,15 +49,3 @@ .remove-shortcut a:hover .icon { background-position: -12px -12px; /* LTR */ } -.add-or-remove-shortcuts .text { - padding: 0 6px 0 10px; /* LTR */ -} -.add-or-remove-shortcuts a:focus .text, -.add-or-remove-shortcuts a:hover .text { - background-color: #5f605b; - border-radius: 0 5px 5px 0; /* LTR */ - color: #fff; - cursor: pointer; - font-size: 10px; - line-height: 12px; -} diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 5258008f5b6c82070c1378d3947d567e10bd376f..a54e011d655276a0365e557ab64ec35cd6a5ea6c 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -1246,6 +1246,19 @@ function system_library_info() { ), ); + // A utility function to limit calls to a function with a given time. + $libraries['drupal.debounce'] = array( + 'title' => 'Drupal debounce', + 'version' => VERSION, + 'js' => array( + 'core/misc/debounce.js' => array('group' => JS_LIBRARY), + ), + 'dependencies' => array( + // @todo remove drupal dependency. + array('system', 'drupal'), + ), + ); + // jQuery. $libraries['jquery'] = array( 'title' => 'jQuery', @@ -1861,7 +1874,6 @@ function system_library_info() { array('system', 'jquery'), ), ); - $libraries['drupal.tableselect'] = array( 'title' => 'Tableselect', 'version' => VERSION, diff --git a/core/modules/toolbar/config/toolbar.breakpoints.yml b/core/modules/toolbar/config/toolbar.breakpoints.yml new file mode 100644 index 0000000000000000000000000000000000000000..c623c0e8fc3581c5f21773b3646e0731e4f95908 --- /dev/null +++ b/core/modules/toolbar/config/toolbar.breakpoints.yml @@ -0,0 +1,3 @@ +narrow: 'only screen and (min-width: 16.5em)' +standard: 'only screen and (min-width: 38.125em)' +wide: 'only screen and (min-width: 50em)' diff --git a/core/modules/toolbar/config/toolbar.config.yml b/core/modules/toolbar/config/toolbar.config.yml new file mode 100644 index 0000000000000000000000000000000000000000..8a987156896160725a5739c6e043e1dc64aa6903 --- /dev/null +++ b/core/modules/toolbar/config/toolbar.config.yml @@ -0,0 +1,3 @@ +breakpoints: + - 'module.toolbar.narrow' + - 'module.toolbar.wide' diff --git a/core/modules/toolbar/css/toolbar.base-rtl.css b/core/modules/toolbar/css/toolbar.base-rtl.css new file mode 100644 index 0000000000000000000000000000000000000000..602d122622c212d6b2abe376f1ae56a1fe8a5368 --- /dev/null +++ b/core/modules/toolbar/css/toolbar.base-rtl.css @@ -0,0 +1,78 @@ +/** + * @file toolbar.base-rtl.css + */ +html.js .toolbar { + left: auto; + right: 0; +} +.js .toolbar .bar li { + float: right; +} + +/** + * Administration menu. + */ +.js .toolbar .bar { + left: auto; + right: 0; +} +@media only screen { + .js .toolbar .bar li, + .js .toolbar .tray li { + float: none; + } +} +@media only screen and (min-width: 16.5em) { + .js .toolbar .bar li, + .js .toolbar .horizontal li { + float: right; + } +} + +/** + * Toolbar tray. + */ +.toolbar .vertical { + left: auto; + right: -100%; +} +.toolbar .horizontal { + left: auto; + right: 0; +} +.toolbar .vertical > .lining { + left: auto; + right: -100%; +} +.toolbar .vertical.active, +.toolbar .vertical.active > .lining { + left: auto; + right: 0; +} +@media only screen and (min-width: 16.5em) { + .toolbar .vertical.active > .lining:before { + left: auto; + right: -1px; + } +} + +/** + * At larger screen sizes, the tray pushes the page content. + */ +@media only screen and (min-width: 38.125em) { + body.toolbar-tray-open.toolbar-vertical { + margin-left: 0; + margin-right: 240px; + margin-right: 15rem; + } +} +/** + * ToolBar tray orientation toggle. + */ +.toolbar .horizontal .toggle-orientation { + left: 0; + right: auto; +} +.toolbar .vertical .toggle-orientation { + float: left; +} diff --git a/core/modules/toolbar/css/toolbar.base.css b/core/modules/toolbar/css/toolbar.base.css new file mode 100644 index 0000000000000000000000000000000000000000..cbdf15310da96f3b45f22f69e5b779083096d15b --- /dev/null +++ b/core/modules/toolbar/css/toolbar.base.css @@ -0,0 +1,213 @@ +/** + * @file toolbar.base.css + * + * + * Aggressive resets so we can achieve a consistent look in hostile CSS + * environments. + */ +html.js #toolbar-administration, +html .toolbar * { + -moz-box-sizing: border-box; + -o-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + margin: 0; + padding: 0; + vertical-align: baseline; +} +html.js #toolbar-administration { + font-size: small; + line-height: 1; +} +html.js .toolbar { + left: 0; /* LTR */ + position: absolute; + top: 0; + width: 100%; +} +/** + * Very specific overrides for Drupal system CSS. + */ +.toolbar li, +.toolbar .menu li, +.toolbar .item-list, +.toolbar .item-list li, +.toolbar .menu li.expanded { + list-style-type: none; + list-style-image: none; +} +.toolbar .menu li { + padding-top: 0; +} +.js .toolbar .bar li, +.js .toolbar .menu li { + display: block; +} +.js .toolbar .bar li, +.js .toolbar .horizontal li { + float: left; /* LTR */ +} +.js .toolbar a { + display: block; + line-height: 1; +} +/** + * Administration menu. + */ +.js .toolbar .bar { + left: 0; /* LTR */ + position: absolute; + top: 0; + z-index: 1250; + width: 100%; +} +@media only screen { + .js .toolbar .bar li, + .js .toolbar .tray li { + float: none; /* LTR */ + } +} +@media only screen and (min-width: 16.5em) { + .js .toolbar .bar li, + .js .toolbar .horizontal li { + float: left; /* LTR */ + } +} +@media only screen and (min-width: 28.125em) { + .js .toolbar .bar { + position: fixed; + } +} + +/** + * Toolbar tray. + */ +.js .toolbar .tray { + display: none; + position: absolute; +} +.toolbar .tray { + z-index: 250; +} +.toolbar .horizontal { + width: 100%; +} +.toolbar .vertical, +.toolbar .vertical > .lining:before { + bottom: 0; + width: 240px; + width: 15rem; +} +.toolbar .vertical { + left: -100%; /* LTR */ + position: absolute; +} +.toolbar .horizontal { + left: 0; /* LTR */ + height: 0; + /* Set one higher than the contextual links gear. */ + z-index: 1000; +} +.toolar .tray .lining { + position: relative; +} +.toolbar .vertical > .lining, +.toolbar .vertical > .lining:before { + left: -100%; /* LTR */ + min-height: 100%; + position: absolute; + width: 100%; +} +.toolbar .vertical > .lining:before { + bottom: 0; + -moz-box-sizing: content-box; + -o-box-sizing: content-box; + -webkit-box-sizing: content-box; + box-sizing: content-box; + content: ''; + display: none; + height: 100%; + /* Support for devices that do not support position fixed. */ + position: absolute; + position: fixed; + top: 0; + z-index: -1; +} +.toolbar .tray.active { + display: block; +} +.toolbar .horizontal.active { + height: auto; +} +.toolbar .vertical.active, +.toolbar .vertical.active > .lining { + left: 0; /* LTR */ +} +.toolbar .horizontal .menu li ul { + display: none; +} +@media only screen { + .toolbar .vertical, + .toolbar .vertical > .lining:before { + bottom: auto; + width: 100%; + } +} + +@media only screen and (min-width: 16.5em) { + .toolbar .vertical { + bottom: 0; + } + .toolbar .vertical, + .toolbar .vertical > .lining:before { + width: 240px; + width: 15rem; + } + .toolbar .vertical.active > .lining:before { + display: block; + left: -1px; /* LTR */ + } +} +@media only screen and (min-width: 28.125em) { + .toolbar .tray.horizontal { + position: fixed; + } +} +/** + * At larger screen sizes, the tray pushes the page content. + */ +@media only screen and (min-width: 38.125em) { + body.toolbar-tray-open.toolbar-vertical { + margin-left: 240px; /* LTR */ + margin-left: 15rem; /* LTR */ + } +} +/** + * ToolBar tray orientation toggle. + * + * Hide the orientation toggle from browsers that do not interpret + * media queries. They get a standard horizontal toolbar. + */ +.toolbar .horizontal .toggle-orientation { + display: none; +} +@media only screen { + .toolbar .tray .toggle-orientation { + display: none; + } +} +@media only screen and (min-width: 16.5em) { + .toolbar .tray .toggle-orientation { + display: block; + } +} +.toolbar .horizontal .toggle-orientation { + bottom: 0; + position: absolute; + right: 0; /* LTR */ + top: 0; +} +.toolbar .vertical .toggle-orientation { + float: right; /* LTR */ + width: 100%; +} diff --git a/core/modules/toolbar/css/toolbar.icons-rtl.css b/core/modules/toolbar/css/toolbar.icons-rtl.css new file mode 100644 index 0000000000000000000000000000000000000000..aadd3337c704d21d1e998cbd22f7c1db10445151 --- /dev/null +++ b/core/modules/toolbar/css/toolbar.icons-rtl.css @@ -0,0 +1,43 @@ +/** + * @file toolbar.icons-rtl.css + */ +.toolbar .icon { + padding-left: 1.3333em; + padding-right: 2.75em; +} +.toolbar .icon:before { + left: auto; + right: 0.6667em; +} +.toolbar .menu ul .icon { + padding-left: 0; + padding-right: 1.3333em; +} +.toolbar .vertical .menu ul { + margin-left: 0; + margin-right: 1.5em; +} +.toolbar .vertical .menu ul ul { + margin-left: 0; + margin-right: 0.75em; +} + +@media only screen and (min-width: 16.5em) { + .toolbar .bar .icon:before { + background-size: auto auto; + left: auto; + right: 0; + } +} + +@media only screen and (min-width: 36em) { + .toolbar .bar .icon { + background-position: right center; + padding-left: 1.3333em; + padding-right: 2.75em; + } + .toolbar .bar .icon:before { + left: 0; + right: 0.6667em; + } +} diff --git a/core/modules/toolbar/css/toolbar.icons.css b/core/modules/toolbar/css/toolbar.icons.css new file mode 100644 index 0000000000000000000000000000000000000000..7fc06bfb181cff2127cb92eb52ab718b0d7c6ee6 --- /dev/null +++ b/core/modules/toolbar/css/toolbar.icons.css @@ -0,0 +1,144 @@ +/** + * @file toolbar.icons.css + */ +.toolbar .icon { + padding-left: 2.75em; /* LTR */ + position: relative; +} +.toolbar .icon:before { + background-attachment: scroll; + background-color: transparent; + background-position: center center; + background-repeat: no-repeat; + content: ''; + display: block; + height: 100%; + left: 0.6667em; /* LTR */ + position: absolute; + top: 0; + width: 20px; +} +.toolbar button.icon { + background-color: transparent; + border: 0; + font-size: 1em; +} +.toolbar .menu ul .icon { + padding-left: 1.3333em; /* LTR */ +} +.toolbar .menu ul a.icon:before { + display: none; +} +.toolbar .vertical .menu ul { + margin-left: 1.5em; /* LTR */ +} +.toolbar .vertical .menu ul ul { + margin-left: 0.75em; /* LTR */ +} + +/** + * Top level icons + */ +.icon-home:before { + background-image: url("../images/icon-home.png"); +} +.icon-home:active:before, +.icon-home.active:before { + background-image: url("../images/icon-home-active.png"); +} +.icon-menu:before { + background-image: url("../images/icon-menu.png"); +} +.icon-menu:active:before, +.icon-menu.active:before { + background-image: url("../images/icon-menu-active.png"); +} + +/** + * Main menu icons. + */ +.icon-content:before { + background-image: url("../images/icon-content.png"); +} +.icon-content:active:before, +.icon-content.active:before { + background-image: url("../images/icon-content-active.png"); +} +.icon-structure:before { + background-image: url("../images/icon-structure.png"); +} +.icon-structure:active:before, +.icon-structure.active:before { + background-image: url("../images/icon-structure-active.png"); +} +.icon-appearance:before { + background-image: url("../images/icon-appearance.png"); +} +.icon-appearance:active:before, +.icon-appearance.active:before { + background-image: url("../images/icon-appearance-active.png"); +} +.icon-people:before { + background-image: url("../images/icon-people.png"); +} +.icon-people:active:before, +.icon-people.active:before { + background-image: url("../images/icon-people-active.png"); +} +.icon-extend:before { + background-image: url("../images/icon-extend.png"); +} +.icon-extend:active:before, +.icon-extend.active:before { + background-image: url("../images/icon-extend-active.png"); +} +.icon-configuration:before { + background-image: url("../images/icon-configuration.png"); +} +.icon-configuration:active:before, +.icon-configuration.active:before { + background-image: url("../images/icon-configuration-active.png"); +} +.icon-reports:before { + background-image: url("../images/icon-reports.png"); +} +.icon-reports:active:before, +.icon-reports.active:before { + background-image: url("../images/icon-reports-active.png"); +} +.icon-help:before { + background-image: url("../images/icon-help.png"); +} +.icon-help:active:before, +.icon-help.active:before { + background-image: url("../images/icon-help-active.png"); +} + +@media only screen and (min-width: 16.5em) { + .toolbar .bar .icon { + margin-left: 0; + margin-right: 0; + padding-left: 0; + padding-right: 0; + text-indent: -9999px; + width: 4em; + } + .toolbar .bar .icon:before { + left: 0; /* LTR */ + width: 100%; + } +} + +@media only screen and (min-width: 36em) { + .toolbar .bar .icon { + background-position: left center; /* LTR */ + padding-left: 2.75em; /* LTR */ + padding-right: 1.3333em; /* LTR */ + text-indent: 0; + width: auto; + } + .toolbar .bar .icon:before { + left: 0.6667em; /* LTR */ + width: 20px; + } +} diff --git a/core/modules/toolbar/css/toolbar.menu-rtl.css b/core/modules/toolbar/css/toolbar.menu-rtl.css new file mode 100644 index 0000000000000000000000000000000000000000..1435225423fcb3c118068694c29090c8985bff0c --- /dev/null +++ b/core/modules/toolbar/css/toolbar.menu-rtl.css @@ -0,0 +1,19 @@ +/** + * @file toolbar.menu-rtl.css + */ +.toolbar .vertical .handle + a { + margin-left: 3em; + margin-right: 0; +} + +/** + * Handle. + */ +.toolbar .icon.handle { + left: 0; + right: auto; +} +.toolbar .icon.handle:before { + left: auto; + right: 0; +} diff --git a/core/modules/toolbar/css/toolbar.menu.css b/core/modules/toolbar/css/toolbar.menu.css new file mode 100644 index 0000000000000000000000000000000000000000..c77c4c50f61f6869304791c9dfc2a5c7bd815c75 --- /dev/null +++ b/core/modules/toolbar/css/toolbar.menu.css @@ -0,0 +1,101 @@ +/** + * @file toolbar.menu.css + */ +.toolbar .menu { + list-style: none; + margin: 0; + padding: 0; +} +.toolbar .box { + display: block; + line-height: 1em; /* this prevents the value "normal" from being returned as the line-height */ + position: relative; + width: auto; +} +.toolbar .horizontal .menu .handle, +.toolbar .horizontal .menu ul, +.toolbar .vertical .menu ul { + display: none; +} +.toolbar .vertical li.open > ul { + display: block; /* Show the sub-menus */ +} +.toolbar .vertical .handle + a { + margin-right: 3em; /* LTR */ +} +.toolbar .tray .active-trail > .box a, +.toolbar .tray a.active { + color: #000; + font-weight: bold; +} + +/** + * Items. + */ +.toolbar .level-2 > ul { + background-color: #fafafa; + border-bottom-color: #cccccc; + border-top-color: #e5e5e5; +} +.toolbar .level-3 > ul { + background-color: #f5f5f5; + border-bottom-color: #c5c5c5; + border-top-color: #dddddd; +} +.toolbar .level-4 > ul { + background-color: #eeeeee; + border-bottom-color: #bbbbbb; + border-top-color: #d5d5d5; +} +.toolbar .level-5 > ul { + background-color: #e5e5e5; + border-bottom-color: #b5b5b5; + border-top-color: #cccccc; +} +.toolbar .level-6 > ul { + background-color: #eeeeee; + border-bottom-color: #aaaaaa; + border-top-color: #c5c5c5; +} +.toolbar .level-7 > ul { + background-color: #fafafa; + border-bottom-color: #b5b5b5; + border-top-color: #cccccc; +} +.toolbar .level-8 > ul { + background-color: #dddddd; + border-bottom-color: #cccccc; + border-top-color: #dddddd; +} + +/** + * Handle. + */ +.toolbar .handle:hover { + cursor: pointer; +} +.toolbar .icon.handle { + bottom: 0; + display: block; + height: 100%; + padding: 0; + position: absolute; + right: 0; /* LTR */ + text-indent: -9999px; + top: 0; + width: 3em; + z-index: 1; +} +.toolbar .icon.handle:before { + background-image: url("../images/icon-open.png"); + left: 0; /* LTR */ +} +.toolbar .icon.handle.open:before { + background-image: url("../images/icon-collapse.png"); +} +.toolbar .menu .menu .icon.handle:before { + background-image: url("../images/icon-child-open.png"); +} +.toolbar .menu .menu .icon.handle.open:before { + background-image: url("../images/icon-child-collapse.png"); +} diff --git a/core/modules/toolbar/css/toolbar.theme-rtl.css b/core/modules/toolbar/css/toolbar.theme-rtl.css new file mode 100644 index 0000000000000000000000000000000000000000..fa5a1dfa1303148617583488ff7c593c72fc74fb --- /dev/null +++ b/core/modules/toolbar/css/toolbar.theme-rtl.css @@ -0,0 +1,56 @@ +/** + * @file toolbar.theme-rtl.css + */ + +/** + * Toolbar tray. + */ +.toolbar .horizontal > .lining { + padding-right: 0; + padding-left: 5em; +} +.toolbar .vertical > .lining, +.toolbar .vertical > .lining:before { + border-left: 1px solid #aaaaaa; + border-right: 0 none; +} +.toolbar .vertical > .lining:before { + box-shadow: 1px 0 5px 2px rgba(0, 0, 0, 0.3333); +} +.toolbar .horizontal .menu li + li { + border-left: 0 none ; + border-right: 1px solid #dddddd; +} +.toolbar .horizontal .menu li:last-child { + border-left: 1px solid #dddddd; +} +.toolbar .vertical .menu .menu .menu { + margin-left: 0; + margin-right: 1.3333em; +} +.toolbar .vertical .menu .menu .menu .menu { + margin-left: 0; + margin-right: 0.25em; +} +.toolbar .vertical .menu .menu .menu a { + padding-left: 0; + padding-right: 0.5em; +} + +/** + * Orientation toggle. + */ +.toolbar .horizontal .toggle-orientation { + border-left: 0 none; + border-right: 1px solid #c9c9c9; +} +.toolbar .toggle-orientation > .lining { + float: left; +} +.toolbar .toggle-orientation button:before { + left: auto; + right: 0; +} +.toolbar .toggle-orientation [value="vertical"]:before { + background-image: url('../images/icon-toggle-vertical-rtl.png'); /* LTR */ +} diff --git a/core/modules/toolbar/css/toolbar.theme.css b/core/modules/toolbar/css/toolbar.theme.css new file mode 100644 index 0000000000000000000000000000000000000000..08a573c62587bbffeaf256501da9537f9e1a9f08 --- /dev/null +++ b/core/modules/toolbar/css/toolbar.theme.css @@ -0,0 +1,148 @@ +/** + * @file toolbar.theme.css + */ +.toolbar { + font-family: "Source Sans Pro", "Lucida Grande", Verdana, sans-serif; + /* Set base font size to 13px based on root ems. */ + font-size: 0.8125rem; + -moz-tap-highlight-color: rgba(0,0,0,0); + -o-tap-highlight-color: rgba(0,0,0,0); + -webkit-tap-highlight-color: rgba(0,0,0,0); + tap-highlight-color: rgba(0,0,0,0); + -moz-touch-callout: none; + -o-touch-callout: none; + -webkit-touch-callout: none; + touch-callout: none; +} +.toolbar a { + cursor: pointer; + padding: 1em 1.3333em; + text-decoration: none; +} +.toolbar a:hover { + text-decoration: underline; +} + +/** + * Toolbar bar. + */ +.toolbar .bar { + background-color: #0f0f0f; + box-shadow: 0 0 3px 1px rgba(0, 0, 0, 0.3333); + color: #dddddd; +} +.toolbar .bar 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 { + 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. + */ +.toolbar .tray > .lining { + background-color: #ffffff; +} +.toolbar .horizontal > .lining { + padding-right: 5em; /* LTR */ +} +.toolbar .vertical > .lining, +.toolbar .vertical > .lining:before { + background-color: #ffffff; + border-right: 1px solid #aaaaaa; /* LTR */ +} +.toolbar .vertical > .lining:before { + box-shadow: -1px 0 5px 2px rgba(0, 0, 0, 0.3333); /* LTR */ +} +.toolbar .horizontal { + border-bottom: 1px solid #aaaaaa; + box-shadow: 0 1px 3px 1px rgba(0, 0, 0, 0.3333); +} +.toolbar .horizontal .tray { + background-color: #f5f5f5; +} +.toolbar .tray a { + color: #707070; +} +.toolbar .tray a:hover, +.toolbar .tray a:active, +.toolbar .tray a.active { + color: #000; +} +.toolbar .horizontal .menu { + background-color: #ffffff; +} +.toolbar .horizontal .menu li + li { + border-left: 1px solid #dddddd; /* LTR */ +} +.toolbar .horizontal .menu li:last-child { + border-right: 1px solid #dddddd; /* LTR */ +} +.toolbar .vertical .menu li + li { + border-top: 1px solid #dddddd; +} +.toolbar .vertical .menu li:last-child { + border-bottom: 1px solid #dddddd; +} +.toolbar .vertical .menu .menu li { + border: 0 none; +} +.toolbar .vertical .menu ul ul { + border-bottom: 1px solid #dddddd; + border-top: 1px solid #dddddd; +} +.toolbar .vertical .menu li:last-child > ul { + border-bottom: 0; +} +.toolbar .vertical .menu .menu .menu { + margin-left: 1.3333em; /* LTR */ +} +.toolbar .vertical .menu .menu .menu .menu { + margin-left: 0.25em; /* LTR */ +} +.toolbar .menu .menu a { + color: #434343; +} +.toolbar .vertical .menu .menu .menu a { + padding-left: 0.6667em; /* LTR */ +} + +/** + * Orientation toggle. + */ +.toolbar .toggle-orientation { + background-color: #f5f5f5; + padding: 0.6667em; +} +.toolbar .horizontal .toggle-orientation { + border-left: 1px solid #c9c9c9; /* LTR */ +} +.toolbar .toggle-orientation > .lining { + float: right; /* LTR */ + padding: 0.1667em; +} +.toolbar .toggle-orientation button { + cursor: pointer; + display: inline-block; + height: 16px; + padding: 0; + text-indent: -999em; + width: 20px; +} +.toolbar .toggle-orientation button:before { + left: 0; /* LTR */ +} +.toolbar .toggle-orientation [value="vertical"]:before { + background-image: url('../images/icon-toggle-vertical.png'); /* LTR */ +} +.toolbar .toggle-orientation [value="horizontal"]:before { + background-image: url('../images/icon-toggle-horizontal.png'); +} diff --git a/core/modules/toolbar/images/icon-appearance-active.png b/core/modules/toolbar/images/icon-appearance-active.png new file mode 100644 index 0000000000000000000000000000000000000000..2b11761d01db85754340c2e38b77a3038ecc28a5 --- /dev/null +++ b/core/modules/toolbar/images/icon-appearance-active.png @@ -0,0 +1,4 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���´IDATxÚ¬” À D‘€„I˜$LB%LN0 H@&aƒ¤$Œ¬B›\Â/æZPŠŽ#éNŠIZ-ÆŽ°uIŠI؃뛬ÈKÂ"ž±=˜€eT´°:+¨*¿sý6ã›Ç½Ày+¯¬—®Ó{ÀXA`f¡»gždi#GÀXÿzPÏÌÍ~'‘Y;†ê +ઊ/A©‹¢4ôïý‡ÕØüx¼Ÿ–z�s÷€576����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-appearance.png b/core/modules/toolbar/images/icon-appearance.png new file mode 100644 index 0000000000000000000000000000000000000000..fd581f691a1e882641c1e93c9155cedf6679cc5a --- /dev/null +++ b/core/modules/toolbar/images/icon-appearance.png @@ -0,0 +1,4 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<��AIDATxÚœ”±‘Â0E¥£Z “;€ ƒ£ˆBê¨À¦‚sv¡/q|.2BJà/óÍ,º“%ügvdü´ú+¯5eY6Æ°–ç<Ïw&R#ßDš¦ß>3<Û¦i~b€Ö“]A˜Ö™¶o=0‘Àæ€Þú€‘0Q‚ØF{€‰nôó?ÛÞ#GÀDK„T¾àÑÿ-’l†±ÀJ�VÜ\6Þ#Žˆƒë©xxfø$ÇÛt?�(¹~KðkQ°@&§ˆÊ\é,áž2´ào•åÄRgBmôÝãq×jþÔ{mðòAgE%JVh+°¾ê*՛ЧÂ3>ßm 9ÔÝýU?$táËÉêìlPéÂÙЧÄK/àc×Æð_í@Ÿß¹5¤ìH\è ¡ ¡ú.¶ƒ +úÕ±c„®s•îCº0�@»„^ŒÇ€Æ����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-child-collapse.png b/core/modules/toolbar/images/icon-child-collapse.png new file mode 100644 index 0000000000000000000000000000000000000000..b7a744f2a684f48589e235d66c53c481936305bf --- /dev/null +++ b/core/modules/toolbar/images/icon-child-collapse.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������VÎŽW���tEXtSoftware�Adobe ImageReadyqÉe<���OIDATxÚb`#0RP^^.�¤ú¸°³³óYA ÙÄ@|ˆqÆH¤!0€Ó0FÁkÕ1Há<ò…£Il¨€��äº(HãLÜ����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-child-open.png b/core/modules/toolbar/images/icon-child-open.png new file mode 100644 index 0000000000000000000000000000000000000000..74e0b77ccd4fc8fbbd432525c3bf90d359f9f116 --- /dev/null +++ b/core/modules/toolbar/images/icon-child-open.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������VÎŽW���tEXtSoftware�Adobe ImageReadyqÉe<���TIDATxÚb`#0bl<Ô¤ðè»°¾Þ®Y€‡ÂF ÞðPyÂ.‚ºJ�‹a C®ù@´AXÃiAƒ…Y!.CFÁP��°‰Ê€s»ò����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-collapse.png b/core/modules/toolbar/images/icon-collapse.png new file mode 100644 index 0000000000000000000000000000000000000000..8b247b5a2ef30844acab77e4e8519d9025653d75 --- /dev/null +++ b/core/modules/toolbar/images/icon-collapse.png @@ -0,0 +1,4 @@ +‰PNG + +��� IHDR���������rP6Ì���tEXtSoftware�Adobe ImageReadyqÉe<��3IDATxÚ´T» Â040BF€ € € ’*%eZ(S¦L6�& L@F00wÒE|A𤓼w—çϹgžDY–K€ã •º�5P¤iZßózw"†J"`8䆘3?b‰&ȹ1Hí¢'St+ñ)vSòìḢW1Fü¹Õ÷JËùXˆ¡z'¾±Úlba¾ò&Ô±:µMh²,‹Ý9ÖÒª«}@ˆK¨4¾Š#u¬î‘ù®â€ Os`ÕjóFÈ„=߶îØ;¡—‚žß—E"µJ!ÎÏÀ:t„¬ËóÜoÅ.}Ù‚Ùñ« +V¯Ç˜:\fÁÖå‚Î!·¤°r-¯}äÕÔñv¢-"yÍtôf$þ^À{Æ›Ýt~Ï~ñÒ^�œJ«˜y����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-configuration-active.png b/core/modules/toolbar/images/icon-configuration-active.png new file mode 100644 index 0000000000000000000000000000000000000000..1eea537c976a781722e6a9085e575e39e84c4b32 --- /dev/null +++ b/core/modules/toolbar/images/icon-configuration-active.png @@ -0,0 +1,4 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���›IDATxÚbdÀ +@œ€Ä�Ä€ø`>ÿGÂ︀B€n(7ÐÂPBšH4t=! šðýhá‰ôCâ3ô>š+ ºð?C°„#^€¦x>šaýhòç (� dMû±xÙ@B†àÐüŸCha¨4½GÓxžCq…ó¨¡8 e ¶¡Ô6”ª†�4k‰§É~¼����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-configuration.png b/core/modules/toolbar/images/icon-configuration.png new file mode 100644 index 0000000000000000000000000000000000000000..a5d46b2268692f295b8a9006807f6c455dcec6e6 --- /dev/null +++ b/core/modules/toolbar/images/icon-configuration.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<��IDATxÚœ“-Â@…w[ƒYÙ#p€Šâ8œ�[‹«ä`qp‚–¤É ¨D‚Ç›dH6›ý™e’Í6o³_g^_µ²ªišÛÊF¬SÛ¶O%(íÝ[P‚mÝÅ€¹K†á\Uu:gi‚µ„¦qÖ'=PªÚg£ï^Æž9#®±,yê0#¯Ø³Ô³Ž§1(Êœb¾øÙ eKJ%¬Œs¦\P†ÙžÝ‚9Ä%ánÒsW®Î¸ð=Gވ‡rfyæóªàLé®3‡8¸Rhc_PÍ ÷Zî¬à¿ã7⃵(TKÚaŸ;ë¯qzª¥qBÅ@)4KòXOé%]PMÆ CЯ��†¨y±ô•A¹����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-content-active.png b/core/modules/toolbar/images/icon-content-active.png new file mode 100644 index 0000000000000000000000000000000000000000..24b6982dfc9605d5b6c0016f3b8862584b1b07a4 --- /dev/null +++ b/core/modules/toolbar/images/icon-content-active.png @@ -0,0 +1,4 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���›IDATxÚbd@�(&\�â „5�ñp6C˜Èó±Ê‚C1#ƒþ£ +¨áB¬.¥†0C ¨i àC|€O˜RÕ…„\Ø<‰»/ñG<òHuár¼Œ/÷ÈzûIu!(|ðÈ Õ@P„(ä¨O –ùÉñ2U#…ª û?¹RÝ…��å'sz³P¨����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-content.png b/core/modules/toolbar/images/icon-content.png new file mode 100644 index 0000000000000000000000000000000000000000..32081b6d14444b07f3c9f82ed79726ce6d11312a --- /dev/null +++ b/core/modules/toolbar/images/icon-content.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���µIDATxÚbd€‚òòr åÀ@¸ÐÙÙ¹›dX=‘‚4tº8ù`>ÐÐ|.„ ÍŒx\öÍPd—RâB¬.¥†0C ¨i àC|�=|Ñ”ª.dÀëB Íý@Ê€@â.$Ú@ ¸ÄñÈ? É…Ør¥^ÞO o�ZêHŠ—Aá#€GþI.„Fˆ0¼@Šúb™ŸÔH)$'R蓰ѳӀº À�Ü4·»¬¨!����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-extend-active.png b/core/modules/toolbar/images/icon-extend-active.png new file mode 100644 index 0000000000000000000000000000000000000000..faa13c54cedeac5fdc776f13e8644e7b33466db9 --- /dev/null +++ b/core/modules/toolbar/images/icon-extend-active.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���’IDATxÚ¼ÔÑ �`#ÁF0JG0‚ n4#Á΃K.r¥æ$âÅ'ZƒØcÒ¸zZOÖB}Oýušhs ÔÌÐw`ÕÍ6ahú�QÔŽã`( ˜Ýa,412*‰_5I’0cî�ËØ5!¶|ž´Pß:œv˜‹Mô©h sf”õ•…͆õ`�‘3¯íÆ¥<����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-extend.png b/core/modules/toolbar/images/icon-extend.png new file mode 100644 index 0000000000000000000000000000000000000000..52219ff8506fbf17e52aec2b3670ce7c9a5ef2a6 --- /dev/null +++ b/core/modules/toolbar/images/icon-extend.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<��,IDATxÚœ“1Â0E›vbË8B‘:À álaí„8åL°tÏ €±Gà™:¤dâôåÛ±“DYeYn`6é¹R¶‡#»ô…¦Êþ ÖÂò¾ÐN`UUnÞ…‡€&ÄÇoŒ`Ž•S)Ö¸´V\³+AýÕ Íè5áw°eQç¦ižþúý~ÎÄ·ì?w²†5§c¹V¹P¸‚Û*U9rü'eËiåüsJŸ#÷›¾ñ”Hè! L…‘ž²&©è¿–[cè²R!5ím ÌAÐÂ;ÕbŒ'+Éd„úŠú‹ú,F"¦\.u–ëJÇþå™v*BéÝÇïÔ˜×+Íý©ÙBÄÖ&&'u<Im×…&öyÆ-@×À…íK€� ®‰ˆ’éç����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-help-active.png b/core/modules/toolbar/images/icon-help-active.png new file mode 100644 index 0000000000000000000000000000000000000000..a46315b210c08781c372d5c287de59f489c4487e --- /dev/null +++ b/core/modules/toolbar/images/icon-help-active.png @@ -0,0 +1,4 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���ÐIDATxÚbdÀ€ØˆÄ>�ñ ¾À@H�âû@ü¾U‡€\²ž€Aèx=šP;O¢a0|›¡ûq(~•ÛOÀÂõèa†Í la¤€Ç`¸úû„` ž÷8" +œ4:ÌÅDC l .o34iX0‡8ŸÃ#ä#‚.œdAß°@ó&!à�¥ý‰É·dæœ^f ṖºÐˆ¬yŸ˜Xk "ía͸J™ýPCød=ÍKª—‡T)±�‰ð2$Jü����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-help.png b/core/modules/toolbar/images/icon-help.png new file mode 100644 index 0000000000000000000000000000000000000000..0a8fe2e98dba8729bb5f267c3e3aefbc34e635ee --- /dev/null +++ b/core/modules/toolbar/images/icon-help.png @@ -0,0 +1,4 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<��>IDATxÚ´”Á±‚0†!Cv %P‚T V tà;qDŽœ,A;0¨H Ú%¼?ïmœÉ.ñàÎì„ É·›ÍŸMÁš¦É1¬ágz„ßú¾B{RTahá+!ÞÞ|f�™LNð2‰7 ¯'@‚]áyò¹™ãªœÉû«ùÀ�s:Ù†T³S�ôã×kWBðÚfØ~.B© €¹Œ‚úÖ¦$ÇLÑKV.Øw%IML…&=+™Œƒ'PÜP}œì*N ¸Œ€míå�¶\àøšÓ;`8J‹3æ¶ü§hë¼™[›‘`%«È£LQ¡ŸÒ‘Iw…ðRÞ Ã +»½Ô´«[Dy:·9\˜.c@wúÞ -M#è6suF‹}}#Ä?ÐþD9ot¤:é[—¶ë+ûW€�êm<ëP|ª����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-home-active.png b/core/modules/toolbar/images/icon-home-active.png new file mode 100644 index 0000000000000000000000000000000000000000..32ed2a471a53046962360f745bb1fdf0af2ca673 --- /dev/null +++ b/core/modules/toolbar/images/icon-home-active.png @@ -0,0 +1,6 @@ +‰PNG + +��� IHDR���������Ä´l;���tEXtSoftware�Adobe ImageReadyqÉe<���üIDATxÚÜ”m +ƒ0†-ü!BÑxw=ÙØÉܼ»€®**~v©8èì»ê-¢Ñ<¼I´šö·6ƒK)XÜ Ú÷½þ�(e‘Ý+CÛ¶Å]×Eà”óhÊ\.àëNkЦi0´Ï +œÙ#‡åÁ5„ÐÇZ´ëC`Ðmßt]÷WWUõRúõ,pY–ÊPaEQȶÏÛülyçyŽaªJCèÖ7M“Œà,ËF¥�Vþ>BðQš¦*í/*G„.¼)qÙz–—$ U¥Z–…pÇ‹`Û¶‘Ì{§Ùà·.HîÓkë*>LñOŒâ0{ +0�†¯\ ÓlJ����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-home.png b/core/modules/toolbar/images/icon-home.png new file mode 100644 index 0000000000000000000000000000000000000000..5d8d5018b8bdcbd05dc08199975b301038e4fd16 --- /dev/null +++ b/core/modules/toolbar/images/icon-home.png @@ -0,0 +1,6 @@ +‰PNG + +��� IHDR���������Ä´l;���tEXtSoftware�Adobe ImageReadyqÉe<��IDATxÚÔ”A +ƒ0E x€¡GH‚¸ª;ÁUâqJ#.ª‚ ‚(‚ ¸¨Gè¼€¦£¨ÔŠ¢Æ’?1ó‘ãŽh©0Ë2Ëò*B¾8MS‚ +a‹!J©,ŠbÎN’ô ÛÓGùð3Ôë/¸´µH’$¹ðsÐ8ŽqUUá”kÏáÜÝIpEº +!É„„¬AÐuJ¶ºbö}Ÿ:žçy¸þh3PEQŠØu]hymEUU‹ì8ÎÐY–µ'´‡óµ m8Ø°Þ˜ÿÝGÃ3M“²‚5MC#»Í&/èºÞ7a]åã²,uµD÷ðÜS¬Õï)~o� ¿†=èʱ����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-menu-active.png b/core/modules/toolbar/images/icon-menu-active.png new file mode 100644 index 0000000000000000000000000000000000000000..ab6462e0f1ae96f28eb89ca745ed4e57aec62fab --- /dev/null +++ b/core/modules/toolbar/images/icon-menu-active.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������Ä´l;���tEXtSoftware�Adobe ImageReadyqÉe<���IIDATxÚb` `üÿÿ¿v ¶Á,Pƒëia0M‚‚¦`´Œ_¿~béøß¿£éx ¥ãW¯^–Ç´Ï 4IÇ��æq2¡{ßL‹����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-menu.png b/core/modules/toolbar/images/icon-menu.png new file mode 100644 index 0000000000000000000000000000000000000000..a02939ffd92ad56edbec657249bb1f9860e18ec4 --- /dev/null +++ b/core/modules/toolbar/images/icon-menu.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������Ä´l;���tEXtSoftware�Adobe ImageReadyqÉe<���\IDATxÚbb `<sæŒv ¶Á,ÿþýZOƒi,ÿþ¥Á@`J€iÈ̸cÇÚ¤c`ªMǃÿÿÿ?šŽiœŽ/^<ÄÊcš%·!—Ž�rM0_þ !î����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-open.png b/core/modules/toolbar/images/icon-open.png new file mode 100644 index 0000000000000000000000000000000000000000..fb71f8884268a362ca7d8c15474ed7fa60b5ebb5 --- /dev/null +++ b/core/modules/toolbar/images/icon-open.png @@ -0,0 +1,5 @@ +‰PNG + +��� IHDR���������rP6Ì���tEXtSoftware�Adobe ImageReadyqÉe<��=IDATxÚ¬”ÑmÂ0†‹Ø�wƒv@6¨ŸòÈUGècž’ € ,ÐlÐŒÀýÿêOd…„ˆ“~qw_îlŸ#Óaiš®°ì ®óÀu… +è;I’¢µ K&H¡ +‰%|¯øMÿúÔÃWÝÀ|b2‡A•º|Í509 ÞŒ4䱋-ôÆ[ýŸ©Ñ šâ+å«Í¦b3͘·"ÇêÔò¾=¨®Òaífªªi/þº8ÖåûÏ÷º�žz6Ó=jªb�€‹`2ÊŸ[•Z†‘ô*ýÈ·ZýÏ·Á3#€7 0ßjD\W -`'HFØÕj,6÷6G�ߢ-ɉtÏ8F/S®‡¦ç—ce5ý…fmŠ1¯ §'¶à4kæÁÙtõ=}þ«Ñóž¡òá÷ì/íŸ��£VY¤¤b����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-people-active.png b/core/modules/toolbar/images/icon-people-active.png new file mode 100644 index 0000000000000000000000000000000000000000..0a406fbe16f9939975c9d95775c6aa1d3210d9c8 --- /dev/null +++ b/core/modules/toolbar/images/icon-people-active.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���·IDATxÚb`Š@�ˆ÷ñ(Þ# Ãó)1ð?¼Ÿïc1p=%&`1ÐXÍŒ8ÄY�Äȉ٨×ÎãCœ@Ùû¡¾ÁjØy‘ŽXÄÐ , Â0X8bKRï‘ c"!Ñ~À\pÀ ðD†óA,1¾€Ò¬Ù�õ&÷£»‘„T`€'=^€úò± ý=‘×@È0" BÆxA©2v��Ž½oæŽXø����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-people.png b/core/modules/toolbar/images/icon-people.png new file mode 100644 index 0000000000000000000000000000000000000000..b62d83c3ca2522fff006bb5d22957bbc189059e0 --- /dev/null +++ b/core/modules/toolbar/images/icon-people.png @@ -0,0 +1,4 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���ùIDATxÚb`ì€] ¢¢B�Hb¨Ð ìèèø@ŒLXÄ c€²û‰u!6°ˆ)Pbà,b(1°‹ØD²#1H^_�Œ$Ù ¶‡†—šºPoBåâ¤g!Ð²È +™¡†í‡¨Ä8"å¿„¦ ¨X€ ã‘#G ‡a1àÇ|,âùè‘"@dðàŠiý,Ðdr€AbI§Æ2>�ó$o‚kDΖŒD"� gJ.€| 2˜‘à y™˜°nd$`ÈUçI &ò¤†11;°� À�³9ÞdÝs����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-reports-active.png b/core/modules/toolbar/images/icon-reports-active.png new file mode 100644 index 0000000000000000000000000000000000000000..96f467357d28928b16e13bb379c9592016eec6f8 --- /dev/null +++ b/core/modules/toolbar/images/icon-reports-active.png @@ -0,0 +1,4 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���ðIDATxÚ¬”Ñ †Áã]Fp6°Nຂ¨Ô ªèÅ :BG Tr<.,¹3wÿ] +å#IÓh¥Tƒ*ÙõT»DÍ:ÖÂLæŸ0šÜÚ(Õáó]˜'û!ó« +%³N!g;&}X²æñÃMQoô©ÝRy8à†žÛc6Áê7`'Ð�R)z€æÐX�¦(¼§ÀSx/ÈÂQà#ê%�Àeý†Fè˜?…š-´NàÚ¦-@4rƒdLµ7ÂU ÿO¨¾)o™õuž²ÄàеðQ¬tÚØÃủ+así�Ê|47 ‚z÷����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-reports.png b/core/modules/toolbar/images/icon-reports.png new file mode 100644 index 0000000000000000000000000000000000000000..49ede88cdb2820de6baaff7dd07c3b40cf7e0e0f --- /dev/null +++ b/core/modules/toolbar/images/icon-reports.png @@ -0,0 +1,5 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<��IDATxÚ¬TÁ Â0LQþdFè´00B_}Ͼʅ `‚f„ŽÐ26 +È2IKX²š&öåìØ.Ú¶”R¨1™º®{¨LÑì´d—ô–¸"ë´f:ù³@¹ih–1säAUŠéJÉd0ü`S¶=|Ê`†gÿ(èŒ!j½Í’\ÁÎ…"ƒ Û³©*�ÙÁ¥5‚Jr8ª !DF�5:à4G�] +xt#ÜoQ”ðúÌõöŒÏ¶âKÒ±4‘Òq¡:ìc¥EÖ&2HæOîµ0Gé^öyø¨ÚcÈÛÀþš†,tºDÅH§Yß3 Ãw'¤Œ^�:3PÀdV����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-structure-active.png b/core/modules/toolbar/images/icon-structure-active.png new file mode 100644 index 0000000000000000000000000000000000000000..3ab2375fc5f06ba8efd57fac47917fe3ab643539 --- /dev/null +++ b/core/modules/toolbar/images/icon-structure-active.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���IDATxÚb`q€¯$#£rÀ"uàÿÿÿH·‘±ˆÿcÁ ¸ô0QÛËT7…€üPxAÙHì”Ç0쨛H5”DpÄ(±Ø[¤€Ò#6’Ä#w€f±t)cŽb V�âP¹B 6€Ê¡ÇòB¨º~(ß�óðå|9W˜œr€ˆ\‚QÚ@å‡^`�ÈÅc'6CÄ����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-structure.png b/core/modules/toolbar/images/icon-structure.png new file mode 100644 index 0000000000000000000000000000000000000000..7a8302f8dd48adb129a4312978f7c9e43a757fe9 --- /dev/null +++ b/core/modules/toolbar/images/icon-structure.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������‰ ���tEXtSoftware�Adobe ImageReadyqÉe<���¥IDATxÚb`q€ŸdEE…rÀ"u ££ã�6=,,VC«LÔö2Õ $äåH^s@b? Øf`ý/3¢%‘ý˜åJJ,XÒ—#./åqÈí§—¦'�éx �b ¾�•+b¨z,/„ªë‡ò 1ÿjˆZî`@²�›ÜA¨ÈrC'§ "—`+@òC¯€0�ÇŒ+SÞu\����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-toggle-horizontal.png b/core/modules/toolbar/images/icon-toggle-horizontal.png new file mode 100644 index 0000000000000000000000000000000000000000..759701cb47736bcb1e87da4f595b6c0ead74b80f --- /dev/null +++ b/core/modules/toolbar/images/icon-toggle-horizontal.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������¸Ûà���tEXtSoftware�Adobe ImageReadyqÉe<���cIDATxÚb,//g 01諈;::HÒSQQAmG®|ŽÄ›7o>{ö,ÁÁÁáëëK”m@ G…°ˆ~Ú®^½Šæ6 (HÀ‘ÚÚÚÄ,ý£}¤j0�p«#÷m‰´V����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-toggle-vertical-rtl.png b/core/modules/toolbar/images/icon-toggle-vertical-rtl.png new file mode 100644 index 0000000000000000000000000000000000000000..95e3fbaf11272cff75af05e25964ccd18f824336 --- /dev/null +++ b/core/modules/toolbar/images/icon-toggle-vertical-rtl.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������¸Ûà���tEXtSoftware�Adobe ImageReadyqÉe<���hIDATxÚb,//g °�qGGAuÈ\&²�mW¯^%GÛâÅ‹Ïž=K²6 X $k …xt’$,¸$¬}}}IÓjllLšm±±±ÚÚÚ$‡$A=” Zz#��Û`u8: B����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/images/icon-toggle-vertical.png b/core/modules/toolbar/images/icon-toggle-vertical.png new file mode 100644 index 0000000000000000000000000000000000000000..dd3240e6e9d65f45ff72b9d2a90b0666b762c599 --- /dev/null +++ b/core/modules/toolbar/images/icon-toggle-vertical.png @@ -0,0 +1,3 @@ +‰PNG + +��� IHDR���������¸Ûà���tEXtSoftware�Adobe ImageReadyqÉe<���kIDATxÚb,//g ° ñ;::ꩨ¨`b ÖvõêU’µ={vñâÅ„ý†6oÞ|ôèQ¢‚V¯^ ´Š|¿‘¦-44ÔØؘÛBÁ€4¿A�ÐBrü¦Mµ aÁLoÄh0�…õZº}8‹����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/toolbar/js/toolbar.js b/core/modules/toolbar/js/toolbar.js new file mode 100644 index 0000000000000000000000000000000000000000..08a68d202d55dd2533f1478037d95335c40e60b2 --- /dev/null +++ b/core/modules/toolbar/js/toolbar.js @@ -0,0 +1,343 @@ +/** + * @file toolbar.js + * + * Defines the behavior of the Drupal administration toolbar. + */ +(function ($, Drupal, drupalSettings) { + +"use strict"; + +Drupal.toolbar = Drupal.toolbar || {}; + +/** + * Store the state of the active tab so it will remain active across page loads. + */ +var activeTab = JSON.parse(localStorage.getItem('Drupal.toolbar.activeTab')); + +/** + * Store the state of the trays to maintain them across page loads. + */ +var locked = JSON.parse(localStorage.getItem('Drupal.toolbar.trayVerticalLocked')) || false; +var orientation = (locked) ? 'vertical' : 'horizontal'; + +/** + * Holds the jQuery objects of the toolbar DOM element, the trays and messages. + */ +var $toolbar; +var $trays; +var $messages; + +/** + * Holds the mediaQueryList object. + */ +var mql = { + standard: null, + wide: null +}; + +/** + * Register tabs with the toolbar. + * + * The Drupal toolbar allows modules to register top-level tabs. These may point + * directly to a resource or toggle the visibility of a tray. + * + * Modules register tabs with hook_toolbar(). + */ +Drupal.behaviors.toolbar = { + attach: function(context) { + var options = $.extend(this.options, drupalSettings.toolbar); + $toolbar = $(context).find('#toolbar-administration').once('toolbar'); + if ($toolbar.length) { + // Add subtrees. + // @todo Optimize this to delay adding each subtree to the DOM until it is + // needed; however, take into account screen readers for determining + // when the DOM elements are needed. + if (Drupal.toolbar.subtrees) { + for (var id in Drupal.toolbar.subtrees) { + $('#toolbar-link-' + id).after(Drupal.toolbar.subtrees[id]); + } + } + // Append a messages element for appending interaction updates for screen + // readers. + $messages = $(Drupal.theme('toolbarMessageBox')).appendTo($toolbar); + // Store the trays in a scoped variable. + $trays = $toolbar.find('.tray'); + $trays + // Add the tray orientation toggles. + .find('.lining') + .append(Drupal.theme('toolbarOrientationToggle')); + // Store media queries. + mql.standard = window.matchMedia(options.breakpoints['module.toolbar.standard']); + // Set up switching between the vertical and horizontal presentation + // of the toolbar trays based on a breakpoint. + mql.wide = window.matchMedia(options.breakpoints['module.toolbar.wide']); + mql.wide.addListener(Drupal.toolbar.mediaQueryChangeHandler); + // Set the orientation of the tray. + // If the tray is set to vertical in localStorage, persist the vertical + // presentation. If the tray is not locked to vertical, let the media + // 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(); + // 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); + // Attach behavior to the window. + $(window) + .on('resize.toolbar', setHeight); + // Attach behaviors to the toolbar. + $toolbar + .on('click.toolbar', '.bar a', Drupal.toolbar.toggleTray) + .on('click.toolbar', '.toggle-orientation button', Drupal.toolbar.orientationChangeHandler); + // Restore the open tab. Only open the tab on wide screens. + if (activeTab && window.matchMedia(options.breakpoints['module.toolbar.standard']).matches) { + $toolbar.find('[data-toolbar-tray="' + activeTab + '"]').trigger('click.toolbar'); + } + else { + // Update the page and toolbar dimension indicators. + updatePeripherals(); + } + } + }, + // Default options. + options: { + breakpoints: { + 'module.toolbar.standard': '', + 'module.toolbar.wide': '' + } + } +}; + +/** + * Set subtrees. + * + * JSONP callback. + * @see toolbar_subtrees_jsonp(). + */ +Drupal.toolbar.setSubtrees = function(subtrees) { + Drupal.toolbar.subtrees = subtrees; +}; + +/** + * Toggle a toolbar tab and the associated tray. + */ +Drupal.toolbar.toggleTray = function (event) { + var strings = { + opened: Drupal.t('opened'), + closed: Drupal.t('closed') + }; + var $tab = $(event.target); + var name = $tab.attr('data-toolbar-tray'); + // Activate the selected tab and associated tray. + var $activateTray = $toolbar.find('[data-toolbar-tray="' + name + '"].tray').toggleClass('active'); + if ($activateTray.length) { + event.preventDefault(); + event.stopPropagation(); + $tab.toggleClass('active'); + // Toggle aria-pressed. + var value = $tab.attr('aria-pressed'); + $tab.attr('aria-pressed', (value === 'false') ? 'true' : 'false'); + // Append a message that a tray has been opened. + setMessage(Drupal.t('@tray tray @state.', { + '@tray': name, + '@state': (value === 'true') ? strings.closed : strings.opened + })); + // Store the active tab name or remove the setting. + if ($tab.hasClass('active')) { + localStorage.setItem('Drupal.toolbar.activeTab', JSON.stringify(name)); + } + else { + localStorage.removeItem('Drupal.toolbar.activeTab'); + } + // Disable non-selected tabs and trays. + $toolbar.find('.bar a') + .not($tab) + .removeClass('active') + // Set aria-pressed to false. + .attr('aria-pressed', 'false'); + $toolbar.find('.tray').not($activateTray).removeClass('active'); + // Update the page and toolbar dimension indicators. + updatePeripherals(); + } +}; + +/** + * The height of the toolbar offsets the top of the page content. + * + * Page components can register with the offsettopchange event to know when + * the height of the toolbar changes. + */ +Drupal.toolbar.setHeight = function () { + // Set the top of the all the trays to the height of the bar. + var barHeight = $toolbar.find('.bar').outerHeight(); + var height = barHeight; + var bhpx = barHeight + 'px'; + var tray; + for (var i = 0, il = $trays.length; i < il; i++) { + tray = $trays[i]; + if (!tray.style.top.length || (tray.style.top !== bhpx)) { + tray.style.top = bhpx; + } + } + /** + * Get the height of the active tray and include it in the total + * height of the toolbar. + */ + height += $trays.filter('.active.horizontal').outerHeight() || 0; + // Indicate the height of the toolbar in the attribute data-offset-top. + var offset = parseInt($toolbar.attr('data-offset-top'), 10); + if (offset !== height) { + $toolbar.attr('data-offset-top', height); + // Alter the padding on the top of the body element. + $('body').css('padding-top', height); + $(document).trigger('offsettopchange', height); + $(window).trigger('resize'); + } +}; + +/** + * Respond to configured media query applicability changes. + */ +Drupal.toolbar.mediaQueryChangeHandler = function (mql) { + var orientation = (mql.matches) ? 'horizontal' : 'vertical'; + changeOrientation(orientation); + // Update the page and toolbar dimension indicators. + updatePeripherals(); +}; + +/** + * Respond to the toggling of the tray orientation. + */ +Drupal.toolbar.orientationChangeHandler = function (event) { + event.preventDefault(); + event.stopPropagation(); + var $button = $(event.target); + var orientation = event.target.value; + var $tray = $button.closest('.tray'); + changeOrientation(orientation, true); + // Update the page and toolbar dimension indicators. + updatePeripherals(); +}; + +/** + * Change the orientation of the tray between vertical and horizontal. + * + * @param {String} newOrientation + * Either 'vertical' or 'horizontal'. The orientation to change the tray to. + * + * @param {Boolean} isLock + * Whether the orientation of the tray should be locked if it is being toggled + * to vertical. + */ +function changeOrientation (newOrientation, isLock) { + var oldOrientation = orientation; + if (isLock) { + locked = (newOrientation === 'vertical'); + if (locked) { + localStorage.setItem('Drupal.toolbar.trayVerticalLocked', JSON.stringify(locked)); + } + else { + localStorage.removeItem('Drupal.toolbar.trayVerticalLocked'); + } + } + if ((!locked && newOrientation === 'horizontal') || newOrientation === 'vertical') { + $trays + .removeClass('horizontal vertical') + .addClass(newOrientation); + orientation = newOrientation; + toggleOrientationToggle((newOrientation === 'vertical') ? 'horizontal' : 'vertical'); + } +} + +/** + * Mark up the body tag to reflect the current state of the toolbar. + */ +function setBodyState () { + var $activeTray = $trays.filter('.active'); + $('body') + .toggleClass('toolbar-tray-open', !!$activeTray.length) + .toggleClass('toolbar-vertical', (!!$activeTray.length && orientation === 'vertical')) + .toggleClass('toolbar-horizontal', (!!$activeTray.length && orientation === 'horizontal')); +} + +/** + * Change the orientation toggle active state. + */ +function toggleOrientationToggle (orientation) { + var strings = { + horizontal: Drupal.t('Horizontal orientation'), + vertical: Drupal.t('Vertical orientation') + }; + var antiOrientation = (orientation === 'vertical') ? 'horizontal' : 'vertical'; + var iconClass = 'icon-toggle-' + orientation; + var iconAntiClass = 'icon-toggle-' + antiOrientation; + // Append a message that the tray orientation has been changed. + setMessage(Drupal.t('Tray orientation changed to @orientation.', { + '@orientation': antiOrientation + })); + // Change the tray orientation. + $trays.find('.toggle-orientation button') + .val(orientation) + .text(strings[orientation]) + .removeClass(iconAntiClass) + .addClass(iconClass); +} + +/** + * Updates elements peripheral to the toolbar. + * + * When the dimensions and orientation of the toolbar change, elements on the + * page must either be changed or informed of the changes. + */ +function updatePeripherals () { + // Adjust the body to accommodate trays. + setBodyState(); + // Adjust the height of the toolbar. + Drupal.toolbar.setHeight(); +} + +/** + * Places the message in the toolbar's ARIA live message area. + * + * The message will be read by speaking User Agents. + * + * @param {String} message + * A string to be inserted into the message area. + */ +function setMessage (message) { + $messages.html(Drupal.theme('toolbarTrayMessage', message)); +} + +/** + * A toggle is an interactive element often bound to a click handler. + * + * @return {String} + * A string representing a DOM fragment. + */ +Drupal.theme.toolbarOrientationToggle = function () { + return '<div class="toggle-orientation"><div class="lining">' + + '<button class="icon" type="button"></button>' + + '</div></div>'; +}; + +/** + * A region to post messages that a screen reading UA will announce. + * + * @return {String} + * A string representing a DOM fragment. + */ +Drupal.theme.toolbarMessageBox = function () { + return '<div id="toolbar-messages" class="element-invisible" role="region" aria-live="polite"></div>'; +}; + +/** + * Wrap a message string in a p tag. + * + * @return {String} + * A string representing a DOM fragment. + */ +Drupal.theme.toolbarTrayMessage = function (message) { + return '<p>' + message + '</p>'; +}; + +}(jQuery, Drupal, drupalSettings)); diff --git a/core/modules/toolbar/js/toolbar.menu.js b/core/modules/toolbar/js/toolbar.menu.js new file mode 100644 index 0000000000000000000000000000000000000000..ff093e454c1ed61f0d98e210fef40e6814d8ac77 --- /dev/null +++ b/core/modules/toolbar/js/toolbar.menu.js @@ -0,0 +1,181 @@ +/** + * Builds a nested accordion widget. + * + * Invoke on an HTML list element with the jQuery plugin pattern. + * - For example, $('.menu').toolbarMenu(); + */ + +(function ($, Drupal) { + +"use strict"; + +/** + * Store the open menu tray. + */ +var activeItem = JSON.parse(localStorage.getItem('Drupal.toolbar.menu.activeItem')); + + $.fn.toolbarMenu = function () { + + var ui = { + 'handleOpen': Drupal.t('Extend'), + 'handleClose': Drupal.t('Collapse') + }; + /** + * Handle clicks from the disclosure button on an item with sub-items. + * + * @param {Object} event + * A jQuery Event object. + */ + function toggleClickHandler (event) { + var $toggle = $(event.target); + var $item = $toggle.closest('li'); + // Toggle the list item. + toggleList($item); + // Close open siblings and their open children. + var $openItems = $item.siblings().filter('.open'); + toggleList($openItems, false); + // Save link of the closest open item through a unique selector. + var href = $toggle.siblings('a[href]').attr('href'); + if ($toggle.hasClass('open')) { + localStorage.setItem('Drupal.toolbar.menu.activeItem', JSON.stringify(href)); + } + else { + localStorage.removeItem('Drupal.toolbar.menu.activeItem'); + } + } + /** + * Toggle the open/close state of a list is a menu. + * + * @param {jQuery} $item + * The li item to be toggled. + * + * @param {Boolean} switcher + * A flag that forces toggleClass to add or a remove a class, rather than + * simply toggling its presence. + */ + function toggleList ($item, switcher) { + var $toggle = $item.find('> .box > .handle'); + switcher = (typeof switcher !== 'undefined') ? switcher : !$item.hasClass('open'); + // Toggle the item open state. + $item.toggleClass('open', switcher); + // Twist the toggle. + $toggle.toggleClass('open', switcher); + // Adjust the toggle text. + $toggle + .find('.action') + // Expand Structure, Collapse Structure + .text((switcher) ? ui.handleClose : ui.handleOpen); + } + /** + * Add markup to the menu elements. + * + * Items with sub-elements have a list toggle attached to them. Menu item + * links and the corresponding list toggle are wrapped with in a div + * classed with .box. The .box div provides a positioning context for the + * item list toggle. + * + * @param {jQuery} $menu + * The root of the menu to be initialized. + */ + function initItems ($menu) { + var options = { + 'class': 'icon handle', + 'action': ui.handleOpen, + 'text': '' + }; + // Initialize items and their links. + $menu.find('li > a').wrap('<div class="box">'); + // Add a handle to each list item if it has a menu. + $menu.find('li').each(function (index, element) { + var $item = $(element); + if ($item.find('> ul.menu').length) { + var $box = $item.find('> .box'); + options.text = Drupal.t('@label', {'@label': $box.find('a').text()}); + $item.find('> .box') + .append(Drupal.theme('toolbarMenuItemToggle', options)); + } + }); + } + /** + * Adds a level class to each list based on its depth in the menu. + * + * This function is called recursively on each sub level of lists elements + * until the depth of the menu is exhausted. + * + * @param {jQuery} $lists + * A jQuery object of ul elements. + * + * @param {Integer} level + * The current level number to be assigned to the list elements. + */ + function markListLevels ($lists, level) { + level = (!level) ? 1 : level; + var $lis = $lists.find('> li').addClass('level-' + level); + $lists = $lis.find('> ul'); + if ($lists.length) { + markListLevels($lists, level + 1); + } + } + /** + * On page load, open the active menu item. + * + * Marks the trail of the active link in the menu back to the root of the + * menu with .active-trail. + * + * @param {jQuery} $menu + * The root of the menu. + */ + function openActiveItem ($menu) { + var pathItem = $menu.find('a[href="' + location.pathname + '"]'); + if (pathItem.length && !activeItem) { + activeItem = location.pathname; + } + if (activeItem) { + var $activeItem = $menu.find('a[href="' + activeItem + '"]').addClass('active'); + var $activeTrail = $activeItem.parentsUntil('.root', 'li').addClass('active-trail'); + toggleList($activeTrail, true); + } + } + /** + * Store the last-clicked menu item to decorate the active menu trail. + * + * @param {jQuery} event + * A jQuery click event. + */ + function storeActiveItem (event) { + var href = $(event.target).attr('href'); + if (href) { + localStorage.setItem('Drupal.toolbar.menu.activeItem', JSON.stringify(href)); + } + else { + localStorage.removeItem('Drupal.toolbar.menu.activeItem'); + } + } + // Bind event handlers. + $(document) + .on('click.toolbar', '.handle', toggleClickHandler) + .on('click.toolbar', 'li > .box > a', storeActiveItem); + // Return the jQuery object. + return this.each(function (selector) { + var $menu = $(this).once('toolbar-menu'); + if ($menu.length) { + $menu.addClass('root'); + initItems($menu); + markListLevels($menu); + // Restore previous and active states. + openActiveItem($menu); + } + }); + }; + + /** + * A toggle is an interactive element often bound to a click handler. + * + * @return {String} + * A string representing a DOM fragment. + */ + Drupal.theme.toolbarMenuItemToggle = function (options) { + return '<button class="' + options['class'] + '"><span class="action">' + options.action + '</span><span class="label">' + options.text + '</span></button>'; + }; + +}(jQuery, Drupal)); diff --git a/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarHookToolbarTest.php b/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarHookToolbarTest.php new file mode 100644 index 0000000000000000000000000000000000000000..442eb4ae8d76802c5fc1c5ebfa209a5971daf800 --- /dev/null +++ b/core/modules/toolbar/lib/Drupal/toolbar/Tests/ToolbarHookToolbarTest.php @@ -0,0 +1,57 @@ +<?php + +/** + * @file + * Definition of Drupal\toolbar\Tests\ToolbarHookToolbarTest. + */ + +namespace Drupal\toolbar\Tests; + +use Drupal\simpletest\WebTestBase; + +/** + * Tests the toolbar tab and tray registration. + */ +class ToolbarHookToolbarTest extends WebTestBase { + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = array('toolbar', 'toolbar_test'); + + public static function getInfo() { + return array( + 'name' => 'Toolbar hook_toolbar', + 'description' => 'Tests the implementation of hook_toolbar by a module.', + 'group' => 'Toolbar', + ); + } + + function setUp() { + parent::setUp(); + + // Create an administrative user and log it in. + $this->admin_user = $this->drupalCreateUser(array('access toolbar')); + $this->drupalLogin($this->admin_user); + } + + /** + * Tests for inclusion of a tab and tray in the toolbar by a module + * implementing hook_toolbar. + */ + function testHookToolbar() { + $this->drupalGet('/node'); + $this->assertResponse(200); + + // Assert that the toolbar is present in the HTML. + $this->assertRaw('id="toolbar-administration"'); + + // Assert that the tab registered by toolbar_test is present. + $this->assertRaw('id="toolbar-tab-testing"'); + + // Assert that the tray registered by toolbar_test is present. + $this->assertRaw('id="toolbar-tray-testing"'); + } +} diff --git a/core/modules/toolbar/templates/toolbar.tpl.php b/core/modules/toolbar/templates/toolbar.tpl.php deleted file mode 100644 index b3d561c363e758a682466847b0ea2c25aec9fccc..0000000000000000000000000000000000000000 --- a/core/modules/toolbar/templates/toolbar.tpl.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/** - * @file - * Default template for admin toolbar. - * - * Available variables: - * - $attributes: An instance of Attributes class that can be manipulated as an - * array and printed as a string. - * It includes the 'class' information, which includes: - * - toolbar: The current template type, i.e., "theming hook". - * - $toolbar['toolbar_user']: User account / logout links. - * - $toolbar['toolbar_menu']: Top level Administration menu links. - * - $toolbar['toolbar_drawer']: A place for extended toolbar content. - * - * @see template_preprocess() - * @see template_preprocess_toolbar() - * - * @ingroup themeable - */ -?> -<nav id="toolbar" role="navigation" class="<?php print $attributes['class']; ?> clearfix" <?php print $attributes; ?>> - <div class="toolbar-menu clearfix"> - <?php print render($toolbar['toolbar_home']); ?> - <?php print render($toolbar['toolbar_user']); ?> - <?php print render($toolbar['toolbar_menu']); ?> - <?php if ($toolbar['toolbar_drawer']):?> - <?php print render($toolbar['toolbar_toggle']); ?> - <?php endif; ?> - </div> - - <?php print render($toolbar['toolbar_drawer']); ?> -</nav> diff --git a/core/modules/toolbar/templates/toolbar.twig b/core/modules/toolbar/templates/toolbar.twig new file mode 100644 index 0000000000000000000000000000000000000000..c2181dfa57ec3db3db20ad019342a4881d6cd90c --- /dev/null +++ b/core/modules/toolbar/templates/toolbar.twig @@ -0,0 +1,39 @@ +{# +/** + * @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 + */ +#} + +<nav id="{{ attributes.id }}" class="{{ attributes.class }}"{{ attributes }}> + <!-- Tabs --> + {{ tabs }} + + <!-- Trays --> + {% for tray in trays %} + <div id="{{ tray.attributes.id }}" class="{{ tray.attributes.class }}"{{ tray.attributes }}> + <div class="lining clearfix"> + <h3 class="element-invisible">{{ tray.heading }}</h3> + {{ tray.content }} + </div> + </div> + {% endfor %} +</nav> diff --git a/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.info b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.info new file mode 100644 index 0000000000000000000000000000000000000000..b8e0c59779effdb08ed6bcf31f6b283bc40d3e0e --- /dev/null +++ b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.info @@ -0,0 +1,6 @@ +name = "Toolbar module API tests" +description = "Support module for toolbar testing." +package = Testing +version = VERSION +core = 8.x +hidden = TRUE diff --git a/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module new file mode 100644 index 0000000000000000000000000000000000000000..cadddc9baa23548f57e59c3b0757b1ec3407b573 --- /dev/null +++ b/core/modules/toolbar/tests/modules/toolbar_test/toolbar_test.module @@ -0,0 +1,40 @@ +<?php + +/** + * @file + * A dummy module to test API interaction with the Toolbar module. + */ + +/** + * Um + */ +function toolbar_test_toolbar() { + $tray_items = array( + l('link 1', '<front>'), + l('link 2', '<front>'), + l('link 3', '<front>'), + ); + $items['testing'] = array( + 'tab' => array( + 'title' => t('Test tab'), + 'href' => '', + 'html' => FALSE, + 'attributes' => array( + 'title' => t('Test tab'), + ), + ), + 'tray' => array( + '#heading' => t('Test tray'), + 'content' => array( + '#theme' => 'item_list', + '#items' => $tray_items, + '#attributes' => array( + 'class' => array('menu'), + ), + ), + ), + 'weight' => 50, + ); + + return $items; +} diff --git a/core/modules/toolbar/toolbar-rtl.css b/core/modules/toolbar/toolbar-rtl.css deleted file mode 100644 index e12154724a70d587bcbba4c8a20ea806383dd2a7..0000000000000000000000000000000000000000 --- a/core/modules/toolbar/toolbar-rtl.css +++ /dev/null @@ -1,37 +0,0 @@ - -#toolbar, -#toolbar * { - text-align: right; -} -#toolbar ul li { - float: right; -} -#toolbar ul li a { - display: inline-block; - float: none; - zoom: 1; -} -#toolbar div.toolbar-menu { - padding: 5px 50px 5px 50px; -} -#toolbar-user { - float: left; -} -#toolbar ul#toolbar-user li { - float: none; - display: inline; -} -#toolbar-menu { - float: none; -} -#toolbar-home { - float: right; -} -#toolbar ul li.home a { - position: absolute; - right: 10px; -} -#toolbar div.toolbar-menu a.toggle { - left: 10px; - right: auto; -} diff --git a/core/modules/toolbar/toolbar.api.php b/core/modules/toolbar/toolbar.api.php new file mode 100644 index 0000000000000000000000000000000000000000..42ca3fe0fda70c6343eeda47af59b6a0f08579e8 --- /dev/null +++ b/core/modules/toolbar/toolbar.api.php @@ -0,0 +1,106 @@ +<?php + +/** + * @file + * Hooks provided by the Toolbar module. + */ + +/** + * @addtogroup hooks + * @{ + */ + +/** + * 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. + * + * This hook is invoked in toolbar_view(). + * + * @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. + * + * @see toolbar_view() + * @ingroup toolbar_tabs + */ +function hook_toolbar() { + $items = array(); + + // The 'Home' tab is a simple link, with no corresponding tray. + $items['home'] = array( + 'tab' => array( + 'title' => t('Home'), + 'href' => '<front>', + 'html' => FALSE, + 'attributes' => array( + 'title' => t('Home page'), + ), + ), + 'weight' => -10, + ); + + /** + * A tab may be associated with a tray. + * + * 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. + */ + $items['commerce'] = array( + 'tab' => array( + 'title' => t('Shopping cart'), + 'href' => '', + 'html' => FALSE, + 'attributes' => array( + 'title' => t('Shopping cart'), + ), + ), + 'tray' => array( + '#heading' => t('Shopping cart actions'), + 'content' => array( + '#theme' => 'item_list', + '#items' => array( /* An item list renderable array */ ), + ), + ), + 'weight' => 50, + ); + + return $items; +} + +/** + * 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 + * array is one item returned by a module from hook_toolbar(). Additional items + * may be added, or existing items altered. + * + * @param $items + * 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; +} + +/** + * @} End of "addtogroup hooks". + */ diff --git a/core/modules/toolbar/toolbar.css b/core/modules/toolbar/toolbar.css deleted file mode 100644 index bd1811036fea0d788df5d54a6af747611dedfba8..0000000000000000000000000000000000000000 --- a/core/modules/toolbar/toolbar.css +++ /dev/null @@ -1,129 +0,0 @@ - -body.toolbar { - padding-top: 2.2em; -} -body.toolbar-drawer { - padding-top: 5.3em; -} - -/** - * Aggressive resets so we can achieve a consistent look in hostile CSS - * environments. - */ -#toolbar, -#toolbar * { - border: 0; - font-size: 100%; - line-height: inherit; - list-style: none; - margin: 0; - outline: 0; - padding: 0; - text-align: left; /* LTR */ - vertical-align: baseline; -} - -/** - * Base styles. - * - * We use a keyword for the toolbar font size to make it display consistently - * across different themes, while still allowing browsers to resize the text. - */ -#toolbar { - background: #666; - color: #ccc; - font: normal small "Lucida Grande", Verdana, sans-serif; - left: 0; - margin: 0 -20px; - padding: 0 20px; - position: fixed; - right: 0; - top: 0; - box-shadow: 0 3px 20px #000; - z-index: 600; -} -#toolbar div.collapsed { - display: none; - visibility: hidden; -} -#toolbar a { - color: #fff; - font-size: .846em; - text-decoration: none; -} -#toolbar ul li, -#toolbar ul li a { - float: left; /* LTR */ -} - -/** - * Administration menu. - */ -#toolbar div.toolbar-menu { - background: #000; - line-height: 20px; - padding: 5px 50px 5px 10px; /* LTR */ - position: relative; -} -#toolbar-home a span { - background: url(toolbar.png) no-repeat 0 -45px; - display: block; - height: 14px; - margin: 3px 0px; - text-indent: -9999px; - vertical-align: text-bottom; - width: 11px; -} -#toolbar-user { - float: right; /* LTR */ -} -#toolbar-menu { - float: left; /* LTR */ -} -#toolbar div.toolbar-menu a.toggle { - background: url(toolbar.png) 0 -20px no-repeat; - bottom: 0; - cursor: pointer; - height: 25px; - overflow: hidden; - position: absolute; - right: 10px; /* LTR */ - text-indent: -9999px; - width: 25px; -} -#toolbar div.toolbar-menu a.toggle:focus, -#toolbar div.toolbar-menu a.toggle:hover { - background-position: -50px -20px; -} -#toolbar div.toolbar-menu a.toggle-active { - background-position: -25px -20px; -} -#toolbar div.toolbar-menu a.toggle-active.toggle:focus, -#toolbar div.toolbar-menu a.toggle-active.toggle:hover { - background-position: -75px -20px; -} -#toolbar div.toolbar-menu ul li a { - padding: 0 10px; - border-radius: 10px; -} -#toolbar div.toolbar-menu ul li a:focus, -#toolbar div.toolbar-menu ul li a:hover, -#toolbar div.toolbar-menu ul li a:active, -#toolbar div.toolbar-menu ul li a.active:focus { - background: #444; -} -#toolbar div.toolbar-menu ul li a.active:hover, -#toolbar div.toolbar-menu ul li a.active:active, -#toolbar div.toolbar-menu ul li a.active, -#toolbar div.toolbar-menu ul li.active-trail a { - background: url(toolbar.png) 0 0 repeat-x; - text-shadow: #333 0 1px 0; -} - -/** - * Collapsed drawer of additional toolbar content. - */ -#toolbar div.toolbar-drawer { - position: relative; - padding: 0 10px; -} diff --git a/core/modules/toolbar/toolbar.info b/core/modules/toolbar/toolbar.info index 758dc9c6e9065af9638165c490a0337fbd009782..a6fd8414d583370df5eb280a45746da0396bb977 100644 --- a/core/modules/toolbar/toolbar.info +++ b/core/modules/toolbar/toolbar.info @@ -3,3 +3,7 @@ description = Provides a toolbar that shows the top-level administration menu it core = 8.x package = Core version = VERSION + +dependencies[] = breakpoint + +configure = admin/structure/toolbar diff --git a/core/modules/toolbar/toolbar.install b/core/modules/toolbar/toolbar.install new file mode 100644 index 0000000000000000000000000000000000000000..2b23e3d7ff5022198294df7b36cd590580976fca --- /dev/null +++ b/core/modules/toolbar/toolbar.install @@ -0,0 +1,46 @@ +<?php + +/** + * @file + * Install, update and uninstall functions for the toolbar module. + */ + +/** + * Implements hook_schema(). + */ +function toolbar_schema() { + $schema['cache_toolbar'] = drupal_get_schema_unprocessed('system', 'cache'); + $schema['cache_toolbar']['description'] = 'Cache table for the Toolbar module to store per-user hashes of rendered toolbar subtrees.'; + return $schema; +} + +/** + * @defgroup updates-7.x-to-8.x Updates from 7.x to 8.x + * @{ + * Update functions from 7.x to 8.x. + */ + +/** + * Creates the {cache_toolbar} cache table. + */ +function toolbar_update_8000() { + $schema['cache_toolbar'] = drupal_get_schema_unprocessed('system', 'cache'); + $schema['cache_toolbar']['description'] = 'Cache table for the Toolbar module to store per-user hashes of rendered toolbar subtrees.'; + db_create_table('cache_toolbar', $schema['cache_toolbar']); +} + +/** + * Enable the Breakpoint and Config modules. + * + * The 7.x version of the Toolbar module had no dependencies. The 8.x version + * depends on the Breakpoint and Configuration manager modules. + */ +function toolbar_update_8001() { + // Enable the modules without re-installing the schema. + update_module_enable(array('breakpoint', 'config')); +} + +/** + * @} End of "defgroup updates-7.x-to-8.x". + * The next series of updates should start at 9000. + */ diff --git a/core/modules/toolbar/toolbar.js b/core/modules/toolbar/toolbar.js deleted file mode 100644 index 2353050f46e0b3a537af73f7a35562ce4da751d0..0000000000000000000000000000000000000000 --- a/core/modules/toolbar/toolbar.js +++ /dev/null @@ -1,115 +0,0 @@ -(function ($) { - -"use strict"; - -Drupal.toolbar = Drupal.toolbar || {}; - -/** - * Attach toggling behavior and notify the overlay of the toolbar. - */ -Drupal.behaviors.toolbar = { - attach: function(context, settings) { - var $toolbar = $('#toolbar').once('toolbar'); - if ($toolbar.length) { - - // Set the initial state of the toolbar. - Drupal.toolbar.init(); - - $(window).on('resize.toolbar', Drupal.toolbar.height); - - // Toggling toolbar drawer. - $toolbar.find('a.toggle').once('toolbar-toggle').click(function(e) { - e.preventDefault(); - Drupal.toolbar.toggle(); - // Allow resize event handlers to recalculate sizes/positions. - $(window).triggerHandler('resize'); - }); - } - } -}; - -/** - * Retrieve last saved cookie settings and set up the initial toolbar state. - */ -Drupal.toolbar.init = function() { - // Retrieve the collapsed status from a stored cookie. - var collapsed = $.cookie('Drupal.toolbar.collapsed'); - - // Expand or collapse the toolbar based on the cookie value. - if (collapsed === '1') { - Drupal.toolbar.collapse(); - } - else { - Drupal.toolbar.expand(); - } -}; - -/** - * Collapse the toolbar. - */ -Drupal.toolbar.collapse = function() { - var toggle_text = Drupal.t('Show shortcuts'); - $('#toolbar div.toolbar-drawer').addClass('collapsed'); - $('#toolbar a.toggle') - .removeClass('toggle-active') - .attr('title', toggle_text) - .html(toggle_text); - $('body').removeClass('toolbar-drawer').css('paddingTop', Drupal.toolbar.height()); - $.cookie( - 'Drupal.toolbar.collapsed', - 1, - { - path: Drupal.settings.basePath, - // The cookie should "never" expire. - expires: 36500 - } - ); - Drupal.toolbar.height(); - $(document).trigger('offsettopchange'); -}; - -/** - * Expand the toolbar. - */ -Drupal.toolbar.expand = function() { - var toggle_text = Drupal.t('Hide shortcuts'); - $('#toolbar div.toolbar-drawer').removeClass('collapsed'); - $('#toolbar a.toggle') - .addClass('toggle-active') - .attr('title', toggle_text) - .html(toggle_text); - $('body').addClass('toolbar-drawer').css('paddingTop', Drupal.toolbar.height()); - $.cookie( - 'Drupal.toolbar.collapsed', - 0, - { - path: Drupal.settings.basePath, - // The cookie should "never" expire. - expires: 36500 - } - ); - Drupal.toolbar.height(); - $(document).trigger('offsettopchange'); -}; - -/** - * Toggle the toolbar. - */ -Drupal.toolbar.toggle = function() { - if ($('#toolbar div.toolbar-drawer').hasClass('collapsed')) { - Drupal.toolbar.expand(); - } - else { - Drupal.toolbar.collapse(); - } -}; - -Drupal.toolbar.height = function() { - // @TODO this needs to be cached outside this function. - var $toolbar = $('#toolbar'); - var height = $toolbar.outerHeight(); - $toolbar.attr('data-offset-top', height); - return height; -}; - -})(jQuery); diff --git a/core/modules/toolbar/toolbar.module b/core/modules/toolbar/toolbar.module index a54743a9eb4730dcc565a15cee8302a8de073f4d..e543326c08fc8de7b33bec615c2898d4f14ad6f9 100644 --- a/core/modules/toolbar/toolbar.module +++ b/core/modules/toolbar/toolbar.module @@ -5,6 +5,9 @@ * Administration toolbar for quick access to top level administration items. */ +use Symfony\Component\HttpFoundation\JsonResponse; +use Drupal\Core\Template\Attribute; + /** * Implements hook_help(). */ @@ -16,7 +19,7 @@ function toolbar_help($path, $arg) { $output .= '<h3>' . t('Uses') . '</h3>'; $output .= '<dl>'; $output .= '<dt>' . t('Displaying administrative links') . '</dt>'; - $output .= '<dd>' . t('The Toolbar module displays a bar containing top-level administrative links across the top of the screen. Below that, the Toolbar module has a <em>drawer</em> section where it displays links provided by other modules, such as the core <a href="@shortcuts-help">Shortcut module</a>. The drawer can be hidden/shown by using the show/hide shortcuts link at the end of the toolbar.', array('@shortcuts-help' => url('admin/help/shortcut'))) . '</dd>'; + $output .= '<dd>' . t('The Toolbar module displays a bar containing top-level administrative links across the top of the screen. Below that, the Toolbar module has a <em>drawer</em> section where it displays links provided by other modules, such as the core <a href="@shortcuts-help">Shortcut module</a>. The drawer can be hidden/shown by clicking on its corresponding tab.', array('@shortcuts-help' => url('admin/help/shortcut'))) . '</dd>'; $output .= '</dl>'; return $output; } @@ -41,12 +44,6 @@ function toolbar_theme($existing, $type, $theme, $path) { 'render element' => 'toolbar', 'template' => 'toolbar', ); - $items['toolbar_toggle'] = array( - 'variables' => array( - 'collapsed' => NULL, - 'attributes' => array(), - ), - ); return $items; } @@ -54,62 +51,76 @@ function toolbar_theme($existing, $type, $theme, $path) { * Implements hook_menu(). */ function toolbar_menu() { - $items['toolbar/toggle'] = array( - 'title' => 'Toggle drawer visibility', + $items['toolbar/subtrees/%'] = array( + 'page callback' => 'toolbar_subtrees_jsonp', + 'page arguments' => array(2), + 'access callback' => '_toolbar_subtrees_access', + 'access arguments' => array(2), 'type' => MENU_CALLBACK, - 'page callback' => 'toolbar_toggle_page', - 'access arguments' => array('access toolbar'), ); return $items; } /** - * Page callback: Toggles the visibility of the toolbar drawer. + * Access callback: Returns if the user has access to the rendered subtree requested by the hash. * * @see toolbar_menu(). */ -function toolbar_toggle_page() { - global $base_path; - // Toggle the value in the cookie. - setcookie('Drupal.toolbar.collapsed', !_toolbar_is_collapsed(), NULL, $base_path); - // Redirect the user from where he used the toggle element. - drupal_goto(); +function _toolbar_subtrees_access($hash) { + return user_access('access toolbar') && ($hash == _toolbar_get_subtree_hash()); } /** - * Formats an element used to toggle the toolbar drawer's visibility. - * - * @param $variables - * An associative array containing: - * - collapsed: A boolean value representing the toolbar drawer's visibility. - * - attributes: An associative array of HTML attributes. + * Page callback: Returns the rendered subtree of each top-level toolbar link. * - * @return - * An HTML string representing the element for toggling. - * - * @ingroup themable + * @see toolbar_menu(). */ -function theme_toolbar_toggle($variables) { - if ($variables['collapsed']) { - $toggle_text = t('Show shortcuts'); - } - else { - $toggle_text = t('Hide shortcuts'); - $variables['attributes']['class'][] = 'toggle-active'; - } - return l($toggle_text, 'toolbar/toggle', array('query' => drupal_get_destination(), 'attributes' => array('title' => $toggle_text) + $variables['attributes'])); +function toolbar_subtrees_jsonp($hash) { + _toolbar_initialize_page_cache(); + $subtrees = toolbar_get_rendered_subtrees(); + $response = new JsonResponse($subtrees); + $response->setCallback('Drupal.toolbar.setSubtrees'); + return $response; } /** - * Determines the current state of the toolbar drawer's visibility. + * Use Drupal's page cache for toolbar/subtrees/*, even for authenticated users. * - * @return - * TRUE when drawer is collapsed, FALSE when it is expanded. + * This gets invoked after full bootstrap, so must duplicate some of what's + * done by _drupal_bootstrap_page_cache(). + * + * @todo Replace this hack with something better integrated with DrupalKernel + * once Drupal's page caching itself is properly integrated. */ -function _toolbar_is_collapsed() { - // PHP converts dots into underscores in cookie names to avoid problems with - // its parser, so we use a converted cookie name. - return isset($_COOKIE['Drupal_toolbar_collapsed']) ? $_COOKIE['Drupal_toolbar_collapsed'] : 0; +function _toolbar_initialize_page_cache() { + $GLOBALS['conf']['system.performance']['cache']['page']['enabled'] = TRUE; + drupal_page_is_cacheable(TRUE); + + // If we have a cache, serve it. + // @see _drupal_bootstrap_page_cache() + $cache = drupal_page_get_cache(); + if (is_object($cache)) { + header('X-Drupal-Cache: HIT'); + // Restore the metadata cached with the page. + $_GET['q'] = $cache->data['path']; + date_default_timezone_set(drupal_get_user_timezone()); + + drupal_serve_page_from_cache($cache); + + // We are done. + exit; + } + + // Otherwise, create a new page response (that will be cached). + header('X-Drupal-Cache: MISS'); + + // The Expires HTTP header is the heart of the client-side HTTP caching. The + // additional server-side page cache only takes effect when the client + // accesses the callback URL again (e.g., after clearing the browser cache or + // when force-reloading a Drupal page). + $max_age = 3600 * 24 * 365; + drupal_add_http_header('Expires', gmdate(DATE_RFC1123, REQUEST_TIME + $max_age)); + drupal_add_http_header('Cache-Control', 'private, max-age=' . $max_age); } /** @@ -121,7 +132,6 @@ function toolbar_page_build(&$page) { $page['page_top']['toolbar'] = array( '#pre_render' => array('toolbar_pre_render'), '#access' => user_access('access toolbar'), - 'toolbar_drawer' => array(), ); } @@ -139,27 +149,42 @@ function toolbar_pre_render($toolbar) { } /** - * Implements hook_preprocess_HOOK() for html.tpl.php. - * - * Add some page classes, so global page theming can adjust to the toolbar. + * Implements template_preprocess_HOOK(). */ -function toolbar_preprocess_html(&$vars) { - if (isset($vars['page']['page_top']['toolbar']) && user_access('access toolbar')) { - $vars['attributes']['class'][] = 'toolbar'; - if (!_toolbar_is_collapsed()) { - $vars['attributes']['class'][] = 'toolbar-drawer'; - } - } -} +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' + )); -/** - * Implements hook_preprocess_HOOK() for toolbar.tpl.php. - * - * Adding the 'overlay-displace-top' class to the toolbar pushes the overlay - * down, so it appears below the toolbar. - */ -function toolbar_preprocess_toolbar(&$variables) { - $variables['attributes']['class'][] = "overlay-displace-top"; + // 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, + ) + ), + ); + } } /** @@ -179,93 +204,148 @@ function toolbar_system_info_alter(&$info, $file, $type) { } /** - * Builds the admin menu as a structured array ready for drupal_render(). - * - * @return - * Array of links and settings relating to the admin menu. + * Implements hook_toolbar(). */ -function toolbar_view() { - global $user; +function toolbar_toolbar() { + $items = array(); - $build = array( - '#theme' => 'toolbar', - '#attached'=> array( - 'library' => array( - array('toolbar', 'drupal.toolbar'), + // The 'Home' tab is a simple link, with no corresponding tray. + $items['home'] = array( + 'tab' => array( + 'title' => t('Home'), + 'href' => '<front>', + 'html' => FALSE, + 'attributes' => array( + 'title' => t('Home page'), + 'class' => array('icon', 'icon-home'), ), ), + 'weight' => -20, ); - // Retrieve the admin menu from the database. - $links = toolbar_menu_navigation_links(toolbar_get_menu_tree()); - $build['toolbar_menu'] = array( - '#theme' => 'links__toolbar_menu', - '#links' => $links, - '#attributes' => array('id' => 'toolbar-menu'), - '#heading' => array('text' => t('Administrative toolbar'), 'level' => 'h2', 'class' => 'element-invisible'), - ); + // Retrieve the administration menu from the database. + $tree = toolbar_get_menu_tree(); - // Add logout & user account links or login link. - if ($user->uid) { - $links = array( - 'account' => array( - 'title' => t('Hello <strong>@username</strong>', array('@username' => user_format_name($user))), - 'href' => 'user', - 'html' => TRUE, - 'attributes' => array('title' => t('User account')), - ), - 'logout' => array( - 'title' => t('Log out'), - 'href' => 'user/logout', + // Add attributes to the links before rendering. + toolbar_menu_navigation_links($tree); + + $menu = array( + 'toolbar_administration' => array( + '#type' => 'container', + '#attributes' => array( + 'class' => array('toolbar-menu',), ), - ); - } - else { - $links = array( - 'login' => array( - 'title' => t('Log in'), - 'href' => 'user', + 'administration_menu' => menu_tree_output($tree), + ), + '#heading' => t('Administration menu'), + ); + + // To conserve bandwidth, we only include the top-level links in the HTML. + // The subtrees are included in a JSONP script, cached by the browser. Here we + // add that JSONP script. We add it as an external script, because it's a + // Drupal path, not a file available via a stream wrapper. + // @see toolbar_subtrees_jsonp() + $menu['toolbar_administration']['#attached']['js'][url('toolbar/subtrees/' . _toolbar_get_subtree_hash())] = array('type' => 'external'); + + $items['administration'] = array( + 'tab' => array( + 'title' => t('Menu'), + 'href' => 'admin', + 'html' => FALSE, + 'attributes' => array( + 'title' => t('Admin menu'), + 'class' => array('icon', 'icon-menu'), ), + ), + 'tray' => $menu, + '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; + } } - $build['toolbar_user'] = array( - '#theme' => 'links__toolbar_user', - '#links' => $links, - '#attributes' => array('id' => 'toolbar-user'), - ); - // Add a "home" link. - $link = array( - 'home' => array( - 'title' => '<span class="home-link">Home</span>', - 'href' => '<front>', - 'html' => TRUE, - 'attributes' => array('title' => t('Home')), + // 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'), ); - $build['toolbar_home'] = array( - '#theme' => 'links', - '#links' => $link, - '#attributes' => array('id' => 'toolbar-home'), + $tab_defaults = array( + 'title' => '', + 'href' => '', + 'html' => FALSE, + 'attributes' => new Attribute(), ); - // Add an anchor to be able to toggle the visibility of the drawer. - $build['toolbar_toggle'] = array( - '#theme' => 'toolbar_toggle', - '#collapsed' => _toolbar_is_collapsed(), - '#attributes' => array('class' => array('toggle')), - ); + 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'; - // Prepare the drawer links CSS classes. - $toolbar_drawer_classes = array( - 'toolbar-drawer', - 'clearfix', - ); - if (_toolbar_is_collapsed()) { - $toolbar_drawer_classes[] = 'collapsed'; + 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; } - $build['toolbar_drawer']['#type'] = 'container'; - $build['toolbar_drawer']['#attributes']['class'] = $toolbar_drawer_classes; return $build; } @@ -299,34 +379,55 @@ function toolbar_get_menu_tree() { * @return * An array of links as defined above. */ -function toolbar_menu_navigation_links($tree) { - $links = array(); - foreach ($tree as $item) { - if (!$item['link']['hidden'] && $item['link']['access']) { - // Make sure we have a path specific ID in place, so we can attach icons - // and behaviors to the items. - $id = str_replace(array('/', '<', '>'), array('-', '', ''), $item['link']['href']); - - $link = $item['link']['localized_options']; - $link['href'] = $item['link']['href']; - // Add icon placeholder. - $link['title'] = '<span class="icon"></span>' . check_plain($item['link']['title']); - // Add admin link ID. - $link['attributes'] = array('id' => 'toolbar-link-' . $id); - if (!empty($item['link']['description'])) { - $link['title'] .= ' <span class="element-invisible">(' . $item['link']['description'] . ')</span>'; - $link['attributes']['title'] = $item['link']['description']; - } - $link['html'] = TRUE; +function toolbar_menu_navigation_links(&$tree) { + foreach ($tree as $key => $item) { + // Configure sub-items. + if (!empty($item['below'])) { + toolbar_menu_navigation_links($tree[$key]['below']); + } + // Make sure we have a path specific ID in place, so we can attach icons + // and behaviors to the items. + $tree[$key]['link']['localized_options']['attributes'] = array( + 'id' => 'toolbar-link-' . str_replace(array('/', '<', '>'), array('-', '', ''), $item['link']['link_path']), + 'class' => array( + 'icon', + 'icon-' . strtolower(str_replace(' ', '-', $item['link']['title'])), + ), + ); + } +} - $class = ' path-' . $id; - if (toolbar_in_active_trail($item['link']['href'])) { - $class .= ' active-trail'; +/** + * Returns the rendered subtree of each top-level toolbar link. + */ +function toolbar_get_rendered_subtrees() { + $subtrees = array(); + $tree = toolbar_get_menu_tree(); + foreach ($tree as $tree_item) { + $item = $tree_item['link']; + if (!$item['hidden'] && $item['access']) { + if ($item['has_children']) { + $query = db_select('menu_links'); + $query->addField('menu_links', 'mlid'); + $query->condition('has_children', 1); + for ($i=1; $i <= $item['depth']; $i++) { + $query->condition('p' . $i, $item['p' . $i]); + } + $parents = $query->execute()->fetchCol(); + $subtree = menu_build_tree($item['menu_name'], array('expanded' => $parents, 'min_depth' => $item['depth']+1)); + toolbar_menu_navigation_links($subtree); + $subtree = menu_tree_output($subtree); + $subtree = drupal_render($subtree); } - $links['menu-' . $item['link']['mlid'] . $class] = $link; + else { + $subtree = ''; + } + + $id = str_replace(array('/', '<', '>'), array('-', '', ''), $item['href']); + $subtrees[$id] = $subtree; } } - return $links; + return $subtrees; } /** @@ -361,23 +462,67 @@ function toolbar_in_active_trail($path) { * Implements hook_library_info(). */ function toolbar_library_info() { - $libraries['drupal.toolbar'] = array( + $libraries['toolbar'] = array( 'title' => 'Toolbar', 'version' => VERSION, 'js' => array( - drupal_get_path('module', 'toolbar') . '/toolbar.js' => array(), + drupal_get_path('module', 'toolbar') . '/js/toolbar.js' => array(), ), 'css' => array( - drupal_get_path('module', 'toolbar') . '/toolbar.css', + drupal_get_path('module', 'toolbar') . '/css/toolbar.base.css', + drupal_get_path('module', 'toolbar') . '/css/toolbar.theme.css', + drupal_get_path('module', 'toolbar') . '/css/toolbar.icons.css', ), 'dependencies' => array( array('system', 'jquery'), array('system', 'drupal'), array('system', 'drupalSettings'), + array('system', 'matchmedia'), + array('system', 'jquery.once'), + array('system', 'drupal.debounce'), + array('toolbar', 'toolbar.menu'), + ), + ); + + $libraries['toolbar.menu'] = array( + 'title' => 'Toolbar nested accordion menus.', + 'version' => VERSION, + 'js' => array( + drupal_get_path('module', 'toolbar') . '/js/toolbar.menu.js' => array(), + ), + 'css' => array( + drupal_get_path('module', 'toolbar') . '/css/toolbar.menu.css', + ), + 'dependencies' => array( + array('system', 'jquery'), + array('system', 'drupal'), array('system', 'jquery.once'), - array('system', 'jquery.cookie'), ), ); return $libraries; } + +/** + * Implements hook_cache_flush(). + */ +function toolbar_cache_flush() { + return array('toolbar'); +} + +/** + * Returns the hash of the per-user rendered toolbar subtrees. + */ +function _toolbar_get_subtree_hash() { + global $user; + $cid = $user->uid . ':' . language(LANGUAGE_TYPE_INTERFACE)->langcode; + if ($cache = cache('toolbar')->get($cid)) { + $hash = $cache->data; + } + else { + $subtrees = toolbar_get_rendered_subtrees(); + $hash = drupal_hash_base64(serialize($subtrees)); + cache('toolbar')->set($cid, $hash); + } + return $hash; +} diff --git a/core/modules/toolbar/toolbar.png b/core/modules/toolbar/toolbar.png deleted file mode 100644 index f2c7f355a6d9d8acb478f25a74ec1670cde26445..0000000000000000000000000000000000000000 --- a/core/modules/toolbar/toolbar.png +++ /dev/null @@ -1,4 +0,0 @@ -‰PNG - -��� IHDR���d���9���÷,~O���·PLTE���ÿÿÿfffÿÿÿfffÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿfffffffff���===>>>GGGHHHPPPQQQXXXfff€€€‚‚‚„„„………‡‡‡ˆˆˆŠŠŠŒŒŒ’’’”””•••———˜˜˜šššœœœŸŸŸ§§§®®®¯¯¯···¸¸¸ÁÁÁÂÂÂ÷÷÷ûûûüüüýýýþþþÿÿÿ¥sØ���tRNS��€ˆ‹Ž‘•™ÐàðO¼^z��IDATxÚíÓ[OÂ@†áo° -¨V£¢‚çÄùÿ¿K71i†’î„‹}.öf.ÞÝIïðf�¯ðb�Ïðd�ð`�÷pg�·01€±ÜÀµ\ÀÈ�. àÂ�Î �ˆš\ÔŒPê Ò`M£Râ�ë¢h±®Uâ�l DBÄ(ÒgÅ°›8Ý!+2VL—â,§Z$MNY1èü6:V,䓳•ˆ¬fÚKzíäøŒ‹òA»ÇŠùZ¾?6Öse]ù…OÔ¥IºñÂ_™þÄ"[Wßߺú¢,ü“ ‘}Œ8DØíÎÁ!yP,Gä9BU©’×ÕÄ©‘ÇÕ%W'‘XþÄþ"òÏ_ÄUŸ!²‘ÀN<*Ù"…ð����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/user/images/icon-user-active.png b/core/modules/user/images/icon-user-active.png new file mode 100644 index 0000000000000000000000000000000000000000..3c9d73b69c8056240328d93e86dc92375ca8bce4 --- /dev/null +++ b/core/modules/user/images/icon-user-active.png @@ -0,0 +1,4 @@ +‰PNG + +��� IHDR���������Ä´l;���tEXtSoftware�Adobe ImageReadyqÉe<��IDATxÚb`vàß¿@Ü�Äçø?߇òÈ6ôïß¿ +@|ˆÿcÁ q²þýû÷þ?þüÇ…Aò¸ô2â’øõë—:O„ý†lllÐYp©þÿÿ?±aˆUžH£(Òñ¹ø‘f< )ŒAàË—/ ÈqÀ£ä�#Éþü~ à °Hƒ"Ì‘——÷ɃÀ§OŸ@†'�±?’ðF ^ÀÇÇ÷î9ÅÅïÞ½¹.�ˆíX‘‘ÑÀH>�Àƒ@¼AHHèŠÁoß¾m�Rù¸Ò%‘�dh£°°ð°ÁoÞ¼éRT‰FÆW¯^¼|ŸÚaÌ£� f …Á´H,”– ø\<´ª4€��´d¦›Õd����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/user/images/icon-user.png b/core/modules/user/images/icon-user.png new file mode 100644 index 0000000000000000000000000000000000000000..3c847c64c4f72337104bf67ad558dd9f7211fef2 --- /dev/null +++ b/core/modules/user/images/icon-user.png @@ -0,0 +1,6 @@ +‰PNG + +��� IHDR���������Ä´l;���tEXtSoftware�Adobe ImageReadyqÉe<��&IDATxÚb`j€‘‚“'O +022�™þ@l�Ä€xáÿÿÿ'˜›› ËàãÇ+� Ýd*`‘~�4ÜÑÒÒò6½,øþ÷ïß|†2@ÅAòŽ$¹øСC oŸ'"8 íìì.íâ¿ÿ +O$0(JøEádÅȈ5ò˜pipuu}�Ž@Ì€�©#É`�º8èò `Á‚/€äÉÎ ›7oENÐ$ïoR|}}?l–^½z5Èu@ÙC3€f€æƒ@zChhèƒW®\Ù�40Wº$|�ZÐ>lð²eËú¡ µ@#ã’%K@^¾Oí0f¦Å�ZD0= +ÐÄ`P¢•ÁòCªÎ0��q—ÛWù����IEND®B`‚ \ No newline at end of file diff --git a/core/modules/user/user.css b/core/modules/user/user.css index 866ee401d93fcc29c55da63c65a4366df7ed66c4..a54a5d0163ec33e09e6cacd75f0c6f56db180768 100644 --- a/core/modules/user/user.css +++ b/core/modules/user/user.css @@ -1,4 +1,3 @@ - #permissions td.module { font-weight: bold; } @@ -88,3 +87,14 @@ div.password-suggestions ul { .profile dd { margin: 0 0 1em 0; } + +/** + * Toolbar icon. + */ +.icon-user:before { + background-image: url("images/icon-user.png"); +} +.icon-user:active:before, +.icon-user.active:before { + background-image: url("images/icon-user-active.png"); +} diff --git a/core/modules/user/user.module b/core/modules/user/user.module index 68b45ea4958268b32fd9de3db27b33522d733123..d576afc2c512046363935b8db44fde5dc2e752b4 100644 --- a/core/modules/user/user.module +++ b/core/modules/user/user.module @@ -3099,6 +3099,66 @@ function user_file_download_access($field, EntityInterface $entity, File $file) } } +/** + * Implements hook_toolbar(). + */ +function user_toolbar() { + global $user; + + // Add logout & user account links or login link. + if ($user->uid) { + $links = array( + 'account' => array( + 'title' => t('View profile'), + 'href' => 'user', + 'html' => TRUE, + 'attributes' => array( + 'title' => t('User account'), + ), + ), + 'logout' => array( + 'title' => t('Log out'), + 'href' => 'user/logout', + ), + ); + } + else { + $links = array( + 'login' => array( + 'title' => t('Log in'), + 'href' => 'user', + ), + ); + } + + $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', + 'html' => FALSE, + 'attributes' => array( + 'title' => t('My account'), + 'class' => array('icon', 'icon-user'), + ), + ), + 'tray' => $user_tray, + 'weight' => 100, + ); + + return $items; +} + /** * Implements hook_library_info(). */ diff --git a/core/profiles/standard/standard.info b/core/profiles/standard/standard.info index 172d672f449154efb5754ab4745b37b1d1d06641..fae6d76fee58b31c66d728c319b9886e08c3df7f 100644 --- a/core/profiles/standard/standard.info +++ b/core/profiles/standard/standard.info @@ -5,6 +5,7 @@ core = 8.x dependencies[] = node dependencies[] = history dependencies[] = block +dependencies[] = breakpoint dependencies[] = color dependencies[] = config dependencies[] = comment