Created
May 21, 2020 23:47
-
-
Save Enalmada/4f9e331a5466470756aafe3da5d3ff91 to your computer and use it in GitHub Desktop.
custom version to support multiple
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! | |
* jScroll - jQuery Plugin for Infinite Scrolling / Auto-Paging | |
* @see @link{https://jscroll.com} | |
* | |
* @copyright Philip Klauzinski | |
* @license Dual licensed under the MIT and GPL Version 2 licenses | |
* @author Philip Klauzinski (https://webtopian.com) | |
* @version 2.4.1 | |
* @requires jQuery v1.8.0+ | |
* @preserve | |
*/ | |
(function($) { | |
'use strict'; | |
// Define the jscroll namespace and default settings | |
$.jscroll = { | |
defaults: { | |
debug: false, | |
autoTrigger: true, | |
autoTriggerUntil: false, | |
loadingHtml: '<small>Loading...</small>', | |
loadingFunction: false, | |
padding: 0, | |
nextSelector: 'a:last', | |
contentSelector: '', | |
pagingSelector: '', | |
callback: false | |
}, | |
instances: 0 | |
}; | |
// Constructor | |
var jScroll = function($e, options) { | |
// Private vars and methods | |
var _data = $e.data('jscroll'), | |
_userOptions = (typeof options === 'function') ? { callback: options } : options, | |
_options = $.extend({}, $.jscroll.defaults, _userOptions, _data || {}), | |
_isWindow = ($e.css('overflow-y') === 'visible'), | |
_$next = $e.find(_options.nextSelector).first(), | |
_$window = $(window), | |
_$body = $('body'), | |
_$scroll = _isWindow ? _$window : $e, | |
_nextHref = $.trim(_$next.prop('href') + ' ' + _options.contentSelector), | |
// Check if a loading image is defined and preload | |
_preloadImage = function() { | |
var src = $(_options.loadingHtml).filter('img').attr('src'); | |
if (src) { | |
var image = new Image(); | |
image.src = src; | |
} | |
}, | |
// Wrap inner content, if it isn't already | |
_wrapInnerContent = function() { | |
if (!$e.find('.jscroll-inner').length) { | |
$e.contents().wrapAll('<div class="jscroll-inner" />'); | |
} | |
}, | |
// Find the next link's parent, or add one, and hide it | |
_nextWrap = function($next) { | |
var $parent; | |
if (_options.pagingSelector) { | |
$next.closest(_options.pagingSelector).hide(); | |
} else { | |
$parent = $next.parent().not('.jscroll-inner,.jscroll-added').addClass('jscroll-next-parent').hide(); | |
if (!$parent.length) { | |
$next.wrap('<div class="jscroll-next-parent" />').parent().hide(); | |
} | |
} | |
}, | |
// Remove the jscroll behavior and data from an element | |
_destroy = function() { | |
var data = $e.data('jscroll'); | |
// don't do anything when called on an uninitialized element | |
if (!data) { | |
return; | |
} | |
$e.removeData('jscroll'); | |
return _$scroll.unbind('.jscroll.instance_'+data.id) | |
.find('.jscroll-inner').children().unwrap() | |
.filter('.jscroll-added').children().unwrap(); | |
}, | |
// Observe the scroll event for when to trigger the next load | |
_observe = function() { | |
if ($e.is(':visible')) { | |
_wrapInnerContent(); | |
var $inner = $e.find('div.jscroll-inner').first(), | |
data = $e.data('jscroll'), | |
borderTopWidth = parseInt($e.css('borderTopWidth'), 10), | |
borderTopWidthInt = isNaN(borderTopWidth) ? 0 : borderTopWidth, | |
iContainerTop = parseInt($e.css('paddingTop'), 10) + borderTopWidthInt, | |
iTopHeight = _isWindow ? _$scroll.scrollTop() : $e.offset().top, | |
innerTop = $inner.length ? $inner.offset().top : 0, | |
iTotalHeight = Math.ceil(iTopHeight - innerTop + _$scroll.height() + iContainerTop); | |
if (!data.waiting && iTotalHeight + _options.padding >= $inner.outerHeight()) { | |
_debug('info', 'jScroll['+data.id+']:', $inner.outerHeight() - iTotalHeight, 'from bottom. Loading next request...'); | |
return _load(); | |
} | |
} | |
}, | |
// Check if the href for the next set of content has been set | |
_checkNextHref = function(data) { | |
data = data || $e.data('jscroll'); | |
if (!data || !data.nextHref) { | |
_debug('warn', 'jScroll['+data.id+']: nextSelector not found - destroying'); | |
_destroy(); | |
return false; | |
} else { | |
_setBindings(); | |
return true; | |
} | |
}, | |
_setBindings = function() { | |
var $next = $e.find(_options.nextSelector).first(), | |
data = $e.data('jscroll'); | |
if (!$next.length) { | |
return; | |
} | |
if (_options.autoTrigger && (_options.autoTriggerUntil === false || _options.autoTriggerUntil > 0)) { | |
_nextWrap($next); | |
var scrollingBodyHeight = _$body.height() - $e.offset().top, | |
scrollingHeight = ($e.height() < scrollingBodyHeight) ? $e.height() : scrollingBodyHeight, | |
windowHeight = ($e.offset().top - _$window.scrollTop() > 0) ? _$window.height() - ($e.offset().top - $(window).scrollTop()) : _$window.height(); | |
if (scrollingHeight <= windowHeight) { | |
_observe(); | |
} | |
_$scroll.unbind('.jscroll.instance_'+data.id).bind('scroll.jscroll.instance_'+data.id, function() { | |
return _observe(); | |
}); | |
if (_options.autoTriggerUntil > 0) { | |
_options.autoTriggerUntil--; | |
} | |
} else { | |
_$scroll.unbind('.jscroll.instance_'+data.id); | |
$next.bind('click.jscroll.instance_'+data.id, function() { | |
_nextWrap($next); | |
_load(); | |
return false; | |
}); | |
} | |
}, | |
// Load the next set of content, if available | |
_load = function() { | |
var $inner = $e.find('div.jscroll-inner').first(), | |
data = $e.data('jscroll'); | |
data.waiting = true; | |
$inner.append('<div class="jscroll-added" />') | |
.children('.jscroll-added').last() | |
.html('<div class="jscroll-loading jscroll-loading-'+data.id+'">' + _options.loadingHtml + '</div>') | |
.promise() | |
.done(function() { | |
if (_options.loadingFunction) { | |
_options.loadingFunction(); | |
} | |
}); | |
return $e.animate({scrollTop: $inner.outerHeight()}, 0, function() { | |
var nextHref = data.nextHref; | |
$inner.find('div.jscroll-added').last().load(nextHref, function(r, status) { | |
if (status === 'error') { | |
return _destroy(); | |
} | |
var $next = $(this).find(_options.nextSelector).first(); | |
data.waiting = false; | |
data.nextHref = $next.prop('href') ? $.trim($next.prop('href') + ' ' + _options.contentSelector) : false; | |
$('.jscroll-next-parent', $e).remove(); // Remove the previous next link now that we have a new one | |
_checkNextHref(); | |
if (_options.callback) { | |
_options.callback.call(this, nextHref); | |
} | |
_debug('dir', data); | |
}); | |
}); | |
}, | |
// Safe console debug - http://klauzinski.com/javascript/safe-firebug-console-in-javascript | |
_debug = function(m) { | |
if (_options.debug && typeof console === 'object' && (typeof m === 'object' || typeof console[m] === 'function')) { | |
if (typeof m === 'object') { | |
var args = []; | |
for (var sMethod in m) { | |
if (typeof console[sMethod] === 'function') { | |
args = (m[sMethod].length) ? m[sMethod] : [m[sMethod]]; | |
console[sMethod].apply(console, args); | |
} else { | |
console.log.apply(console, args); | |
} | |
} | |
} else { | |
console[m].apply(console, Array.prototype.slice.call(arguments, 1)); | |
} | |
} | |
}; | |
// Initialization | |
$e.data('jscroll', $.extend({}, _data, {initialized: true, waiting: false, nextHref: _nextHref, id: ++$.jscroll.instances})); | |
_wrapInnerContent(); | |
_preloadImage(); | |
_setBindings(); | |
// Expose API methods via the jQuery.jscroll namespace, e.g. $('sel').jscroll.method() | |
$.extend($e.jscroll, { | |
destroy: _destroy | |
}); | |
return $e; | |
}; | |
// Define the jscroll plugin method and loop | |
$.fn.jscroll = function(m) { | |
return this.each(function() { | |
var $this = $(this), | |
data = $this.data('jscroll'); | |
// Instantiate jScroll on this element if it hasn't been already | |
if (data && data.initialized) { | |
return; | |
} | |
jScroll($this, m); | |
}); | |
}; | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment