Files
clearlinux.github.io/modules/contrib/views_infinite_scroll/js/infinite-scroll.js
T
2023-01-20 10:37:00 -08:00

128 lines
4.3 KiB
JavaScript

/**
* @file
* Infinite Scroll JS.
*/
(function ($, Drupal, debounce) {
"use strict";
// Cached reference to $(window).
var $window = $(window);
// The threshold for how far to the bottom you should reach before reloading.
var scrollThreshold = 200;
// The selector for the automatic pager.
var automaticPagerSelector = '[data-drupal-views-infinite-scroll-pager="automatic"]';
// The selector for both manual load and automatic pager.
var pagerSelector = '[data-drupal-views-infinite-scroll-pager]';
// The selector for the automatic pager.
var contentWrapperSelector = '[data-drupal-views-infinite-scroll-content-wrapper]';
// The event and namespace that is bound to window for automatic scrolling.
var scrollEvent = 'scroll.views_infinite_scroll';
/**
* Insert a views infinite scroll view into the document.
*
* @param {jQuery} $newView
* New content detached from the DOM.
*/
$.fn.infiniteScrollInsertView = function ($newView) {
// Extract the view DOM ID from the view classes.
var matches = /(js-view-dom-id-\w+)/.exec(this.attr('class'));
if (!matches) {
return;
}
var currentViewId = matches[1].replace('js-view-dom-id-', 'views_dom_id:');
// Get the existing ajaxViews object.
var view = Drupal.views.instances[currentViewId];
// Remove once so that the exposed form and pager are processed on
// behavior attach.
view.$view.removeOnce('ajax-pager');
view.$exposed_form.removeOnce('exposed-form');
// Make sure infinite scroll can be reinitialized.
var $existingPager = view.$view.find(pagerSelector);
$existingPager.removeOnce('infinite-scroll');
var $newRows = $newView.find(contentWrapperSelector).children();
var $newPager = $newView.find(pagerSelector);
view.$view.find(contentWrapperSelector)
// Trigger a jQuery event on the wrapper to inform that new content was
// loaded and allow other scripts to respond to the event.
.trigger('views_infinite_scroll.new_content', $newRows.clone())
// Add the new rows to existing view.
.append($newRows);
// Replace the pager link with the new link and ajaxPageState values.
$existingPager.replaceWith($newPager);
// Run views and VIS behaviors.
Drupal.attachBehaviors(view.$view[0]);
};
/**
* Handle the automatic paging based on the scroll amount.
*
* @type {Drupal~behavior}
*
* @prop {Drupal~behaviorAttach} attach
* Initialize infinite scroll pagers and bind the scroll event.
* @prop {Drupal~behaviorDetach} detach
* During `unload` remove the scroll event binding.
*/
Drupal.behaviors.views_infinite_scroll_automatic = {
attach : function (context, settings) {
$(context).find(automaticPagerSelector).once('infinite-scroll').each(function () {
var $pager = $(this);
$pager.addClass('visually-hidden');
var isLoadNeeded = function () {
return window.innerHeight + window.pageYOffset > $pager.offset().top - scrollThreshold;
};
$window.on(scrollEvent, debounce(function () {
if (isLoadNeeded()) {
$pager.find('[rel=next]').click();
$window.off(scrollEvent);
}
}, 200));
if (isLoadNeeded()) {
$window.trigger(scrollEvent);
}
});
},
detach: function (context, settings, trigger) {
// In the case where the view is removed from the document, remove it's
// events. This is important in the case a view being refreshed for a reason
// other than a scroll. AJAX filters are a good example of the event needing
// to be destroyed earlier than above.
if (trigger === 'unload') {
if ($(context).find(automaticPagerSelector).removeOnce('infinite-scroll').length) {
$window.off(scrollEvent);
}
}
}
};
/**
* Views AJAX pagination filter.
*
* In case the Entity View Attachment is rendered in a view context,
* the default filter function prevents the required 'Use AJAX' setting
* to work.
*
* @return {Boolean}
* Whether to apply the Views AJAX paginator. VIS requires this setting
* for pagination.
*/
Drupal.views.ajaxView.prototype.filterNestedViews = function () {
return this.$view.hasClass('view-eva') || !this.$view.parents('.view').length;
};
})(jQuery, Drupal, Drupal.debounce);