diff --git a/core/core.libraries.yml b/core/core.libraries.yml index 275a3ac685dfe36ac86f072a6bff4cabd6880b01..907fb4c7fefd143240045388583fa817871ce938 100644 --- a/core/core.libraries.yml +++ b/core/core.libraries.yml @@ -484,8 +484,8 @@ drupal.autocomplete: - core/drupal - core/drupalSettings - core/drupal.ajax - - core/tabbable.jquery.shim - core/drupal.jquery.position + - core/tabbable drupal.batch: version: VERSION @@ -561,8 +561,8 @@ drupal.dialog: - core/drupalSettings - core/drupal.debounce - core/drupal.displace - - core/tabbable.jquery.shim - core/drupal.jquery.position + - core/tabbable drupal.dialog.ajax: version: VERSION @@ -867,15 +867,6 @@ transliteration: js: assets/vendor/transliteration/bundle.umd.min.js: { minified: true } -tabbable.jquery.shim: - version: VERSION - js: - misc/jquery.tabbable.shim.js: {} - dependencies: - - core/drupal - - core/tabbable - - core/jquery - internal.underscore: # Internal library. Do not depend on it outside core nor add new core usage. # The library will be removed as soon as the following issues are fixed: diff --git a/core/misc/jquery.tabbable.shim.js b/core/misc/jquery.tabbable.shim.js deleted file mode 100644 index cce6815c2467777d93fd78d6f79783df4257eb47..0000000000000000000000000000000000000000 --- a/core/misc/jquery.tabbable.shim.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file - * Defines a backwards-compatible shim for the jQuery UI :tabbable selector. - */ - -(($, Drupal, { isTabbable }) => { - $.extend($.expr[':'], { - tabbable(element) { - Drupal.deprecationError({ - message: - 'The :tabbable selector is deprecated in Drupal 9.2.0 and will be removed in Drupal 11.0.0. Use the core/tabbable library instead. See https://www.drupal.org/node/3183730', - }); - - return isTabbable(element); - }, - }); -})(jQuery, Drupal, window.tabbable); diff --git a/core/modules/system/tests/modules/tabbable_shim_test/src/Controller/TabbableShimDialogIntegrationTestController.php b/core/modules/system/tests/modules/tabbable_shim_test/src/Controller/TabbableShimDialogIntegrationTestController.php deleted file mode 100644 index 6be67334b30a1755eb49f8a0329c9088c94e6e97..0000000000000000000000000000000000000000 --- a/core/modules/system/tests/modules/tabbable_shim_test/src/Controller/TabbableShimDialogIntegrationTestController.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -namespace Drupal\tabbable_shim_test\Controller; - -use Drupal\Core\Controller\ControllerBase; - -/** - * For testing the jQuery :tabbable shim as used in a dialog. - */ -class TabbableShimDialogIntegrationTestController extends ControllerBase { - - /** - * Provides a page with the jQuery UI dialog library for testing . - * - * @return array - * The render array. - */ - public function build() { - return [ - 'container' => [ - '#type' => 'container', - '#attributes' => [ - 'id' => 'tabbable-dialog-test-container', - ], - ], - '#attached' => [ - 'library' => ['core/drupal.dialog'], - ], - ]; - } - -} diff --git a/core/modules/system/tests/modules/tabbable_shim_test/src/Controller/TabbableShimTestController.php b/core/modules/system/tests/modules/tabbable_shim_test/src/Controller/TabbableShimTestController.php deleted file mode 100644 index 82b2b780092134e1a47791577f6d4dc12a35aceb..0000000000000000000000000000000000000000 --- a/core/modules/system/tests/modules/tabbable_shim_test/src/Controller/TabbableShimTestController.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php - -namespace Drupal\tabbable_shim_test\Controller; - -use Drupal\Core\Controller\ControllerBase; - -/** - * For testing the jQuery :tabbable shim. - */ -class TabbableShimTestController extends ControllerBase { - - /** - * Provides a page with the tabbingManager library for testing :tabbable. - * - * @return array - * The render array. - */ - public function build() { - return [ - 'container' => [ - '#type' => 'container', - '#attributes' => [ - 'id' => 'tabbable-test-container', - ], - ], - '#attached' => ['library' => ['core/drupal.autocomplete']], - ]; - } - -} diff --git a/core/modules/system/tests/modules/tabbable_shim_test/tabbable_shim_test.info.yml b/core/modules/system/tests/modules/tabbable_shim_test/tabbable_shim_test.info.yml deleted file mode 100644 index 4689243d510cd4b29cb6b26cf3b50042da970d4e..0000000000000000000000000000000000000000 --- a/core/modules/system/tests/modules/tabbable_shim_test/tabbable_shim_test.info.yml +++ /dev/null @@ -1,5 +0,0 @@ -name: 'Tabbable Shim Test' -type: module -description: 'Module for the testing the :tabbable selector shim' -package: Testing -version: VERSION diff --git a/core/modules/system/tests/modules/tabbable_shim_test/tabbable_shim_test.routing.yml b/core/modules/system/tests/modules/tabbable_shim_test/tabbable_shim_test.routing.yml deleted file mode 100644 index 0be12dfb2f6b40414cb1e0e78553392f7f2f447f..0000000000000000000000000000000000000000 --- a/core/modules/system/tests/modules/tabbable_shim_test/tabbable_shim_test.routing.yml +++ /dev/null @@ -1,15 +0,0 @@ -tabbable_test_page: - path: '/tabbable-shim-test' - defaults: - _controller: '\Drupal\tabbable_shim_test\Controller\TabbableShimTestController::build' - _title: 'Tabbable testing' - requirements: - _access: 'TRUE' - -tabbable_dialog_integration_test_page: - path: '/tabbable-shim-dialog-integration-test' - defaults: - _controller: '\Drupal\tabbable_shim_test\Controller\TabbableShimDialogIntegrationTestController::build' - _title: 'Tabbable dialog integration testing' - requirements: - _access: 'TRUE' diff --git a/core/tests/Drupal/Nightwatch/Tests/tabbableShimTest.js b/core/tests/Drupal/Nightwatch/Tests/tabbableShimTest.js deleted file mode 100644 index c76026d6ff899313db47175f53b6acdb55b41586..0000000000000000000000000000000000000000 --- a/core/tests/Drupal/Nightwatch/Tests/tabbableShimTest.js +++ /dev/null @@ -1,335 +0,0 @@ -// Testing the shimmed jQuery UI :tabbable selector. - -// Test confirming the :tabbable shim returns the same values as jQuery UI -// :tabbable. -// -// An array of objects with the following properties: -// - element: the element to test -// - tabbable: the number of items the :tabbable selector should return when -// the element is the only item in the container being queried. -const tabbableTestScenarios = [ - { - element: '<div>', - tabbable: 0, - }, - { - element: '<div tabindex="0">', - tabbable: 1, - }, - { - element: '<div tabindex="0" hidden>', - tabbable: 0, - }, - { - element: '<div tabindex="0" style="display:none;">', - tabbable: 0, - }, - { - element: '<div href="#">', - tabbable: 0, - }, - { - element: '<a>', - tabbable: 0, - }, - { - element: '<a href="#">', - tabbable: 1, - }, - { - element: '<a tabindex="0">', - tabbable: 1, - }, - { - element: '<a tabindex="-1">', - tabbable: 0, - }, - { - element: '<input type="hidden">', - tabbable: 0, - }, - { - element: '<input type="hidden" tabindex="0">', - tabbable: 0, - }, - { - element: '<input type="hidden" tabindex="1">', - tabbable: 0, - }, - { - element: - '<details><summary>Summary is now tabbable because IE is not supported anymore</summary>Hooray</details>', - tabbable: 1, - }, - { - element: - '<details>A details without a summary should be :tabbable</details>', - tabbable: 1, - }, - { - element: '<ul><li>List item</li></ul>', - tabbable: 0, - }, - { - element: '<ul><li tabindex="0">List item</li></ul>', - tabbable: 1, - }, -]; - -// Element types to add to the test scenarios. -const elementTypesUsedByTabbableTest = [ - 'input-button', - 'input-checkbox', - 'input-color', - 'input-date', - 'input-datetime-local', - 'input-email', - 'input-file', - 'input-image', - 'input-month', - 'input-number', - 'input-password', - 'input-radio', - 'input-range', - 'input-reset', - 'input-search', - 'input-submit', - 'input-tel', - 'input-text', - 'input-time', - 'input-url', - 'input-week', - 'select', - 'button', - 'textarea', -]; - -// Create multiple test scenarios. - -// For each element type being tested, create multiple variations with different -// attributes and store them in the `element:` property. The `tabbable:` property -// is the number of elements in `element:` that would match the :tabbable -// selector. -// Tha variations include: -// - The element with no additional attributes. -// - Separate scenarios for tabindex 0, 1, and -1. -// - With the hidden attribute -// - With `style="display:none;"` -// - With `style="visibility: hidden;"` -elementTypesUsedByTabbableTest.forEach((item) => { - let elementType = item; - let selfClose = ''; - let type = ''; - if (item.indexOf('-') > 0) { - [elementType, type] = item.split('-'); - type = ` type="${type}"`; - selfClose = ' /'; - } - - tabbableTestScenarios.push({ - element: `<${elementType}${type}${selfClose}>`, - tabbable: 1, - }); - tabbableTestScenarios.push({ - element: `<${elementType}${type} tabindex="0"${selfClose}>`, - tabbable: 1, - }); - tabbableTestScenarios.push({ - element: `<${elementType}${type} tabindex="1"${selfClose}>`, - tabbable: 1, - }); - tabbableTestScenarios.push({ - element: `<${elementType}${type} tabindex="-1"${selfClose}>`, - tabbable: 0, - }); - tabbableTestScenarios.push({ - element: `<${elementType}${type} hidden${selfClose}>`, - tabbable: 0, - }); - tabbableTestScenarios.push({ - element: `<${elementType}${type} style="display:none;"${selfClose}>`, - tabbable: 0, - }); - tabbableTestScenarios.push({ - element: `<${elementType}${type} style="visibility: hidden;"${selfClose}>`, - tabbable: 0, - }); -}); - -// The default options for items in dialogIntegrationTestScenarios. -const defaultDialogOptions = { - buttons: [ - { - text: 'Ok', - click: () => {}, - }, - ], -}; - -// Contains scenarios for testing dialog's use of the :tabbable selector. -// These are based on the "focus tabbable" tests within jQuery UI -// @see -// https://github.com/jquery/jquery-ui/blob/1.12.1/tests/unit/dialog/core.js -const dialogIntegrationTestScenarios = [ - { - info: 'An element that was focused previously.', - markup: '<div><input><input></div>', - options: {}, - // eslint-disable-next-line object-shorthand, func-names - testActions: function ($element) { - const $input = $element - .find('input:last') - .trigger('focus') - .trigger('blur'); - $element.dialog('instance')._focusTabbable(); - return $input[0]; - }, - }, - { - info: 'First element inside the dialog matching [autofocus]', - markup: '<div><input><input autofocus></div>', - options: defaultDialogOptions, - // eslint-disable-next-line object-shorthand, func-names - testActions: function ($element) { - return $element.find('input')[1]; - }, - }, - { - info: 'Tabbable element inside the content element', - markup: '<div><input><input></div>', - options: defaultDialogOptions, - // eslint-disable-next-line object-shorthand, func-names - testActions: function ($element) { - return $element.find('input')[0]; - }, - }, - { - info: 'Tabbable element inside the buttonpane', - markup: '<div>text</div>', - options: defaultDialogOptions, - // eslint-disable-next-line object-shorthand, func-names - testActions: function ($element) { - return $element.dialog('widget').find('.ui-dialog-buttonpane button')[0]; - }, - }, - { - info: 'The close button', - markup: '<div>text</div>', - options: {}, - // eslint-disable-next-line object-shorthand, func-names - testActions: function ($element) { - return $element - .dialog('widget') - .find('.ui-dialog-titlebar .ui-dialog-titlebar-close')[0]; - }, - }, - { - info: 'The dialog itself', - markup: '<div>text</div>', - options: { autoOpen: false }, - // eslint-disable-next-line object-shorthand, func-names - testActions: function ($element) { - $element.dialog('widget').find('.ui-dialog-titlebar-close').hide(); - $element.dialog('open'); - return $element.parent()[0]; - }, - }, - { - info: 'Focus starts on second input', - markup: '<div><input><input autofocus></div>', - options: { - // eslint-disable-next-line object-shorthand, func-names - open: function () { - const inputs = jQuery(this).find('input'); - inputs.last().on('keydown', function (event) { - event.preventDefault(); - inputs.first().trigger('focus'); - }); - }, - }, - // eslint-disable-next-line object-shorthand, func-names - testActions: function ($element) { - const inputs = $element.find('input'); - return inputs[1]; - }, - }, -]; - -module.exports = { - '@tags': ['core'], - before(browser) { - browser.drupalInstall().drupalInstallModule('tabbable_shim_test'); - }, - after(browser) { - browser.drupalUninstall(); - }, - 'test tabbable': (browser) => { - browser - .drupalRelativeURL('/tabbable-shim-test') - .waitForElementPresent('#tabbable-test-container', 1000); - - tabbableTestScenarios.forEach((iteration) => { - browser.execute( - // eslint-disable-next-line func-names, prefer-arrow-callback - function (scenario) { - const $container = jQuery('#tabbable-test-container'); - $container.empty(); - $container.append(jQuery(scenario.element)); - - return { - expected: scenario.tabbable, - actual: $container.find(':tabbable').length, - element: scenario.element, - }; - }, - [iteration], - (result) => { - browser.assert.ok(typeof result.value.actual === 'number'); - browser.assert.ok(typeof result.value.expected === 'number'); - browser.assert.equal( - result.value.actual, - result.value.expected, - `Expected :tabbable to return ${result.value.expected} for element ${result.value.element}`, - ); - }, - ); - }); - browser.assert.deprecationErrorExists( - 'The :tabbable selector is deprecated in Drupal 9.2.0 and will be removed in Drupal 11.0.0. Use the core/tabbable library instead. See https://www.drupal.org/node/3183730', - ); - browser.drupalLogAndEnd({ onlyOnError: false }); - }, - 'test tabbable dialog integration': (browser) => { - browser - .drupalRelativeURL('/tabbable-shim-dialog-integration-test') - .waitForElementPresent('#tabbable-dialog-test-container', 1000); - - dialogIntegrationTestScenarios.forEach((iteration) => { - browser.execute( - // eslint-disable-next-line func-names - function (scenario, testActions) { - // Create the jQuery element that will be used in the test steps. - const $element = jQuery(scenario.markup).dialog(scenario.options); - - // Convert the testActions string into a function. testActions is a - // string due to functions being removed from objects passed to - // browser.execute(). - // The expectedActiveElement function performs steps specific to a test - // iteration, then returns the element expected to be active after - // those steps. - // eslint-disable-next-line no-new-func - const expectedActiveElement = new Function(`return ${testActions}`)(); - return expectedActiveElement($element) === document.activeElement; - }, - [iteration, iteration.testActions.toString()], - (result) => { - browser.assert.equal(result.value, true, iteration.info); - }, - ); - }); - browser.assert.deprecationErrorExists( - 'The :tabbable selector is deprecated in Drupal 9.2.0 and will be removed in Drupal 11.0.0. Use the core/tabbable library instead. See https://www.drupal.org/node/3183730', - ); - browser.drupalLogAndEnd({ onlyOnError: false }); - }, -};