1/*! 2 * jScroll - jQuery Plugin for Infinite Scrolling / Auto-Paging 3 * @see @link{http://jscroll.com} 4 * 5 * @copyright 2011-2017, Philip Klauzinski 6 * @license Dual licensed under the MIT and GPL Version 2 licenses. 7 * @author Philip Klauzinski (http://webtopian.com) 8 * @version 2.3.7 9 * @requires jQuery v1.4.3+ 10 * @preserve 11 */ 12(function($) { 13 14 'use strict'; 15 16 // Define the jscroll namespace and default settings 17 $.jscroll = { 18 defaults: { 19 debug: false, 20 autoTrigger: true, 21 autoTriggerUntil: false, 22 loadingHtml: '<small>Loading...</small>', 23 loadingFunction: false, 24 padding: 0, 25 nextSelector: 'a:last', 26 contentSelector: '', 27 pagingSelector: '', 28 callback: false 29 } 30 }; 31 32 // Constructor 33 var jScroll = function($e, options) { 34 35 // Private vars and methods 36 var _data = $e.data('jscroll'), 37 _userOptions = (typeof options === 'function') ? { callback: options } : options, 38 _options = $.extend({}, $.jscroll.defaults, _userOptions, _data || {}), 39 _isWindow = ($e.css('overflow-y') === 'visible'), 40 _$next = $e.find(_options.nextSelector).first(), 41 _$window = $(window), 42 _$body = $('body'), 43 _$scroll = _isWindow ? _$window : $e, 44 _nextHref = $.trim(_$next.attr('href') + ' ' + _options.contentSelector), 45 46 // Check if a loading image is defined and preload 47 _preloadImage = function() { 48 var src = $(_options.loadingHtml).filter('img').attr('src'); 49 if (src) { 50 var image = new Image(); 51 image.src = src; 52 } 53 }, 54 55 // Wrap inner content, if it isn't already 56 _wrapInnerContent = function() { 57 if (!$e.find('.jscroll-inner').length) { 58 $e.contents().wrapAll('<div class="jscroll-inner" />'); 59 } 60 }, 61 62 // Find the next link's parent, or add one, and hide it 63 _nextWrap = function($next) { 64 var $parent; 65 if (_options.pagingSelector) { 66 $next.closest(_options.pagingSelector).hide(); 67 } else { 68 $parent = $next.parent().not('.jscroll-inner,.jscroll-added').addClass('jscroll-next-parent').hide(); 69 if (!$parent.length) { 70 $next.wrap('<div class="jscroll-next-parent" />').parent().hide(); 71 } 72 } 73 }, 74 75 // Remove the jscroll behavior and data from an element 76 _destroy = function() { 77 return _$scroll.unbind('.jscroll') 78 .removeData('jscroll') 79 .find('.jscroll-inner').children().unwrap() 80 .filter('.jscroll-added').children().unwrap(); 81 }, 82 83 // Observe the scroll event for when to trigger the next load 84 _observe = function() { 85 if ($e.is(':visible')) { 86 _wrapInnerContent(); 87 var $inner = $e.find('div.jscroll-inner').first(), 88 data = $e.data('jscroll'), 89 borderTopWidth = parseInt($e.css('borderTopWidth'), 10), 90 borderTopWidthInt = isNaN(borderTopWidth) ? 0 : borderTopWidth, 91 iContainerTop = parseInt($e.css('paddingTop'), 10) + borderTopWidthInt, 92 iTopHeight = _isWindow ? _$scroll.scrollTop() : $e.offset().top, 93 innerTop = $inner.length ? $inner.offset().top : 0, 94 iTotalHeight = Math.ceil(iTopHeight - innerTop + _$scroll.height() + iContainerTop); 95 96 if (!data.waiting && iTotalHeight + _options.padding >= $inner.outerHeight()) { 97 //data.nextHref = $.trim(data.nextHref + ' ' + _options.contentSelector); 98 _debug('info', 'jScroll:', $inner.outerHeight() - iTotalHeight, 'from bottom. Loading next request...'); 99 return _load(); 100 } 101 } 102 }, 103 104 // Check if the href for the next set of content has been set 105 _checkNextHref = function(data) { 106 data = data || $e.data('jscroll'); 107 if (!data || !data.nextHref) { 108 _debug('warn', 'jScroll: nextSelector not found - destroying'); 109 _destroy(); 110 return false; 111 } else { 112 _setBindings(); 113 return true; 114 } 115 }, 116 117 _setBindings = function() { 118 var $next = $e.find(_options.nextSelector).first(); 119 if (!$next.length) { 120 return; 121 } 122 if (_options.autoTrigger && (_options.autoTriggerUntil === false || _options.autoTriggerUntil > 0)) { 123 _nextWrap($next); 124 var scrollingBodyHeight = _$body.height() - $e.offset().top, 125 scrollingHeight = ($e.height() < scrollingBodyHeight) ? $e.height() : scrollingBodyHeight, 126 windowHeight = ($e.offset().top - _$window.scrollTop() > 0) ? _$window.height() - ($e.offset().top - $(window).scrollTop()) : _$window.height(); 127 if (scrollingHeight <= windowHeight) { 128 _observe(); 129 } 130 _$scroll.unbind('.jscroll').bind('scroll.jscroll', function() { 131 return _observe(); 132 }); 133 if (_options.autoTriggerUntil > 0) { 134 _options.autoTriggerUntil--; 135 } 136 } else { 137 _$scroll.unbind('.jscroll'); 138 $next.bind('click.jscroll', function() { 139 _nextWrap($next); 140 _load(); 141 return false; 142 }); 143 } 144 }, 145 146 // Load the next set of content, if available 147 _load = function() { 148 var $inner = $e.find('div.jscroll-inner').first(), 149 data = $e.data('jscroll'); 150 151 data.waiting = true; 152 $inner.append('<div class="jscroll-added" />') 153 .children('.jscroll-added').last() 154 .html('<div class="jscroll-loading" id="jscroll-loading">' + _options.loadingHtml + '</div>') 155 .promise() 156 .done(function(){ 157 if (_options.loadingFunction) { 158 _options.loadingFunction(); 159 } 160 }); 161 162 return $e.animate({scrollTop: $inner.outerHeight()}, 0, function() { 163 var nextHref = data.nextHref; 164 $inner.find('div.jscroll-added').last().load(nextHref, function(r, status) { 165 if (status === 'error') { 166 return _destroy(); 167 } 168 169 if (_options.callback) { 170 _options.callback.call(this, nextHref); 171 } 172 173 var $next = $(this).find(_options.nextSelector).first(); 174 data.waiting = false; 175 data.nextHref = $next.attr('href') ? $.trim($next.attr('href') + ' ' + _options.contentSelector) : false; 176 $('.jscroll-next-parent', $e).remove(); // Remove the previous next link now that we have a new one 177 _checkNextHref(); 178 179 _debug('dir', data); 180 }); 181 }); 182 }, 183 184 // Safe console debug - http://klauzinski.com/javascript/safe-firebug-console-in-javascript 185 _debug = function(m) { 186 if (_options.debug && typeof console === 'object' && (typeof m === 'object' || typeof console[m] === 'function')) { 187 if (typeof m === 'object') { 188 var args = []; 189 for (var sMethod in m) { 190 if (typeof console[sMethod] === 'function') { 191 args = (m[sMethod].length) ? m[sMethod] : [m[sMethod]];
192 console[sMethod].apply(console, args); 193 } else { 194 console.log.apply(console, args); 195 } 196 } 197 } else { 198 console[m].apply(console, Array.prototype.slice.call(arguments, 1)); 199 } 200 } 201 }; 202 203 // Initialization 204 $e.data('jscroll', $.extend({}, _data, {initialized: true, waiting: false, nextHref: _nextHref})); 205 _wrapInnerContent(); 206 _preloadImage(); 207 _setBindings(); 208 209 // Expose API methods via the jQuery.jscroll namespace, e.g. $('sel').jscroll.method() 210 $.extend($e.jscroll, { 211 destroy: _destroy 212 }); 213 return $e; 214 }; 215 216 // Define the jscroll plugin method and loop 217 $.fn.jscroll = function(m) { 218 return this.each(function() { 219 var $this = $(this), 220 data = $this.data('jscroll'), jscroll; 221 222 // Instantiate jScroll on this element if it hasn't been already 223 if (data && data.initialized) { 224 return; 225 } 226 jscroll = new jScroll($this, m); 227 }); 228 }; 229 230})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.