├── .gitignore ├── .jshintrc ├── .travis.yml ├── LICENSE.md ├── Makefile ├── README.md ├── bower.json ├── dist └── page-accelerator.min.js ├── package.json ├── src ├── ajax.js └── page-accelerator.js └── test ├── SpecRunner.html ├── spec-commonjs.js └── spec-default.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | "boss": true, 3 | "curly": true, 4 | "eqeqeq": true, 5 | "eqnull": true, 6 | "expr": true, 7 | "immed": true, 8 | "noarg": true, 9 | "onevar": true, 10 | "quotmark": "single", 11 | "smarttabs": true, 12 | "trailing": true, 13 | "undef": true, 14 | "unused": true, 15 | "browser": true 16 | } 17 | 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - "6.4.0" 5 | 6 | notification: 7 | email: 8 | on_success: never 9 | on_failure: always 10 | 11 | script: 12 | - make test_js 13 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2016 Evandro Leopoldino Goncalves 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | JSHINT=./node_modules/jshint/bin/jshint 2 | MOCHA_PHANTOM=./node_modules/mocha-phantomjs/bin/mocha-phantomjs 3 | UGLIFY=./node_modules/uglify-js/bin/uglifyjs 4 | 5 | .SILENT: 6 | 7 | jshint: 8 | $(JSHINT) src/*.js 9 | 10 | test_js: 11 | $(MOCHA_PHANTOM) test/SpecRunner.html 12 | 13 | minify: 14 | $(UGLIFY) src/ajax.js src/page-accelerator.js --mangle --output dist/page-accelerator.min.js 15 | echo "minified!" 16 | 17 | deploy: jshint minify 18 | echo "deployed!" 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pageAccelerator 2 | [![Build 3 | Status](https://travis-ci.org/Easyfood/pageAccelerator.svg?branch=master)](https://travis-ci.org/Easyfood/pageAccelerator) 4 | [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/evandrolg/pageAccelerator?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 5 | [![CDNJS](https://img.shields.io/cdnjs/v/page-accelerator.svg)](https://cdnjs.com/libraries/page-accelerator) 6 | 7 | A very light solution to load web pages faster. 8 | 9 | ## Browser Support 10 | - Google Chrome 5.0+ 11 | - Firefox 4.0+ 12 | - Edge 14+ 13 | - Opera 11.5+ 14 | - Safari 5.0+ 15 | 16 | ** For IE10+ you need to use some [polyfill](https://cdnjs.cloudflare.com/polyfill/) to add support for Promises. 17 | 18 | # How does it work? 19 | It's an agnostic library that uses ajax and pushState to deliver a faster navigation experience. pageAccelerator is a very light version of [turbolinks](https://github.com/turbolinks/turbolinks) and [pjax](https://github.com/defunkt/jquery-pjax) (our minfied file is just 2.2KB!). Basically what it does is follow every link in your application and each click it loads the page in background and replaces the content correctly, keeping the real datas from body and head, updating the title. 20 | 21 | ## Installation 22 | To install pageAccelerator, execute: 23 | 24 | ```shell 25 | npm install page-accelerator --save 26 | ``` 27 | 28 | or 29 | 30 | ```shell 31 | bower install page-accelerator --save 32 | ``` 33 | 34 | Or simply use the minified file from the `dist/` directory. 35 | 36 | ## How to use? 37 | pageAccelerator doesn't depend on jQuery, Zepto or any other library to work. You need just to include it at the end of your HTML code: 38 | 39 | ```html 40 | 41 | ``` 42 | 43 | Then you need to call the `pageAccelerator` function, such as the example bellow: 44 | 45 | ```js 46 | pageAccelerator(); 47 | ``` 48 | 49 | Just call it and pageAccelerator was already following the web application links. 50 | 51 | For links that you don't want to be followed, you need simply add `data-pageAccelerator="false"`. 52 | 53 | ## Parameters 54 | `pageAccelerator` can also receive an object as a parameter with the following options: 55 | * **beforeLoading** function: Will be called whenever a new page was requested by a click or the browser back 56 | * **afterLoading** function: Will be called whenever a new page has been loaded 57 | 58 | ## Team 59 | pageAccelerator was made with love by a bunch of [awesome contributors](https://github.com/EasyFood/pageAccelerator/graphs/contributors). 60 | 61 | ## Author 62 | |[![@evandrolg](https://avatars3.githubusercontent.com/u/444054?v=3&s=96)](https://github.com/evandrolg)| 63 | |:---:| 64 | |[@evandrolg](http://www.github.com/evandrolg)| 65 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "page-accelerator", 3 | "version": "0.1.1", 4 | "homepage": "https://github.com/Easyfood/pageAccelerator", 5 | "authors": [ 6 | "evandrolg" 7 | ], 8 | "description": "A very light solution to load web pages faster", 9 | "main": "dist/page-accelerator.min.js", 10 | "keywords": [ 11 | "pageAccelerator", 12 | "accelerator", 13 | "front-end", 14 | "turbo-links", 15 | "speed", 16 | "fast", 17 | "ajax", 18 | "performace" 19 | ], 20 | "ignore": [ 21 | "**/.*", 22 | "test", 23 | "*.md" 24 | ], 25 | "license": "MIT" 26 | } 27 | -------------------------------------------------------------------------------- /dist/page-accelerator.min.js: -------------------------------------------------------------------------------- 1 | (function(t){var e=t._PageAccelerator=t._PageAccelerator||{};e.ajax={get:function(e){return new t.Promise(function(t,r){var n=new XMLHttpRequest;n.open("GET",e,true);n.onload=function(){if(n.status>=200&&n.status<400){t(n.response);return}r(n.response)};n.onerror=function(){r(Error("Network Error"))};n.send()})}}})(window);(function(t,e){if(typeof exports==="object"&&exports){e(exports)}else if(typeof define==="function"&&define.amd){define(["exports"],e)}else{e(t)}})(this,function(t){var e=t===window;var r=e?t:window;var n=document;var a=r._PageAccelerator=r._PageAccelerator||{};a.PageAccelerator=function(){this.url=n.location.href;this.beforeLoading=function(){};this.afterLoading=function(){};this.metaKeyIsPressed=false};a.PageAccelerator.prototype={_updateObject:function(t,e){var r=e.attributes;for(var n=0,a=r.length;n 5 | * http://github.com/EasyFood 6 | * License: MIT 7 | */ 8 | 9 | (function(global) { 10 | 11 | var M = global._PageAccelerator = global._PageAccelerator || {}; 12 | 13 | M.ajax = { 14 | get: function(url) { 15 | return new global.Promise(function(resolve, reject) { 16 | var req = new XMLHttpRequest(); 17 | req.open('GET', url, true); 18 | 19 | req.onload = function() { 20 | if (req.status >= 200 && req.status < 400) { 21 | resolve(req.response); 22 | return; 23 | } 24 | 25 | reject(req.response); 26 | }; 27 | 28 | req.onerror = function() { 29 | reject(Error('Network Error')); 30 | }; 31 | 32 | req.send(); 33 | }); 34 | } 35 | }; 36 | 37 | }(window)); 38 | -------------------------------------------------------------------------------- /src/page-accelerator.js: -------------------------------------------------------------------------------- 1 | /* 2 | * PageAccelerator - A solution to load web pages faster 3 | * http://github.com/EasyFood/PageAccelerator 4 | * author: Evandro Leopoldino Goncalves 5 | * http://github.com/EasyFood 6 | * License: MIT 7 | */ 8 | 9 | (function(global, factory) { 10 | 11 | /*global define: false*/ 12 | /*global exports: true*/ 13 | if (typeof exports === 'object' && exports) { 14 | factory(exports); // CommonJS 15 | } else if (typeof define === 'function' && define.amd) { 16 | define(['exports'], factory); // AMD 17 | } else { 18 | factory(global); // 17 | 18 | 19 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /test/spec-commonjs.js: -------------------------------------------------------------------------------- 1 | describe('commonjs', function() { 2 | describe('instance', function() { 3 | it('should add pageAccelerator in exports object', function() { 4 | expect(window.exports.pageAccelerator).to.be.an('function'); 5 | }); 6 | }); 7 | }); 8 | -------------------------------------------------------------------------------- /test/spec-default.js: -------------------------------------------------------------------------------- 1 | (function(doc) { 2 | 3 | describe('pageAccelerator', function() { 4 | 5 | var _find = function(value) { 6 | return doc.querySelector(value); 7 | }; 8 | 9 | var _click = function(el) { 10 | var ev = document.createEvent("MouseEvent"); 11 | ev.initMouseEvent( 12 | "click", 13 | true /* bubble */, true /* cancelable */, 14 | window, null, 15 | 0, 0, 0, 0, /* coordinates */ 16 | false, false, false, false, /* modifier keys */ 17 | 0 /*left*/, null 18 | ); 19 | el.dispatchEvent(ev); 20 | }; 21 | 22 | var _key = function(type, config) { 23 | var ev = document.createEvent('Event'); 24 | var bubbles = true, cancellable = true; 25 | 26 | ev.initEvent(type, bubbles, cancellable); 27 | 28 | for (var key in config) { 29 | ev[key] = config[key]; 30 | } 31 | 32 | window.dispatchEvent(ev); 33 | } 34 | 35 | describe('instance', function() { 36 | it('should exists pageAccelerator function', function() { 37 | expect(pageAccelerator).to.be.an('function'); 38 | }); 39 | 40 | it('should exists _PageAccelerator namespace', function() { 41 | expect(_PageAccelerator).to.be.an('object'); 42 | }); 43 | 44 | it('should exists ajax object on namespace', function() { 45 | expect(_PageAccelerator.ajax).to.be.an('object'); 46 | }); 47 | 48 | it('should exists get method on ajax object', function() { 49 | expect(_PageAccelerator.ajax.get).to.be.an('function'); 50 | }); 51 | }); 52 | 53 | describe('run', function() { 54 | pageAccelerator(); 55 | 56 | var verifyAjaxWasCalled = function(element, expected) { 57 | var wasCalled = false; 58 | 59 | _PageAccelerator.ajax.get = function(url) { 60 | wasCalled = true; 61 | 62 | return { 63 | then: function() { 64 | return { 65 | catch: function() {} 66 | } 67 | } 68 | } 69 | }; 70 | 71 | _click(element); 72 | 73 | expect(wasCalled).to.be[expected]; 74 | }; 75 | 76 | it('should call ajax method when user requests a new page', function() { 77 | verifyAjaxWasCalled(_find('#link_1'), 'true'); 78 | }); 79 | 80 | it('should not call ajax method when user requests a new page by a link with data-pageAccelerator="false"', function() { 81 | verifyAjaxWasCalled(_find('#link_2'), 'false'); 82 | }); 83 | 84 | it('should not call ajax method when user requests a new page on an external domain', function() { 85 | verifyAjaxWasCalled(_find('#link_3'), 'false'); 86 | }); 87 | 88 | it('should not call ajax method when user requests a new page by a link with href*="#"', function() { 89 | verifyAjaxWasCalled(_find('#link_4'), 'false'); 90 | }); 91 | 92 | it('should not call ajax method when link was clicked when meta key is pressed', function() { 93 | _key('keydown', { metaKey: true }); 94 | verifyAjaxWasCalled(_find('#link_1'), 'false'); 95 | }); 96 | 97 | it('should call ajax method when link was clicked when meta key is released', function() { 98 | _key('keyup', { metaKey: true }); 99 | verifyAjaxWasCalled(_find('#link_1'), 'true'); 100 | }); 101 | 102 | it('should not call ajax method when link was clicked when ctrl key is pressed', function() { 103 | _key('keydown', { ctrlKey: true }); 104 | verifyAjaxWasCalled(_find('#link_1'), 'false'); 105 | }); 106 | 107 | it('should call ajax method when link was clicked when meta ctrl is released', function() { 108 | _key('keyup', { ctrlKey: true }); 109 | verifyAjaxWasCalled(_find('#link_1'), 'true'); 110 | }); 111 | }); 112 | 113 | }); 114 | 115 | }(document)); 116 | --------------------------------------------------------------------------------