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

8.3.x
webchick 2017-01-13 13:43:15 -08:00
parent 2161fb241d
commit 07d2ae1efd
8 changed files with 211 additions and 7 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -0,0 +1,4 @@
#main-canvas.js-outside-in-edit-mode a,
#main-canvas.js-outside-in-edit-mode input {
pointer-events: inherit !important;
}

View File

@ -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

View File

@ -0,0 +1,5 @@
drupal.css_fix:
version: VERSION
css:
theme:
css/css_fix.theme.css: {}

View File

@ -0,0 +1,16 @@
<?php
/**
* @file
* Module for attaching CSS during tests.
*
* CSS pointer-events properties cause testing errors.
*/
/**
* Implements hook_page_attachments().
*/
function outside_in_test_css_page_attachments(array &$attachments) {
// Unconditionally attach an asset to the page.
$attachments['#attached']['library'][] = 'outside_in_test_css/drupal.css_fix';
}

View File

@ -2,6 +2,8 @@
namespace Drupal\Tests\outside_in\FunctionalJavascript;
use Drupal\user\Entity\Role;
/**
* Testing opening and saving block forms in the off-canvas tray.
*
@ -22,6 +24,9 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase {
'outside_in',
'quickedit',
'search',
// Add test module to override CSS pointer-events properties because they
// cause test failures.
'outside_in_test_css',
];
/**
@ -161,13 +166,15 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase {
* Enables Editing mode by pressing "Edit" button in the toolbar.
*/
protected function toggleEditingMode() {
$this->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);
}
}

View File

@ -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');");
}
}