jScroll

jQuery Plugin for Infinite Scrolling / Auto-Paging

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/19670/125710/jScroll.js

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