diff --git a/core/core.libraries.yml b/core/core.libraries.yml
index eb62701..756e1b6 100644
--- a/core/core.libraries.yml
+++ b/core/core.libraries.yml
@@ -193,9 +193,6 @@ drupal.dropbutton:
version: VERSION
js:
misc/dropbutton/dropbutton.js: {}
- css:
- component:
- misc/dropbutton/dropbutton.css: {}
dependencies:
- core/jquery
- core/drupal
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 733fc9f..9d8e845 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1720,7 +1720,7 @@ function drupal_common_theme() {
'variables' => array('links' => array(), 'attributes' => array('class' => array('links')), 'heading' => array(), 'set_active_class' => FALSE),
),
'dropbutton_wrapper' => array(
- 'variables' => array('children' => NULL),
+ 'variables' => array('attributes' => array(), 'children' => NULL),
),
'image' => array(
// HTML 4 and XHTML 1.0 always require an alt attribute. The HTML 5 draft
diff --git a/core/lib/Drupal/Core/Render/Element/Dropbutton.php b/core/lib/Drupal/Core/Render/Element/Dropbutton.php
index 76fab89..a215cc5 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']['data-drupal-dropbutton-menu'] = TRUE;
if (!isset($element['#theme_wrappers'])) {
$element['#theme_wrappers'] = array();
}
diff --git a/core/misc/dropbutton/dropbutton.js b/core/misc/dropbutton/dropbutton.js
index 4f7645c..83cc35c 100644
--- a/core/misc/dropbutton/dropbutton.js
+++ b/core/misc/dropbutton/dropbutton.js
@@ -8,18 +8,21 @@
"use strict";
/**
- * Process elements with the .dropbutton class on page load.
+ * Process elements with the data-drupal-dropbutton attribute on page load.
*
* @type {Drupal~behavior}
+ *
+ * @prop {Drupal~behaviorAttach} attach
+ * Process elements with `data-drupal-dropbutton` attributes.
*/
Drupal.behaviors.dropButton = {
attach: function (context, settings) {
- var $dropbuttons = $(context).find('.dropbutton-wrapper').once('dropbutton');
+ var $dropbuttons = $(context).find('[data-drupal-dropbutton]').once('dropbutton');
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;
@@ -36,10 +39,11 @@
* @function Drupal.DropButton~dropbuttonClickHandler
*
* @param {jQuery.Event} e
+ * jQuery event object.
*/
function dropbuttonClickHandler(e) {
e.preventDefault();
- $(e.target).closest('.dropbutton-wrapper').toggleClass('open');
+ $(e.target).closest('[data-drupal-dropbutton]').toggleClass('is-open');
}
/**
@@ -66,29 +70,36 @@
/**
* @type {jQuery}
*/
- this.$dropbutton = $dropbutton;
+ this.$dropbutton = $dropbutton.addClass('dropbutton');
/**
* @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);
- // Identify the secondary actions.
- var $secondary = this.$actions.slice(1);
- $secondary.addClass('secondary-action');
- // Add toggle link.
- $primary.after(Drupal.theme('dropbuttonToggle', options));
+ var $li = this.$actions.slice(0, 1);
+ $li.find('a, input, button')
+ .addClass('button dropbutton__primary-action')
+ .insertBefore(this.$list)
+ // Add toggle link.
+ .after(Drupal.theme('dropbuttonToggle', options));
+ // Remove parent
for first dropbutton action.
+ $li.remove();
+
+ // Identify the secondary actions, reset their appearance.
+ this.$actions.slice(1).find('a, input, button')
+ .addClass('dropbutton__menu-item reset-appearance')
+ .removeClass('button');
+
// Bind mouse events.
this.$dropbutton
.addClass('dropbutton-multiple')
@@ -122,7 +133,11 @@
});
}
else {
- this.$dropbutton.addClass('dropbutton-single');
+ // If there's only one action, add a button class.
+ this.$actions.find('a, input, button')
+ .addClass('button')
+ .insertBefore(this.$list);
+ this.$list.remove();
}
}
@@ -130,6 +145,7 @@
* Extend the DropButton constructor.
*/
$.extend(DropButton, /** @lends Drupal.DropButton */{
+
/**
* Store all processed DropButtons.
*
@@ -151,9 +167,8 @@
* passing false.
*/
toggle: function (show) {
- var isBool = typeof show === 'boolean';
- show = isBool ? show : !this.$dropbutton.hasClass('open');
- this.$dropbutton.toggleClass('open', show);
+ var toggle = typeof show === 'boolean' ? show : !this.$dropbutton.hasClass('is-open');
+ this.$dropbutton.toggleClass('is-open', toggle);
},
/**
@@ -190,6 +205,7 @@
/**
* @param {jQuery.Event} e
+ * jQuery event object.
*/
focusOut: function (e) {
this.hoverOut.call(this, e);
@@ -197,28 +213,25 @@
/**
* @param {jQuery.Event} e
+ * jQuery event object.
*/
focusIn: function (e) {
this.hoverIn.call(this, e);
}
});
- $.extend(Drupal.theme, /** @lends Drupal.theme */{
-
- /**
- * A toggle is an interactive element often bound to a click handler.
- *
- * @param {object} options
- * @param {string} [options.title]
- * The HTML anchor title attribute and text for the inner span element.
- *
- * @return {string}
- * A string representing a DOM fragment.
- */
- dropbuttonToggle: function (options) {
- return '
';
- }
- });
+ /**
+ * A toggle is an interactive element often bound to a click handler.
+ *
+ * @param {string} title
+ * The text of the inner span element for screen readers.
+ *
+ * @return {string}
+ * A string representing a DOM fragment.
+ */
+ Drupal.theme.dropbuttonToggle = function (title) {
+ return '';
+ };
// Expose constructor in the public space.
Drupal.DropButton = DropButton;
diff --git a/core/modules/book/src/Tests/BookTest.php b/core/modules/book/src/Tests/BookTest.php
index b1c9fa3..1679172 100644
--- a/core/modules/book/src/Tests/BookTest.php
+++ b/core/modules/book/src/Tests/BookTest.php
@@ -641,7 +641,7 @@ public function testAdminBookNodeListing() {
$this->drupalGet('admin/structure/book/' . $this->book->id());
$this->assertText($this->book->label(), 'The book title is displayed on the administrative book listing page.');
- $elements = $this->xpath('//table//ul[@class="dropbutton"]/li/a');
+ $elements = $this->xpath('//table//[@data-drupal-dropbutton]/ul/li/a');
$this->assertEqual((string) $elements[0], 'View', 'View link is found from the list.');
}
diff --git a/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php b/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php
index 13b56d5..a7aa219 100644
--- a/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php
+++ b/core/modules/config_translation/src/Tests/ConfigTranslationOverviewTest.php
@@ -81,7 +81,7 @@ public function testMapperListPage() {
$this->assertLinkByHref('admin/config/people/accounts/translate');
// Make sure there is only a single operation for each dropbutton, either
// 'List' or 'Translate'.
- foreach ($this->cssSelect('ul.dropbutton') as $i => $dropbutton) {
+ foreach ($this->cssSelect('[data-drupal-dropbutton] ul') as $i => $dropbutton) {
$this->assertIdentical(1, $dropbutton->count());
foreach ($dropbutton->li as $link) {
$this->assertTrue(((string) $link->a === 'Translate') || ((string) $link->a === 'List'));
@@ -108,7 +108,7 @@ public function testMapperListPage() {
// Make sure there is only a single 'Translate' operation for each
// dropbutton.
- foreach ($this->cssSelect('ul.dropbutton') as $i => $dropbutton) {
+ foreach ($this->cssSelect('[data-drupal-dropbutton] ul') as $i => $dropbutton) {
$this->assertIdentical(1, $dropbutton->count());
foreach ($dropbutton->li as $link) {
$this->assertIdentical('Translate', (string) $link->a);
diff --git a/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php b/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
index 9ed2e46..781f960 100644
--- a/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
+++ b/core/modules/content_translation/src/Tests/ContentTranslationUITestBase.php
@@ -216,7 +216,7 @@ protected function doTestTranslationOverview() {
$elements = $this->xpath('//table//a[@href=:href]', array(':href' => $view_path));
$this->assertEqual((string) $elements[0], $entity->getTranslation($langcode)->label(), format_string('Label correctly shown for %language translation.', array('%language' => $langcode)));
$edit_path = $entity->url('edit-form', array('language' => $language));
- $elements = $this->xpath('//table//ul[@class="dropbutton"]/li/a[@href=:href]', array(':href' => $edit_path));
+ $elements = $this->xpath('//table//[@data-drupal-dropbutton]/ul/li/a[@href=:href]', array(':href' => $edit_path));
$this->assertEqual((string) $elements[0], t('Edit'), format_string('Edit link correct for %language translation.', array('%language' => $langcode)));
}
}
diff --git a/core/modules/field_ui/src/Tests/ManageFieldsTest.php b/core/modules/field_ui/src/Tests/ManageFieldsTest.php
index c09550f..2dd1895 100644
--- a/core/modules/field_ui/src/Tests/ManageFieldsTest.php
+++ b/core/modules/field_ui/src/Tests/ManageFieldsTest.php
@@ -154,7 +154,7 @@ function manageFieldsPage($type = '') {
// Assert entity operations for all fields.
$number_of_links = 3;
$number_of_links_found = 0;
- $operation_links = $this->xpath('//ul[@class = "dropbutton"]/li/a');
+ $operation_links = $this->xpath('//div[@data-drupal-dropbutton]//a');
$url = base_path() . "admin/structure/types/manage/$type/fields/node.$type.body";
foreach ($operation_links as $link) {
diff --git a/core/modules/language/config/optional/tour.tour.language.yml b/core/modules/language/config/optional/tour.tour.language.yml
index 7ee56b4..6520f47 100644
--- a/core/modules/language/config/optional/tour.tour.language.yml
+++ b/core/modules/language/config/optional/tour.tour.language.yml
@@ -44,7 +44,7 @@ tips:
body: '
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.