Bartosz Dziewoński has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/276664

Change subject: FloatableElement: Hide if the anchor element is outside viewport
......................................................................

FloatableElement: Hide if the anchor element is outside viewport

Bug: T129521
Change-Id: I5b5d7936c4de8f89917feb5f548916030bce70f8
---
M src/mixins/FloatableElement.js
M src/styles/elements/FloatableElement.less
2 files changed, 66 insertions(+), 10 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/oojs/ui refs/changes/64/276664/1

diff --git a/src/mixins/FloatableElement.js b/src/mixins/FloatableElement.js
index ebdd392..55f1f23 100644
--- a/src/mixins/FloatableElement.js
+++ b/src/mixins/FloatableElement.js
@@ -86,22 +86,19 @@
 
                closestScrollableOfContainer = 
OO.ui.Element.static.getClosestScrollableContainer( this.$floatableContainer[ 0 
] );
                closestScrollableOfFloatable = 
OO.ui.Element.static.getClosestScrollableContainer( this.$floatable[ 0 ] );
-               if ( closestScrollableOfContainer !== 
closestScrollableOfFloatable ) {
-                       // If the scrollable is the root, we have to listen to 
scroll events
-                       // on the window because of browser inconsistencies (or 
do we? someone should verify this)
-                       if ( $( closestScrollableOfContainer ).is( 'html, body' 
) ) {
-                               closestScrollableOfContainer = 
OO.ui.Element.static.getWindow( closestScrollableOfContainer );
-                       }
+               this.needsCustomPosition = closestScrollableOfContainer !== 
closestScrollableOfFloatable;
+               // If the scrollable is the root, we have to listen to scroll 
events
+               // on the window because of browser inconsistencies.
+               if ( $( closestScrollableOfContainer ).is( 'html, body' ) ) {
+                       closestScrollableOfContainer = 
OO.ui.Element.static.getWindow( closestScrollableOfContainer );
                }
 
                if ( positioning ) {
                        this.$floatableWindow = $( this.getElementWindow() );
                        this.$floatableWindow.on( 'resize', 
this.onFloatableWindowResizeHandler );
 
-                       if ( closestScrollableOfContainer !== 
closestScrollableOfFloatable ) {
-                               this.$floatableClosestScrollable = $( 
closestScrollableOfContainer );
-                               this.$floatableClosestScrollable.on( 'scroll', 
this.onFloatableScrollHandler );
-                       }
+                       this.$floatableClosestScrollable = $( 
closestScrollableOfContainer );
+                       this.$floatableClosestScrollable.on( 'scroll', 
this.onFloatableScrollHandler );
 
                        // Initial position after visible
                        this.position();
@@ -124,6 +121,50 @@
 };
 
 /**
+ * Check whether the bottom edge of the given element is within the viewport 
of the given container.
+ *
+ * @private
+ * @param {jQuery} $element
+ * @param {jQuery} $container
+ * @return {Boolean}
+ */
+OO.ui.mixin.FloatableElement.prototype.isElementInViewport = function ( 
$element, $container ) {
+       var elemRect, contRect,
+               topEdgeInBounds = false,
+               leftEdgeInBounds = false,
+               bottomEdgeInBounds = false,
+               rightEdgeInBounds = false;
+
+       elemRect = $element[ 0 ].getBoundingClientRect();
+       if ( $container[ 0 ] === window ) {
+               contRect = {
+                       top: 0,
+                       left: 0,
+                       right: document.documentElement.clientWidth,
+                       bottom: document.documentElement.clientHeight
+               };
+       } else {
+               contRect = $container[ 0 ].getBoundingClientRect();
+       }
+
+       if ( elemRect.top >= contRect.top && elemRect.top <= contRect.bottom ) {
+               topEdgeInBounds = true;
+       }
+       if ( elemRect.left >= contRect.left && elemRect.left <= contRect.right 
) {
+               leftEdgeInBounds = true;
+       }
+       if ( elemRect.bottom >= contRect.top && elemRect.bottom <= 
contRect.bottom ) {
+               bottomEdgeInBounds = true;
+       }
+       if ( elemRect.right >= contRect.left && elemRect.right <= 
contRect.right ) {
+               rightEdgeInBounds = true;
+       }
+
+       // We only care that any part of the bottom edge is visible
+       return bottomEdgeInBounds && ( leftEdgeInBounds || rightEdgeInBounds );
+};
+
+/**
  * Position the floatable below its container.
  *
  * This should only be done when both of them are attached to the DOM and 
visible.
@@ -137,6 +178,17 @@
                return this;
        }
 
+       if ( !this.isElementInViewport( this.$floatableContainer, 
this.$floatableClosestScrollable ) ) {
+               this.$floatable.addClass( 'oo-ui-floatableElement-hidden' );
+               return;
+       } else {
+               this.$floatable.removeClass( 'oo-ui-floatableElement-hidden' );
+       }
+
+       if ( !this.needsCustomPosition ) {
+               return;
+       }
+
        pos = OO.ui.Element.static.getRelativePosition( 
this.$floatableContainer, this.$floatable.offsetParent() );
 
        // Position under container
diff --git a/src/styles/elements/FloatableElement.less 
b/src/styles/elements/FloatableElement.less
index 293f4fd..6abbf97 100644
--- a/src/styles/elements/FloatableElement.less
+++ b/src/styles/elements/FloatableElement.less
@@ -1,5 +1,9 @@
 @import '../common';
 
 .oo-ui-floatableElement {
+       &-hidden {
+               display: none;
+       }
+
        .theme-oo-ui-floatableElement();
 }

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: I5b5d7936c4de8f89917feb5f548916030bce70f8
Gerrit-PatchSet: 1
Gerrit-Project: oojs/ui
Gerrit-Branch: master
Gerrit-Owner: Bartosz Dziewoński <matma....@gmail.com>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to