diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php index 251b920..48b53bd 100644 --- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php @@ -116,8 +116,10 @@ public function onRespond(FilterResponseEvent $event) { $response->headers->set('X-Frame-Options', 'SAMEORIGIN', FALSE); // Expose the cache contexts and cache tags associated with this page in a - // X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags header respectively. - if ($response instanceof CacheableResponseInterface) { + // X-Drupal-Cache-Contexts and X-Drupal-Cache-Tags header respectively, when + // either a reverse proxy is being used (so the reverse proxy or CDN can be + // invalidated when appropriate) or when developing/debugging. + if ((Settings::get('reverse_proxy', FALSE) || Settings::get('send_cacheability_headers', FALSE)) && $response instanceof CacheableResponseInterface) { $response_cacheability = $response->getCacheableMetadata(); $response->headers->set('X-Drupal-Cache-Tags', implode(' ', $response_cacheability->getCacheTags())); $response->headers->set('X-Drupal-Cache-Contexts', implode(' ', $this->cacheContextsManager->optimizeTokens($response_cacheability->getCacheContexts()))); diff --git a/core/lib/Drupal/Core/Render/Element/Dropbutton.php b/core/lib/Drupal/Core/Render/Element/Dropbutton.php index 76fab89..c690089 100644 --- a/core/lib/Drupal/Core/Render/Element/Dropbutton.php +++ b/core/lib/Drupal/Core/Render/Element/Dropbutton.php @@ -34,7 +34,8 @@ public function getInfo() { */ public static function preRenderDropbutton($element) { $element['#attached']['library'][] = 'core/drupal.dropbutton'; - $element['#attributes']['class'][] = 'dropbutton'; + $element['#attributes']['class'][] = 'dropbutton__menu'; + $element['#attributes']['class'][] = 'js-dropbutton__menu'; if (!isset($element['#theme_wrappers'])) { $element['#theme_wrappers'] = array(); } diff --git a/core/misc/dropbutton/dropbutton.css b/core/misc/dropbutton/dropbutton.css index 5990514..c2e6820 100644 --- a/core/misc/dropbutton/dropbutton.css +++ b/core/misc/dropbutton/dropbutton.css @@ -7,75 +7,77 @@ /** * When a dropbutton has only one option, it is simply a button. */ -.dropbutton-wrapper, -.dropbutton-wrapper div { +.dropbutton, +.dropbutton div { box-sizing: border-box; } -.js .dropbutton-wrapper, -.js .dropbutton-widget { - display: block; +.js .dropbutton { position: relative; + display: block; + float: left; } @media screen and (max-width:600px) { - .js .dropbutton-wrapper { + .js .dropbutton { width: 100%; } } /* Splitbuttons */ @media screen and (min-width:600px) { - .form-actions .dropbutton-wrapper { + .form-actions .dropbutton { float: left; /* LTR */ } - [dir="rtl"] .form-actions .dropbutton-wrapper { + [dir="rtl"] .form-actions .dropbutton { float: right; } } -.js .form-actions .dropbutton-widget { +.js .form-actions .dropbutton { position: static; } -.js td .dropbutton-widget { - position: absolute; -} -.js td .dropbutton-wrapper { +.js td .dropbutton { min-height: 2em; } -.js td .dropbutton-multiple { - padding-right: 10em; /* LTR */ - margin-right: 2em; /* LTR */ +.js td .dropbutton--multiple { max-width: 100%; } -[dir="rtl"].js td .dropbutton-multiple { - padding-right: 0; - margin-right: 0; - padding-left: 10em; - margin-left: 2em; -} -.js td .dropbutton-multiple .dropbutton-action a, -.js td .dropbutton-multiple .dropbutton-action input, -.js td .dropbutton-multiple .dropbutton-action button { +.js td .dropbutton--multiple .dropbutton__action { width: auto; } /* UL styles are over-scoped in core, so this selector needs weight parity. */ -.js .dropbutton-widget .dropbutton { +.js .dropbutton .dropbutton__menu { + /* Positioning declarations */ + position: absolute; + top: 2em; + /* Box model declarations */ + display: none; + margin: 5px 0; + min-width: 100%; + padding: 5px 0; + /* Other declarations */ + background: #fff; + border: 1px solid #a6a6a6; + border-radius: 5px; list-style-image: none; list-style-type: none; - margin: 0; overflow: hidden; - padding: 0; } -.js .dropbutton li, -.js .dropbutton a { + +.dropbutton--multiple.is-open .dropbutton__menu { + display: block; +} + +.js .dropbutton__menu li, +.js .dropbutton__menu .dropbutton__action { display: block; outline: none; } -.js .dropbutton li:hover, -.js .dropbutton li:focus, -.js .dropbutton a:hover, -.js .dropbutton a:focus { +.js .dropbutton__menu li:hover, +.js .dropbutton__menu li:focus, +.js .dropbutton__menu a:hover, +.js .dropbutton__menu a:focus { outline: initial; } @@ -89,76 +91,100 @@ * The arrow is created using border on a zero-width, zero-height span. * The arrow inherits the link color, but can be overridden with border colors. */ -.js .dropbutton-multiple .dropbutton-widget { +.js .dropbutton--multiple { padding-right: 2em; /* LTR */ } -.js[dir="rtl"] .dropbutton-multiple .dropbutton-widget { +[dir="rtl"].js .dropbutton--multiple { padding-left: 2em; padding-right: 0; } -.dropbutton-multiple.open, -.dropbutton-multiple.open .dropbutton-widget { +.dropbutton--multiple.is-open { max-width: none; -} -.dropbutton-multiple.open { z-index: 100; } -.dropbutton-multiple .dropbutton .secondary-action { - display: none; +.dropbutton--multiple .dropbutton__menu .dropbutton__action { + padding: 0.35em 1em; + color: #262626; + text-decoration: none; } -.dropbutton-multiple.open .dropbutton .secondary-action { - display: block; + +.dropbutton--multiple .dropbutton__menu .dropbutton__action:focus, +.dropbutton--multiple .dropbutton__menu .dropbutton__action:hover { + background: #c8ecfe; } -.dropbutton-toggle { + +.dropbutton__trigger { + /* Positioning declarations */ bottom: 0; - display: block; - position: absolute; right: 0; /* LTR */ - text-indent: 110%; top: 0; - white-space: nowrap; + /* Box model declarations */ + display: block; + height: auto; + margin: 0; + padding: 0; width: 2em; + /* Other declarations */ + cursor: pointer; + text-indent: 110%; + white-space: nowrap; } -[dir="rtl"] .dropbutton-toggle { +[dir="rtl"] .dropbutton__trigger { left: 0; right: auto; } -.dropbutton-toggle button { - background: none; - border: 0; - cursor: pointer; - display: block; - height: 100%; - margin: 0; - padding: 0; - width: 100%; -} -.dropbutton-toggle button:hover, -.dropbutton-toggle button:focus { +.dropbutton__trigger:hover, +.dropbutton__trigger:focus { outline: initial; } -.dropbutton-arrow { - border-bottom-color: transparent; - border-left-color: transparent; - border-right-color: transparent; - border-style: solid; - border-width: 0.3333em 0.3333em 0; - display: block; - height: 0; - line-height: 0; +.dropbutton__trigger:after { + /* Positioning declarations */ position: absolute; right: 40%; /* 0.6667em; */ /* LTR */ top: 50%; + /* Box model declarations */ + content: ""; + display: block; + height: 0; + line-height: 0; margin-top: -0.1666em; width: 0; + /* Other declarations */ + border-bottom-color: transparent; + border-left-color: transparent; + border-right-color: transparent; + border-style: solid; + border-width: 0.3333em 0.3333em 0; overflow: hidden; } -[dir="rtl"] .dropbutton-arrow { +[dir="rtl"] .dropbutton__trigger:after { left: 0.6667em; right: auto; } -.dropbutton-multiple.open .dropbutton-arrow { +.dropbutton--multiple.is-open .dropbutton__trigger:after { + top: 0.6667em; border-bottom: 0.3333em solid; border-top-color: transparent; - top: 0.6667em; +} +.dropbutton--multiple .button.dropbutton__action { + /* Box model declarations */ + padding-left: 1em; + float: left; + /* Other declarations */ + border-radius: 0; + border-top-left-radius: 20em; + border-bottom-left-radius: 20em; + font-size: 0.825rem; +} +.dropbutton .button.dropbutton__trigger { + /* Positioning declarations */ + position: absolute; + /* Box model declarations */ + padding-right: 1em; + float: left; + margin-left: -1px; + /* Other declarations */ + border-radius: 0; + border-top-right-radius: 20em; + border-bottom-right-radius: 20em; } diff --git a/core/misc/dropbutton/dropbutton.js b/core/misc/dropbutton/dropbutton.js index 787cc56..654705f 100644 --- a/core/misc/dropbutton/dropbutton.js +++ b/core/misc/dropbutton/dropbutton.js @@ -14,12 +14,12 @@ */ Drupal.behaviors.dropButton = { attach: function (context, settings) { - var $dropbuttons = $(context).find('.dropbutton-wrapper').once('dropbutton'); + var $dropbuttons = $(context).find('.dropbutton').once('dropbutton__menu'); if ($dropbuttons.length) { // Adds the delegated handler that will toggle dropdowns on click. var $body = $('body').once('dropbutton-click'); if ($body.length) { - $body.on('click', '.dropbutton-toggle', dropbuttonClickHandler); + $body.on('click', '.dropbutton__trigger', dropbuttonClickHandler); } // Initialize all buttons. var il = $dropbuttons.length; @@ -39,7 +39,7 @@ */ function dropbuttonClickHandler(e) { e.preventDefault(); - $(e.target).closest('.dropbutton-wrapper').toggleClass('open'); + $(e.target).closest('.dropbutton').toggleClass('is-open'); } /** @@ -71,27 +71,30 @@ /** * @type {jQuery} */ - this.$list = $dropbutton.find('.dropbutton'); + this.$list = $dropbutton.find('.dropbutton__menu'); /** * Find actions and mark them. * * @type {jQuery} */ - this.$actions = this.$list.find('li').addClass('dropbutton-action'); - + this.$actions = this.$list.find('li'); // Add the special dropdown only if there are hidden actions. if (this.$actions.length > 1) { // Identify the first element of the collection. - var $primary = this.$actions.slice(0, 1); + var $primary = this.$actions.slice(0, 1).find('a'); + // Remove parent
Operations are provided for editing and deleting your languages.
You can edit the name and the direction of the language.
Deleted languages can be added back at a later time. Deleting a language will remove all interface translations associated with it, and content in this language will be set to be language neutral. Note that you cannot delete the default language of the site.
' weight: 5 attributes: - data-class: dropbutton-wrapper + data-class: dropbutton language-continue: id: language-continue plugin: text diff --git a/core/modules/node/src/Tests/AssertButtonsTrait.php b/core/modules/node/src/Tests/AssertButtonsTrait.php index 96eb6c8..8742f94 100644 --- a/core/modules/node/src/Tests/AssertButtonsTrait.php +++ b/core/modules/node/src/Tests/AssertButtonsTrait.php @@ -35,7 +35,7 @@ public function assertButtons($buttons, $dropbutton = TRUE) { $this->assertTrue(empty($save_button)); // Dropbutton elements. - $elements = $this->xpath('//div[@class="dropbutton-wrapper"]//input[@type="submit"]'); + $elements = $this->xpath('//div[@class="dropbutton"]//input[@type="submit"]'); $this->assertEqual($count, count($elements)); foreach ($elements as $element) { $value = isset($element['value']) ? (string) $element['value'] : ''; @@ -46,7 +46,7 @@ public function assertButtons($buttons, $dropbutton = TRUE) { else { // Assert there is a save button. $this->assertTrue(!empty($save_button)); - $this->assertNoRaw('dropbutton-wrapper'); + $this->assertNoRaw('dropbutton'); } } } diff --git a/core/modules/simpletest/src/WebTestBase.php b/core/modules/simpletest/src/WebTestBase.php index cc3b270..c11b73b 100644 --- a/core/modules/simpletest/src/WebTestBase.php +++ b/core/modules/simpletest/src/WebTestBase.php @@ -742,6 +742,13 @@ protected function prepareSettings() { 'value' => FALSE, 'required' => TRUE, ]; + + // Send cacheability headers so tests can check their values. + $settings['settings']['send_cacheability_headers'] = (object) [ + 'value' => TRUE, + 'required' => TRUE, + ]; + $this->writeSettings($settings); // Allow for test-specific overrides. $settings_testing_file = DRUPAL_ROOT . '/' . $this->originalSite . '/settings.testing.php'; diff --git a/core/modules/system/templates/dropbutton-wrapper.html.twig b/core/modules/system/templates/dropbutton-wrapper.html.twig index ca0ff7e..b07aa29 100644 --- a/core/modules/system/templates/dropbutton-wrapper.html.twig +++ b/core/modules/system/templates/dropbutton-wrapper.html.twig @@ -14,10 +14,8 @@ #} {% if children %} {% spaceless %} -