diff --git a/jquery.jscroll.multi-links.js b/jquery.jscroll.multi-links.js new file mode 100644 index 0000000..8c04a66 --- /dev/null +++ b/jquery.jscroll.multi-links.js @@ -0,0 +1,231 @@ +/*! + * jScroll - jQuery Plugin for Infinite Scrolling / Auto-Paging + * @see @link{http://jscroll.com} + * + * @copyright 2011-2017, Philip Klauzinski + * @license Dual licensed under the MIT and GPL Version 2 licenses. + * @author Philip Klauzinski (http://webtopian.com) + * @version 2.3.9 + * @requires jQuery v1.4.3+ + * @preserve + */ +(function($) { + + 'use strict'; + + // Define the jscroll namespace and default settings + $.jscroll = { + defaults: { + debug: false, + autoTrigger: true, + autoTriggerUntil: false, + loadingHtml: 'Loading...', + loadingFunction: false, + padding: 0, + nextSelector: 'a:last', + contentSelector: '', + pagingSelector: '', + callback: false + } + }; + + // 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.attr('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('
'); + } + }, + + // 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('
').parent().hide(); + } + } + }, + + // Remove the jscroll behavior and data from an element + _destroy = function() { + return _$scroll.unbind('.jscroll') + .removeData('jscroll') + .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()) { + //data.nextHref = $.trim(data.nextHref + ' ' + _options.contentSelector); + _debug('info', 'jScroll:', $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: nextSelector not found - destroying'); + _destroy(); + return false; + } else { + _setBindings(); + return true; + } + }, + + _setBindings = function() { + var $next = $e.find(_options.nextSelector).first(); + 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').bind('scroll.jscroll', function() { + return _observe(); + }); + if (_options.autoTriggerUntil > 0) { + _options.autoTriggerUntil--; + } + } else { + _$scroll.unbind('.jscroll'); + $next.bind('click.jscroll', 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; + + //////////// ====== Load the ajax response .before '.jscroll-next-parent' / so it's positioned above the other elements + var $bnx = $e.find('.jscroll-next-parent').first(); + $bnx.before('
'); + + $inner.children('.jscroll-added').last() + .html('
' + _options.loadingHtml + '
') + .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(); + } + $('.jscroll-next-parent', $e).remove(); //////////// ====== Remove the previous next link BEFORE looking for the new one + var $next = $inner.find(_options.nextSelector).first(); //////////// ====== Look for a new next inside 'div.jscroll-inner' + data.waiting = false; + data.nextHref = $next.attr('href') ? $.trim($next.attr('href') + ' ' + _options.contentSelector) : false; + _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})); + _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); \ No newline at end of file