Skip to content

Commit

Permalink
fix(modal): use resizeobserver
Browse files Browse the repository at this point in the history
  • Loading branch information
lubber-de committed Dec 20, 2023
1 parent 7259033 commit ca06749
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 25 deletions.
104 changes: 81 additions & 23 deletions src/definitions/modules/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
id,
observer,
observeAttributes = false,
resizeObserver,
module
;
module = {
Expand Down Expand Up @@ -246,6 +247,9 @@
if (observer) {
observer.disconnect();
}
if (resizeObserver) {
resizeObserver.disconnect();
}
module.verbose('Destroying previous modal');
$module
.removeData(moduleNamespace)
Expand All @@ -263,6 +267,13 @@

observeChanges: function () {
if ('MutationObserver' in window) {
if ('ResizeObserver' in window && settings.observeChanges) {
resizeObserver = new ResizeObserver(function (entries) {
module.refresh();
});
resizeObserver.observe(element);
module.debug('Setting up resize observer', resizeObserver);
}
observer = new MutationObserver(function (mutations) {
var collectNodes = function (parent) {
var nodes = [];
Expand Down Expand Up @@ -299,7 +310,7 @@
return !shouldRefreshInputs;
});

if (shouldRefresh && settings.observeChanges) {
if (!resizeObserver && shouldRefresh && settings.observeChanges) {
module.debug('DOM tree modified, refreshing');
module.refresh();
}
Expand All @@ -319,12 +330,15 @@

refresh: function () {
module.remove.scrolling();
module.cacheSizes();
if (!module.can.useFlex()) {
module.set.modalOffset();
if ($module.css('display') !== 'none') {
module.cacheSizes();
if (!module.can.useFlex()) {
module.set.modalOffset();
}
module.set.screenHeight();
module.set.dimmerHeight();
module.set.type();
}
module.set.screenHeight();
module.set.type();
},

refreshModals: function () {
Expand Down Expand Up @@ -601,7 +615,7 @@
}
hadScrollbar = module.has.scrollbar();
module.showDimmer();
module.cacheSizes();
module.cacheSizes(true);
if (hadScrollbar) {
module.set.bodyMargin();
}
Expand Down Expand Up @@ -729,7 +743,8 @@
if ($dimmable.dimmer('is animating') || !$dimmable.dimmer('is active')) {
if (hadScrollbar) {
if (!isBody) {
$dimmer.css('top', $dimmable.scrollTop());
$dimmer.css('top', settings.detachable ? $dimmable.scrollTop() : 0);
module.set.dimmerHeight();
}
module.save.bodyMargin();
}
Expand All @@ -749,6 +764,7 @@
}
module.remove.clickaway();
module.remove.screenHeight();
module.remove.dimmerHeight();
});
} else {
module.debug('Dimmer is not visible cannot hide');
Expand Down Expand Up @@ -881,13 +897,28 @@
$context.removeAttr('style');
}
},
dimmerStyle: function () {
if ($dimmer.attr('style') === '') {
module.verbose('Removing dimmer style attribute');
$dimmer.removeAttr('style');
}
},
screenHeight: function () {
module.debug('Removing page height');
$context
.css('height', '')
;
module.remove.bodyStyle();
},
dimmerHeight: function () {
module.debug('Removing dimmer height');
$dimmer.css({
top: '',
height: '',
maxHeight: '',
});
module.remove.dimmerStyle();
},
keyboardShortcuts: function () {
module.verbose('Removing keyboard shortcuts');
$document
Expand All @@ -902,12 +933,14 @@
},
},

cacheSizes: function () {
cacheSizes: function (getScrollingMargins) {
$module.addClass(className.loading);
var
scrollHeight = $module.prop('scrollHeight'),
modalWidth = $module.outerWidth(),
modalHeight = $module.outerHeight()
modalHeight = $module.outerHeight(),
scrollingTop = 0,
bottomMargin = 0
;
if (module.cache.pageHeight === undefined || modalHeight !== 0) {
$.extend(module.cache, {
Expand All @@ -921,6 +954,18 @@
});
module.cache.topOffset = -(module.cache.height / 2);
}
if (getScrollingMargins) {
if (module.can.useFlex()) {
$module.addClass(className.scrolling);
scrollingTop = parseInt($module.css('top').replace(/[^\d.]/g, ''), 10) || 0;
bottomMargin = parseInt(window.getComputedStyle($module[0], '::after').height.replace(/[^\d.]/g, ''), 10) || 0;
$module.removeClass(className.scrolling);
}
$.extend(module.cache, {
scrollingTop: scrollingTop,
bottomMargin: bottomMargin,
});
}
$module.removeClass(className.loading);
module.debug('Caching modal and container sizes', module.cache);
},
Expand Down Expand Up @@ -980,15 +1025,16 @@
contextHeight = module.cache.contextHeight,
verticalCenter = module.cache.contextHeight / 2,
topOffset = module.cache.topOffset,
scrollHeight = module.cache.scrollHeight,
scrollingTop = module.cache.scrollingTop || 0,
scrollHeight = module.cache.scrollHeight - (module.cache.bottomMargin || 0),
height = module.cache.height,
paddingHeight = settings.padding,
startPosition = verticalCenter + topOffset
;

return scrollHeight > height
? startPosition + scrollHeight + paddingHeight < contextHeight
: height + (paddingHeight * 2) < contextHeight;
: height + (paddingHeight * 2) - scrollingTop < contextHeight;
},
},
has: {
Expand Down Expand Up @@ -1140,14 +1186,15 @@
},
modalOffset: function () {
if (!settings.detachable) {
var canFit = module.can.fit();
var canFit = module.can.fit(),
scrollTop = (isBody ? $document : $context).scrollTop();
$module
.css({
top: !$module.hasClass('aligned') && canFit
? $document.scrollTop() + (module.cache.contextHeight - module.cache.height) / 2
? scrollTop + (module.cache.contextHeight - module.cache.height) / 2
: (!canFit || $module.hasClass('top')
? $document.scrollTop() + settings.padding
: $document.scrollTop() + (module.cache.contextHeight - module.cache.height - settings.padding)),
? scrollTop + settings.padding
: scrollTop + (module.cache.contextHeight - module.cache.height - settings.padding)),
marginLeft: -(module.cache.width / 2),
})
;
Expand All @@ -1164,13 +1211,24 @@
module.verbose('Setting modal offset for legacy mode');
},
screenHeight: function () {
if (module.can.fit()) {
$context.css('height', '');
} else if (!$module.hasClass('bottom')) {
module.debug('Modal is taller than page content, resizing page height');
$context
.css('height', module.cache.height + (settings.padding * 2) + 'px')
;
if (!isBody && !settings.detachable) {
if (module.can.fit() || hadScrollbar) {
$context.css('height', '');
} else if (!$module.hasClass('bottom')) {
module.debug('Modal is taller than page content, resizing page height');
$context
.css('height', module.cache.height + (settings.padding * 2) + 'px')
;
}
}
},
dimmerHeight: function () {
if (!isBody && !settings.detachable) {
var contextHeight = $context.prop('scrollHeight');
$dimmer.css({
height: contextHeight,
maxHeight: contextHeight,
});
}
},
active: function () {
Expand Down
13 changes: 11 additions & 2 deletions src/definitions/modules/modal.less
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@
opacity: @closeOpacityDimmed;
}
}
.undetached.dimmable.dimmed > .ui.modal:not(.fullscreen) > .close:not(.inside),
.ui.dimmer > .ui.modal:not(.fullscreen) > .close:not(.inside) {
text-shadow: @closeShadow;
}
Expand Down Expand Up @@ -447,6 +448,9 @@
overflow: auto;
overscroll-behavior: @overscrollBehavior;
}
.modals.dimmer {
scrollbar-gutter: stable;
}
.modals.dimmer .ui.scrolling.modal.fullscreen {
top: 0;
}
Expand All @@ -455,12 +459,17 @@
top: @scrollingTop;
}

/* Fix for Firefox, Edge, IE11 */
.modals.dimmer .ui.scrolling.modal:not([class*="overlay fullscreen"])::after {
.modals.dimmer .ui.modal:not([class*="overlay fullscreen"])::after {
content: "\00A0";
position: absolute;
height: 0;
}
.modals.dimmer .ui.scrolling.modal:not([class*="overlay fullscreen"])::after {
height: @scrollingMargin;
}
.dimmable.dimmed > .modals.dimmer {
overflow: auto;
}

/* Undetached Scrolling */
.scrolling.undetached.dimmable.dimmed {
Expand Down

0 comments on commit ca06749

Please sign in to comment.