Issue #2785589 by tedbow, nod_, droplet, drpal, alexpott, Wim Leers, xjm: Fix js and jsdoc of outside-in module
parent
8d0d69f0c0
commit
2c6f28bef9
|
@ -7,32 +7,10 @@
|
|||
|
||||
'use strict';
|
||||
|
||||
$('.outside-in-editable')
|
||||
// Bind an event listener to the .outside-in-editable div
|
||||
// This listen for click events and stops default actions of those elements.
|
||||
.on('click', '.js-outside-in-edit-mode', function (e) {
|
||||
if (localStorage.getItem('Drupal.contextualToolbar.isViewing') === 'false') {
|
||||
e.preventDefault();
|
||||
}
|
||||
})
|
||||
// Bind an event listener to the .outside-in-editable div
|
||||
// When a click occurs try and find the outside-in edit link
|
||||
// and click it.
|
||||
.not('div.contextual a, div.contextual button')
|
||||
.on('click', function (e) {
|
||||
if ($(e.target.offsetParent).hasClass('contextual')) {
|
||||
return;
|
||||
}
|
||||
if (!localStorage.getItem('Drupal.contextualToolbar.isViewing')) {
|
||||
return;
|
||||
}
|
||||
var editLink = $(e.target).find('a[data-dialog-renderer="offcanvas"]')[0];
|
||||
if (!editLink) {
|
||||
var closest = $(e.target).closest('.outside-in-editable');
|
||||
editLink = closest.find('li a[data-dialog-renderer="offcanvas"]')[0];
|
||||
}
|
||||
editLink.click();
|
||||
});
|
||||
var blockConfigureSelector = '[data-dialog-renderer="offcanvas"]';
|
||||
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';
|
||||
|
||||
/**
|
||||
* Reacts to contextual links being added.
|
||||
|
@ -53,45 +31,111 @@
|
|||
// Bind a listener to all 'Quick edit' links for blocks
|
||||
// Click "Edit" button in toolbar to force Contextual Edit which starts
|
||||
// Settings Tray edit mode also.
|
||||
data.$el.find('.outside-inblock-configure a').on('click', function () {
|
||||
if (!isActiveMode()) {
|
||||
$('div.contextual-toolbar-tab.toolbar-tab button').click();
|
||||
}
|
||||
});
|
||||
data.$el.find(blockConfigureSelector)
|
||||
.on('click.outsidein', function () {
|
||||
if (!isInEditMode()) {
|
||||
$(toggleEditSelector).trigger('click.outsidein');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Gets all items that should be toggled with class during edit mode.
|
||||
*
|
||||
* @return {*}
|
||||
* @return {jQuery}
|
||||
* Items that should be toggled.
|
||||
*/
|
||||
var getItemsToToggle = function () {
|
||||
return $('#main-canvas, #toolbar-bar, .outside-in-editable a, .outside-in-editable button')
|
||||
.not('div.contextual a, div.contextual button');
|
||||
};
|
||||
function getItemsToToggle() {
|
||||
return $(itemsToToggleSelector).not(contextualItemsSelector);
|
||||
}
|
||||
|
||||
var isActiveMode = function () {
|
||||
/**
|
||||
* Helper to check the state of the outside-in mode.
|
||||
*
|
||||
* @todo don't use a class for this.
|
||||
*
|
||||
* @return {boolean}
|
||||
* State of the outside-in edit mode.
|
||||
*/
|
||||
function isInEditMode() {
|
||||
return $('#toolbar-bar').hasClass('js-outside-in-edit-mode');
|
||||
};
|
||||
}
|
||||
|
||||
var setToggleActiveMode = function setToggleActiveMode(forceActive) {
|
||||
forceActive = forceActive || false;
|
||||
if (forceActive || !isActiveMode()) {
|
||||
$('#toolbar-bar .contextual-toolbar-tab button').text(Drupal.t('Editing'));
|
||||
/**
|
||||
* Helper to toggle Edit mode.
|
||||
*/
|
||||
function toggleEditMode() {
|
||||
setEditModeState(!isInEditMode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent default click events except contextual links.
|
||||
*
|
||||
* In edit mode the default action of click events is suppressed.
|
||||
*
|
||||
* @param {jQuery.Event} event
|
||||
* The click event.
|
||||
*/
|
||||
function preventClick(event) {
|
||||
// Do not prevent contextual links.
|
||||
if ($(event.target).closest('.contextual-links').length) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to switch edit mode state.
|
||||
*
|
||||
* @param {boolean} editMode
|
||||
* True enable edit mode, false disable edit mode.
|
||||
*/
|
||||
function setEditModeState(editMode) {
|
||||
editMode = !!editMode;
|
||||
var $editButton = $(toggleEditSelector);
|
||||
var $editables;
|
||||
// Turn on edit mode.
|
||||
if (editMode) {
|
||||
$editButton.text(Drupal.t('Editing'));
|
||||
// Close the Manage tray if open when entering edit mode.
|
||||
if ($('#toolbar-item-administration-tray').hasClass('is-active')) {
|
||||
$('#toolbar-item-administration').click();
|
||||
$('#toolbar-item-administration').trigger('click');
|
||||
}
|
||||
|
||||
$editables = $('[data-drupal-outsidein="editable"]').once('outsidein');
|
||||
if ($editables.length) {
|
||||
// Use event capture to prevent clicks on links.
|
||||
document.querySelector('#main-canvas').addEventListener('click', preventClick, true);
|
||||
|
||||
// When a click occurs try and find the outside-in edit link
|
||||
// and click it.
|
||||
$editables
|
||||
.not(contextualItemsSelector)
|
||||
.on('click.outsidein', function (e) {
|
||||
// Contextual links are allowed to function in Edit mode.
|
||||
if ($(e.target).closest('.contextual').length || !localStorage.getItem('Drupal.contextualToolbar.isViewing')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$(e.currentTarget).find(blockConfigureSelector).trigger('click');
|
||||
});
|
||||
}
|
||||
getItemsToToggle().addClass('js-outside-in-edit-mode');
|
||||
$('.edit-mode-inactive').addClass('visually-hidden');
|
||||
}
|
||||
// Disable edit mode.
|
||||
else {
|
||||
$('#toolbar-bar .contextual-toolbar-tab button').text(Drupal.t('Edit'));
|
||||
getItemsToToggle().removeClass('js-outside-in-edit-mode');
|
||||
$('.edit-mode-inactive').removeClass('visually-hidden');
|
||||
$editables = $('[data-drupal-outsidein="editable"]').removeOnce('outsidein');
|
||||
if ($editables.length) {
|
||||
document.querySelector('#main-canvas').removeEventListener('click', preventClick, true);
|
||||
$editables.off('.outsidein');
|
||||
}
|
||||
|
||||
$editButton.text(Drupal.t('Edit'));
|
||||
// Close/remove offcanvas.
|
||||
$('.ui-dialog-offcanvas .ui-dialog-titlebar-close').trigger('click');
|
||||
}
|
||||
};
|
||||
getItemsToToggle().toggleClass('js-outside-in-edit-mode', editMode);
|
||||
$('.edit-mode-inactive').toggleClass('visually-hidden', editMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches contextual's edit toolbar tab behavior.
|
||||
|
@ -105,7 +149,7 @@
|
|||
attach: function () {
|
||||
var editMode = localStorage.getItem('Drupal.contextualToolbar.isViewing') === 'false';
|
||||
if (editMode) {
|
||||
setToggleActiveMode(true);
|
||||
setEditModeState(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -118,11 +162,10 @@
|
|||
* @prop {Drupal~behaviorAttach} attach
|
||||
* Toggle the js-outside-edit-mode class.
|
||||
*/
|
||||
Drupal.behaviors.toggleActiveMode = {
|
||||
Drupal.behaviors.toggleEditMode = {
|
||||
attach: function () {
|
||||
$('.contextual-toolbar-tab.toolbar-tab button').once('toggle-edit-mode').on('click', function () {
|
||||
setToggleActiveMode();
|
||||
});
|
||||
|
||||
$(toggleEditSelector).once('outsidein').on('click.outsidein', toggleEditMode);
|
||||
|
||||
var search = Drupal.ajax.WRAPPER_FORMAT + '=drupal_dialog';
|
||||
var replace = Drupal.ajax.WRAPPER_FORMAT + '=drupal_dialog_offcanvas';
|
||||
|
|
|
@ -18,6 +18,7 @@ drupal.outside_in:
|
|||
dependencies:
|
||||
- core/jquery
|
||||
- core/drupal
|
||||
- core/jquery.once
|
||||
- core/drupal.ajax
|
||||
drupal.off_canvas:
|
||||
version: VERSION
|
||||
|
|
|
@ -93,8 +93,9 @@ function outside_in_preprocess_block(&$variables) {
|
|||
// The main system block does not contain the block contextual links.
|
||||
$variables['#cache']['contexts'][] = 'outside_in_is_applied';
|
||||
if ($variables['plugin_id'] !== 'system_main_block' && \Drupal::service('outside_in.manager')->isApplicable()) {
|
||||
// Add class to all blocks to allow Javascript to target.
|
||||
// Add class and attributes to all blocks to allow Javascript to target.
|
||||
$variables['attributes']['class'][] = 'outside-in-editable';
|
||||
$variables['attributes']['data-drupal-outsidein'] = 'editable';
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,6 +109,7 @@ function outside_in_toolbar_alter(&$items) {
|
|||
if (isset($items['contextual']['tab']) && \Drupal::service('outside_in.manager')->isApplicable()) {
|
||||
$items['contextual']['#weight'] = -1000;
|
||||
$items['contextual']['#attached']['library'][] = 'outside_in/drupal.outside_in';
|
||||
$items['contextual']['tab']['#attributes']['data-drupal-outsidein'] = 'toggle';
|
||||
|
||||
// Set a class on items to mark whether they should be active in edit mode.
|
||||
// @todo Create a dynamic method for modules to set their own items.
|
||||
|
|
|
@ -12,7 +12,17 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase {
|
|||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static $modules = ['block', 'system', 'breakpoint', 'toolbar', 'contextual', 'outside_in'];
|
||||
public static $modules = [
|
||||
'node',
|
||||
'block',
|
||||
'system',
|
||||
'breakpoint',
|
||||
'toolbar',
|
||||
'contextual',
|
||||
'outside_in',
|
||||
'quickedit',
|
||||
'search',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
|
@ -26,72 +36,92 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase {
|
|||
'administer blocks',
|
||||
'access contextual links',
|
||||
'access toolbar',
|
||||
'administer nodes',
|
||||
'access in-place editing',
|
||||
'search content',
|
||||
]);
|
||||
$this->drupalLogin($user);
|
||||
|
||||
$this->placeBlock('system_powered_by_block', ['id' => 'powered']);
|
||||
$this->placeBlock('system_branding_block', ['id' => 'branding']);
|
||||
$this->placeBlock('search_form_block', ['id' => 'search']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests updating the "Powered by Drupal" block in the Off-Canvas tray.
|
||||
* Tests opening Offcanvas tray by click blocks and elements in the blocks.
|
||||
*/
|
||||
public function testPoweredByBlock() {
|
||||
|
||||
public function testBlocks() {
|
||||
$blocks = [
|
||||
[
|
||||
'id' => 'block-powered',
|
||||
'new_page_text' => 'Can you imagine anyone showing the label on this block?',
|
||||
'element_selector' => '.content a',
|
||||
'button_text' => 'Save Powered by Drupal',
|
||||
],
|
||||
[
|
||||
'id' => 'block-branding',
|
||||
'new_page_text' => 'The site that will live a very short life.',
|
||||
'element_selector' => 'a[rel="home"]:nth-child(2)',
|
||||
'button_text' => 'Save Site branding',
|
||||
],
|
||||
[
|
||||
'id' => 'block-search',
|
||||
'element_selector' => '#edit-submit',
|
||||
'button_text' => 'Save Search form',
|
||||
],
|
||||
];
|
||||
$page = $this->getSession()->getPage();
|
||||
$web_assert = $this->assertSession();
|
||||
foreach ($blocks as $block) {
|
||||
$block_selector = '#' . $block['id'];
|
||||
$this->drupalGet('user');
|
||||
$this->toggleEditingMode();
|
||||
$this->openBlockForm($block_selector);
|
||||
|
||||
$this->drupalGet('user');
|
||||
$this->enableEditingMode();
|
||||
switch ($block['id']) {
|
||||
case 'block-powered':
|
||||
// Fill out form, save the form.
|
||||
$page->fillField('settings[label]', $block['new_page_text']);
|
||||
$page->checkField('settings[label_display]');
|
||||
break;
|
||||
|
||||
// Open "Powered by Drupal" block form by clicking div.
|
||||
$page->find('css', '#block-powered')->click();
|
||||
$this->waitForOffCanvasToOpen();
|
||||
$this->assertOffCanvasBlockFormIsValid();
|
||||
case 'block-branding':
|
||||
// Fill out form, save the form.
|
||||
$page->fillField('settings[site_information][site_name]', $block['new_page_text']);
|
||||
break;
|
||||
}
|
||||
|
||||
// Fill out form, save the form.
|
||||
$new_label = 'Can you imagine anyone showing the label on this block?';
|
||||
$page->fillField('settings[label]', $new_label);
|
||||
$page->checkField('settings[label_display]');
|
||||
if (isset($block['new_page_text'])) {
|
||||
$page->pressButton($block['button_text']);
|
||||
// Make sure the changes are present.
|
||||
$this->getSession()->wait(500);
|
||||
$web_assert = $this->assertSession();
|
||||
$web_assert->pageTextContains($block['new_page_text']);
|
||||
}
|
||||
|
||||
// @todo Uncomment the following lines after GastonJS problem solved.
|
||||
// https://www.drupal.org/node/2789381
|
||||
// $this->getTray()->pressButton('Save block');
|
||||
// Make sure the changes are present.
|
||||
// $web_assert->pageTextContains($new_label);
|
||||
}
|
||||
$this->openBlockForm($block_selector);
|
||||
|
||||
/**
|
||||
* Tests updating the System Branding block in the Off-Canvas tray.
|
||||
*
|
||||
* Also tests updating the site name.
|
||||
*/
|
||||
public function testBrandingBlock() {
|
||||
$web_assert = $this->assertSession();
|
||||
$this->drupalGet('user');
|
||||
$page = $this->getSession()->getPage();
|
||||
$this->enableEditingMode();
|
||||
$this->toggleEditingMode();
|
||||
// Canvas should close when editing module is closed.
|
||||
$this->waitForOffCanvasToClose();
|
||||
|
||||
// Open branding block form by clicking div.
|
||||
$page->find('css', '#block-branding')->click();
|
||||
$this->waitForOffCanvasToOpen();
|
||||
$this->assertOffCanvasBlockFormIsValid();
|
||||
// Go into Edit mode again.
|
||||
$this->toggleEditingMode();
|
||||
|
||||
// Fill out form, save the form.
|
||||
$new_site_name = 'The site that will live a very short life.';
|
||||
$page->fillField('settings[site_information][site_name]', $new_site_name);
|
||||
$element_selector = "$block_selector {$block['element_selector']}";
|
||||
// Open block form by clicking a element inside the block.
|
||||
// This confirms that default action for links and form elements is
|
||||
// suppressed.
|
||||
$this->openBlockForm($element_selector);
|
||||
|
||||
// @todo Uncomment the following lines after GastonJS problem solved.
|
||||
// https://www.drupal.org/node/2789381
|
||||
// $this->getTray()->pressButton('Save block');
|
||||
// Make sure the changes are present.
|
||||
//$web_assert->pageTextContains($new_site_name);
|
||||
// Exit edit mode.
|
||||
$this->toggleEditingMode();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables Editing mode by pressing "Edit" button in the toolbar.
|
||||
*/
|
||||
protected function enableEditingMode() {
|
||||
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', 3000);
|
||||
|
@ -114,4 +144,15 @@ class OutsideInBlockFormTest extends OutsideInJavascriptTestBase {
|
|||
$web_assert->elementNotExists('css', 'select[data-drupal-selector="edit-region"]');
|
||||
}
|
||||
|
||||
/**
|
||||
* Open block form by clicking the element found with a css selector.
|
||||
*
|
||||
* @param string $block_selector
|
||||
* A css selector selects the block or an element within it.
|
||||
*/
|
||||
protected function openBlockForm($block_selector) {
|
||||
$this->click($block_selector);
|
||||
$this->waitForOffCanvasToOpen();
|
||||
$this->assertOffCanvasBlockFormIsValid();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,8 @@ abstract class OutsideInJavascriptTestBase extends JavascriptTestBase {
|
|||
* Waits for Off-canvas tray to open.
|
||||
*/
|
||||
protected function waitForOffCanvasToOpen() {
|
||||
$web_assert = $this->assertSession();
|
||||
$web_assert->assertWaitOnAjaxRequest();
|
||||
$this->waitForElement('#drupal-offcanvas');
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue