diff --git a/core/core.libraries.yml b/core/core.libraries.yml index bd81e31..b220cc2 100644 --- a/core/core.libraries.yml +++ b/core/core.libraries.yml @@ -162,6 +162,9 @@ drupal.dialog: misc/dialog/dialog.js: {} misc/dialog/dialog.position.js: {} misc/dialog/dialog.jquery-ui.js: {} + css: + component: + misc/dialog/dialog.css: {} dependencies: - core/jquery - core/drupal diff --git a/core/misc/dialog/dialog.css b/core/misc/dialog/dialog.css new file mode 100644 index 0000000..64d54fb --- /dev/null +++ b/core/misc/dialog/dialog.css @@ -0,0 +1,18 @@ +/** + * @file + * Contains base dialog styles. + */ + +/* Lock body-level scrolling when dialogs are open as modals. */ +body.drupal-dialog-open-modal { + overflow: hidden; +} + +/* Used to calculate the width of the browser's scrollbar dynamically. */ +.drupal-dialog-scrollbar-measure { + width: 100px; + height: 100px; + overflow: scroll; + position: absolute; + top: -9999px; +} diff --git a/core/misc/dialog/dialog.js b/core/misc/dialog/dialog.js index ea1e52c..011929f 100644 --- a/core/misc/dialog/dialog.js +++ b/core/misc/dialog/dialog.js @@ -65,6 +65,9 @@ Drupal.dialog = function (element, options) { var undef; var $element = $(element); + var $body = $('body'); + var originalBodyPad = ''; + var dialog = { open: false, returnValue: undef, @@ -81,6 +84,19 @@ settings = $.extend({}, drupalSettings.dialog, options, settings); // Trigger a global event to allow scripts to bind events to the dialog. $(window).trigger('dialog:beforecreate', [dialog, $element, settings]); + + // Store the current body padding to undo any changes we may do. + originalBodyPad = $body.css('padding-right'); + $body.data('drupal-dialog-padding', originalBodyPad); + + // Add body classes to indicate that the dialog is open. + $body.addClass('drupal-dialog-open'); + // Add an additional class if a modal is open. + if (settings.modal) { + setScrollbarPadding(); + $body.addClass('drupal-dialog-open-modal'); + } + $element.dialog(settings); dialog.open = true; $(window).trigger('dialog:aftercreate', [dialog, $element, settings]); @@ -88,12 +104,48 @@ function closeDialog(value) { $(window).trigger('dialog:beforeclose', [dialog, $element]); + + // Remove the body classes we add in openDialog(). + $body.removeClass('drupal-dialog-open drupal-dialog-open-modal'); + + // Restore original padding-right value for the body. + originalBodyPad = $body.data('drupal-dialog-padding'); + $body.css('padding-right', originalBodyPad); + $element.dialog('close'); dialog.returnValue = value; dialog.open = false; $(window).trigger('dialog:afterclose', [dialog, $element]); } + function isBodyOverflowing() { + var fullWindowWidth = window.innerWidth; + // Workaround for missing window.innerWidth in IE8. + if (!fullWindowWidth) { + var documentElementRect = document.documentElement.getBoundingClientRect(); + fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left); + } + return document.body.clientWidth < fullWindowWidth; + } + + function getScrollbarWidth() { + // Create the measurement node. + var scrollDiv = document.createElement('div'); + scrollDiv.className = 'drupal-dialog-scrollbar-measure'; + document.body.appendChild(scrollDiv); + // Get the scrollbar width. + var width = scrollDiv.offsetWidth - scrollDiv.clientWidth; + // Delete the DIV. + document.body.removeChild(scrollDiv); + return width; + } + + function setScrollbarPadding() { + // Add padding to the body based on how wide our scrollbar is. + var bodyPad = parseInt(($body.css('padding-right') || 0), 10); + if (isBodyOverflowing()) $body.css('padding-right', bodyPad + getScrollbarWidth()); + } + return dialog; }; diff --git a/core/themes/stable/css/core/dialog/dialog.css b/core/themes/stable/css/core/dialog/dialog.css new file mode 100644 index 0000000..64d54fb --- /dev/null +++ b/core/themes/stable/css/core/dialog/dialog.css @@ -0,0 +1,18 @@ +/** + * @file + * Contains base dialog styles. + */ + +/* Lock body-level scrolling when dialogs are open as modals. */ +body.drupal-dialog-open-modal { + overflow: hidden; +} + +/* Used to calculate the width of the browser's scrollbar dynamically. */ +.drupal-dialog-scrollbar-measure { + width: 100px; + height: 100px; + overflow: scroll; + position: absolute; + top: -9999px; +} diff --git a/core/themes/stable/stable.info.yml b/core/themes/stable/stable.info.yml index 3476833..d6dc440 100644 --- a/core/themes/stable/stable.info.yml +++ b/core/themes/stable/stable.info.yml @@ -65,6 +65,10 @@ libraries-override: css: component: misc/vertical-tabs.css: css/core/vertical-tabs.css + core/drupal.dialog: + css: + component: + misc/dialog/dialog.css: css/core/dialog/dialog.css dblog/drupal.dblog: css: