PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.5
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.5
16.3-a.5 16.3-a.7 16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 All 506 releases
← All changes | modules/likes/queuehandler.js +48 -0 16.2-beta → 16.3-a.5 View file →
@@ -346,8 +346,10 @@
346 346
347 347 // Restore widgets to initial unloaded state when they are scrolled out of view.
348 348 jetpackUnloadScrolledOutWidgets();
349 349
350 + jetpackObserveUnloadedWidgets();
351 +
350 352 var unloadedWidgetsInView = jetpackGetUnloadedWidgetsInView();
351 353
352 354 if ( unloadedWidgetsInView.length > 0 ) {
353 355 // Grab any unloaded widgets for a batch request
@@ -411,13 +413,26 @@
411 413 wrapper.classList.remove( 'jetpack-likes-widget-unloaded' );
412 414 wrapper.classList.add( 'jetpack-likes-widget-loading' );
413 415
414 416 wrapper.querySelector( 'iframe' ).addEventListener( 'load', e => {
417 + // A widget scrolled out of view mid-load has its iframe dropped, and a reloaded one
418 + // replaces it, either of which leaves this closure holding a detached iframe. Acting on
419 + // it would hide a placeholder that is now the only thing the widget has left to show.
420 + if ( ! wrapper.contains( e.target ) ) {
421 + return;
422 + }
423 +
415 424 JetpackLikesPostMessage(
416 425 { event: 'loadLikeWidget', name: e.target.name, width: e.target.width },
417 426 window.frames[ 'likes-master' ]
418 427 );
419 428
429 + // The stylesheet is otherwise the only thing that hides the placeholder, so one that never
430 + // applies leaves "Loading…" sitting over a widget that loaded fine.
431 + if ( placeholder ) {
432 + placeholder.style.display = 'none';
433 + }
434 +
420 435 wrapper.classList.remove( 'jetpack-likes-widget-loading' );
421 436 wrapper.classList.add( 'jetpack-likes-widget-loaded' );
422 437 } );
423 438 }
@@ -451,8 +466,16 @@
451 466 widgetWrapper.classList.remove( 'jetpack-likes-widget-loaded' );
452 467 widgetWrapper.classList.remove( 'jetpack-likes-widget-loading' );
453 468 widgetWrapper.classList.add( 'jetpack-likes-widget-unloaded' );
454 469
470 + // An empty string removes the inline declaration rather than setting one, handing the
471 + // placeholder back to the stylesheet. The `display: none` set on load would otherwise
472 + // outrank it, leaving an unloaded widget with neither an iframe nor a placeholder.
473 + const placeholder = widgetWrapper.querySelector( '.likes-widget-placeholder' );
474 + if ( placeholder ) {
475 + placeholder.style.display = '';
476 + }
477 +
455 478 // Remove it from the list of loaded widgets.
456 479 jetpackCommentLikesLoadedWidgets.splice( i, 1 );
457 480
458 481 // Remove comment like widget iFrame.
@@ -469,8 +492,33 @@
469 492 };
470 493 };
471 494
472 495 var jetpackOnScrollStopped = jetpackWidgetsDelayedExec( 250, JetpackLikesWidgetQueueHandler );
496 +
497 +// Scrolling is not the only thing that brings a widget into range. A stylesheet that lands late
498 +// reflows the page without firing a scroll event, and the queue would never look at that widget
499 +// again, leaving it on "Loading…" until the reader happens to scroll.
500 +var jetpackLikesWidgetObserver =
501 + typeof IntersectionObserver === 'function'
502 + ? new IntersectionObserver( jetpackOnScrollStopped, {
503 + rootMargin: `${ jetpackLikesLookAhead }px`,
504 + // jetpackIsScrolledIntoView() wants the widget fully inside the band, so ask to be
505 + // told when it gets there - crossing into partial overlap alone would not load it.
506 + threshold: [ 0, 1 ],
507 + } )
508 + : null;
509 +
510 +// Observing an element twice is a no-op, so every queue pass can call this to pick up widgets
511 +// added after load.
512 +function jetpackObserveUnloadedWidgets() {
513 + if ( ! jetpackLikesWidgetObserver ) {
514 + return;
515 + }
516 +
517 + document
518 + .querySelectorAll( 'div.jetpack-likes-widget-unloaded' )
519 + .forEach( widget => jetpackLikesWidgetObserver.observe( widget ) );
520 +}
473 521
474 522 // Load initial batch of widgets, prior to any scrolling events.
475 523 JetpackLikesWidgetQueueHandler();
476 524