diff --git a/core/modules/settings_tray/css/settings_tray.module.css b/core/modules/settings_tray/css/settings_tray.module.css index 05b5bee..e73eeb8 100644 --- a/core/modules/settings_tray/css/settings_tray.module.css +++ b/core/modules/settings_tray/css/settings_tray.module.css @@ -21,3 +21,7 @@ .dialog-off-canvas__main-canvas.js-settings-tray-edit-mode .contextual-links a { pointer-events: inherit; } + +#settings-tray-edit-message:empty { + display: none !important; +} diff --git a/core/modules/settings_tray/js/settings_tray.es6.js b/core/modules/settings_tray/js/settings_tray.es6.js index b4edd84..8064196 100644 --- a/core/modules/settings_tray/js/settings_tray.es6.js +++ b/core/modules/settings_tray/js/settings_tray.es6.js @@ -2,10 +2,14 @@ * @file * Drupal's Settings Tray library. * + * The Drupal.t() function is used in this file but cannot be destructed here + * aliased because Javascript files are scanned for calls to Drupal.t(). + * @todo Destructure Drupal.t() if in possilbe in https://www.drupal.org/node/2893361 + * * @private */ -(function ($, Drupal) { +(function ($, { announce, ajax, attachBehaviors, toolbar, behaviors }) { const blockConfigureSelector = '[data-settings-tray-edit]'; const toggleEditSelector = '[data-drupal-settingstray="toggle"]'; const itemsToToggleSelector = '[data-off-canvas-main-canvas], #toolbar-bar, [data-drupal-settingstray="editable"] a, [data-drupal-settingstray="editable"] button'; @@ -32,7 +36,7 @@ * Close any active toolbar tray before entering edit mode. */ function closeToolbarTrays() { - $(Drupal.toolbar.models.toolbarModel.get('activeTab')).trigger('click'); + $(toolbar.models.toolbarModel.get('activeTab')).trigger('click'); } /** @@ -60,12 +64,46 @@ } /** + * Display a message informing the user that they have entered edit mode. + * + * This message appear at the top of the page below the toolbar. + * The user will be able to click on the message to remove it. + * It will also be removed when exiting edit mode. + * + * @todo Refactor to use Javascript Message API https://www.drupal.org/node/77245 + */ + function displayEditMessage() { + if ($('#settings-tray-edit-message').length) { + return; + } + const editMsg = Drupal.t('You are now in edit mode.'); + const msgDiv = document.createElement('div'); + msgDiv.setAttribute('id', 'settings-tray-edit-message') + Drupal.dialog(msgDiv, { + position: { + my: 'left+5 top+5', + at: 'left+5 top+5', + of: '.dialog-off-canvas__main-canvas', + }, + autoResize: false, + draggable: false, + minHeight: '50px', + title: editMsg, + dialogClass: 'outside-edit-message', + }).show(); + announce(editMsg); + $(msgDiv).on('click.outsidein', e => $(e.target).remove()); + } + + /** * Helper to switch edit mode state. * * @param {boolean} editMode * True enable edit mode, false disable edit mode. + * @param {boolean} displayMessage + * True if the message about entering edit mode should be shown. */ - function setEditModeState(editMode) { + function setEditModeState(editMode, displayMessage = false) { if (!document.querySelector('[data-off-canvas-main-canvas]')) { throw new Error('data-off-canvas-main-canvas is missing from settings-tray-page-wrapper.html.twig'); } @@ -77,6 +115,10 @@ $editButton.text(Drupal.t('Editing')); closeToolbarTrays(); + if (displayMessage) { + displayEditMessage(); + } + $editables = $('[data-drupal-settingstray="editable"]').once('settingstray'); if ($editables.length) { // Use event capture to prevent clicks on links. @@ -123,7 +165,8 @@ $editButton.text(Drupal.t('Edit')); closeOffCanvas(); - disableQuickEdit(); + disableQuickEdit();// Remove edit mode message. + $('#settings-tray-edit-message').remove(); } getItemsToToggle().toggleClass('js-settings-tray-edit-mode', editMode); $('.edit-mode-inactive').toggleClass('visually-hidden', editMode); @@ -145,7 +188,7 @@ * Helper to toggle Edit mode. */ function toggleEditMode() { - setEditModeState(!isInEditMode()); + setEditModeState(!isInEditMode(), true); } /** @@ -173,7 +216,7 @@ * @todo Fix contextual links to work with use-ajax links in * https://www.drupal.org/node/2764931. */ - Drupal.attachBehaviors(data.$el[0]); + attachBehaviors(data.$el[0]); /** * Bind a listener to all 'Quick edit' links for blocks. Click "Edit" button * in toolbar to force Contextual Edit which starts Settings Tray edit @@ -194,9 +237,7 @@ $(document).on('keyup.settingstray', (e) => { if (isInEditMode() && e.keyCode === 27) { - Drupal.announce( - Drupal.t('Exited edit mode.'), - ); + announce(Drupal.t('Exited edit mode.')); toggleEditMode(); } }); @@ -209,11 +250,11 @@ * @prop {Drupal~behaviorAttach} attach * Toggle the js-settings-tray-edit-mode class. */ - Drupal.behaviors.toggleEditMode = { + behaviors.toggleEditMode = { attach() { $(toggleEditSelector).once('settingstray').on('click.settingstray', toggleEditMode); // Find all Ajax instances that use the 'off_canvas' renderer. - Drupal.ajax.instances + ajax.instances // If there is an element and the renderer is 'off_canvas' then we want // to add our changes. .filter(instance => instance && $(instance.element).attr('data-dialog-renderer') === 'off_canvas') @@ -247,4 +288,4 @@ } }, }); -}(jQuery, Drupal)); +})(jQuery, Drupal); diff --git a/core/modules/settings_tray/js/settings_tray.js b/core/modules/settings_tray/js/settings_tray.js index 88cbb0e..af92c08 100644 --- a/core/modules/settings_tray/js/settings_tray.js +++ b/core/modules/settings_tray/js/settings_tray.js @@ -5,7 +5,13 @@ * @preserve **/ -(function ($, Drupal) { +(function ($, _ref) { + var announce = _ref.announce, + ajax = _ref.ajax, + attachBehaviors = _ref.attachBehaviors, + toolbar = _ref.toolbar, + behaviors = _ref.behaviors; + var blockConfigureSelector = '[data-settings-tray-edit]'; var toggleEditSelector = '[data-drupal-settingstray="toggle"]'; var itemsToToggleSelector = '[data-off-canvas-main-canvas], #toolbar-bar, [data-drupal-settingstray="editable"] a, [data-drupal-settingstray="editable"] button'; @@ -20,7 +26,7 @@ } function closeToolbarTrays() { - $(Drupal.toolbar.models.toolbarModel.get('activeTab')).trigger('click'); + $(toolbar.models.toolbarModel.get('activeTab')).trigger('click'); } function disableQuickEdit() { @@ -31,11 +37,38 @@ $('.ui-dialog-off-canvas .ui-dialog-titlebar-close').trigger('click'); } + function displayEditMessage() { + if ($('#settings-tray-edit-message').length) { + return; + } + var editMsg = Drupal.t('You are now in edit mode.'); + var msgDiv = document.createElement('div'); + msgDiv.setAttribute('id', 'settings-tray-edit-message'); + Drupal.dialog(msgDiv, { + position: { + my: 'left+5 top+5', + at: 'left+5 top+5', + of: '.dialog-off-canvas__main-canvas' + }, + autoResize: false, + draggable: false, + minHeight: '50px', + title: editMsg, + dialogClass: 'outside-edit-message' + }).show(); + announce(editMsg); + $(msgDiv).on('click.outsidein', function (e) { + return $(e.target).remove(); + }); + } + function getItemsToToggle() { return $(itemsToToggleSelector).not(contextualItemsSelector); } function setEditModeState(editMode) { + var displayMessage = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + if (!document.querySelector('[data-off-canvas-main-canvas]')) { throw new Error('data-off-canvas-main-canvas is missing from settings-tray-page-wrapper.html.twig'); } @@ -47,6 +80,10 @@ $editButton.text(Drupal.t('Editing')); closeToolbarTrays(); + if (displayMessage) { + displayEditMessage(); + } + $editables = $('[data-drupal-settingstray="editable"]').once('settingstray'); if ($editables.length) { document.querySelector('[data-off-canvas-main-canvas]').addEventListener('click', preventClick, true); @@ -80,6 +117,8 @@ $editButton.text(Drupal.t('Edit')); closeOffCanvas(); disableQuickEdit(); + + $('#settings-tray-edit-message').remove(); } getItemsToToggle().toggleClass('js-settings-tray-edit-mode', editMode); $('.edit-mode-inactive').toggleClass('visually-hidden', editMode); @@ -90,7 +129,7 @@ } function toggleEditMode() { - setEditModeState(!isInEditMode()); + setEditModeState(!isInEditMode(), true); } $(document).on('drupalContextualLinkAdded', function (event, data) { @@ -101,7 +140,7 @@ } }); - Drupal.attachBehaviors(data.$el[0]); + attachBehaviors(data.$el[0]); data.$el.find(blockConfigureSelector).on('click.settingstray', function () { if (!isInEditMode()) { @@ -114,16 +153,16 @@ $(document).on('keyup.settingstray', function (e) { if (isInEditMode() && e.keyCode === 27) { - Drupal.announce(Drupal.t('Exited edit mode.')); + announce(Drupal.t('Exited edit mode.')); toggleEditMode(); } }); - Drupal.behaviors.toggleEditMode = { + behaviors.toggleEditMode = { attach: function attach() { $(toggleEditSelector).once('settingstray').on('click.settingstray', toggleEditMode); - Drupal.ajax.instances.filter(function (instance) { + ajax.instances.filter(function (instance) { return instance && $(instance.element).attr('data-dialog-renderer') === 'off_canvas'; }).forEach(function (instance) { if (!('dialogOptions' in instance.options.data)) { diff --git a/core/modules/settings_tray/settings_tray.libraries.yml b/core/modules/settings_tray/settings_tray.libraries.yml index 672800d..b9d9b25 100644 --- a/core/modules/settings_tray/settings_tray.libraries.yml +++ b/core/modules/settings_tray/settings_tray.libraries.yml @@ -17,6 +17,8 @@ drupal.settings_tray: - core/drupal - core/jquery.once - core/drupal.ajax + - core/drupal.announce + - toolbar/toolbar drupal.off_canvas: version: VERSION js: diff --git a/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php b/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php index d2881eb..7d05508 100644 --- a/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php +++ b/core/modules/settings_tray/tests/src/FunctionalJavascript/SettingsTrayBlockFormTest.php @@ -273,6 +273,7 @@ protected function openBlockForm($block_selector, $contextual_link_container = ' $this->click($block_selector); $this->waitForOffCanvasToOpen(); $this->assertOffCanvasBlockFormIsValid(); + $this->closeMessageDialog(); } /** @@ -405,6 +406,8 @@ protected function assertEditModeEnabled() { $web_assert->elementContains('css', static::TOOLBAR_EDIT_LINK_SELECTOR, 'Editing'); // The main canvas element should have the "js-settings-tray-edit-mode" class. $web_assert->elementExists('css', '.dialog-off-canvas__main-canvas.js-settings-tray-edit-mode'); + $web_assert->elementTextContains('css', '.settings-tray-edit-message', 'You are now in edit mode'); + $this->closeMessageDialog(); } /** @@ -421,6 +424,7 @@ protected function assertEditModeDisabled() { // The main canvas element should NOT have the "js-settings-tray-edit-mode" // class. $web_assert->elementNotExists('css', '.dialog-off-canvas__main-canvas.js-settings-tray-edit-mode'); + $web_assert->elementNotExists('css', '#settings-tray-edit-message'); } /** @@ -555,4 +559,16 @@ public function testValidationMessages() { } } + /** + * Closes the message dialog that contains "You are in edit mode." message. + * + * Also waits for the dialog to be removed from the page. + */ + protected function closeMessageDialog() { + if ($message_dialog_close_button = $this->assertSession()->waitForElementVisible('css', '[aria-describedby="settings-tray-edit-message"]')) { + $message_dialog_close_button->click(); + $this->waitForNoElement('css', '[aria-describedby="settings-tray-edit-message"]'); + } + } + }