jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/386414 )

Change subject: Allow adding virtual viewport spacing
......................................................................


Allow adding virtual viewport spacing

Users can now override OO.ui.getViewportSpacing() to return additional
spacing that should be taken into account when displaying elements
that are clipped to the viewport, e.g. dropdown menus and popups.
This is meant to be overridden to avoid such menus overlapping any
fixed headers/toolbars/navigation used by the site.

Various code dealing with positioning/clipping elements now makes use
of that functions to pretend that the browser viewport is smaller than
it really is.

Note that funny things will happen if you override it and then put
OOUI widgets inside such a menu, as the widgets will always be
considered to be outside of viewport.

Bug: T106095
Change-Id: Iabfc1ea50f4eb3239e27d87e404ad13e1cddc3bb
---
M demos/demo.js
M src/core.js
M src/mixins/ClippableElement.js
M src/mixins/FloatableElement.js
M src/widgets/PopupWidget.js
5 files changed, 53 insertions(+), 6 deletions(-)

Approvals:
  jenkins-bot: Verified
  VolkerE: Looks good to me, approved



diff --git a/demos/demo.js b/demos/demo.js
index c41e6c0..9ee3e12 100644
--- a/demos/demo.js
+++ b/demos/demo.js
@@ -29,7 +29,10 @@
                                new OO.ui.MenuOptionWidget( { data: 'icons', 
label: 'Icons' } ),
                                new OO.ui.MenuOptionWidget( { data: 'toolbars', 
label: 'Toolbars' } ),
                                new OO.ui.MenuOptionWidget( { data: 'widgets', 
label: 'Widgets' } )
-                       ]
+                       ],
+                       // Funny effect... This dropdown is considered to 
always be "out of viewport"
+                       // due to the getViewportSpacing() override below. 
Don't let it disappear.
+                       hideWhenOutOfView: false
                },
                classes: [ 'demo-pageDropdown' ]
        } );
@@ -99,6 +102,15 @@
        OO.ui.isMobile = function () {
                return demo.mode.platform === 'mobile';
        };
+       OO.ui.getViewportSpacing = function () {
+               return {
+                       // Contents of dialogs are shown on top of the fixed 
menu
+                       top: demo.mode.page === 'dialogs' ? 0 : 
demo.$menu.outerHeight(),
+                       right: 0,
+                       bottom: 0,
+                       left: 0
+               };
+       };
 };
 
 /* Setup */
diff --git a/src/core.js b/src/core.js
index 1073da9..c2b11e1 100644
--- a/src/core.js
+++ b/src/core.js
@@ -524,3 +524,20 @@
 OO.ui.isMobile = function () {
        return false;
 };
+
+/**
+ * Get the additional spacing that should be taken into account when 
displaying elements that are
+ * clipped to the viewport, e.g. dropdown menus and popups. This is meant to 
be overridden to avoid
+ * such menus overlapping any fixed headers/toolbars/navigation used by the 
site.
+ *
+ * @return {Object} Object with the properties 'top', 'right', 'bottom', 
'left', each representing
+ *     the extra spacing from that edge of viewport (in pixels)
+ */
+OO.ui.getViewportSpacing = function () {
+       return {
+               top: 0,
+               right: 0,
+               bottom: 0,
+               left: 0
+       };
+};
diff --git a/src/mixins/ClippableElement.js b/src/mixins/ClippableElement.js
index 8d61c82..43c2220 100644
--- a/src/mixins/ClippableElement.js
+++ b/src/mixins/ClippableElement.js
@@ -246,7 +246,7 @@
  * @chainable
  */
 OO.ui.mixin.ClippableElement.prototype.clip = function () {
-       var extraHeight, extraWidth,
+       var extraHeight, extraWidth, viewportSpacing,
                desiredWidth, desiredHeight, allotedWidth, allotedHeight,
                naturalWidth, naturalHeight, clipWidth, clipHeight,
                $item, itemRect, $viewport, viewportRect, availableRect,
@@ -270,6 +270,8 @@
                return out;
        }
 
+       viewportSpacing = OO.ui.getViewportSpacing();
+
        if ( this.$clippableScrollableContainer.is( 'html, body' ) ) {
                $viewport = $( this.$clippableScrollableContainer[ 0 
].ownerDocument.body );
                // Dimensions of the browser window, rather than the element!
@@ -279,6 +281,10 @@
                        right: document.documentElement.clientWidth,
                        bottom: document.documentElement.clientHeight
                };
+               viewportRect.top += viewportSpacing.top;
+               viewportRect.left += viewportSpacing.left;
+               viewportRect.right -= viewportSpacing.right;
+               viewportRect.bottom -= viewportSpacing.bottom;
        } else {
                $viewport = this.$clippableScrollableContainer;
                viewportRect = $viewport[ 0 ].getBoundingClientRect();
@@ -330,8 +336,10 @@
        desiredWidth = Math.max( 0, availableRect.right - availableRect.left );
        desiredHeight = Math.max( 0, availableRect.bottom - availableRect.top );
        // It should never be desirable to exceed the dimensions of the browser 
viewport... right?
-       desiredWidth = Math.min( desiredWidth, 
document.documentElement.clientWidth );
-       desiredHeight = Math.min( desiredHeight, 
document.documentElement.clientHeight );
+       desiredWidth = Math.min( desiredWidth,
+               document.documentElement.clientWidth - viewportSpacing.left - 
viewportSpacing.right );
+       desiredHeight = Math.min( desiredHeight,
+               document.documentElement.clientHeight - viewportSpacing.top - 
viewportSpacing.right );
        allotedWidth = Math.ceil( desiredWidth - extraWidth );
        allotedHeight = Math.ceil( desiredHeight - extraHeight );
        naturalWidth = this.$clippable.prop( 'scrollWidth' );
diff --git a/src/mixins/FloatableElement.js b/src/mixins/FloatableElement.js
index dc74067..c5b6da3 100644
--- a/src/mixins/FloatableElement.js
+++ b/src/mixins/FloatableElement.js
@@ -193,17 +193,22 @@
  */
 OO.ui.mixin.FloatableElement.prototype.isElementInViewport = function ( 
$element, $container ) {
        var elemRect, contRect, topEdgeInBounds, bottomEdgeInBounds, 
leftEdgeInBounds, rightEdgeInBounds,
-               startEdgeInBounds, endEdgeInBounds,
+               startEdgeInBounds, endEdgeInBounds, viewportSpacing,
                direction = $element.css( 'direction' );
 
        elemRect = $element[ 0 ].getBoundingClientRect();
        if ( $container[ 0 ] === window ) {
+               viewportSpacing = OO.ui.getViewportSpacing();
                contRect = {
                        top: 0,
                        left: 0,
                        right: document.documentElement.clientWidth,
                        bottom: document.documentElement.clientHeight
                };
+               contRect.top += viewportSpacing.top;
+               contRect.left += viewportSpacing.left;
+               contRect.right -= viewportSpacing.right;
+               contRect.bottom -= viewportSpacing.bottom;
        } else {
                contRect = $container[ 0 ].getBoundingClientRect();
        }
diff --git a/src/widgets/PopupWidget.js b/src/widgets/PopupWidget.js
index 322187a..d0ca042 100644
--- a/src/widgets/PopupWidget.js
+++ b/src/widgets/PopupWidget.js
@@ -454,7 +454,7 @@
 OO.ui.PopupWidget.prototype.computePosition = function () {
        var direction, align, vertical, start, end, near, far, sizeProp, 
popupSize, anchorSize, anchorPos,
                anchorOffset, anchorMargin, parentPosition, positionProp, 
positionAdjustment, floatablePos,
-               offsetParentPos, containerPos, popupPosition,
+               offsetParentPos, containerPos, popupPosition, viewportSpacing,
                popupPos = {},
                anchorCss = { left: '', right: '', top: '', bottom: '' },
                popupPositionOppositeMap = {
@@ -575,6 +575,11 @@
                { top: 0, left: 0 } :
                this.$container.offset();
        containerPos[ far ] = containerPos[ near ] + this.$container[ 'inner' + 
sizeProp ]();
+       if ( this.$container[ 0 ] === document.documentElement ) {
+               viewportSpacing = OO.ui.getViewportSpacing();
+               containerPos[ near ] += viewportSpacing[ near ];
+               containerPos[ far ] -= viewportSpacing[ far ];
+       }
        // Take into account how much the popup will move because of the 
adjustments we're going to make
        popupPos[ near ] += ( positionProp === near ? 1 : -1 ) * 
positionAdjustment;
        popupPos[ far ] += ( positionProp === near ? 1 : -1 ) * 
positionAdjustment;

-- 
To view, visit https://gerrit.wikimedia.org/r/386414
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Iabfc1ea50f4eb3239e27d87e404ad13e1cddc3bb
Gerrit-PatchSet: 4
Gerrit-Project: oojs/ui
Gerrit-Branch: master
Gerrit-Owner: Bartosz Dziewoński <[email protected]>
Gerrit-Reviewer: Bartosz Dziewoński <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Jforrester <[email protected]>
Gerrit-Reviewer: VolkerE <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to