RelatedArticles should use IntersectionObserver rather than deprecated mediawiki.viewport module

Bug: T284251
Change-Id: Ia3139df0beb24268a1e37b85c755b0d0f62910b5
This commit is contained in:
jdlrobson 2021-10-26 13:41:02 -07:00
parent 6ffacad442
commit 923f594916
2 changed files with 34 additions and 16 deletions

View file

@ -96,7 +96,6 @@
"mediawiki.user", "mediawiki.user",
"mediawiki.api", "mediawiki.api",
"mediawiki.Uri", "mediawiki.Uri",
"mediawiki.viewport",
"ext.relatedArticles.readMore.gateway", "ext.relatedArticles.readMore.gateway",
"mediawiki.util" "mediawiki.util"
], ],

View file

@ -11,11 +11,7 @@
data.descriptionSource data.descriptionSource
), ),
// Make sure this is never undefined as I'm paranoid // Make sure this is never undefined as I'm paranoid
LIMIT = mw.config.get( 'wgRelatedArticlesCardLimit', 3 ), LIMIT = mw.config.get( 'wgRelatedArticlesCardLimit', 3 );
debouncedLoad = mw.util.debounce( 100, function () {
loadRelatedArticles(); // eslint-disable-line no-use-before-define
} ),
$window = $( window );
/** /**
* Load related articles when the user scrolls past half of the window height. * Load related articles when the user scrolls past half of the window height.
@ -23,15 +19,19 @@
* @ignore * @ignore
*/ */
function loadRelatedArticles() { function loadRelatedArticles() {
var readMore = $( '.read-more-container' ).get( 0 ), var readMore = document.querySelector( '.read-more-container' ),
scrollThreshold = $window.height() * 2; isSupported = 'IntersectionObserver' in window;
if ( !readMore ) { if ( !readMore || !isSupported ) {
// The container is not in the HTML for some reason and cannot be queried. // The container is not in the HTML for some reason and cannot be queried.
// See T281547 // See T281547
return; return;
} }
if ( mw.viewport.isElementCloseToViewport( readMore, scrollThreshold ) ) {
/**
* @param {Element} container
*/
function initRelatedArticlesModule( container ) {
$.when( $.when(
// Note we load dependencies here rather than ResourceLoader // Note we load dependencies here rather than ResourceLoader
// to avoid PHP exceptions when Cards not installed // to avoid PHP exceptions when Cards not installed
@ -44,18 +44,37 @@
).then( function ( _, pages ) { ).then( function ( _, pages ) {
if ( pages.length ) { if ( pages.length ) {
mw.track( 'ext.relatedArticles.init', pages ); mw.track( 'ext.relatedArticles.init', pages );
} else { } else if ( container.parentNode ) {
$( readMore ).remove(); container.parentNode.removeChild( container );
} }
} ); } );
// detach handler to stop subsequent loads on scroll
$window.off( 'scroll', debouncedLoad );
} }
var doc = document.documentElement;
// IntersectionObserver will not work if the component is already visible on the page.
// To handle this case, we compare scroll height to viewport height.
if ( ( doc.scrollHeight / 2 ) < doc.clientHeight ) {
// Load straight away. We are on a stub page.
initRelatedArticlesModule( readMore );
return;
}
// eslint-disable-next-line compat/compat
var observer = /** @type {IntersectionObserver} */( new IntersectionObserver( function ( entries ) {
if ( !entries[ 0 ].isIntersecting ) {
return;
}
// @ts-ignore
observer.unobserve( readMore );
observer.disconnect();
// @ts-ignore
initRelatedArticlesModule( readMore );
}, {
rootMargin: '-100% 0% 0% 0%'
} ) );
observer.observe( readMore );
} }
function showReadMore() { function showReadMore() {
// try related articles load on scroll
$window.on( 'scroll', debouncedLoad );
// try an initial load, in case of no scroll // try an initial load, in case of no scroll
loadRelatedArticles(); loadRelatedArticles();
} }