diff --git a/core/core.libraries.yml b/core/core.libraries.yml index 9cfd1cf..48ecfe4 100644 --- a/core/core.libraries.yml +++ b/core/core.libraries.yml @@ -182,6 +182,22 @@ drupal.dialog.ajax: - core/drupal.ajax - core/drupal.dialog +drupal.dialog.off_canvas: + version: VERSION + js: + misc/dialog/off-canvas.js: {} + css: + component: + misc/dialog/off-canvas.css: {} + misc/dialog/off-canvas.motion.css: {} + dependencies: + - core/jquery + - core/drupal + - core/drupal.ajax + - core/drupal.announce + - core/drupal.dialog + - core/drupal.dialog.ajax + drupal.displace: version: VERSION js: diff --git a/core/core.services.yml b/core/core.services.yml index 8bce755..a7b1654 100644 --- a/core/core.services.yml +++ b/core/core.services.yml @@ -1059,6 +1059,11 @@ services: arguments: ['@title_resolver'] tags: - { name: render.main_content_renderer, format: drupal_dialog } + main_content_renderer.off_canvas: + class: Drupal\Core\Render\MainContent\OffCanvasRender + arguments: ['@title_resolver', '@renderer'] + tags: + - { name: render.main_content_renderer, format: drupal_dialog.off_canvas } main_content_renderer.modal: class: Drupal\Core\Render\MainContent\ModalRenderer arguments: ['@title_resolver'] diff --git a/core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php b/core/lib/Drupal/Core/Ajax/OpenOffCanvasDialogCommand.php similarity index 91% rename from core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php rename to core/lib/Drupal/Core/Ajax/OpenOffCanvasDialogCommand.php index d78dc35..96ad51c 100644 --- a/core/modules/outside_in/src/Ajax/OpenOffCanvasDialogCommand.php +++ b/core/lib/Drupal/Core/Ajax/OpenOffCanvasDialogCommand.php @@ -1,8 +1,6 @@ dialogOptions['modal'] = FALSE; $this->dialogOptions['autoResize'] = FALSE; $this->dialogOptions['resizable'] = 'w'; diff --git a/core/modules/outside_in/src/Render/MainContent/OffCanvasRender.php b/core/lib/Drupal/Core/Render/MainContent/OffCanvasRender.php similarity index 86% rename from core/modules/outside_in/src/Render/MainContent/OffCanvasRender.php rename to core/lib/Drupal/Core/Render/MainContent/OffCanvasRender.php index 5d24c09..c1eeaab 100644 --- a/core/modules/outside_in/src/Render/MainContent/OffCanvasRender.php +++ b/core/lib/Drupal/Core/Render/MainContent/OffCanvasRender.php @@ -1,17 +1,16 @@ setAttachments($main_content['#attached']); // If the main content doesn't provide a title, use the title resolver. diff --git a/core/misc/ajax.js b/core/misc/ajax.js index fefe9f3..524e978 100644 --- a/core/misc/ajax.js +++ b/core/misc/ajax.js @@ -64,6 +64,7 @@ element_settings.event = 'click'; } element_settings.dialogType = $(this).data('dialog-type'); + element_settings.drupalDialogRenderer = $(this).data('dialog-renderer'); element_settings.dialog = $(this).data('dialog-options'); element_settings.base = $(this).attr('id'); element_settings.element = this; @@ -312,6 +313,8 @@ * Options for {@link Drupal.dialog}. * @prop {string} [dialogType] * One of `'modal'` or `'dialog'`. + * @prop {string} [drupalDialogRenderer] + * Renderer for the dialog, 'off_canvas' supported. * @prop {string} [prevent] * List of events on which to stop default action and stop propagation. */ @@ -526,7 +529,11 @@ else { ajax.options.url += '&'; } - ajax.options.url += Drupal.ajax.WRAPPER_FORMAT + '=drupal_' + (element_settings.dialogType || 'ajax'); + var wrapper = 'drupal_' + (element_settings.dialogType || 'ajax'); + if (element_settings.drupalDialogRenderer) { + wrapper += '.' + element_settings.drupalDialogRenderer; + } + ajax.options.url += Drupal.ajax.WRAPPER_FORMAT + '=' + wrapper; // Bind the ajaxSubmit function to the element event. $(ajax.element).on(element_settings.event, function (event) { diff --git a/core/misc/dialog/off-canvas.css b/core/misc/dialog/off-canvas.css new file mode 100644 index 0000000..170e962 --- /dev/null +++ b/core/misc/dialog/off-canvas.css @@ -0,0 +1,39 @@ +/** + * @file + * CSS for Offcanvas tray. + */ +/* Position the dialog-off-canvas tray container outside the right of the viewport. */ +.ui-dialog-off-canvas { + box-sizing: border-box; + height: 100%; + overflow: visible; +} + +/* Wrap the form that's inside the dialog-off-canvas tray. */ +.ui-dialog-off-canvas .ui-dialog-content { + padding: 0 20px; + /* Prevent horizontal scrollbar. */ + overflow-x: hidden; + overflow-y: auto; +} + +[dir="rtl"] .ui-dialog-off-canvas .ui-dialog-content { + text-align: right; +} + +/* + * Force the tray to be 100% width at the same breakpoint the dialog system uses + * to expand dialog widths. + */ +@media all and (max-width: 48em) { + /* 768px */ + .ui-dialog.ui-dialog-off-canvas { + width: 100% !important; + } + + /* When tray is at 100% width stop the body from scrolling */ + .js-tray-open { + height: 100%; + overflow-y: hidden; + } +} diff --git a/core/modules/outside_in/js/offcanvas.js b/core/misc/dialog/off-canvas.js similarity index 72% rename from core/modules/outside_in/js/offcanvas.js rename to core/misc/dialog/off-canvas.js index 8cda69d..3d37fd6 100644 --- a/core/modules/outside_in/js/offcanvas.js +++ b/core/misc/dialog/off-canvas.js @@ -1,10 +1,6 @@ /** * @file * Drupal's off-canvas library. - * - * @todo This functionality should extracted into a new core library or a part - * of the current drupal.dialog.ajax library. - * https://www.drupal.org/node/2784443 */ (function ($, Drupal, debounce, displace) { @@ -12,7 +8,7 @@ 'use strict'; // The minimum width to use body displace needs to match the width at which - // the tray will be %100 width. @see outside_in.module.css + // the tray will be %100 width. @see off-canvas.css var minDisplaceWidth = 768; /** @@ -22,7 +18,7 @@ */ var edge = document.documentElement.dir === 'rtl' ? 'left' : 'right'; - var $mainCanvasWrapper = $('[data-offcanvas-main-canvas]'); + var $mainCanvasWrapper = $('[data-off-canvas-main-canvas]'); /** * Resets the size of the dialog. @@ -51,7 +47,7 @@ $element .dialog('option', adjustedOptions) - .trigger('dialogContentResize.offcanvas'); + .trigger('dialogContentResize.off-canvas'); } /** @@ -64,7 +60,7 @@ var $element = event.data.$element; var $widget = $element.dialog('widget'); - var $offsets = $widget.find('> :not(#drupal-offcanvas, .ui-resizable-handle)'); + var $offsets = $widget.find('> :not(#drupal-off-canvas, .ui-resizable-handle)'); var offset = 0; var modalHeight; @@ -102,25 +98,25 @@ $(window).on({ 'dialog:aftercreate': function (event, dialog, $element, settings) { - if ($element.is('#drupal-offcanvas')) { + if ($element.is('#drupal-off-canvas')) { var eventData = {settings: settings, $element: $element}; - $('.ui-dialog-offcanvas, .ui-dialog-offcanvas .ui-dialog-titlebar').toggleClass('ui-dialog-empty-title', !settings.title); + $('.ui-dialog-off-canvas, .ui-dialog-off-canvas .ui-dialog-titlebar').toggleClass('ui-dialog-empty-title', !settings.title); $element - .on('dialogresize.offcanvas', eventData, debounce(bodyPadding, 100)) - .on('dialogContentResize.offcanvas', eventData, handleDialogResize) - .on('dialogContentResize.offcanvas', eventData, debounce(bodyPadding, 100)) - .trigger('dialogresize.offcanvas'); + .on('dialogresize.off-canvas', eventData, debounce(bodyPadding, 100)) + .on('dialogContentResize.off-canvas', eventData, handleDialogResize) + .on('dialogContentResize.off-canvas', eventData, debounce(bodyPadding, 100)) + .trigger('dialogresize.off-canvas'); $element.dialog('widget').attr('data-offset-' + edge, ''); $(window) - .on('resize.offcanvas scroll.offcanvas', eventData, debounce(resetSize, 100)) - .trigger('resize.offcanvas'); + .on('resize.off-canvas scroll.off-canvas', eventData, debounce(resetSize, 100)) + .trigger('resize.off-canvas'); } }, 'dialog:beforecreate': function (event, dialog, $element, settings) { - if ($element.is('#drupal-offcanvas')) { + if ($element.is('#drupal-off-canvas')) { $('body').addClass('js-tray-open'); // @see http://api.jqueryui.com/position/ settings.position = { @@ -128,17 +124,17 @@ at: edge + ' top', of: window }; - settings.dialogClass += ' ui-dialog-offcanvas'; + settings.dialogClass += ' ui-dialog-off-canvas'; // Applies initial height to dialog based on window height. // See http://api.jqueryui.com/dialog for all dialog options. settings.height = $(window).height(); } }, 'dialog:beforeclose': function (event, dialog, $element) { - if ($element.is('#drupal-offcanvas')) { + if ($element.is('#drupal-off-canvas')) { $('body').removeClass('js-tray-open'); - $(document).off('.offcanvas'); - $(window).off('.offcanvas'); + $(document).off('.off-canvas'); + $(window).off('.off-canvas'); $mainCanvasWrapper.css('padding-' + edge, 0); } } diff --git a/core/misc/dialog/off-canvas.motion.css b/core/misc/dialog/off-canvas.motion.css new file mode 100644 index 0000000..c1379be --- /dev/null +++ b/core/misc/dialog/off-canvas.motion.css @@ -0,0 +1,31 @@ +/** + * @file + * Motion effects for off-canvas tray dialog. + * + * Motion effects are in a separate file so that they can be easily turned off + * to improve performance if desired. + * + * @todo Add a configuration option for browser rendering performance to disable + * this file: https://www.drupal.org/node/2784443. + */ + +/* Transition the dialog-offcanvas tray container, with 2s delay to match main canvas speed. */ +.ui-dialog-off-canvas .ui-dialog-content { + -webkit-transition: all .7s ease 2s; + -moz-transition: all .7s ease 2s; + transition: all .7s ease 2s; +} + +@media (max-width: 700px) { + .ui-dialog-off-canvas .ui-dialog-content { + -webkit-transition: all .7s ease; + -moz-transition: all .7s ease; + transition: all .7s ease; + } +} + +.dialog-off-canvas__main-canvas { + -webkit-transition: all .7s ease; + -moz-transition: all .7s ease; + transition: all .7s ease; +} diff --git a/core/modules/outside_in/css/offcanvas.css b/core/modules/outside_in/css/offcanvas.css deleted file mode 100644 index fb671db..0000000 --- a/core/modules/outside_in/css/offcanvas.css +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @file - * CSS for Offcanvas tray. - * - * @todo Move CSS into core dialog library https://www.drupal.org/node/2784443. - */ -/* Position the dialog-offcanvas tray container outside the right of the viewport. */ -.ui-dialog-offcanvas { - box-sizing: border-box; - height: 100%; - overflow: visible; -} - -/* Wrap the form that's inside the dialog-offcanvas tray. */ -.ui-dialog-offcanvas .ui-dialog-content { - padding: 0 20px; - /* Prevent horizontal scrollbar. */ - overflow-x: hidden; - overflow-y: auto; -} -[dir="rtl"] .ui-dialog-offcanvas .ui-dialog-content { - text-align: right; -} diff --git a/core/modules/outside_in/css/offcanvas.motion.css b/core/modules/outside_in/css/offcanvas.motion.css deleted file mode 100644 index 1c06994..0000000 --- a/core/modules/outside_in/css/offcanvas.motion.css +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @file - * Motion effects for off-canvas tray dialog. - * - * Motion effects are in a separate file so that they can be easily turned off - * to improve performance if desired. - * - * @todo Move motion effects file into a core Off-Canvas library and add a - * configuration option for browser rendering performance to disable this - * file: https://www.drupal.org/node/2784443. - */ - -/* Transition the dialog-offcanvas tray container, with 2s delay to match main canvas speed. */ -.ui-dialog-offcanvas .ui-dialog-content { - -webkit-transition: all .7s ease 2s; - -moz-transition: all .7s ease 2s; - transition: all .7s ease 2s; -} - -@media (max-width: 700px) { - .ui-dialog-offcanvas .ui-dialog-content { - -webkit-transition: all .7s ease; - -moz-transition: all .7s ease; - transition: all .7s ease; - } -} - -.dialog-offcanvas__main-canvas { - -webkit-transition: all .7s ease; - -moz-transition: all .7s ease; - transition: all .7s ease; -} diff --git a/core/modules/outside_in/css/outside_in.module.css b/core/modules/outside_in/css/outside_in.module.css index 5ac00ab..2022837 100644 --- a/core/modules/outside_in/css/outside_in.module.css +++ b/core/modules/outside_in/css/outside_in.module.css @@ -21,18 +21,3 @@ #main-canvas.js-outside-in-edit-mode .contextual-links a { pointer-events: inherit; } - -/* - * Force the tray to be 100% width at the same breakpoint the dialog system uses - * to expand dialog widths. - */ -@media all and (max-width: 48em) { /* 768px */ - .ui-dialog.ui-dialog-offcanvas { - width: 100% !important; - } - /* When tray is at 100% width stop the body from scrolling */ - .js-tray-open { - height: 100%; - overflow-y: hidden; - } -} diff --git a/core/modules/outside_in/css/outside_in.motion.css b/core/modules/outside_in/css/outside_in.motion.css index 450bffe..61d68b7 100644 --- a/core/modules/outside_in/css/outside_in.motion.css +++ b/core/modules/outside_in/css/outside_in.motion.css @@ -4,10 +4,6 @@ * * Motion effects are in a separate file so that they can be easily turned off * to improve performance if desired. - * - * @todo Move motion effects file into a core Off-Canvas library and add a - * configuration option for browser rendering performance to disable this - * file: https://www.drupal.org/node/2784443. */ @@ -19,9 +15,9 @@ } /* Transition the editables on the page, their contextual links and their hover states. */ -.dialog-offcanvas__main-canvas .contextual, -.dialog-offcanvas__main-canvas .js-outside-in-edit-mode .outside-in-editable, -.dialog-offcanvas__main-canvas.js-tray-open .js-outside-in-edit-mode .outside-in-editable { +.dialog-off-canvas__main-canvas .contextual, +.dialog-off-canvas__main-canvas .js-outside-in-edit-mode .outside-in-editable, +.dialog-off-canvas__main-canvas.js-tray-open .js-outside-in-edit-mode .outside-in-editable { -webkit-transition: all .7s ease; -moz-transition: all .7s ease; transition: all .7s ease; diff --git a/core/modules/outside_in/css/outside_in.theme.css b/core/modules/outside_in/css/outside_in.theme.css index 91c01ab..011d198 100644 --- a/core/modules/outside_in/css/outside_in.theme.css +++ b/core/modules/outside_in/css/outside_in.theme.css @@ -60,16 +60,16 @@ } /* Style the editables while in edit mode. */ -.dialog-offcanvas__main-canvas.js-outside-in-edit-mode .outside-in-editable { +.dialog-off-canvas__main-canvas.js-outside-in-edit-mode .outside-in-editable { outline: 1px dashed rgba(0,0,0,0.5); box-shadow: 0 0 0 1px rgba(255,255,255,0.7); } -.dialog-offcanvas__main-canvas.js-outside-in-edit-mode .outside-in-editable:hover, -.dialog-offcanvas__main-canvas.js-outside-in-edit-mode .outside-in-editable.outside-in-active-editable { +.dialog-off-canvas__main-canvas.js-outside-in-edit-mode .outside-in-editable:hover, +.dialog-off-canvas__main-canvas.js-outside-in-edit-mode .outside-in-editable.outside-in-active-editable { background-color: rgba(0,0,0,0.2); } -/* Style the dialog-offcanvas container. */ +/* Style the dialog-off-canvas container. */ .ui-dialog-outside-in { background: #444; border: 0 solid transparent; diff --git a/core/modules/outside_in/js/outside_in.js b/core/modules/outside_in/js/outside_in.js index 36f85b0..9ec88de 100644 --- a/core/modules/outside_in/js/outside_in.js +++ b/core/modules/outside_in/js/outside_in.js @@ -9,7 +9,7 @@ var blockConfigureSelector = '[data-outside-in-edit]'; var toggleEditSelector = '[data-drupal-outsidein="toggle"]'; - var itemsToToggleSelector = '[data-offcanvas-main-canvas], #toolbar-bar, [data-drupal-outsidein="editable"] a, [data-drupal-outsidein="editable"] button'; + var itemsToToggleSelector = '[data-off-canvas-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]'; @@ -115,10 +115,10 @@ } /** - * Closes/removes offcanvas. + * Closes/removes off canvas. */ function closeOffCanvas() { - $('.ui-dialog-offcanvas .ui-dialog-titlebar-close').trigger('click'); + $('.ui-dialog-off-canvas .ui-dialog-titlebar-close').trigger('click'); } /** @@ -139,7 +139,7 @@ $editables = $('[data-drupal-outsidein="editable"]').once('outsidein'); if ($editables.length) { // Use event capture to prevent clicks on links. - document.querySelector('[data-offcanvas-main-canvas]').addEventListener('click', preventClick, true); + document.querySelector('[data-off-canvas-main-canvas]').addEventListener('click', preventClick, true); // When a click occurs try and find the outside-in edit link // and click it. @@ -172,7 +172,7 @@ else { $editables = $('[data-drupal-outsidein="editable"]').removeOnce('outsidein'); if ($editables.length) { - document.querySelector('[data-offcanvas-main-canvas]').removeEventListener('click', preventClick, true); + document.querySelector('[data-off-canvas-main-canvas]').removeEventListener('click', preventClick, true); $editables.off('.outsidein'); $(quickEditItemSelector).off('.outsidein'); } @@ -214,26 +214,17 @@ attach: function () { $(toggleEditSelector).once('outsidein').on('click.outsidein', toggleEditMode); - - var search = Drupal.ajax.WRAPPER_FORMAT + '=drupal_dialog'; - var replace = Drupal.ajax.WRAPPER_FORMAT + '=drupal_dialog_offcanvas'; - // Loop through all Ajax links and change the format to dialog-offcanvas when - // needed. + // Loop through all Ajax links to set active editable ID. Drupal.ajax.instances .filter(function (instance) { var hasElement = instance && !!instance.element; var rendererOffcanvas = false; - var wrapperOffcanvas = false; if (hasElement) { - rendererOffcanvas = $(instance.element).attr('data-dialog-renderer') === 'offcanvas'; - wrapperOffcanvas = instance.options.url.indexOf('drupal_dialog_offcanvas') === -1; + rendererOffcanvas = $(instance.element).attr('data-dialog-renderer') === 'off_canvas'; } - return hasElement && rendererOffcanvas && wrapperOffcanvas; + return hasElement && rendererOffcanvas; }) .forEach(function (instance) { - // @todo Move logic for data-dialog-renderer attribute into ajax.js - // https://www.drupal.org/node/2784443 - instance.options.url = instance.options.url.replace(search, replace); // Check to make sure existing dialogOptions aren't overridden. if (!('dialogOptions' in instance.options.data)) { instance.options.data.dialogOptions = {}; @@ -247,7 +238,7 @@ // Manage Active editable class on opening and closing of the dialog. $(window).on({ 'dialog:beforecreate': function (event, dialog, $element, settings) { - if ($element.is('#drupal-offcanvas')) { + if ($element.is('#drupal-off-canvas')) { $('body .outside-in-active-editable').removeClass('outside-in-active-editable'); var $activeElement = $('#' + settings.outsideInActiveEditableId); if ($activeElement.length) { @@ -257,7 +248,7 @@ } }, 'dialog:beforeclose': function (event, dialog, $element) { - if ($element.is('#drupal-offcanvas')) { + if ($element.is('#drupal-off-canvas')) { $('body .outside-in-active-editable').removeClass('outside-in-active-editable'); } } diff --git a/core/modules/outside_in/outside_in.libraries.yml b/core/modules/outside_in/outside_in.libraries.yml index 5eddea4..cf12dc0 100644 --- a/core/modules/outside_in/outside_in.libraries.yml +++ b/core/modules/outside_in/outside_in.libraries.yml @@ -20,14 +20,3 @@ drupal.outside_in: - core/drupal - core/jquery.once - core/drupal.ajax -drupal.off_canvas: - version: VERSION - js: - js/offcanvas.js: {} - dependencies: - - core/jquery - - core/drupal - - core/drupal.ajax - - core/drupal.announce - - core/drupal.dialog - - core/drupal.dialog.ajax diff --git a/core/modules/outside_in/outside_in.links.contextual.yml b/core/modules/outside_in/outside_in.links.contextual.yml index 99b36ef..b0c0f13 100644 --- a/core/modules/outside_in/outside_in.links.contextual.yml +++ b/core/modules/outside_in/outside_in.links.contextual.yml @@ -1,4 +1,4 @@ outside_in.block_configure: title: 'Quick edit' - route_name: 'entity.block.offcanvas_form' + route_name: 'entity.block.off_canvas_form' group: 'block' diff --git a/core/modules/outside_in/outside_in.module b/core/modules/outside_in/outside_in.module index a7fab7b..3da4520 100644 --- a/core/modules/outside_in/outside_in.module +++ b/core/modules/outside_in/outside_in.module @@ -30,18 +30,18 @@ function outside_in_help($route_name, RouteMatchInterface $route_match) { /** * Implements hook_contextual_links_view_alter(). * - * Change Configure Blocks into offcanvas links. + * Change Configure Blocks into off canvas links. */ function outside_in_contextual_links_view_alter(&$element, $items) { if (isset($element['#links']['outside-inblock-configure'])) { $element['#links']['outside-inblock-configure']['attributes'] = [ 'class' => ['use-ajax'], 'data-dialog-type' => 'dialog', - 'data-dialog-renderer' => 'offcanvas', + 'data-dialog-renderer' => 'off_canvas', 'data-outside-in-edit' => TRUE, ]; - $element['#attached']['library'][] = 'outside_in/drupal.off_canvas'; + $element['#attached']['library'][] = 'core/drupal.dialog.off_canvas'; } } @@ -58,33 +58,13 @@ function outside_in_block_view_alter(array &$build) { } /** - * Implements hook_element_info_alter(). - */ -function outside_in_element_info_alter(&$type) { - if (isset($type['page'])) { - $type['page']['#theme_wrappers']['outside_in_page_wrapper'] = ['#weight' => -1000]; - } -} - -/** - * Implements hook_theme(). - */ -function outside_in_theme() { - return [ - 'outside_in_page_wrapper' => [ - 'variables' => ['children' => NULL], - ], - ]; -} - -/** * Implements hook_entity_type_build(). */ function outside_in_entity_type_build(array &$entity_types) { /* @var $entity_types \Drupal\Core\Entity\EntityTypeInterface[] */ $entity_types['block'] - ->setFormClass('offcanvas', BlockEntityOffCanvasForm::class) - ->setLinkTemplate('offcanvas-form', '/admin/structure/block/manage/{block}/offcanvas'); + ->setFormClass('off_canvas', BlockEntityOffCanvasForm::class) + ->setLinkTemplate('off_canvas-form', '/admin/structure/block/manage/{block}/off-canvas'); } /** @@ -130,14 +110,14 @@ function outside_in_toolbar_alter(&$items) { */ function outside_in_block_alter(&$definitions) { if (!empty($definitions['system_branding_block'])) { - $definitions['system_branding_block']['forms']['offcanvas'] = SystemBrandingOffCanvasForm::class; + $definitions['system_branding_block']['forms']['off_canvas'] = SystemBrandingOffCanvasForm::class; } // Since menu blocks use derivatives, check the definition ID instead of // relying on the plugin ID. foreach ($definitions as &$definition) { if ($definition['id'] === 'system_menu_block') { - $definition['forms']['offcanvas'] = SystemMenuOffCanvasForm::class; + $definition['forms']['off_canvas'] = SystemMenuOffCanvasForm::class; } } } diff --git a/core/modules/outside_in/outside_in.routing.yml b/core/modules/outside_in/outside_in.routing.yml index 79bc38d..18a564c 100644 --- a/core/modules/outside_in/outside_in.routing.yml +++ b/core/modules/outside_in/outside_in.routing.yml @@ -1,7 +1,7 @@ -entity.block.offcanvas_form: - path: '/admin/structure/block/manage/{block}/offcanvas' +entity.block.off_canvas_form: + path: '/admin/structure/block/manage/{block}/off-canvas' defaults: - _entity_form: 'block.offcanvas' + _entity_form: 'block.off_canvas' _title_callback: '\Drupal\outside_in\Block\BlockEntityOffCanvasForm::title' requirements: _permission: 'administer blocks' diff --git a/core/modules/outside_in/outside_in.services.yml b/core/modules/outside_in/outside_in.services.yml index 48f5824..c678291 100644 --- a/core/modules/outside_in/outside_in.services.yml +++ b/core/modules/outside_in/outside_in.services.yml @@ -1,10 +1,4 @@ services: - main_content_renderer.off_canvas: - class: Drupal\outside_in\Render\MainContent\OffCanvasRender - arguments: ['@title_resolver', '@renderer'] - tags: - - { name: render.main_content_renderer, format: drupal_dialog_offcanvas } - outside_in.manager: class: Drupal\outside_in\OutsideInManager arguments: ['@router.admin_context', '@current_route_match', '@current_user'] diff --git a/core/modules/outside_in/src/Block/BlockEntityOffCanvasForm.php b/core/modules/outside_in/src/Block/BlockEntityOffCanvasForm.php index a77f51f..1d6ea37 100644 --- a/core/modules/outside_in/src/Block/BlockEntityOffCanvasForm.php +++ b/core/modules/outside_in/src/Block/BlockEntityOffCanvasForm.php @@ -92,7 +92,7 @@ protected function submitVisibility(array $form, FormStateInterface $form_state) */ protected function getPluginForm(BlockPluginInterface $block) { if ($block instanceof PluginWithFormsInterface) { - return $this->pluginFormFactory->createInstance($block, 'offcanvas', 'configure'); + return $this->pluginFormFactory->createInstance($block, 'off_canvas', 'configure'); } return $block; } diff --git a/core/modules/outside_in/tests/modules/offcanvas_test/offcanvas_test.routing.yml b/core/modules/outside_in/tests/modules/offcanvas_test/offcanvas_test.routing.yml deleted file mode 100644 index 761693b..0000000 --- a/core/modules/outside_in/tests/modules/offcanvas_test/offcanvas_test.routing.yml +++ /dev/null @@ -1,29 +0,0 @@ -offcanvas_test.links: - path: '/offcanvas-test-links' - defaults: - _controller: '\Drupal\offcanvas_test\Controller\TestController::linksDisplay' - _title: 'Links' - requirements: - _access: 'TRUE' - -offcanvas_test.thing1: - path: '/offcanvas-thing1' - defaults: - _controller: '\Drupal\offcanvas_test\Controller\TestController::thing1' - _title: 'Thing 1' - requirements: - _access: 'TRUE' - -offcanvas_test.thing2: - path: '/offcanvas-thing2' - defaults: - _controller: '\Drupal\offcanvas_test\Controller\TestController::thing2' - requirements: - _access: 'TRUE' - -offcanvas_test.dialog_links: - path: '/offcanvas-dialog-links' - defaults: - _controller: '\Drupal\offcanvas_test\Controller\TestController::otherDialogLinks' - requirements: - _access: 'TRUE' diff --git a/core/modules/outside_in/tests/modules/offcanvas_test/src/Plugin/Block/TestBlock.php b/core/modules/outside_in/tests/modules/offcanvas_test/src/Plugin/Block/TestBlock.php deleted file mode 100644 index efb38e0..0000000 --- a/core/modules/outside_in/tests/modules/offcanvas_test/src/Plugin/Block/TestBlock.php +++ /dev/null @@ -1,49 +0,0 @@ - [ - '#title' => $this->t('Click Me 1!'), - '#type' => 'link', - '#url' => Url::fromRoute('offcanvas_test.thing1'), - '#attributes' => [ - 'class' => ['use-ajax'], - 'data-dialog-type' => 'offcanvas', - ], - ], - 'offcanvas_link_2' => [ - '#title' => $this->t('Click Me 2!'), - '#type' => 'link', - '#url' => Url::fromRoute('offcanvas_test.thing2'), - '#attributes' => [ - 'class' => ['use-ajax'], - 'data-dialog-type' => 'offcanvas', - ], - ], - '#attached' => [ - 'library' => [ - 'outside_in/drupal.off_canvas', - ], - ], - ]; - } - -} diff --git a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php index c39f2f8..4242620 100644 --- a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php +++ b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInBlockFormTest.php @@ -119,14 +119,14 @@ public function testBlocks($block_id, $new_page_text, $element_selector, $label_ // Exit edit mode using ESC. $web_assert->elementTextContains('css', '.contextual-toolbar-tab button', 'Editing'); - $web_assert->elementAttributeContains('css', '.dialog-offcanvas__main-canvas', 'class', 'js-outside-in-edit-mode'); + $web_assert->elementAttributeContains('css', '.dialog-off-canvas__main-canvas', 'class', 'js-outside-in-edit-mode'); // Simulate press the Escape key. $this->getSession()->executeScript('jQuery("body").trigger(jQuery.Event("keyup", { keyCode: 27 }));'); $this->waitForOffCanvasToClose(); $this->getSession()->wait(100); $web_assert->elementTextContains('css', '#drupal-live-announce', 'Exited edit mode.'); $web_assert->elementTextNotContains('css', '.contextual-toolbar-tab button', 'Editing'); - $web_assert->elementAttributeNotContains('css', '.dialog-offcanvas__main-canvas', 'class', 'js-outside-in-edit-mode'); + $web_assert->elementAttributeNotContains('css', '.dialog-off-canvas__main-canvas', 'class', 'js-outside-in-edit-mode'); } /** diff --git a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php index 48ba899..a202211 100644 --- a/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php +++ b/core/modules/outside_in/tests/src/FunctionalJavascript/OutsideInJavascriptTestBase.php @@ -2,92 +2,12 @@ namespace Drupal\Tests\outside_in\FunctionalJavascript; -use Drupal\FunctionalJavascriptTests\JavascriptTestBase; +use Drupal\Tests\system\FunctionalJavascript\OffCanvasTestBase; /** * Base class contains common test functionality for the Settings Tray module. */ -abstract class OutsideInJavascriptTestBase extends JavascriptTestBase { - - /** - * {@inheritdoc} - */ - protected function drupalGet($path, array $options = array(), array $headers = array()) { - $return = parent::drupalGet($path, $options, $headers); - - // After the page loaded we need to additionally wait until the settings - // tray Ajax activity is done. - $this->assertSession()->assertWaitOnAjaxRequest(); - - return $return; - } - - /** - * Enables a theme. - * - * @param string $theme - * The theme. - */ - public function enableTheme($theme) { - // Enable the theme. - \Drupal::service('theme_installer')->install([$theme]); - $theme_config = \Drupal::configFactory()->getEditable('system.theme'); - $theme_config->set('default', $theme); - $theme_config->save(); - } - - /** - * Waits for Off-canvas tray to open. - */ - protected function waitForOffCanvasToOpen() { - $web_assert = $this->assertSession(); - $web_assert->assertWaitOnAjaxRequest(); - $this->waitForElement('#drupal-offcanvas'); - } - - /** - * Waits for Off-canvas tray to close. - */ - protected function waitForOffCanvasToClose() { - $this->waitForNoElement('#drupal-offcanvas'); - } - - /** - * Waits for an element to appear on the page. - * - * @param string $selector - * CSS selector. - * @param int $timeout - * (optional) Timeout in milliseconds, defaults to 10000. - */ - protected function waitForElement($selector, $timeout = 10000) { - $condition = "(jQuery('$selector').length > 0)"; - $this->assertJsCondition($condition, $timeout); - } - - /** - * Gets the Off-Canvas tray element. - * - * @return \Behat\Mink\Element\NodeElement|null - */ - protected function getTray() { - $tray = $this->getSession()->getPage()->find('css', '.ui-dialog[aria-describedby="drupal-offcanvas"]'); - $this->assertEquals(FALSE, empty($tray), 'The tray was found.'); - return $tray; - } - - /** - * Waits for an element to be removed from the page. - * - * @param string $selector - * CSS selector. - * @param int $timeout - * (optional) Timeout in milliseconds, defaults to 10000. - */ - protected function waitForNoElement($selector, $timeout = 10000) { - $condition = "(jQuery('$selector').length == 0)"; - $this->assertJsCondition($condition, $timeout); - } +abstract class OutsideInJavascriptTestBase extends OffCanvasTestBase { /** * Clicks a contextual link. diff --git a/core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php b/core/modules/system/src/Tests/Ajax/OffCanvasDialogTest.php similarity index 72% rename from core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php rename to core/modules/system/src/Tests/Ajax/OffCanvasDialogTest.php index f351042..ca0ce04 100644 --- a/core/modules/outside_in/src/Tests/Ajax/OffCanvasDialogTest.php +++ b/core/modules/system/src/Tests/Ajax/OffCanvasDialogTest.php @@ -1,27 +1,19 @@ drupalLogin($this->drupalCreateUser(['administer contact forms'])); @@ -32,9 +24,9 @@ public function testDialog() { $dialog_renderable = AjaxTestController::dialogContents(); $dialog_contents = \Drupal::service('renderer')->renderRoot($dialog_renderable); - $offcanvas_expected_response = [ + $off_canvas_expected_response = [ 'command' => 'openDialog', - 'selector' => '#drupal-offcanvas', + 'selector' => '#drupal-off-canvas', 'settings' => NULL, 'data' => $dialog_contents, 'dialogOptions' => @@ -52,8 +44,8 @@ public function testDialog() { ]; // Emulate going to the JS version of the page and check the JSON response. - $ajax_result = $this->drupalGetAjax('ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_dialog_offcanvas']]); - $this->assertEqual($offcanvas_expected_response, $ajax_result[3], 'Off-canvas dialog JSON response matches.'); + $ajax_result = $this->drupalGetAjax('ajax-test/dialog-contents', ['query' => [MainContentViewSubscriber::WRAPPER_FORMAT => 'drupal_dialog.off_canvas']]); + $this->assertEqual($off_canvas_expected_response, $ajax_result[3], 'Off-canvas dialog JSON response matches.'); } } diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 6581e60..d5e14ef 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -224,6 +224,9 @@ function system_theme() { ), 'template' => 'entity-add-list', ), + 'off_canvas_page_wrapper' => [ + 'variables' => ['children' => NULL], + ], )); } @@ -1445,3 +1448,12 @@ function system_query_entity_reference_alter(AlterableInterface $query) { $handler = $query->getMetadata('entity_reference_selection_handler'); $handler->entityQueryAlter($query); } + +/** + * Implements hook_element_info_alter(). + */ +function system_element_info_alter(&$type) { + if (isset($type['page'])) { + $type['page']['#theme_wrappers']['off_canvas_page_wrapper'] = ['#weight' => -1000]; + } +} diff --git a/core/modules/system/templates/off-canvas-page-wrapper.html.twig b/core/modules/system/templates/off-canvas-page-wrapper.html.twig new file mode 100644 index 0000000..c2f5fb9 --- /dev/null +++ b/core/modules/system/templates/off-canvas-page-wrapper.html.twig @@ -0,0 +1,18 @@ +{# +/** + * @file + * Default theme implementation for a page wrapper. + * + * For consistent wrapping to {{ page }} render in all themes. + * + * Available variables: + * - children: Contains the child elements of the page. + * + * @ingroup themeable + */ +#} +{% if children %} +
+ {{ children }} +
+{% endif %} diff --git a/core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.info.yml b/core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.info.yml new file mode 100644 index 0000000..f7544e7 --- /dev/null +++ b/core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.info.yml @@ -0,0 +1,6 @@ +name: 'Database Renderer Test' +type: module +description: 'Support module for Dialog Renderer tests.' +core: 8.x +package: Testing +version: VERSION diff --git a/core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.routing.yml b/core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.routing.yml new file mode 100644 index 0000000..3cfbde0 --- /dev/null +++ b/core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.routing.yml @@ -0,0 +1,15 @@ +dialog_renderer_test.links: + path: '/dialog_renderer-test-links' + defaults: + _controller: '\Drupal\dialog_renderer_test\Controller\TestController::linksDisplay' + _title: 'Links' + requirements: + _access: 'TRUE' + +dialog_renderer_test.modal_content: + path: '/dialog_renderer-content' + defaults: + _controller: '\Drupal\dialog_renderer_test\Controller\TestController::modalContent' + _title: 'Thing 1' + requirements: + _access: 'TRUE' diff --git a/core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.services.yml b/core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.services.yml new file mode 100644 index 0000000..1bf58fa --- /dev/null +++ b/core/modules/system/tests/modules/dialog_renderer_test/dialog_renderer_test.services.yml @@ -0,0 +1,6 @@ +services: + main_content_renderer.wide_modal: + class: Drupal\dialog_renderer_test\Render\MainContent\WideModalRenderer + arguments: ['@title_resolver', '@renderer'] + tags: + - { name: render.main_content_renderer, format: drupal_modal.wide } diff --git a/core/modules/system/tests/modules/dialog_renderer_test/src/Controller/TestController.php b/core/modules/system/tests/modules/dialog_renderer_test/src/Controller/TestController.php new file mode 100644 index 0000000..573a656 --- /dev/null +++ b/core/modules/system/tests/modules/dialog_renderer_test/src/Controller/TestController.php @@ -0,0 +1,65 @@ + 'markup', + '#markup' => 'Look at me in a modal!', + ]; + } + + /** + * Displays test links that will open in the modal dialog. + * + * @return array + * Render array with links. + */ + public function linksDisplay() { + return [ + 'normal_modal' => [ + '#title' => 'Normal Modal!', + '#type' => 'link', + '#url' => Url::fromRoute('dialog_renderer_test.modal_content'), + '#attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'modal', + ], + '#attached' => [ + 'library' => [ + 'core/drupal.ajax', + ], + ], + ], + 'wide_modal' => [ + '#title' => 'Wide Modal!', + '#type' => 'link', + '#url' => Url::fromRoute('dialog_renderer_test.modal_content'), + '#attributes' => [ + 'class' => ['use-ajax'], + 'data-dialog-type' => 'modal', + 'data-dialog-renderer' => 'wide', + ], + '#attached' => [ + 'library' => [ + 'core/drupal.ajax', + ], + ], + ], + ]; + } + +} diff --git a/core/modules/system/tests/modules/dialog_renderer_test/src/Render/MainContent/WideModalRenderer.php b/core/modules/system/tests/modules/dialog_renderer_test/src/Render/MainContent/WideModalRenderer.php new file mode 100644 index 0000000..6309f24 --- /dev/null +++ b/core/modules/system/tests/modules/dialog_renderer_test/src/Render/MainContent/WideModalRenderer.php @@ -0,0 +1,47 @@ +setAttachments($main_content['#attached']); + + // If the main content doesn't provide a title, use the title resolver. + $title = isset($main_content['#title']) ? $main_content['#title'] : $this->titleResolver->getTitle($request, $route_match->getRouteObject()); + + // Determine the title: use the title provided by the main content if any, + // otherwise get it from the routing information. + $options = $request->request->get('dialogOptions', []); + // Override width option. + $options['width'] = 700; + + $response->addCommand(new OpenModalDialogCommand($title, $content, $options)); + return $response; + } + +} diff --git a/core/modules/outside_in/tests/modules/offcanvas_test/offcanvas_test.info.yml b/core/modules/system/tests/modules/off_canvas_test/off_canvas_test.info.yml similarity index 91% rename from core/modules/outside_in/tests/modules/offcanvas_test/offcanvas_test.info.yml rename to core/modules/system/tests/modules/off_canvas_test/off_canvas_test.info.yml index 8c6cc80..cb3dd2c 100644 --- a/core/modules/outside_in/tests/modules/offcanvas_test/offcanvas_test.info.yml +++ b/core/modules/system/tests/modules/off_canvas_test/off_canvas_test.info.yml @@ -6,4 +6,3 @@ version: VERSION core: 8.x dependencies: - block - - outside_in diff --git a/core/modules/system/tests/modules/off_canvas_test/off_canvas_test.routing.yml b/core/modules/system/tests/modules/off_canvas_test/off_canvas_test.routing.yml new file mode 100644 index 0000000..4ae56c4 --- /dev/null +++ b/core/modules/system/tests/modules/off_canvas_test/off_canvas_test.routing.yml @@ -0,0 +1,29 @@ +off_canvas_test.links: + path: '/off-canvas-test-links' + defaults: + _controller: '\Drupal\off_canvas_test\Controller\TestController::linksDisplay' + _title: 'Links' + requirements: + _access: 'TRUE' + +off_canvas_test.thing1: + path: '/off-canvas-thing1' + defaults: + _controller: '\Drupal\off_canvas_test\Controller\TestController::thing1' + _title: 'Thing 1' + requirements: + _access: 'TRUE' + +off_canvas_test.thing2: + path: '/off-canvas-thing2' + defaults: + _controller: '\Drupal\off_canvas_test\Controller\TestController::thing2' + requirements: + _access: 'TRUE' + +off_canvas_test.dialog_links: + path: '/off-canvas-dialog-links' + defaults: + _controller: '\Drupal\off_canvas_test\Controller\TestController::otherDialogLinks' + requirements: + _access: 'TRUE' diff --git a/core/modules/outside_in/tests/modules/offcanvas_test/src/Controller/TestController.php b/core/modules/system/tests/modules/off_canvas_test/src/Controller/TestController.php similarity index 68% rename from core/modules/outside_in/tests/modules/offcanvas_test/src/Controller/TestController.php rename to core/modules/system/tests/modules/off_canvas_test/src/Controller/TestController.php index 9ee8e17..b69a340 100644 --- a/core/modules/outside_in/tests/modules/offcanvas_test/src/Controller/TestController.php +++ b/core/modules/system/tests/modules/off_canvas_test/src/Controller/TestController.php @@ -1,6 +1,6 @@ [ + 'off_canvas_link_1' => [ '#title' => 'Click Me 1!', '#type' => 'link', - '#url' => Url::fromRoute('offcanvas_test.thing1'), + '#url' => Url::fromRoute('off_canvas_test.thing1'), '#attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'dialog', - 'data-dialog-renderer' => 'offcanvas', + 'data-dialog-renderer' => 'off_canvas', ], '#attached' => [ 'library' => [ - 'outside_in/drupal.outside_in', + 'core/drupal.ajax', ], ], ], - 'offcanvas_link_2' => [ + 'off_canvas_link_2' => [ '#title' => 'Click Me 2!', '#type' => 'link', - '#url' => Url::fromRoute('offcanvas_test.thing2'), + '#url' => Url::fromRoute('off_canvas_test.thing2'), '#attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'dialog', - 'data-dialog-renderer' => 'offcanvas', + 'data-dialog-renderer' => 'off_canvas', 'data-dialog-options' => Json::encode([ 'width' => 555, ]), ], '#attached' => [ 'library' => [ - 'outside_in/drupal.outside_in', + 'core/drupal.ajax', ], ], ], 'other_dialog_links' => [ '#title' => 'Display more links!', '#type' => 'link', - '#url' => Url::fromRoute('offcanvas_test.dialog_links'), + '#url' => Url::fromRoute('off_canvas_test.dialog_links'), '#attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'dialog', - 'data-dialog-renderer' => 'offcanvas', + 'data-dialog-renderer' => 'off_canvas', ], '#attached' => [ 'library' => [ - 'outside_in/drupal.outside_in', + 'core/drupal.ajax', ], ], ], @@ -96,12 +96,12 @@ public function linksDisplay() { } /** - * Displays dialogs links to be displayed inside the offcanvas tray. + * Displays dialogs links to be displayed inside the off canvas tray. * - * This links are used to test opening a modal and another offcanvas link from - * inside the offcanvas tray. + * This links are used to test opening a modal and another off canvas link from + * inside the off canvas tray. * - * @todo Update tests to check these links work in the offcanvas tray. + * @todo Update tests to check these links work in the off canvas tray. * https://www.drupal.org/node/2790073 * * @return array @@ -113,25 +113,25 @@ public function otherDialogLinks() { '#links' => [ 'modal_link' => [ 'title' => 'Open modal!', - 'url' => Url::fromRoute('offcanvas_test.thing2'), + 'url' => Url::fromRoute('off_canvas_test.thing2'), 'attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'modal', ], ], - 'offcanvas_link' => [ + 'off_canvas_link' => [ 'title' => 'Offcanvas link!', - 'url' => Url::fromRoute('offcanvas_test.thing2'), + 'url' => Url::fromRoute('off_canvas_test.thing2'), 'attributes' => [ 'class' => ['use-ajax'], 'data-dialog-type' => 'dialog', - 'data-dialog-renderer' => 'offcanvas', + 'data-dialog-renderer' => 'off_canvas', ], ], ], '#attached' => [ 'library' => [ - 'outside_in/drupal.outside_in', + 'core/drupal.ajax', ], ], ]; diff --git a/core/modules/system/tests/src/FunctionalJavascript/ModalRendererTest.php b/core/modules/system/tests/src/FunctionalJavascript/ModalRendererTest.php new file mode 100644 index 0000000..ce234a1 --- /dev/null +++ b/core/modules/system/tests/src/FunctionalJavascript/ModalRendererTest.php @@ -0,0 +1,34 @@ +assertSession(); + $this->drupalGet('/dialog_renderer-test-links'); + $this->clickLink('Normal Modal!'); + $session_assert->assertWaitOnAjaxRequest(); + $session_assert->elementAttributeNotContains('css', '.ui-dialog', 'style', 'width: 700px;'); + $this->drupalGet('/dialog_renderer-test-links'); + $this->clickLink('Wide Modal!'); + $session_assert->assertWaitOnAjaxRequest(); + $session_assert->elementAttributeContains('css', '.ui-dialog', 'style', 'width: 700px;'); + } + +} diff --git a/core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php b/core/modules/system/tests/src/FunctionalJavascript/OffCanvasTest.php similarity index 65% rename from core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php rename to core/modules/system/tests/src/FunctionalJavascript/OffCanvasTest.php index b81c723..bfcda1c 100644 --- a/core/modules/outside_in/tests/src/FunctionalJavascript/OffCanvasTest.php +++ b/core/modules/system/tests/src/FunctionalJavascript/OffCanvasTest.php @@ -1,18 +1,18 @@ enableTheme($theme); - $this->drupalGet('/offcanvas-test-links'); + $this->drupalGet('/off-canvas-test-links'); $page = $this->getSession()->getPage(); $web_assert = $this->assertSession(); // Make sure off-canvas tray is on page when first loaded. - $web_assert->elementNotExists('css', '#drupal-offcanvas'); + $web_assert->elementNotExists('css', '#drupal-off-canvas'); // Check opening and closing with two separate links. // Make sure tray updates to new content. @@ -40,16 +40,16 @@ public function testOffCanvasLinks() { $this->waitForOffCanvasToOpen(); // Check that the canvas is not on the page. - $web_assert->elementExists('css', '#drupal-offcanvas'); + $web_assert->elementExists('css', '#drupal-off-canvas'); // Check that response text is on page. $web_assert->pageTextContains("Thing $link_index says hello"); - $offcanvas_tray = $this->getTray(); + $off_canvas_tray = $this->getTray(); // Check that tray is visible. - $this->assertEquals(TRUE, $offcanvas_tray->isVisible()); - $header_text = $offcanvas_tray->find('css', '.ui-dialog-title')->getText(); + $this->assertEquals(TRUE, $off_canvas_tray->isVisible()); + $header_text = $off_canvas_tray->find('css', '.ui-dialog-title')->getText(); - $tray_text = $offcanvas_tray->findById('drupal-offcanvas')->getText(); + $tray_text = $off_canvas_tray->findById('drupal-off-canvas')->getText(); $this->assertEquals("Thing $link_index says hello", $tray_text); if ($link_index == '2') { @@ -57,7 +57,7 @@ public function testOffCanvasLinks() { $web_assert->elementExists('css', '.ui-dialog-empty-title'); $this->assertEquals('', $header_text); - $style = $page->find('css', '.ui-dialog-offcanvas')->getAttribute('style'); + $style = $page->find('css', '.ui-dialog-off-canvas')->getAttribute('style'); self::assertTrue(strstr($style, 'width: 555px;') !== FALSE, 'Dialog width respected.'); } else { @@ -85,21 +85,21 @@ public function testNarrowWidth() { $this->enableTheme($theme); // Testing at the wider width. $this->getSession()->resizeWindow($narrow_width_breakpoint + $offset, $height); - $this->drupalGet('/offcanvas-test-links'); - $this->assertFalse($page->find('css', '.dialog-offcanvas__main-canvas')->hasAttribute('style'), 'Body not padded on wide page load.'); + $this->drupalGet('/off-canvas-test-links'); + $this->assertFalse($page->find('css', '.dialog-off-canvas__main-canvas')->hasAttribute('style'), 'Body not padded on wide page load.'); $page->clickLink("Click Me 1!"); $this->waitForOffCanvasToOpen(); // Check that the main canvas is padded when page is not narrow width and // tray is open. - $web_assert->elementAttributeContains('css', '.dialog-offcanvas__main-canvas', 'style', 'padding-right'); + $web_assert->elementAttributeContains('css', '.dialog-off-canvas__main-canvas', 'style', 'padding-right'); // Testing at the narrower width. $this->getSession()->resizeWindow($narrow_width_breakpoint - $offset, $height); - $this->drupalGet('/offcanvas-test-links'); - $this->assertFalse($page->find('css', '.dialog-offcanvas__main-canvas')->hasAttribute('style'), 'Body not padded on narrow page load.'); + $this->drupalGet('/off-canvas-test-links'); + $this->assertFalse($page->find('css', '.dialog-off-canvas__main-canvas')->hasAttribute('style'), 'Body not padded on narrow page load.'); $page->clickLink("Click Me 1!"); $this->waitForOffCanvasToOpen(); - $this->assertFalse($page->find('css', '.dialog-offcanvas__main-canvas')->hasAttribute('style'), 'Body not padded on narrow page with tray open.'); + $this->assertFalse($page->find('css', '.dialog-off-canvas__main-canvas')->hasAttribute('style'), 'Body not padded on narrow page with tray open.'); } } diff --git a/core/modules/system/tests/src/FunctionalJavascript/OffCanvasTestBase.php b/core/modules/system/tests/src/FunctionalJavascript/OffCanvasTestBase.php new file mode 100644 index 0000000..bcd56a7 --- /dev/null +++ b/core/modules/system/tests/src/FunctionalJavascript/OffCanvasTestBase.php @@ -0,0 +1,93 @@ +assertSession(); + $web_assert->assertWaitOnAjaxRequest(); + $this->waitForElement('#drupal-off-canvas'); + } + + /** + * Waits for an element to appear on the page. + * + * @param string $selector + * CSS selector. + * @param int $timeout + * (optional) Timeout in milliseconds, defaults to 10000. + */ + protected function waitForElement($selector, $timeout = 10000) { + $condition = "(jQuery('$selector').length > 0)"; + $this->assertJsCondition($condition, $timeout); + } + + /** + * {@inheritdoc} + */ + protected function drupalGet($path, array $options = [], array $headers = []) { + $return = parent::drupalGet($path, $options, $headers); + + // After the page loaded we need to additionally wait until the settings + // tray Ajax activity is done. + $this->assertSession()->assertWaitOnAjaxRequest(); + + return $return; + } + + /** + * Enables a theme. + * + * @param string $theme + * The theme. + */ + public function enableTheme($theme) { + // Enable the theme. + \Drupal::service('theme_installer')->install([$theme]); + $theme_config = \Drupal::configFactory()->getEditable('system.theme'); + $theme_config->set('default', $theme); + $theme_config->save(); + } + + /** + * Waits for Off-canvas tray to close. + */ + protected function waitForOffCanvasToClose() { + $this->waitForNoElement('#drupal-off-canvas'); + } + + /** + * Waits for an element to be removed from the page. + * + * @param string $selector + * CSS selector. + * @param int $timeout + * (optional) Timeout in milliseconds, defaults to 10000. + */ + protected function waitForNoElement($selector, $timeout = 10000) { + $condition = "(jQuery('$selector').length == 0)"; + $this->assertJsCondition($condition, $timeout); + } + + /** + * Gets the Off-Canvas tray element. + * + * @return \Behat\Mink\Element\NodeElement|null + * The tray page element. + */ + protected function getTray() { + $tray = $this->getSession()->getPage()->find('css', '.ui-dialog[aria-describedby="drupal-off-canvas"]'); + $this->assertEquals(FALSE, empty($tray), 'The tray was found.'); + return $tray; + } + +} diff --git a/core/modules/outside_in/tests/src/Unit/Ajax/OpenOffCanvasDialogCommandTest.php b/core/modules/system/tests/src/Unit/Ajax/OpenOffCanvasDialogCommandTest.php similarity index 76% rename from core/modules/outside_in/tests/src/Unit/Ajax/OpenOffCanvasDialogCommandTest.php rename to core/modules/system/tests/src/Unit/Ajax/OpenOffCanvasDialogCommandTest.php index cd14d6d..1bed8a1 100644 --- a/core/modules/outside_in/tests/src/Unit/Ajax/OpenOffCanvasDialogCommandTest.php +++ b/core/modules/system/tests/src/Unit/Ajax/OpenOffCanvasDialogCommandTest.php @@ -1,13 +1,13 @@ 'openDialog', - 'selector' => '#drupal-offcanvas', + 'selector' => '#drupal-off-canvas', 'settings' => NULL, 'data' => '

Text!

', 'dialogOptions' => [ diff --git a/core/themes/stable/css/core/dialog/off-canvas.css b/core/themes/stable/css/core/dialog/off-canvas.css new file mode 100644 index 0000000..cf5f47f --- /dev/null +++ b/core/themes/stable/css/core/dialog/off-canvas.css @@ -0,0 +1,39 @@ +/** + * @file + * CSS for Offcanvas tray. + */ +/* Position the dialog-offcanvas tray container outside the right of the viewport. */ +.ui-dialog-off-canvas { + box-sizing: border-box; + height: 100%; + overflow: visible; +} + +/* Wrap the form that's inside the dialog-offcanvas tray. */ +.ui-dialog-off-canvas .ui-dialog-content { + padding: 0 20px; + /* Prevent horizontal scrollbar. */ + overflow-x: hidden; + overflow-y: auto; +} + +[dir="rtl"] .ui-dialog-off-canvas .ui-dialog-content { + text-align: right; +} + +/* + * Force the tray to be 100% width at the same breakpoint the dialog system uses + * to expand dialog widths. + */ +@media all and (max-width: 48em) { + /* 768px */ + .ui-dialog.ui-dialog-off-canvas { + width: 100% !important; + } + + /* When tray is at 100% width stop the body from scrolling */ + .js-tray-open { + height: 100%; + overflow-y: hidden; + } +} diff --git a/core/themes/stable/css/core/dialog/off-canvas.motion.css b/core/themes/stable/css/core/dialog/off-canvas.motion.css new file mode 100644 index 0000000..c1379be --- /dev/null +++ b/core/themes/stable/css/core/dialog/off-canvas.motion.css @@ -0,0 +1,31 @@ +/** + * @file + * Motion effects for off-canvas tray dialog. + * + * Motion effects are in a separate file so that they can be easily turned off + * to improve performance if desired. + * + * @todo Add a configuration option for browser rendering performance to disable + * this file: https://www.drupal.org/node/2784443. + */ + +/* Transition the dialog-offcanvas tray container, with 2s delay to match main canvas speed. */ +.ui-dialog-off-canvas .ui-dialog-content { + -webkit-transition: all .7s ease 2s; + -moz-transition: all .7s ease 2s; + transition: all .7s ease 2s; +} + +@media (max-width: 700px) { + .ui-dialog-off-canvas .ui-dialog-content { + -webkit-transition: all .7s ease; + -moz-transition: all .7s ease; + transition: all .7s ease; + } +} + +.dialog-off-canvas__main-canvas { + -webkit-transition: all .7s ease; + -moz-transition: all .7s ease; + transition: all .7s ease; +} diff --git a/core/themes/stable/stable.info.yml b/core/themes/stable/stable.info.yml index 7e585b1..3aceac6 100644 --- a/core/themes/stable/stable.info.yml +++ b/core/themes/stable/stable.info.yml @@ -65,6 +65,11 @@ libraries-override: css: component: misc/vertical-tabs.css: css/core/vertical-tabs.css + core/drupal.dialog.off_canvas: + css: + component: + misc/dialog/off-canvas.css: css/core/dialog/off-canvas.css + misc/dialog/off-canvas.motion.css: css/core/dialog/off-canvas.motion.css dblog/drupal.dblog: css: diff --git a/core/modules/outside_in/templates/outside-in-page-wrapper.html.twig b/core/themes/stable/templates/layout/off-canvas-page-wrapper.html.twig similarity index 80% rename from core/modules/outside_in/templates/outside-in-page-wrapper.html.twig rename to core/themes/stable/templates/layout/off-canvas-page-wrapper.html.twig index adedc6b..c2f5fb9 100644 --- a/core/modules/outside_in/templates/outside-in-page-wrapper.html.twig +++ b/core/themes/stable/templates/layout/off-canvas-page-wrapper.html.twig @@ -12,7 +12,7 @@ */ #} {% if children %} -
+
{{ children }}
{% endif %}