refreshless-8.x-1.x-dev/modules/refreshless_turbo_gin/js/sticky.js
modules/refreshless_turbo_gin/js/sticky.js
/**
* @file
* Gin sticky region replacement for RefreshLess.
*
* Gin's does not have a detach, which results in theirs failing to attach again
* on cached previews or snapshots, and also leaves their IntersectionObserver
* running. This fixes those issues.
*/
(function(html, Drupal, $, once) {
'use strict';
/**
* Our event namespace.
*
* @type {String}
*
* @see https://learn.jquery.com/events/event-basics/#namespacing-events
*/
const eventNamespace = 'gin-sticky';
/**
* once() identfier.
*
* This is the same as Gin's behaviour. Probably doesn't matter, but might as
* well play it safe and match the original.
*
* @type {String}
*/
const onceName = 'ginSticky';
/**
* Property name on elements that we save our IntersectionObserver to.
*
* @type {String}
*/
const observerPropName = 'ginStickyObserver';
/**
* Sticky class added to the region depending on intersection ratio.
*
* @type {String}
*/
const isStickyClass = 'region-sticky--is-sticky';
Drupal.behaviors.ginSticky = {
attach(context, settings) {
$(once(onceName, '.region-sticky-watcher', context)).each((
i, element,
) => {
$(element).prop(observerPropName, new IntersectionObserver((
entries, observer,
) => {
entries.forEach((entry) => {
const $region = $(entry.target).next('.region-sticky');
if ($region.length === 0) {
return;
}
$region.toggleClass(isStickyClass, entry.intersectionRatio < 1);
$region[0].toggleAttribute(
'data-offset-top', entry.intersectionRatio < 1,
);
Drupal.displace(true);
});
}), {threshold: [1]});
$(element).prop(observerPropName).observe(element);
});
},
detach(context, settings, trigger) {
if (trigger !== 'unload') {
return;
}
$(once.remove(
onceName, '.region-sticky-watcher', context,
)).each((i, element) => {
$(element).prop(observerPropName)?.disconnect();
$(element).removeProp(observerPropName);
$(element).next('.region-sticky').removeClass(isStickyClass).removeAttr(
'data-offset-top',
);
});
},
};
// @todo Detach behaviours before cache in refreshless.js instead.
$(html).on(`refreshless:before-cache.${eventNamespace}`, (event) => {
Drupal.behaviors.ginSticky.detach(event.target, drupalSettings, 'unload');
});
})(document.documentElement, Drupal, jQuery, once);
