├── docs ├── .nojekyll ├── CNAME ├── img │ ├── jscroll.png │ └── favicons │ │ ├── favicon-128.png │ │ ├── mstile-70x70.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon-96x96.png │ │ ├── mstile-144x144.png │ │ ├── mstile-150x150.png │ │ ├── mstile-310x150.png │ │ ├── mstile-310x310.png │ │ ├── favicon-196x196.png │ │ ├── apple-touch-icon-57x57.png │ │ ├── apple-touch-icon-60x60.png │ │ ├── apple-touch-icon-72x72.png │ │ ├── apple-touch-icon-76x76.png │ │ ├── apple-touch-icon-114x114.png │ │ ├── apple-touch-icon-120x120.png │ │ ├── apple-touch-icon-144x144.png │ │ └── apple-touch-icon-152x152.png ├── _sidebar.md ├── _coverpage.md ├── contributing.md ├── usage.md ├── README.md ├── installation.md ├── css │ └── docs.css ├── js │ └── docs.js ├── configuration.md └── index.html ├── .gitignore ├── .editorconfig ├── .travis.yml ├── bower.json ├── Gruntfile.js ├── package.json ├── .eslintrc ├── dist └── jquery.jscroll.min.js ├── README.md └── jquery.jscroll.js /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | jscroll.com -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | .project 3 | .settings/ 4 | bower_components/ 5 | node_modules/ -------------------------------------------------------------------------------- /docs/img/jscroll.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/jscroll.png -------------------------------------------------------------------------------- /docs/img/favicons/favicon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/favicon-128.png -------------------------------------------------------------------------------- /docs/img/favicons/mstile-70x70.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/mstile-70x70.png -------------------------------------------------------------------------------- /docs/img/favicons/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/favicon-16x16.png -------------------------------------------------------------------------------- /docs/img/favicons/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/favicon-32x32.png -------------------------------------------------------------------------------- /docs/img/favicons/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/favicon-96x96.png -------------------------------------------------------------------------------- /docs/img/favicons/mstile-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/mstile-144x144.png -------------------------------------------------------------------------------- /docs/img/favicons/mstile-150x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/mstile-150x150.png -------------------------------------------------------------------------------- /docs/img/favicons/mstile-310x150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/mstile-310x150.png -------------------------------------------------------------------------------- /docs/img/favicons/mstile-310x310.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/mstile-310x310.png -------------------------------------------------------------------------------- /docs/img/favicons/favicon-196x196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/favicon-196x196.png -------------------------------------------------------------------------------- /docs/img/favicons/apple-touch-icon-57x57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/apple-touch-icon-57x57.png -------------------------------------------------------------------------------- /docs/img/favicons/apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /docs/img/favicons/apple-touch-icon-72x72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/apple-touch-icon-72x72.png -------------------------------------------------------------------------------- /docs/img/favicons/apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /docs/img/favicons/apple-touch-icon-114x114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/apple-touch-icon-114x114.png -------------------------------------------------------------------------------- /docs/img/favicons/apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /docs/img/favicons/apple-touch-icon-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/apple-touch-icon-144x144.png -------------------------------------------------------------------------------- /docs/img/favicons/apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pklauzinski/jscroll/HEAD/docs/img/favicons/apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | - [Home](/) 2 | - [Installation](installation.md) 3 | - [Usage](usage.md) 4 | - [Configuration](configuration.md) 5 | - [Contributing](contributing.md) -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | indent_size = 4 4 | end_of_line = lf 5 | charset = utf-8 6 | trim_trailing_whitespace = true 7 | insert_final_newline = false -------------------------------------------------------------------------------- /docs/_coverpage.md: -------------------------------------------------------------------------------- 1 | ![jScroll logo](img/jscroll.png) 2 | 3 | # jScroll 4 | 5 |
6 | 7 | [GitHub](https://github.com/pklauzinski/jscroll) 8 | [Get Started](#introduction) -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "stable" 4 | before_script: 5 | - npm install -g grunt-cli 6 | notifications: 7 | webhooks: 8 | urls: 9 | - https://webhooks.gitter.im/e/7b6dee6d870a12710299 10 | on_success: change # options: [always|never|change] default: always 11 | on_failure: always # options: [always|never|change] default: always 12 | on_start: never # options: [always|never|change] default: always -------------------------------------------------------------------------------- /docs/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | ## Coding style 4 | 5 | In lieu of a formal styleguide, take care to maintain the existing coding style and adhere to the [eslint config](https://github.com/pklauzinski/jscroll/blob/master/.eslintrc). Lint and test your code using [NPM](https://npmjs.org) and [grunt](https://gruntjs.com). 6 | 7 | ## Test 8 | 9 | NPM will run linting tests automatically, as configured in `package.json`. 10 | 11 | ```bash 12 | npm test 13 | ``` 14 | 15 | Ensure that all tests pass before submitting a [pull request](https://github.com/pklauzinski/jscroll/pulls). -------------------------------------------------------------------------------- /docs/usage.md: -------------------------------------------------------------------------------- 1 | # Usage 2 | 3 | ## Initialization 4 | 5 | The `jscroll` method is called on the selector for which you want your scrollable content contained within. Always ensure that the content you want to call jScroll on has already been rendered in the DOM before initializing it. 6 | 7 | To initialize jScroll on the `DOMContentLoaded` event: 8 | 9 | ```javascript 10 | $(function() { 11 | $('.jscroll').jscroll(); 12 | }); 13 | ``` 14 | 15 | ## Customizing 16 | 17 | The `jscroll` method takes an optional object literal as a parameter for overriding the default options. An example of how this can be done is shown below. 18 | 19 | ```javascript 20 | var options = { 21 | loadingHtml: 'Loading Loading...', 22 | padding: 20, 23 | nextSelector: 'a.jscroll-next:last', 24 | contentSelector: 'li' 25 | }; 26 | 27 | $('.jscroll').jscroll(options); 28 | ``` 29 | 30 | See [configuration](configuration.md) for a listing of all options. -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jscroll", 3 | "homepage": "http://jscroll.com", 4 | "authors": [ 5 | { 6 | "name": "Philip Klauzinski", 7 | "homepage": "http://webtopian.com" 8 | } 9 | ], 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/pklauzinski/jscroll" 13 | }, 14 | "description": "jScroll - jQuery Plugin for Infinite Scrolling / Auto-Paging", 15 | "main": "jquery.jscroll.js", 16 | "dependencies": { 17 | "jquery": ">=1.4.3" 18 | }, 19 | "moduleType": [ 20 | "globals" 21 | ], 22 | "keywords": [ 23 | "jscroll", 24 | "infinite-scroll", 25 | "infinite-scrolling", 26 | "infinite-ajax-scroll", 27 | "jquery-scrolling", 28 | "ajax-scrolling", 29 | "scrolling", 30 | "auto-paging", 31 | "jquery-plugin", 32 | "ecosystem:jquery" 33 | ], 34 | "license": ["MIT", "GPL-2.0"], 35 | "ignore": [ 36 | "**/.*", 37 | "node_modules", 38 | "bower_components", 39 | "test", 40 | "tests", 41 | "Gruntfile.js" 42 | ] 43 | } 44 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | 3 | 'use strict'; 4 | 5 | grunt.initConfig({ 6 | 7 | pkg: grunt.file.readJSON('package.json'), 8 | 9 | /** 10 | * https://github.com/gyandeeps/gruntify-eslint 11 | */ 12 | eslint: { 13 | options: { 14 | configFile: '.eslintrc' 15 | }, 16 | src: ['Gruntfile.js', 'jquery.jscroll.js'] 17 | }, 18 | 19 | /** 20 | * https://github.com/gruntjs/grunt-contrib-uglify 21 | */ 22 | uglify: { 23 | options: { 24 | output: { 25 | comments: 'some' 26 | } 27 | }, 28 | jscroll: { 29 | files: { 30 | 'dist/jquery.jscroll.min.js': [ 31 | 'jquery.jscroll.js' 32 | ] 33 | } 34 | } 35 | } 36 | 37 | }); 38 | 39 | grunt.loadNpmTasks('gruntify-eslint'); 40 | grunt.loadNpmTasks('grunt-contrib-uglify'); 41 | grunt.registerTask('default', ['eslint', 'uglify']); 42 | }; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jscroll", 3 | "version": "2.4.1", 4 | "description": "jScroll is a jQuery plugin for infinite scrolling / auto-paging.", 5 | "main": "jquery.jscroll.js", 6 | "scripts": { 7 | "build": "grunt", 8 | "test": "grunt eslint" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "https://github.com/pklauzinski/jscroll.git" 13 | }, 14 | "keywords": [ 15 | "jscroll", 16 | "infinite-scroll", 17 | "infinite-scrolling", 18 | "jquery-scrolling", 19 | "ajax-scrolling", 20 | "scrolling", 21 | "auto-paging", 22 | "lazy-loading", 23 | "jquery-plugin", 24 | "ecosystem:jquery" 25 | ], 26 | "author": { 27 | "name": "Philip Klauzinski", 28 | "url": "https://webtopian.com" 29 | }, 30 | "license": "MIT", 31 | "bugs": { 32 | "url": "https://github.com/pklauzinski/jscroll/issues" 33 | }, 34 | "homepage": "https://jscroll.com", 35 | "peerDependencies": { 36 | "jquery": ">=1.8.0" 37 | }, 38 | "devDependencies": { 39 | "grunt": "^1.0.2", 40 | "grunt-contrib-uglify": "3.3.0", 41 | "gruntify-eslint": "^4.0.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | ## Introduction 2 | 3 | **jScroll** is a jQuery plugin for infinite scrolling, written by [Philip Klauzinski](https://philip.klauzinski.com). Infinite scrolling; also known as lazy loading, endless scrolling, autopager, endless pages, etc.; is the ability to load content via AJAX within the current page or content area as you scroll down. The new content can be loaded automatically each time you scroll to the end of the existing content, or it can be triggered to load by clicking a navigation link at the end of the existing content. 4 | 5 | An example of infinite scrolling is your Facebook "News Feed" page. You may notice that when you scroll to the bottom of this page, new content will often load automatically, or you will be given a link to "Older Posts" which will load more content when clicked. 6 | 7 | [Continue to Installation →](installation.md) 8 | 9 | ## Twitter 10 | 11 | ?> Follow me on Twitter [@webtopian](https://twitter.com/webtopian) for updates on jScroll and other projects I'm working on. 12 | 13 | ## jScroll Facebook Page 14 | 15 | ?> [Follow jScroll on Facebook](https://www.facebook.com/jScroll.Infinite.Scrolling) for version updates and other announcements. -------------------------------------------------------------------------------- /docs/installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | ## Dependencies 4 | 5 | jScroll requires [jQuery](https://jquery.com) **v1.8.0** or higher as a **peer dependency**. 6 | 7 | ## CDN 8 | 9 | ### Unpkg 10 | 11 | Include the script from [unpkg](https://unpkg.com/) with the version number specified, where `#.#.#` represents the [semver](https://semver.org). 12 | 13 | ```html 14 | 15 | ``` 16 | 17 | Alternatively, you may omit the version tag to load the latest released version. 18 | 19 | ```html 20 | 21 | ``` 22 | 23 | ### CDNJS 24 | 25 | Include the script from [cdnjs](https://cdnjs.com/libraries/jscroll) with the version number specified, where `#.#.#` represents the [semver](https://semver.org). 26 | 27 | ```html 28 | 29 | ``` 30 | 31 | ## Package Managers 32 | 33 | ### NPM 34 | 35 | ```bash 36 | $ npm install jscroll --save 37 | ``` 38 | ### Yarn 39 | 40 | ```bash 41 | $ yarn add jscroll 42 | ``` 43 | 44 | ### Bower 45 | 46 | ```bash 47 | $ bower install jscroll --save 48 | ``` -------------------------------------------------------------------------------- /docs/css/docs.css: -------------------------------------------------------------------------------- 1 | .content { 2 | padding-top: 20px; 3 | } 4 | .markdown-section { 5 | padding: 1.5em; 6 | } 7 | .cover img { 8 | max-width: 100px; 9 | } 10 | @media (min-height: 600px) { 11 | .cover img { 12 | max-width: 200px; 13 | } 14 | } 15 | #carbon, .markdown-section p.warn:first-child { 16 | max-width: 400px; 17 | } 18 | #carbon { 19 | margin: 1em auto; 20 | padding: 1em; 21 | background: rgba(0, 0, 0, 0.05); 22 | text-align: left; 23 | } 24 | #carbonads { 25 | position: relative; 26 | } 27 | .carbon-img { 28 | margin-right: 1em; 29 | } 30 | .carbon-text { 31 | max-width: 200px; 32 | line-height: 1.2; 33 | } 34 | #carbonads a { 35 | text-decoration: none; 36 | font-weight: normal; 37 | } 38 | #carbonads img { 39 | display: block; 40 | } 41 | .carbon-wrap { 42 | display: flex; 43 | } 44 | .carbon-wrap a { 45 | display: block; 46 | } 47 | .carbon-poweredby { 48 | position: absolute; 49 | right: 0; 50 | bottom: 0; 51 | font-size: 11px; 52 | line-height: 1; 53 | font-style: italic; 54 | } 55 | .sidebar h1 a { 56 | display: block; 57 | } 58 | .sidebar h1 a img { 59 | max-width:100px; 60 | display: block; 61 | margin: 0 auto; 62 | } 63 | .sidebar-nav { 64 | border-top: 1px solid rgba(0,0,0,.07); 65 | } -------------------------------------------------------------------------------- /docs/js/docs.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | window.$docsify = { 3 | name: 'jScroll', 4 | repo: 'https://github.com/pklauzinski/jscroll', 5 | executeScript: true, 6 | search: 'auto', 7 | //coverpage: true, 8 | loadSidebar: true, 9 | maxLevel: 4, 10 | subMaxLevel: 2, 11 | auto2top: true, 12 | ga: 'UA-23834740-2', 13 | plugins: [ 14 | function(hook, vm) { 15 | hook.ready(function() { 16 | var title = document.querySelector('.sidebar h1 a'), 17 | logo = document.createElement('img'); 18 | 19 | logo.src = 'img/jscroll.png'; 20 | title.insertBefore(logo, title.firstChild); 21 | }); 22 | hook.doneEach(function() { 23 | var p = document.createElement('p'), 24 | content = document.querySelector('.markdown-section'); 25 | 26 | p.id = 'carbon-top'; 27 | p.className = 'warn'; 28 | content.insertBefore(p, content.firstChild); 29 | adCarbon('carbon-top'); 30 | }); 31 | } 32 | ] 33 | }; 34 | 35 | function adCarbon(id) { 36 | var carbon = document.getElementById(id), 37 | script = document.createElement(('script')); 38 | 39 | if (carbon) { 40 | script.id = '_carbonads_js'; 41 | script.async = true; 42 | script.src = '//cdn.carbonads.com/carbon.js?serve=CKYILKJE&placement=jscrollcom'; 43 | carbon.appendChild(script); 44 | } 45 | } 46 | })(); -------------------------------------------------------------------------------- /docs/configuration.md: -------------------------------------------------------------------------------- 1 | # Configuration 2 | 3 | ## debug 4 | 5 | - Type: `Boolean` 6 | - Default: `false` 7 | 8 | When set to `true`, outputs useful information to the console display if the `console` object exists. 9 | 10 | ## autoTrigger 11 | 12 | - Type: `Boolean` 13 | - Default: `true` 14 | 15 | When set to `true`, triggers the loading of the next set of content automatically when the user scrolls to the bottom of the containing element. When set to `false`, the required next link will trigger the loading of the next set of content when clicked. 16 | 17 | ## autoTriggerUntil 18 | 19 | - Type: `Boolean|Number` 20 | - Default: `false` 21 | 22 | Set to an integer greater than `0` to turn off `autoTrigger` of paging after the specified number of pages. Requires `autoTrigger` to be `true`. 23 | 24 | ## loadingHtml 25 | 26 | - Type: `String` 27 | - Default: `Loading...` 28 | 29 | The HTML to show at the bottom of the content while loading the next set. 30 | 31 | ## loadingFunction 32 | 33 | - Type: `Function|Boolean` 34 | - Default: `false` 35 | 36 | A JavaScript function to run after the `loadingHtml` has been drawn. 37 | 38 | ## padding 39 | 40 | - Type: `Number` 41 | - Default: `0` 42 | 43 | The distance from the bottom of the scrollable content at which to trigger the loading of the next set of content. This only applies when `autoTrigger` is set to `true`. 44 | 45 | ## nextSelector 46 | 47 | - Type: `String` 48 | - Default: `a:last` 49 | 50 | The selector to use for finding the link which contains the `href` pointing to the next set of content. If this selector is not found, or if it does not contain an `href` attribute, jScroll will self-destroy and unbind from the element upon which it was called. 51 | 52 | ## contentSelector 53 | 54 | - Type: `String` 55 | - Default: `''` 56 | 57 | A convenience selector for loading only part of the content in the response for the next set of content. This selector will be ignored if left blank and will apply the entire response to the DOM. 58 | 59 | !> For more information on the `contentSelector` option and how it loads a response fragment, see the [jQuery documentation for the .load() method](http://api.jquery.com/load/). 60 | 61 | ## pagingSelector 62 | 63 | - Type: `String` 64 | - Default: `''` 65 | 66 | Optionally define a selector for your paging controls so that they will be hidden, instead of just hiding the next page link. 67 | 68 | ## callback 69 | 70 | - Type: `Function|Boolean` 71 | - Default: `false` 72 | 73 | Optionally define a callback function to be called after a set of content has been loaded. -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | jScroll - jQuery plugin for infinite scrolling / auto-paging 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
Loading …
34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true 4 | }, 5 | "globals": { 6 | "jQuery": true 7 | }, 8 | "rules": { 9 | "curly": [ 10 | 2, 11 | "all" 12 | ], 13 | "eqeqeq": 2, 14 | "no-eq-null": 2, 15 | "guard-for-in": 2, 16 | "no-unused-vars": [ 17 | 2, 18 | { 19 | "args": "none" 20 | } 21 | ], 22 | "strict": [ 23 | 2, 24 | "safe" 25 | ], 26 | "no-use-before-define": [ 27 | 2, 28 | { 29 | "functions": false, 30 | "variables": false 31 | } 32 | ], 33 | "operator-linebreak": [ 34 | 2, 35 | "after" 36 | ], 37 | "max-len": [ 38 | 2, 39 | { 40 | "code": 200, 41 | "tabWidth": 4, 42 | "ignoreComments": true 43 | } 44 | ], 45 | "indent": [ 46 | 2, 47 | 4, 48 | { 49 | "SwitchCase": 1 50 | } 51 | ], 52 | "quotes": [ 53 | 2, 54 | "single" 55 | ], 56 | "no-multi-str": 2, 57 | "no-mixed-spaces-and-tabs": 2, 58 | "no-trailing-spaces": 2, 59 | "space-unary-ops": [ 60 | 2, 61 | { 62 | "nonwords": false, 63 | "overrides": {} 64 | } 65 | ], 66 | "brace-style": [ 67 | 2, 68 | "1tbs", 69 | { 70 | "allowSingleLine": true 71 | } 72 | ], 73 | "comma-spacing": [ 74 | 2, 75 | { 76 | "before": false, 77 | "after": true 78 | } 79 | ], 80 | "comma-dangle": [ 81 | 2, 82 | "never" 83 | ], 84 | "comma-style": [ 85 | "error", 86 | "last" 87 | ], 88 | "keyword-spacing": [ 89 | 2, 90 | {} 91 | ], 92 | "space-infix-ops": 2, 93 | "space-before-blocks": [ 94 | 2, 95 | "always" 96 | ], 97 | "space-before-function-paren": [ 98 | 2, 99 | { 100 | "anonymous": "ignore", 101 | "named": "never" 102 | } 103 | ], 104 | "array-bracket-spacing": [ 105 | 2, 106 | "never" 107 | ], 108 | "space-in-parens": [ 109 | 2, 110 | "never" 111 | ], 112 | "no-multiple-empty-lines": 2, 113 | "no-with": 2, 114 | "no-spaced-func": 2, 115 | "key-spacing": [ 116 | 2, 117 | { 118 | "beforeColon": false, 119 | "afterColon": true 120 | } 121 | ], 122 | "dot-notation": 2, 123 | "semi": [ 124 | 2, 125 | "always" 126 | ], 127 | "eol-last": ["error", "never"] 128 | } 129 | } -------------------------------------------------------------------------------- /dist/jquery.jscroll.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jScroll - jQuery Plugin for Infinite Scrolling / Auto-Paging 3 | * @see @link{https://jscroll.com} 4 | * 5 | * @copyright Philip Klauzinski 6 | * @license Dual licensed under the MIT and GPL Version 2 licenses 7 | * @author Philip Klauzinski (https://webtopian.com) 8 | * @version 2.4.1 9 | * @requires jQuery v1.8.0+ 10 | * @preserve 11 | */ 12 | !function(m){"use strict";m.jscroll={defaults:{debug:!1,autoTrigger:!0,autoTriggerUntil:!1,loadingHtml:"Loading...",loadingFunction:!1,padding:0,nextSelector:"a:last",contentSelector:"",pagingSelector:"",callback:!1}};var l=function(a,t){var n,e=a.data("jscroll"),l="function"==typeof t?{callback:t}:t,s=m.extend({},m.jscroll.defaults,l,e||{}),d="visible"===a.css("overflow-y"),o=a.find(s.nextSelector).first(),r=m(window),i=m("body"),f=d?r:a,c=m.trim(o.prop("href")+" "+s.contentSelector),g=function(){a.find(".jscroll-inner").length||a.contents().wrapAll('
')},u=function(t){s.pagingSelector?t.closest(s.pagingSelector).hide():t.parent().not(".jscroll-inner,.jscroll-added").addClass("jscroll-next-parent").hide().length||t.wrap('
').parent().hide()},p=function(){return f.unbind(".jscroll").removeData("jscroll").find(".jscroll-inner").children().unwrap().filter(".jscroll-added").children().unwrap()},j=function(){if(a.is(":visible")){g();var t=a.find("div.jscroll-inner").first(),n=a.data("jscroll"),e=parseInt(a.css("borderTopWidth"),10),l=isNaN(e)?0:e,o=parseInt(a.css("paddingTop"),10)+l,r=d?f.scrollTop():a.offset().top,i=t.length?t.offset().top:0,c=Math.ceil(r-i+f.height()+o);if(!n.waiting&&c+s.padding>=t.outerHeight())return b("info","jScroll:",t.outerHeight()-c,"from bottom. Loading next request..."),v()}},h=function(){var t=a.find(s.nextSelector).first();if(t.length)if(s.autoTrigger&&(!1===s.autoTriggerUntil||0').children(".jscroll-added").last().html('
'+s.loadingHtml+"
").promise().done(function(){s.loadingFunction&&s.loadingFunction()}),a.animate({scrollTop:t.outerHeight()},0,function(){var o=r.nextHref;t.find("div.jscroll-added").last().load(o,function(t,n){if("error"===n)return p();var e,l=m(this).find(s.nextSelector).first();r.waiting=!1,r.nextHref=!!l.prop("href")&&m.trim(l.prop("href")+" "+s.contentSelector),m(".jscroll-next-parent",a).remove(),(e=e||a.data("jscroll"))&&e.nextHref?h():(b("warn","jScroll: nextSelector not found - destroying"),p()),s.callback&&s.callback.call(this,o),b("dir",r)})})},b=function(t){if(s.debug&&"object"==typeof console&&("object"==typeof t||"function"==typeof console[t]))if("object"==typeof t){var n=[];for(var e in t)"function"==typeof console[e]?(n=t[e].length?t[e]:[t[e]],console[e].apply(console,n)):console.log.apply(console,n)}else console[t].apply(console,Array.prototype.slice.call(arguments,1))};return a.data("jscroll",m.extend({},e,{initialized:!0,waiting:!1,nextHref:c})),g(),(n=m(s.loadingHtml).filter("img").attr("src"))&&((new Image).src=n),h(),m.extend(a.jscroll,{destroy:p}),a};m.fn.jscroll=function(e){return this.each(function(){var t=m(this),n=t.data("jscroll");n&&n.initialized||l(t,e)})}}(jQuery); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jScroll - jQuery Plugin for Infinite Scrolling / Auto-Paging 2 | 3 | [![Build Status](https://travis-ci.org/pklauzinski/jscroll.svg?branch=master)](https://travis-ci.org/pklauzinski/jscroll) 4 | [![npm version](https://img.shields.io/npm/v/jscroll.svg)](https://www.npmjs.com/package/jscroll) 5 | [![Bower version](https://img.shields.io/bower/v/jscroll.svg)](https://github.com/pklauzinski/jscroll) 6 | [![Join the chat at https://gitter.im/pklauzinski/jscroll](https://badges.gitter.im/pklauzinski/jscroll.svg)](https://gitter.im/pklauzinski/jscroll?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 7 | 8 | Official site at [jscroll.com](https://jscroll.com/). 9 | 10 | * Copyright © [Philip Klauzinski](https://webtopian.com) 11 | * Dual licensed under the MIT and GPL Version 2 licenses. 12 | * http://www.opensource.org/licenses/mit-license.php 13 | * http://www.gnu.org/licenses/gpl-2.0.html 14 | 15 | > Requires jQuery v1.8.0+ 16 | 17 | ## Facebook Page 18 | 19 | Follow us on Facebook for commit updates: https://www.facebook.com/jScroll.Infinite.Scrolling 20 | 21 | ## Usage 22 | 23 | The `jscroll` method is called on the selector for which you want your scrollable content contained within. For example: 24 | 25 | ```javascript 26 | $('.jscroll').jscroll(); 27 | ``` 28 | 29 | The `jscroll` method takes an optional object literal as a parameter for overriding the default options. An example of how this can be done is shown below. 30 | 31 | ```javascript 32 | $('.jscroll').jscroll({ 33 | loadingHtml: 'Loading Loading...', 34 | padding: 20, 35 | nextSelector: 'a.jscroll-next:last', 36 | contentSelector: 'li' 37 | }); 38 | ``` 39 | 40 | ## Options 41 | 42 | * `debug (false)` - When set to true, outputs useful information to the console display if the `console` object exists. 43 | * `autoTrigger (true)` - When set to true, triggers the loading of the next set of content automatically when the user scrolls to the bottom of the containing element. When set to false, the required next link will trigger the loading of the next set of content when clicked. 44 | * `autoTriggerUntil (false)` - Set to an integer greater than 0 to turn off `autoTrigger` of paging after the specified number of pages. Requires `autoTrigger` to be `true`. 45 | * `loadingHtml ('Loading...')` - The HTML to show at the bottom of the content while loading the next set. 46 | * `loadingFunction` (false) - A JavaScript function to run after the loadingHtml has been drawn. 47 | * `padding (0)` - The distance from the bottom of the scrollable content at which to trigger the loading of the next set of content. This only applies when autoTrigger is set to true. 48 | * `nextSelector ('a:last')` - The selector to use for finding the link which contains the href pointing to the next set of content. If this selector is not found, or if it does not contain a href attribute, jScroll will self-destroy and unbind from the element upon which it was called. 49 | * `contentSelector ('')` - A convenience selector for loading only part of the content in the response for the next set of content. This selector will be ignored if left blank and will apply the entire response to the DOM. 50 | * `pagingSelector ('')` - Optionally define a selector for your paging controls so that they will be hidden, instead of just hiding the next page link. 51 | * `callback (false)` - Optionally define a callback function to be called after a set of content has been loaded. 52 | 53 | For more information on the `contentSelector` option and how it loads a response fragment, see the [jQuery documentation for the .load() method](https://api.jquery.com/load/). 54 | 55 | ## Contributing 56 | 57 | In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using [grunt](https://gruntjs.com). 58 | 59 | 60 | ## LICENSES: 61 | 62 | * MIT: http://www.opensource.org/licenses/mit-license.php 63 | * GPL-2.0: http://www.gnu.org/licenses/gpl-2.0.html 64 | -------------------------------------------------------------------------------- /jquery.jscroll.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * jScroll - jQuery Plugin for Infinite Scrolling / Auto-Paging 3 | * @see @link{https://jscroll.com} 4 | * 5 | * @copyright Philip Klauzinski 6 | * @license Dual licensed under the MIT and GPL Version 2 licenses 7 | * @author Philip Klauzinski (https://webtopian.com) 8 | * @version 2.4.1 9 | * @requires jQuery v1.8.0+ 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: 'Loading...', 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.prop('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('
'); 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('
').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 | _debug('info', 'jScroll:', $inner.outerHeight() - iTotalHeight, 'from bottom. Loading next request...'); 98 | return _load(); 99 | } 100 | } 101 | }, 102 | 103 | // Check if the href for the next set of content has been set 104 | _checkNextHref = function(data) { 105 | data = data || $e.data('jscroll'); 106 | if (!data || !data.nextHref) { 107 | _debug('warn', 'jScroll: nextSelector not found - destroying'); 108 | _destroy(); 109 | return false; 110 | } else { 111 | _setBindings(); 112 | return true; 113 | } 114 | }, 115 | 116 | _setBindings = function() { 117 | var $next = $e.find(_options.nextSelector).first(); 118 | if (!$next.length) { 119 | return; 120 | } 121 | if (_options.autoTrigger && (_options.autoTriggerUntil === false || _options.autoTriggerUntil > 0)) { 122 | _nextWrap($next); 123 | var scrollingBodyHeight = _$body.height() - $e.offset().top, 124 | scrollingHeight = ($e.height() < scrollingBodyHeight) ? $e.height() : scrollingBodyHeight, 125 | windowHeight = ($e.offset().top - _$window.scrollTop() > 0) ? _$window.height() - ($e.offset().top - $(window).scrollTop()) : _$window.height(); 126 | if (scrollingHeight <= windowHeight) { 127 | _observe(); 128 | } 129 | _$scroll.unbind('.jscroll').bind('scroll.jscroll', function() { 130 | return _observe(); 131 | }); 132 | if (_options.autoTriggerUntil > 0) { 133 | _options.autoTriggerUntil--; 134 | } 135 | } else { 136 | _$scroll.unbind('.jscroll'); 137 | $next.bind('click.jscroll', function() { 138 | _nextWrap($next); 139 | _load(); 140 | return false; 141 | }); 142 | } 143 | }, 144 | 145 | // Load the next set of content, if available 146 | _load = function() { 147 | var $inner = $e.find('div.jscroll-inner').first(), 148 | data = $e.data('jscroll'); 149 | 150 | data.waiting = true; 151 | $inner.append('
') 152 | .children('.jscroll-added').last() 153 | .html('
' + _options.loadingHtml + '
') 154 | .promise() 155 | .done(function() { 156 | if (_options.loadingFunction) { 157 | _options.loadingFunction(); 158 | } 159 | }); 160 | 161 | return $e.animate({scrollTop: $inner.outerHeight()}, 0, function() { 162 | var nextHref = data.nextHref; 163 | $inner.find('div.jscroll-added').last().load(nextHref, function(r, status) { 164 | if (status === 'error') { 165 | return _destroy(); 166 | } 167 | var $next = $(this).find(_options.nextSelector).first(); 168 | data.waiting = false; 169 | data.nextHref = $next.prop('href') ? $.trim($next.prop('href') + ' ' + _options.contentSelector) : false; 170 | $('.jscroll-next-parent', $e).remove(); // Remove the previous next link now that we have a new one 171 | _checkNextHref(); 172 | if (_options.callback) { 173 | _options.callback.call(this, nextHref); 174 | } 175 | _debug('dir', data); 176 | }); 177 | }); 178 | }, 179 | 180 | // Safe console debug - http://klauzinski.com/javascript/safe-firebug-console-in-javascript 181 | _debug = function(m) { 182 | if (_options.debug && typeof console === 'object' && (typeof m === 'object' || typeof console[m] === 'function')) { 183 | if (typeof m === 'object') { 184 | var args = []; 185 | for (var sMethod in m) { 186 | if (typeof console[sMethod] === 'function') { 187 | args = (m[sMethod].length) ? m[sMethod] : [m[sMethod]]; 188 | console[sMethod].apply(console, args); 189 | } else { 190 | console.log.apply(console, args); 191 | } 192 | } 193 | } else { 194 | console[m].apply(console, Array.prototype.slice.call(arguments, 1)); 195 | } 196 | } 197 | }; 198 | 199 | // Initialization 200 | $e.data('jscroll', $.extend({}, _data, {initialized: true, waiting: false, nextHref: _nextHref})); 201 | _wrapInnerContent(); 202 | _preloadImage(); 203 | _setBindings(); 204 | 205 | // Expose API methods via the jQuery.jscroll namespace, e.g. $('sel').jscroll.method() 206 | $.extend($e.jscroll, { 207 | destroy: _destroy 208 | }); 209 | return $e; 210 | }; 211 | 212 | // Define the jscroll plugin method and loop 213 | $.fn.jscroll = function(m) { 214 | return this.each(function() { 215 | var $this = $(this), 216 | data = $this.data('jscroll'); 217 | 218 | // Instantiate jScroll on this element if it hasn't been already 219 | if (data && data.initialized) { 220 | return; 221 | } 222 | jScroll($this, m); 223 | }); 224 | }; 225 | 226 | })(jQuery); --------------------------------------------------------------------------------