├── .gitignore ├── bower.json ├── gulpfile.js ├── inphinity.js ├── inphinity.min.js ├── package.json ├── readme.md └── src └── inphinity.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "inphinity.js", 3 | "main": "inphinity.js", 4 | "version": "1.0.5", 5 | "homepage": "https://github.com/raphamorim/inphinity", 6 | "authors": [ 7 | "Raphael H. Amorim " 8 | ], 9 | "description": "A infinity scroll without jQuery or other dependency", 10 | "keywords": [ 11 | "infinity", 12 | "scroll", 13 | "native", 14 | "without", 15 | "jQuery", 16 | "dependency", 17 | "infinite", 18 | "wordpress", 19 | "jekyll", 20 | "blog" 21 | ], 22 | "license": "MIT", 23 | "ignore": [ 24 | "**/.*", 25 | "node_modules", 26 | "bower_components", 27 | "test", 28 | "tests" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'), 2 | uglify = require('gulp-uglify'), 3 | rename = require('gulp-rename'), 4 | concat = require('gulp-concat'); 5 | 6 | gulp.task('build', function() { 7 | return gulp.src('src/**/*.js') 8 | .pipe(concat('./inphinity.js')) 9 | .pipe(gulp.dest('./')) 10 | .pipe(rename('inphinity.min.js')) 11 | .pipe(uglify()) 12 | .pipe(gulp.dest('./')); 13 | }); 14 | 15 | gulp.task('default', ['build'], function(){ 16 | console.log('default task done!') 17 | }); -------------------------------------------------------------------------------- /inphinity.js: -------------------------------------------------------------------------------- 1 | /*! 2 | -------------------------------- 3 | Inphinity.js 4 | -------------------------------- 5 | + https://github.com/raphamorim/inphinity 6 | + version 1.0.6 7 | + Copyright 2015 Raphael Amorim 8 | + Licensed under the MIT license 9 | 10 | + Documentation: https://github.com/raphamorim/inphinity 11 | */ 12 | 13 | var inphinity = (function() { 14 | this.loading = false; 15 | this.debug = false; 16 | this.url = ''; 17 | this.currentPage = 1; 18 | this.itemSelector = 'div.post'; 19 | this.nextSelector = 'div.navigation a:first'; 20 | this.navSelector = 'div.navigation'; 21 | this.basePath = false; 22 | this.path = false; 23 | this.dataType = 'html'; 24 | this.bag = false; 25 | this.bagClassName = false; 26 | this.loader = true; 27 | this.trustedRequest = false; 28 | this.defaults = { 29 | finishedMsg: "That's all folks!", 30 | loadingMsg: 'Loading more...', 31 | animationSpeed: 500 32 | }; 33 | 34 | this.scroller = function(scrollTop) { 35 | if (this.loading === true) 36 | return; 37 | 38 | var scrollActivate = (this.element.offsetTop + this.element.offsetHeight), 39 | diff = scrollActivate - scrollTop; 40 | 41 | if (diff <= 750) { 42 | this.loading = true; 43 | this.request(); 44 | } 45 | }; 46 | 47 | this.getPath = function() { 48 | var path = this.basePath; 49 | if (path.match(/^(.*?)\b2\b(.*?$)/)) { 50 | path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1); 51 | 52 | // if there is any 2 in the url at all. 53 | } else if (path.match(/^(.*?)2(.*?$)/)) { 54 | if (path.match(/^(.*?page=)2(\/.*|$)/)) { 55 | path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1); 56 | return path; 57 | } 58 | 59 | path = path.match(/^(.*?)2(.*?$)/).slice(1); 60 | } else { 61 | // page= is used in drupal too but second page is page=1 not page=2: 62 | if (path.match(/^(.*?page=)1(\/.*|$)/)) { 63 | path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1); 64 | return path; 65 | } else { 66 | this.currentPage = path.match(/\d+/)[0] - 1; 67 | path = [this.path, '']; 68 | } 69 | } 70 | return path; 71 | }; 72 | 73 | this.getUrlPath = function() { 74 | var nextSel = (document.querySelector(this.nextSelector).href).split('/'); 75 | return nextSel[nextSel.length - 1]; 76 | }; 77 | 78 | this.createBag = function() { 79 | var bag = document.createElement('div'); 80 | bag.style.display = 'none'; 81 | this.bagClassName = this.bagClassName || 'ph-bag'; 82 | bag.className = this.bagClassName; 83 | document.querySelector('body').appendChild(bag); 84 | this.bag = document.querySelector('.' + this.bagClassName); 85 | }; 86 | 87 | this.createLoader = function() { 88 | var loader = document.createElement('div'); 89 | loader.style.display = 'none'; 90 | loader.className = 'ph-loader'; 91 | if (this.defaults.loadingMsg) 92 | loader.innerHTML = this.defaults.loadingMsg; 93 | 94 | this.element.appendChild(loader); 95 | this.loader = document.querySelector('.ph-loader'); 96 | }; 97 | 98 | this.updateLoader = function() { 99 | this.element.removeChild(this.loader); 100 | this.createLoader(); 101 | }; 102 | 103 | this.loaderToggle = function(status, fn) { 104 | if (!this.loader) { 105 | if (typeof(fn) === 'function') 106 | fn() 107 | return; 108 | } 109 | this.loader.style.display = 'block'; 110 | 111 | if (status === true) 112 | this.animation().fadeIn(this.loader, fn); 113 | else if (status === false) 114 | this.animation().fadeOut(this.loader, fn); 115 | }; 116 | 117 | this.request = function() { 118 | var self = this, 119 | url = self.path + '' + (self.currentPage + 1), 120 | xhr = new XMLHttpRequest(); 121 | 122 | if (window.location.pathname.indexOf(self.path) > -1) 123 | url = '../' + url; 124 | 125 | self.loaderToggle(true); 126 | 127 | xhr.open('GET', encodeURI(url)); 128 | xhr.onload = function() { 129 | if (xhr.status === 200 || self.trustedRequest) { 130 | var bodyItems = (/]*>((.|[\n\r])*)<\/body>/im.exec(xhr.responseText).slice(1))[0]; 131 | self.trustedRequest = true; 132 | self.loaderToggle(false, self.render.bind(self, bodyItems)); 133 | } else { 134 | self._debug('Request failed. Returned status of ' + xhr.status); 135 | } 136 | }; 137 | xhr.send(); 138 | }; 139 | 140 | this.render = function(bodyItems, skip) { 141 | var self = this; 142 | self.bag.innerHTML = bodyItems; 143 | var nextPosts = self.bag.querySelectorAll(self.itemSelector); 144 | 145 | if (!nextPosts.length) 146 | return self.finished(); 147 | 148 | if (skip !== true) { 149 | var navSel = document.querySelector(self.navSelector); 150 | return self.animation().fadeOut(navSel, function() { 151 | return self.render(bodyItems, true); 152 | }); 153 | } 154 | 155 | for (var i = 0; i < nextPosts.length; i++) { 156 | self.element.appendChild(nextPosts[i]) 157 | } 158 | 159 | self.toNext(); 160 | } 161 | 162 | this.toNext = function() { 163 | if (this.loader) this.updateLoader(); 164 | this.currentPage = this.currentPage + 1; 165 | this.loading = false; 166 | } 167 | 168 | this.finished = function(){ 169 | var finished = document.createElement('div'); 170 | finished.className = 'ph-end'; 171 | finished.innerHTML = this.defaults.finishedMsg; 172 | this.element.appendChild(finished); 173 | } 174 | 175 | this.on = function(selector) { 176 | this.sel = selector; 177 | this.element = document.querySelector(selector); 178 | return this; 179 | }; 180 | 181 | this.set = function(config) { 182 | if (config.navSelector) 183 | this.navSelector = config.navSelector; 184 | if (config.nextSelector) 185 | this.nextSelector = config.nextSelector; 186 | if (config.itemSelector) 187 | this.itemSelector = config.itemSelector; 188 | if (config.path) 189 | this.path = config.path; 190 | if (config.basePath) 191 | this.basePath = config.basePath; 192 | if (config.loader === false) 193 | this.loader = config.loader; 194 | if (config.loadingMsg) 195 | this.defaults.loadingMsg = config.loadingMsg; 196 | if (config.finishedMsg) 197 | this.defaults.finishedMsg = config.finishedMsg; 198 | if (config.animationSpeed) { 199 | this.defaults.animationSpeed = config.animationSpeed; 200 | 201 | if (config.animationSpeed === "slow") 202 | this.defaults.animationSpeed = 800; 203 | if (config.animationSpeed === "normal") 204 | this.defaults.animationSpeed = 500; 205 | if (config.animationSpeed === "fast") 206 | this.defaults.animationSpeed = 300; 207 | } 208 | if(!!document.querySelector(config.navSelector)) { 209 | this.init(); 210 | } 211 | }; 212 | 213 | this.init = function() { 214 | this.basePath = this.basePath || this.getUrlPath(); 215 | this.path = this.path || this.getPath()[0] || 'page'; 216 | if (this.loader) this.createLoader(); 217 | this.createBag(); 218 | this.setEventScroll(); 219 | 220 | }; 221 | 222 | this.setEventScroll = function() { 223 | var self = this; 224 | window.addEventListener("scroll", function(ev) { 225 | self.scroller(window.scrollY || ev.target.activeElement.scrollTop); 226 | }); 227 | }; 228 | 229 | this._debug = function(message) { 230 | console.log('Inphinity: ', message); 231 | }; 232 | 233 | this.animation = function() { 234 | var self = this; 235 | return { 236 | fadeOut: function(el, callback) { 237 | el.style.opacity = 1; 238 | var last = +new Date(); 239 | var tick = function() { 240 | el.style.opacity = +el.style.opacity - (new Date() - last) / self.defaults.animationSpeed; 241 | last = +new Date(); 242 | 243 | if (+el.style.opacity > 0) { 244 | (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16) 245 | } else { 246 | el.style.display = 'none'; 247 | if (typeof callback === 'undefined') return true; 248 | callback(); 249 | } 250 | }; 251 | tick(); 252 | }, 253 | fadeIn: function(el, callback) { 254 | el.style.opacity = 0; 255 | var last = +new Date(); 256 | var tick = function() { 257 | el.style.opacity = +el.style.opacity + (new Date() - last) / self.defaults.animationSpeed; 258 | last = +new Date(); 259 | 260 | if (+el.style.opacity < 1) { 261 | (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16) 262 | } else { 263 | if (typeof callback === 'undefined') return true; 264 | callback(); 265 | } 266 | }; 267 | tick(); 268 | } 269 | } 270 | }; 271 | 272 | return this.on.bind(this); 273 | })(); 274 | -------------------------------------------------------------------------------- /inphinity.min.js: -------------------------------------------------------------------------------- 1 | var inphinity=function(){return this.loading=!1,this.debug=!1,this.url="",this.currentPage=1,this.itemSelector="div.post",this.nextSelector="div.navigation a:first",this.navSelector="div.navigation",this.basePath=!1,this.path=!1,this.dataType="html",this.bag=!1,this.bagClassName=!1,this.loader=!0,this.trustedRequest=!1,this.defaults={finishedMsg:"That's all folks!",loadingMsg:"Loading more...",animationSpeed:500},this.scroller=function(e){if(this.loading!==!0){var t=this.element.offsetTop+this.element.offsetHeight,i=t-e;750>=i&&(this.loading=!0,this.request())}},this.getPath=function(){var e=this.basePath;if(e.match(/^(.*?)\b2\b(.*?$)/))e=e.match(/^(.*?)\b2\b(.*?$)/).slice(1);else if(e.match(/^(.*?)2(.*?$)/)){if(e.match(/^(.*?page=)2(\/.*|$)/))return e=e.match(/^(.*?page=)2(\/.*|$)/).slice(1);e=e.match(/^(.*?)2(.*?$)/).slice(1)}else{if(e.match(/^(.*?page=)1(\/.*|$)/))return e=e.match(/^(.*?page=)1(\/.*|$)/).slice(1);this.currentPage=e.match(/\d+/)[0]-1,e=[this.path,""]}return e},this.getUrlPath=function(){var e=document.querySelector(this.nextSelector).href.split("/");return e[e.length-1]},this.createBag=function(){var e=document.createElement("div");e.style.display="none",this.bagClassName=this.bagClassName||"ph-bag",e.className=this.bagClassName,document.querySelector("body").appendChild(e),this.bag=document.querySelector("."+this.bagClassName)},this.createLoader=function(){var e=document.createElement("div");e.style.display="none",e.className="ph-loader",this.defaults.loadingMsg&&(e.innerHTML=this.defaults.loadingMsg),this.element.appendChild(e),this.loader=document.querySelector(".ph-loader")},this.updateLoader=function(){this.element.removeChild(this.loader),this.createLoader()},this.loaderToggle=function(e,t){return this.loader?(this.loader.style.display="block",void(e===!0?this.animation().fadeIn(this.loader,t):e===!1&&this.animation().fadeOut(this.loader,t))):void("function"==typeof t&&t())},this.request=function(){var e=this,t=e.path+""+(e.currentPage+1),i=new XMLHttpRequest;window.location.pathname.indexOf(e.path)>-1&&(t="../"+t),e.loaderToggle(!0),i.open("GET",encodeURI(t)),i.onload=function(){if(200===i.status||e.trustedRequest){var t=/]*>((.|[\n\r])*)<\/body>/im.exec(i.responseText).slice(1)[0];e.trustedRequest=!0,e.loaderToggle(!1,e.render.bind(e,t))}else e._debug("Request failed. Returned status of "+i.status)},i.send()},this.render=function(e,t){var i=this;i.bag.innerHTML=e;var a=i.bag.querySelectorAll(i.itemSelector);if(!a.length)return i.finished();if(t!==!0){var n=document.querySelector(i.navSelector);return i.animation().fadeOut(n,function(){return i.render(e,!0)})}for(var s=0;s0)window.requestAnimationFrame&&requestAnimationFrame(n)||setTimeout(n,16);else{if(t.style.display="none","undefined"==typeof i)return!0;i()}};n()},fadeIn:function(t,i){t.style.opacity=0;var a=+new Date,n=function(){if(t.style.opacity=+t.style.opacity+(new Date-a)/e.defaults.animationSpeed,a=+new Date,+t.style.opacity<1)window.requestAnimationFrame&&requestAnimationFrame(n)||setTimeout(n,16);else{if("undefined"==typeof i)return!0;i()}};n()}}},this.on.bind(this)}(); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "inphinity.js", 3 | "version": "1.0.6", 4 | "description": "A infinity scroll without jQuery or other dependency", 5 | "main": "inphinity.js", 6 | "scripts": { 7 | "build": "gulp build", 8 | "test": "npm test" 9 | }, 10 | "repository": { 11 | "type": "git", 12 | "url": "git+https://github.com/raphamorim/inphinity.git" 13 | }, 14 | "author": "Raphael Amorim", 15 | "license": "MIT", 16 | "bugs": { 17 | "url": "https://github.com/raphamorim/inphinity/issues" 18 | }, 19 | "homepage": "https://github.com/raphamorim/inphinity#readme", 20 | "devDependencies": { 21 | "gulp": "^3.9.0", 22 | "gulp-concat": "^2.6.0", 23 | "gulp-rename": "^1.2.2", 24 | "gulp-uglify": "^1.2.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Inphinity 2 | 3 | > Infinity Scroll without [jQuery](https://jquery.com/) or other dependency. 4 | 5 | Inphinity was made to Jekyll static blogs, Drupal and Wordpress sites/blogs. 6 | 7 | ##### Who is using this? 8 | 9 | - [My personal blog](http://raphamorim.com/blog) 10 | - [Free Time](http://free-time.github.io/) 11 | 12 | ## How to use? 13 | 14 | #### Getting 15 | 16 | First at all, get Inphinity using [Download Option](https://github.com/raphamorim/inphinity/archive/master.zip) or via bower. To get using [Bower](http://bower.io) just run this command 17 | 18 | ```sh 19 | bower install inphinity 20 | ``` 21 | 22 | Add the source before body tag end: 23 | 24 | ```html 25 | 26 | 27 | ``` 28 | 29 | #### Usage 30 | 31 | Relax! A better documentation coming soon (and you can help!). For while, see a simple example: 32 | 33 | ```javascript 34 | inphinity('#posts').set({ 35 | navSelector : "p.pagination", 36 | nextSelector : "p.pagination a.older", 37 | itemSelector : ".container ul#posts li.post", 38 | finishedMsg: "That's all folks!", 39 | loadingMsg: 'Loading more...', 40 | animationSpeed: "slow" 41 | }); 42 | ``` 43 | 44 | ### Options 45 | 46 | ####• navSelector 47 | Description: Pagination nav 48 | 49 | Default: `div.navigation` 50 | 51 | ####• nextSelector 52 | Description: href attribute, who specifies the URL of the next page. 53 | 54 | Default: `div.navigation a:first` 55 | 56 | ####• itemSelector 57 | Description: List items in structure 58 | 59 | Default: `div.post` 60 | 61 | ####• finishedMsg 62 | Description: Message to show when finish pages when ends 63 | 64 | Format: raw HTML 65 | 66 | Default: `That's all folks!` 67 | 68 | ####• loadingMsg 69 | Description: Message to show when load more items 70 | 71 | Format: raw HTML 72 | 73 | Default: `Loading more...` 74 | 75 | ####• loader 76 | Description: Enable/Disable loader 77 | 78 | Suggestions: `true`, `false` 79 | 80 | Default: `true` 81 | 82 | ####• animationSpeed 83 | Description: Set speed of the animations 84 | 85 | Suggestions: `normal`, `slow`, `fast` 86 | 87 | Default: `500` 88 | 89 | 90 | ## Version 91 | 92 | Currently in **v1.0.6** :) 93 | 94 | ## Credits 95 | 96 | Infinitely inspired by [Infinity Scroll](https://github.com/infinite-scroll/infinite-scroll) 97 | 98 | ## License 99 | 100 | The MIT License (MIT) 101 | 102 | Copyright (c) 2015 [Raphael Amorim](http://github.com/raphamorim) 103 | 104 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 105 | 106 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 107 | 108 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 109 | -------------------------------------------------------------------------------- /src/inphinity.js: -------------------------------------------------------------------------------- 1 | /*! 2 | -------------------------------- 3 | Inphinity.js 4 | -------------------------------- 5 | + https://github.com/raphamorim/inphinity 6 | + version 1.0.6 7 | + Copyright 2015 Raphael Amorim 8 | + Licensed under the MIT license 9 | 10 | + Documentation: https://github.com/raphamorim/inphinity 11 | */ 12 | 13 | var inphinity = (function() { 14 | this.loading = false; 15 | this.debug = false; 16 | this.url = ''; 17 | this.currentPage = 1; 18 | this.itemSelector = 'div.post'; 19 | this.nextSelector = 'div.navigation a:first'; 20 | this.navSelector = 'div.navigation'; 21 | this.basePath = false; 22 | this.path = false; 23 | this.dataType = 'html'; 24 | this.bag = false; 25 | this.bagClassName = false; 26 | this.loader = true; 27 | this.trustedRequest = false; 28 | this.defaults = { 29 | finishedMsg: "That's all folks!", 30 | loadingMsg: 'Loading more...', 31 | animationSpeed: 500 32 | }; 33 | 34 | this.scroller = function(scrollTop) { 35 | if (this.loading === true) 36 | return; 37 | 38 | var scrollActivate = (this.element.offsetTop + this.element.offsetHeight), 39 | diff = scrollActivate - scrollTop; 40 | 41 | if (diff <= 750) { 42 | this.loading = true; 43 | this.request(); 44 | } 45 | }; 46 | 47 | this.getPath = function() { 48 | var path = this.basePath; 49 | if (path.match(/^(.*?)\b2\b(.*?$)/)) { 50 | path = path.match(/^(.*?)\b2\b(.*?$)/).slice(1); 51 | 52 | // if there is any 2 in the url at all. 53 | } else if (path.match(/^(.*?)2(.*?$)/)) { 54 | if (path.match(/^(.*?page=)2(\/.*|$)/)) { 55 | path = path.match(/^(.*?page=)2(\/.*|$)/).slice(1); 56 | return path; 57 | } 58 | 59 | path = path.match(/^(.*?)2(.*?$)/).slice(1); 60 | } else { 61 | // page= is used in drupal too but second page is page=1 not page=2: 62 | if (path.match(/^(.*?page=)1(\/.*|$)/)) { 63 | path = path.match(/^(.*?page=)1(\/.*|$)/).slice(1); 64 | return path; 65 | } else { 66 | this.currentPage = path.match(/\d+/)[0] - 1; 67 | path = [this.path, '']; 68 | } 69 | } 70 | return path; 71 | }; 72 | 73 | this.getUrlPath = function() { 74 | var nextSel = (document.querySelector(this.nextSelector).href).split('/'); 75 | return nextSel[nextSel.length - 1]; 76 | }; 77 | 78 | this.createBag = function() { 79 | var bag = document.createElement('div'); 80 | bag.style.display = 'none'; 81 | this.bagClassName = this.bagClassName || 'ph-bag'; 82 | bag.className = this.bagClassName; 83 | document.querySelector('body').appendChild(bag); 84 | this.bag = document.querySelector('.' + this.bagClassName); 85 | }; 86 | 87 | this.createLoader = function() { 88 | var loader = document.createElement('div'); 89 | loader.style.display = 'none'; 90 | loader.className = 'ph-loader'; 91 | if (this.defaults.loadingMsg) 92 | loader.innerHTML = this.defaults.loadingMsg; 93 | 94 | this.element.appendChild(loader); 95 | this.loader = document.querySelector('.ph-loader'); 96 | }; 97 | 98 | this.updateLoader = function() { 99 | this.element.removeChild(this.loader); 100 | this.createLoader(); 101 | }; 102 | 103 | this.loaderToggle = function(status, fn) { 104 | if (!this.loader) { 105 | if (typeof(fn) === 'function') 106 | fn() 107 | return; 108 | } 109 | this.loader.style.display = 'block'; 110 | 111 | if (status === true) 112 | this.animation().fadeIn(this.loader, fn); 113 | else if (status === false) 114 | this.animation().fadeOut(this.loader, fn); 115 | }; 116 | 117 | this.request = function() { 118 | var self = this, 119 | url = self.path + '' + (self.currentPage + 1), 120 | xhr = new XMLHttpRequest(); 121 | 122 | if (window.location.pathname.indexOf(self.path) > -1) 123 | url = '../' + url; 124 | 125 | self.loaderToggle(true); 126 | 127 | xhr.open('GET', encodeURI(url)); 128 | xhr.onload = function() { 129 | if (xhr.status === 200 || self.trustedRequest) { 130 | var bodyItems = (/]*>((.|[\n\r])*)<\/body>/im.exec(xhr.responseText).slice(1))[0]; 131 | self.trustedRequest = true; 132 | self.loaderToggle(false, self.render.bind(self, bodyItems)); 133 | } else { 134 | self._debug('Request failed. Returned status of ' + xhr.status); 135 | } 136 | }; 137 | xhr.send(); 138 | }; 139 | 140 | this.render = function(bodyItems, skip) { 141 | var self = this; 142 | self.bag.innerHTML = bodyItems; 143 | var nextPosts = self.bag.querySelectorAll(self.itemSelector); 144 | 145 | if (!nextPosts.length) 146 | return self.finished(); 147 | 148 | if (skip !== true) { 149 | var navSel = document.querySelector(self.navSelector); 150 | return self.animation().fadeOut(navSel, function() { 151 | return self.render(bodyItems, true); 152 | }); 153 | } 154 | 155 | for (var i = 0; i < nextPosts.length; i++) { 156 | self.element.appendChild(nextPosts[i]) 157 | } 158 | 159 | self.toNext(); 160 | } 161 | 162 | this.toNext = function() { 163 | if (this.loader) this.updateLoader(); 164 | this.currentPage = this.currentPage + 1; 165 | this.loading = false; 166 | } 167 | 168 | this.finished = function(){ 169 | var finished = document.createElement('div'); 170 | finished.className = 'ph-end'; 171 | finished.innerHTML = this.defaults.finishedMsg; 172 | this.element.appendChild(finished); 173 | } 174 | 175 | this.on = function(selector) { 176 | this.sel = selector; 177 | this.element = document.querySelector(selector); 178 | return this; 179 | }; 180 | 181 | this.set = function(config) { 182 | if (config.navSelector) 183 | this.navSelector = config.navSelector; 184 | if (config.nextSelector) 185 | this.nextSelector = config.nextSelector; 186 | if (config.itemSelector) 187 | this.itemSelector = config.itemSelector; 188 | if (config.path) 189 | this.path = config.path; 190 | if (config.basePath) 191 | this.basePath = config.basePath; 192 | if (config.loader === false) 193 | this.loader = config.loader; 194 | if (config.loadingMsg) 195 | this.defaults.loadingMsg = config.loadingMsg; 196 | if (config.finishedMsg) 197 | this.defaults.finishedMsg = config.finishedMsg; 198 | if (config.animationSpeed) { 199 | this.defaults.animationSpeed = config.animationSpeed; 200 | 201 | if (config.animationSpeed === "slow") 202 | this.defaults.animationSpeed = 800; 203 | if (config.animationSpeed === "normal") 204 | this.defaults.animationSpeed = 500; 205 | if (config.animationSpeed === "fast") 206 | this.defaults.animationSpeed = 300; 207 | } 208 | if(!!document.querySelector(config.navSelector)) { 209 | this.init(); 210 | } 211 | }; 212 | 213 | this.init = function() { 214 | this.basePath = this.basePath || this.getUrlPath(); 215 | this.path = this.path || this.getPath()[0] || 'page'; 216 | if (this.loader) this.createLoader(); 217 | this.createBag(); 218 | this.setEventScroll(); 219 | 220 | }; 221 | 222 | this.setEventScroll = function() { 223 | var self = this; 224 | window.addEventListener("scroll", function(ev) { 225 | self.scroller(window.scrollY || ev.target.activeElement.scrollTop); 226 | }); 227 | }; 228 | 229 | this._debug = function(message) { 230 | console.log('Inphinity: ', message); 231 | }; 232 | 233 | this.animation = function() { 234 | var self = this; 235 | return { 236 | fadeOut: function(el, callback) { 237 | el.style.opacity = 1; 238 | var last = +new Date(); 239 | var tick = function() { 240 | el.style.opacity = +el.style.opacity - (new Date() - last) / self.defaults.animationSpeed; 241 | last = +new Date(); 242 | 243 | if (+el.style.opacity > 0) { 244 | (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16) 245 | } else { 246 | el.style.display = 'none'; 247 | if (typeof callback === 'undefined') return true; 248 | callback(); 249 | } 250 | }; 251 | tick(); 252 | }, 253 | fadeIn: function(el, callback) { 254 | el.style.opacity = 0; 255 | var last = +new Date(); 256 | var tick = function() { 257 | el.style.opacity = +el.style.opacity + (new Date() - last) / self.defaults.animationSpeed; 258 | last = +new Date(); 259 | 260 | if (+el.style.opacity < 1) { 261 | (window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16) 262 | } else { 263 | if (typeof callback === 'undefined') return true; 264 | callback(); 265 | } 266 | }; 267 | tick(); 268 | } 269 | } 270 | }; 271 | 272 | return this.on.bind(this); 273 | })(); 274 | --------------------------------------------------------------------------------