From 07d2ae1efd6a141c91111a60287147423a780499 Mon Sep 17 00:00:00 2001 From: webchick Date: Fri, 13 Jan 2017 13:43:15 -0800 Subject: [PATCH] Issue #2782915 by tedbow, droplet, nickgs, drpal, xjm, tkoleary, cashwilliams, tim.plunkett, alexpott, phenaproxima, nod_: Standardize the behavior of links when Outside In editing mode is enabled --- .../outside_in/css/outside_in.module.css | 9 ++ core/modules/outside_in/js/outside_in.js | 39 +++++++- .../outside_in_test_css/css/css_fix.theme.css | 4 + .../outside_in_test_css.info.yml | 8 ++ .../outside_in_test_css.libraries.yml | 5 + .../outside_in_test_css.module | 16 ++++ .../OutsideInBlockFormTest.php | 95 ++++++++++++++++++- .../OutsideInJavascriptTestBase.php | 42 ++++++++ 8 files changed, 211 insertions(+), 7 deletions(-) create mode 100644 core/modules/outside_in/tests/modules/outside_in_test_css/css/css_fix.theme.css create mode 100644 core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.info.yml create mode 100644 core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.libraries.yml create mode 100644 core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.module diff --git a/core/modules/outside_in/css/outside_in.module.css b/core/modules/outside_in/css/outside_in.module.css index a534dd159a4..a44000ae986 100644 --- a/core/modules/outside_in/css/outside_in.module.css +++ b/core/modules/outside_in/css/outside_in.module.css @@ -38,3 +38,12 @@ [dir="rtl"] .toolbar .toolbar-bar .contextual-toolbar-tab.toolbar-tab { float: right; } + +#main-canvas.js-outside-in-edit-mode a, +#main-canvas.js-outside-in-edit-mode input { + pointer-events: none; +} +#main-canvas.js-outside-in-edit-mode .contextual-links a { + pointer-events: inherit; +} + diff --git a/core/modules/outside_in/js/outside_in.js b/core/modules/outside_in/js/outside_in.js index 19bcfeb2842..e6bd34e70ae 100644 --- a/core/modules/outside_in/js/outside_in.js +++ b/core/modules/outside_in/js/outside_in.js @@ -11,6 +11,7 @@ var toggleEditSelector = '[data-drupal-outsidein="toggle"]'; var itemsToToggleSelector = '#main-canvas, #toolbar-bar, [data-drupal-outsidein="editable"] a, [data-drupal-outsidein="editable"] button'; var contextualItemsSelector = '[data-contextual-id] a, [data-contextual-id] button'; + var quickEditItemSelector = '[data-quickedit-entity-id]'; /** * Reacts to contextual links being added. @@ -36,6 +37,8 @@ if (!isInEditMode()) { $(toggleEditSelector).trigger('click.outsidein'); } + // Always disable QuickEdit regardless of whether "EditMode" was just enabled. + disableQuickEdit(); }); }); @@ -101,7 +104,21 @@ .find('.toolbar-tab') .not('.contextual-toolbar-tab') .has('.toolbar-tray.is-active') - .find('.toolbar-item').click(); + .find('.toolbar-item').trigger('click'); + } + + /** + * Disables the QuickEdit module editor if open. + */ + function disableQuickEdit() { + $('.quickedit-toolbar button.action-cancel').trigger('click'); + } + + /** + * Closes/removes offcanvas. + */ + function closeOffCanvas() { + $('.ui-dialog-offcanvas .ui-dialog-titlebar-close').trigger('click'); } /** @@ -133,8 +150,21 @@ if ($(e.target).closest('.contextual').length || !localStorage.getItem('Drupal.contextualToolbar.isViewing')) { return; } - $(e.currentTarget).find(blockConfigureSelector).trigger('click'); + disableQuickEdit(); + }); + $(quickEditItemSelector) + .not(contextualItemsSelector) + .on('click.outsidein', function (e) { + // For all non-contextual links or the contextual QuickEdit link close the off-canvas tray. + if (!$(e.target).parent().hasClass('contextual') || $(e.target).parent().hasClass('quickedit')) { + closeOffCanvas(); + } + // Do not trigger if target is quick edit link to avoid loop. + if ($(e.target).parent().hasClass('contextual') || $(e.target).parent().hasClass('quickedit')) { + return; + } + $(e.currentTarget).find('li.quickedit a').trigger('click'); }); } } @@ -144,11 +174,12 @@ if ($editables.length) { document.querySelector('#main-canvas').removeEventListener('click', preventClick, true); $editables.off('.outsidein'); + $(quickEditItemSelector).off('.outsidein'); } $editButton.text(Drupal.t('Edit')); - // Close/remove offcanvas. - $('.ui-dialog-offcanvas .ui-dialog-titlebar-close').trigger('click'); + closeOffCanvas(); + disableQuickEdit(); } getItemsToToggle().toggleClass('js-outside-in-edit-mode', editMode); $('.edit-mode-inactive').toggleClass('visually-hidden', editMode); diff --git a/core/modules/outside_in/tests/modules/outside_in_test_css/css/css_fix.theme.css b/core/modules/outside_in/tests/modules/outside_in_test_css/css/css_fix.theme.css new file mode 100644 index 00000000000..dc9d72ad209 --- /dev/null +++ b/core/modules/outside_in/tests/modules/outside_in_test_css/css/css_fix.theme.css @@ -0,0 +1,4 @@ +#main-canvas.js-outside-in-edit-mode a, +#main-canvas.js-outside-in-edit-mode input { + pointer-events: inherit !important; +} diff --git a/core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.info.yml b/core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.info.yml new file mode 100644 index 00000000000..c7df21f183a --- /dev/null +++ b/core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.info.yml @@ -0,0 +1,8 @@ +name: 'CSS Test fix' +type: module +description: 'Provides CSS fixes for tests.' +package: Testing +version: VERSION +core: 8.x +dependencies: +- outside_in diff --git a/core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.libraries.yml b/core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.libraries.yml new file mode 100644 index 00000000000..0fdaffd8493 --- /dev/null +++ b/core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.libraries.yml @@ -0,0 +1,5 @@ +drupal.css_fix: + version: VERSION + css: + theme: + css/css_fix.theme.css: {} diff --git a/core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.module b/core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.module new file mode 100644 index 00000000000..2cd32e2bf74 --- /dev/null +++ b/core/modules/outside_in/tests/modules/outside_in_test_css/outside_in_test_css.module @@ -0,0 +1,16 @@ +waitForElement('div[data-contextual-id="block:block=powered:langcode=en|outside_in::langcode=en"] .contextual-links a'); - - $this->waitForElement('#toolbar-bar'); + $this->waitForElement('div[data-contextual-id="block:block=powered:langcode=en|outside_in::langcode=en"] .contextual-links a', 10000); + // Waiting for QuickEdit icon animation. + $this->assertSession()->assertWaitOnAjaxRequest(); $edit_button = $this->getSession()->getPage()->find('css', '#toolbar-bar div.contextual-toolbar-tab button'); $edit_button->press(); + // Waiting for Toolbar animation. + $this->assertSession()->assertWaitOnAjaxRequest(); } /** @@ -195,4 +202,86 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase { $this->assertOffCanvasBlockFormIsValid(); } + /** + * Tests QuickEdit links behavior. + */ + public function testQuickEditLinks() { + $quick_edit_selector = '#quickedit-entity-toolbar'; + $body_selector = '.field--name-body p'; + $block_selector = '#block-powered'; + $web_assert = $this->assertSession(); + // Create a Content type and two test nodes. + $this->createContentType(['type' => 'page']); + $auth_role = Role::load(Role::AUTHENTICATED_ID); + $this->grantPermissions($auth_role, [ + 'edit any page content', + 'access content', + ]); + $node = $this->createNode( + [ + 'title' => 'Page One', + 'type' => 'page', + 'body' => [ + [ + 'value' => 'Regular NODE body for the test.', + 'format' => 'plain_text', + ], + ], + ] + ); + $page = $this->getSession()->getPage(); + // Load the same page twice. + foreach ([1, 2] as $page_load_times) { + $this->drupalGet('node/' . $node->id()); + // Waiting for Toolbar module. + // @todo Remove the hack after https://www.drupal.org/node/2542050. + $this->waitForElement('.toolbar-fixed'); + // Waiting for Toolbar animation. + $web_assert->assertWaitOnAjaxRequest(); + // The 2nd page load we should already be in edit mode. + if ($page_load_times == 1) { + $this->toggleEditingMode(); + } + // In Edit mode clicking field should open QuickEdit toolbar. + $page->find('css', $body_selector)->click(); + $this->waitForElement($quick_edit_selector); + // Exit Edit mode. + $this->toggleEditingMode(); + // Exiting Edit mode should close QuickEdit toolbar. + $web_assert->elementNotExists('css', $quick_edit_selector); + // When not in Edit mode QuickEdit toolbar should not open. + $page->find('css', $body_selector)->click(); + $web_assert->elementNotExists('css', $quick_edit_selector); + + // Enter Edit mode. + $this->toggleEditingMode(); + $this->openBlockForm($block_selector); + $page->find('css', $body_selector)->click(); + $this->waitForElement($quick_edit_selector); + // Offcanvas should be closed when opening QuickEdit toolbar. + $this->waitForOffCanvasToClose(); + + $this->openBlockForm($block_selector); + // QuickEdit toolbar should be closed when opening Offcanvas. + $web_assert->elementNotExists('css', $quick_edit_selector); + } + + // Check using contextual links to invoke QuickEdit and open the tray. + $this->drupalGet('node/' . $node->id()); + $web_assert->assertWaitOnAjaxRequest(); + $this->toggleEditingMode(); + // Open QuickEdit toolbar before going into Edit mode. + $this->clickContextualLink('.node', "Quick edit"); + $this->waitForElement($quick_edit_selector); + // Open off-canvas and enter Edit mode via contextual link. + $this->clickContextualLink($block_selector, "Quick edit"); + $this->waitForOffCanvasToOpen(); + // QuickEdit toolbar should be closed when opening Offcanvas. + $web_assert->elementNotExists('css', $quick_edit_selector); + // Open QuickEdit toolbar via contextual link while in Edit mode. + $this->clickContextualLink('.node', "Quick edit", FALSE); + $this->waitForOffCanvasToClose(); + $this->waitForElement($quick_edit_selector); + } + } diff --git a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php index 7534a258eb9..48ba8993eeb 100644 --- a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php +++ b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php @@ -89,4 +89,46 @@ abstract class OutsideInJavascriptTestBase extends JavascriptTestBase { $this->assertJsCondition($condition, $timeout); } + /** + * Clicks a contextual link. + * + * @todo Remove this function when related trait added in + * https://www.drupal.org/node/2821724. + * + * @param string $selector + * The selector for the element that contains the contextual link. + * @param string $link_locator + * The link id, title, or text. + * @param bool $force_visible + * If true then the button will be forced to visible so it can be clicked. + */ + protected function clickContextualLink($selector, $link_locator, $force_visible = TRUE) { + if ($force_visible) { + $this->toggleContextualTriggerVisibility($selector); + } + + $element = $this->getSession()->getPage()->find('css', $selector); + $element->find('css', '.contextual button')->press(); + $element->findLink($link_locator)->click(); + + if ($force_visible) { + $this->toggleContextualTriggerVisibility($selector); + } + } + + /** + * Toggles the visibility of a contextual trigger. + * + * @todo Remove this function when related trait added in + * https://www.drupal.org/node/2821724. + * + * @param string $selector + * The selector for the element that contains the contextual link. + */ + protected function toggleContextualTriggerVisibility($selector) { + // Hovering over the element itself with should be enough, but does not + // work. Manually remove the visually-hidden class. + $this->getSession()->executeScript("jQuery('{$selector} .contextual .trigger').toggleClass('visually-hidden');"); + } + }