├── .npmignore ├── entry.js ├── src ├── modules │ ├── createAnimationPromise.js │ ├── getAnimation.js │ ├── renderPage.js │ └── loadPage.js └── index.js ├── .gitignore ├── .github ├── workflows │ └── npm-publish.yml └── ISSUE_TEMPLATE │ └── issue-template.md ├── package.json ├── webpack.config.js ├── LICENSE ├── readme.md └── dist ├── swupjs.min.js └── swupjs.js /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | entry.js 3 | webpack.config.js 4 | .idea 5 | .github 6 | -------------------------------------------------------------------------------- /entry.js: -------------------------------------------------------------------------------- 1 | // this is here for webpack to expose Swupjs as window.Swupjs 2 | import Swupjs from './src/index.js' 3 | module.exports = Swupjs -------------------------------------------------------------------------------- /src/modules/createAnimationPromise.js: -------------------------------------------------------------------------------- 1 | module.exports = function (fn) { 2 | return new Promise(resolve => { 3 | fn(resolve) 4 | }) 5 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.DS_Store 3 | !.gitignore 4 | !.htaccess 5 | !web.config 6 | node_modules 7 | bower_components 8 | Thumbs.db 9 | wiki-common 10 | wiki-images files 11 | wiki-wishlist 12 | *.sublime-project 13 | *.sublime-workspace 14 | .editorconfig 15 | .idea 16 | lib -------------------------------------------------------------------------------- /.github/workflows/npm-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow publishes a package to NPM 2 | 3 | name: Publish package 4 | 5 | on: 6 | release: 7 | types: [published] 8 | 9 | jobs: 10 | publish-npm: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | - uses: actions/setup-node@v1 15 | with: 16 | node-version: 12 17 | registry-url: https://registry.npmjs.org/ 18 | - run: npm ci 19 | - run: npm publish --access public 20 | env: 21 | NODE_AUTH_TOKEN: ${{secrets.npm_token}} 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Issue template 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe your issue**: 11 | Describe your issue here... 12 | 13 | **Swup config or any additional relevant code used**: 14 | 15 | ```javascript 16 | const swup = Swup(); 17 | ``` 18 | 19 | **Before creating this issue, did you think of...**: 20 | - [ ] Have you checked closed issues for similar/related problems. 21 | - [ ] Have you provided all helpful information available? 22 | - [ ] Have you considered creating a demo so we can help you better? 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "swupjs", 3 | "version": "1.7.1", 4 | "description": "Complete, flexible, easy to use page transition library - swup extension.", 5 | "main": "lib/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "compile": "babel --presets es2015,stage-0 -d lib/ src/", 9 | "build": "webpack-cli", 10 | "prepublish": "npm run compile" 11 | }, 12 | "author": "Georgy Marchuk", 13 | "license": "MIT", 14 | "repository": { 15 | "type": "git", 16 | "url": "https://github.com/gmrchk/swupjs.git" 17 | }, 18 | "keywords": [ 19 | "js", 20 | "animation", 21 | "page", 22 | "transition" 23 | ], 24 | "devDependencies": { 25 | "babel-cli": "^6.26.0", 26 | "babel-loader": "^7.1.4", 27 | "babel-preset-es2015": "^6.24.1", 28 | "babel-preset-stage-0": "^6.24.1", 29 | "uglifyjs-webpack-plugin": "^1.2.5", 30 | "webpack": "^4.8.3", 31 | "webpack-cli": "^5.0.1" 32 | }, 33 | "dependencies": { 34 | "swup": "^1.9.0" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin') 2 | 3 | module.exports = { 4 | mode: "production", 5 | entry: { 6 | "swupjs": "./entry.js", 7 | "swupjs.min": "./entry.js", 8 | }, 9 | output: { 10 | library: "Swupjs", 11 | libraryTarget: "umd", 12 | filename: "[name].js", 13 | }, 14 | module: { 15 | rules: [ 16 | { 17 | test: /\.js$/, 18 | loader: 'babel-loader', 19 | exclude: /node_modules/, 20 | options: { 21 | presets: ['es2015', 'stage-0'], 22 | } 23 | } 24 | ] 25 | }, 26 | optimization: { 27 | minimizer: [ 28 | // we specify a custom UglifyJsPlugin here to get source maps in production 29 | new UglifyJsPlugin({ 30 | uglifyOptions: { 31 | compress: false, 32 | ecma: 6, 33 | mangle: true 34 | }, 35 | include: /\.min\.js$/ 36 | }) 37 | ] 38 | } 39 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Georgy Marchuk 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 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import Swup from 'swup' 2 | 3 | // modules 4 | import loadPage from './modules/loadPage' 5 | import renderPage from './modules/renderPage' 6 | import getAnimation from './modules/getAnimation' 7 | import createAnimationPromise from './modules/createAnimationPromise' 8 | 9 | export default class Swupjs extends Swup { 10 | constructor(setOptions) { 11 | let defaults = { 12 | animations: { 13 | '*': { 14 | out: function (next) { 15 | next() 16 | }, 17 | in: function (next) { 18 | next() 19 | } 20 | } 21 | } 22 | } 23 | 24 | let options = { 25 | ...defaults, 26 | ...setOptions 27 | } 28 | 29 | super(options) 30 | 31 | this.animations = options.animations 32 | } 33 | 34 | /** 35 | * make modules accessible in instance 36 | */ 37 | loadPage = loadPage 38 | renderPage = renderPage 39 | getAnimation = getAnimation 40 | createAnimationPromise = createAnimationPromise 41 | } 42 | -------------------------------------------------------------------------------- /src/modules/getAnimation.js: -------------------------------------------------------------------------------- 1 | module.exports = function (transition, animations, type) { 2 | 3 | let animation = null 4 | let animationName = null 5 | let topRating = 0 6 | 7 | Object.keys(animations).forEach(item => { 8 | let rating = 0 9 | if (item.includes('>')) { 10 | let route = item.split('>') 11 | let from = route[0] 12 | let to = route[1] 13 | 14 | // TO equals to TO 15 | if (to == transition.to || to == "*") { 16 | rating++ 17 | } 18 | 19 | // equals to CUSTOM animation 20 | if (to == transition.custom) { 21 | rating=rating+2 22 | } 23 | 24 | // FROM equals or is ANY 25 | if (from == transition.from || from == "*") { 26 | rating++ 27 | } 28 | } 29 | 30 | // set new final animation 31 | if (rating > topRating) { 32 | topRating = rating 33 | animationName = item 34 | animation = animations[item] 35 | } 36 | }) 37 | 38 | if (animation == null || topRating == 1) { 39 | animation = animations['*'] 40 | animationName = '*' 41 | } 42 | 43 | return animation[type] 44 | } -------------------------------------------------------------------------------- /src/modules/renderPage.js: -------------------------------------------------------------------------------- 1 | const { forEach } = Array.prototype; 2 | import Link from 'swup/lib/Link'; 3 | 4 | module.exports = function (page, popstate) { 5 | document.documentElement.classList.remove('is-leaving') 6 | 7 | // replace state in case the url was redirected 8 | let link = new Link() 9 | link.setPath(page.responseURL) 10 | 11 | if (window.location.pathname !== link.getPath()) { 12 | window.history.replaceState({ 13 | url: link.getPath(), 14 | random: Math.random(), 15 | source: "swup", 16 | }, 17 | document.title, 18 | link.getPath(), 19 | ); 20 | } 21 | 22 | if (!popstate || this.options.animateHistoryBrowsing) { 23 | document.documentElement.classList.add('is-rendering') 24 | } 25 | 26 | this.triggerEvent('willReplaceContent'); 27 | 28 | // replace blocks 29 | for (var i = 0; i < page.blocks.length; i++) { 30 | document.body.querySelector(`[data-swup="${i}"]`).outerHTML = page.blocks[i] 31 | } 32 | 33 | // set title 34 | document.title = page.title; 35 | 36 | // handle classes after render 37 | // remove 38 | if (this.options.pageClassPrefix !== false) { 39 | document.body.className.split(' ').forEach(className => { 40 | // empty string for page class 41 | if (className != "" && className.includes(this.options.pageClassPrefix)) { 42 | document.body.classList.remove(className) 43 | } 44 | }) 45 | } 46 | 47 | // add 48 | if (page.pageClass != "") { 49 | page.pageClass.split(' ').forEach(className => { 50 | if (className != "" && className.includes(this.options.pageClassPrefix)) { 51 | document.body.classList.add(className) 52 | } 53 | }) 54 | } 55 | 56 | this.triggerEvent('contentReplaced') 57 | this.triggerEvent('pageView') 58 | 59 | if (!this.options.cache) { 60 | this.cache.empty(this.options.debugMode) 61 | } 62 | 63 | // scrolling 64 | if (!this.options.doScrollingRightAway || this.scrollToElement) { 65 | this.doScrolling(popstate) 66 | } 67 | 68 | // detect animation end 69 | let animationPromises = [] 70 | if (!popstate || this.options.animateHistoryBrowsing) { 71 | this.triggerEvent('animationInStart') 72 | let animationPromise = this.createAnimationPromise(this.getAnimation(this.transition, this.animations, 'in')) 73 | animationPromises.push(animationPromise) 74 | } 75 | 76 | //preload pages if possible 77 | this.preloadPages() 78 | 79 | if (!popstate || this.options.animateHistoryBrowsing) { 80 | Promise 81 | .all(animationPromises) 82 | .then(() => { 83 | this.triggerEvent('animationInDone') 84 | // remove "to-{page}" classes 85 | document.documentElement.className.split(' ').forEach(classItem => { 86 | if (new RegExp("^to-").test(classItem) || classItem === "is-changing" || classItem === "is-rendering" || classItem === "is-popstate") { 87 | document.documentElement.classList.remove(classItem); 88 | } 89 | }) 90 | }) 91 | } 92 | 93 | // update current url 94 | this.getUrl() 95 | // reset scroll-to element 96 | this.scrollToElement = null 97 | } -------------------------------------------------------------------------------- /src/modules/loadPage.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function (data, popstate) { 3 | // scrolling 4 | if (this.options.doScrollingRightAway && !this.scrollToElement) { 5 | this.doScrolling(popstate) 6 | } 7 | 8 | // create array for storing animation promises 9 | let animationPromises = [] 10 | 11 | // set transition object 12 | if (data.customTransition != null) { 13 | this.updateTransition(window.location.pathname, data.url, data.customTransition) 14 | document.documentElement.classList.add(`to-${ this.classify(data.customTransition) }`) 15 | } else { 16 | this.updateTransition(window.location.pathname, data.url) 17 | } 18 | 19 | if (!popstate || this.options.animateHistoryBrowsing) { 20 | // start animation 21 | this.triggerEvent('animationOutStart') 22 | document.documentElement.classList.add('is-changing') 23 | document.documentElement.classList.add('is-leaving') 24 | if (popstate) { 25 | document.documentElement.classList.add('is-popstate') 26 | } 27 | document.documentElement.classList.add('to-' + this.classify(data.url)) 28 | 29 | // animation promise 30 | let animationPromise = this.createAnimationPromise(this.getAnimation(this.transition, this.animations, 'out')) 31 | animationPromises.push(animationPromise) 32 | 33 | Promise 34 | .all(animationPromises) 35 | .then(() => { 36 | this.triggerEvent('animationOutDone') 37 | }) 38 | 39 | // create pop element with or without anchor 40 | if (this.scrollToElement != null) { 41 | var pop = data.url + this.scrollToElement; 42 | } else { 43 | var pop = data.url; 44 | } 45 | if(!popstate) 46 | this.createState(pop) 47 | } else { 48 | // proceed without animating 49 | this.triggerEvent('animationSkipped') 50 | } 51 | 52 | if (this.cache.exists(data.url)) { 53 | var xhrPromise = new Promise(resolve => { 54 | resolve() 55 | }) 56 | this.triggerEvent('pageRetrievedFromCache') 57 | } else { 58 | if (!this.preloadPromise || this.preloadPromise.route != data.url) { 59 | var xhrPromise = new Promise((resolve, reject) => { 60 | this.getPage(data, (response, request) => { 61 | if (request.status === 500) { 62 | this.triggerEvent('serverError') 63 | reject(data.url) 64 | return; 65 | } else { 66 | // get json data 67 | var page = this.getDataFromHtml(response, request) 68 | if (page != null) { 69 | page.url = data.url 70 | } else { 71 | reject(data.url) 72 | return; 73 | } 74 | // render page 75 | this.cache.cacheUrl(page, this.options.debugMode) 76 | this.triggerEvent('pageLoaded') 77 | } 78 | resolve() 79 | }) 80 | }) 81 | } else { 82 | var xhrPromise = this.preloadPromise 83 | } 84 | } 85 | 86 | Promise 87 | .all(animationPromises.concat([xhrPromise])) 88 | .then(() => { 89 | this.renderPage(this.cache.getPage(data.url), popstate) 90 | this.preloadPromise = null 91 | }) 92 | .catch(errorUrl => { 93 | // rewrite the skipPopStateHandling function to redirect manually when the history.go is processed 94 | this.options.skipPopStateHandling = function () { 95 | window.location = errorUrl 96 | return true 97 | } 98 | 99 | // go back to the actual page were still at 100 | window.history.go(-1) 101 | }); 102 | } -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # swupjs 2 | 3 | | WARNING: this repository is deprecated in favour of [JS-plugin](https://swup.js.org/plugins/js-plugin) | 4 | | --- | 5 | 6 | Swupjs is an extension of [swup](https://github.com/gmrchk/swup), which modifies the module for use with JavaScript animations. 7 | 8 | Swupjs only slightly modifies swup, where all the capabilities of swup remain the same, with only one exception - timing and animations are based on JavaScript, not CSS transitions. 9 | For more information about functionality and idea of swupjs, refer to [swup](https://github.com/gmrchk/swup) documentation. 10 | 11 | ## Installation 12 | ```bash 13 | npm install swupjs 14 | ``` 15 | 16 | or include the file from the dist folder 17 | 18 | ```html 19 | 20 | ``` 21 | 22 | ## How it works 23 | Swupjs is enabled similarly as swup. 24 | ```javascript 25 | let options = {} 26 | const swupjs = new Swupjs(options) 27 | ``` 28 | 29 | ## Animations option 30 | To use your animations for page transitions, you first need to define the animation object. 31 | 32 | ```javascript 33 | animations: { 34 | '*': { 35 | out: function (next) { 36 | next() 37 | }, 38 | in: function (next) { 39 | next() 40 | } 41 | } 42 | } 43 | ``` 44 | 45 | The example above is the default setup in swupjs and defines two animations, where **out** is the animation (function) being executed before content replace, and **in** is animation being executed after the content is replaced. 46 | As one may have noticed, one parameter is passed into both functions. 47 | Call of `next` function serves as an indicator, that animation is done - so in a real world `next()` would be called as a callback of the animation. 48 | As you can see, by default no animation is being executed and `next()` is called right away. 49 | 50 | **Note:** Although the whole purpose of swup is to enable page transitions, this can still enhance your user experience even without the animation as it can shorten your load time drastically when preload and/or cache options are set to `true`. In most cases, your page change should be immediate without any wait time. 51 | 52 | ```javascript 53 | out: function (next) { 54 | setTimeout(next, 2000) 55 | } 56 | ``` 57 | In the example above, next function is called after two seconds, which means that swupjs would wait two seconds (or any time necessary for the load of the new page content), before continuing to the content replace. 58 | 59 | Animation object needs to be passed as a part of your options. 60 | 61 | ```javascript 62 | let options = { 63 | animations: { 64 | '*': { 65 | out: function (next) { 66 | next() 67 | }, 68 | in: function (next) { 69 | next() 70 | } 71 | } 72 | } 73 | } 74 | const swupjs = new Swupjs(options) 75 | ``` 76 | 77 | Basic usage with tools like GSAP would look something like the following: 78 | ```javascript 79 | let options = { 80 | animations: { 81 | '*': { 82 | in: function(next){ 83 | document.querySelector('#swup').style.opacity = 0; 84 | TweenLite.to(document.querySelector('#swup'), .5, { 85 | opacity: 1, 86 | onComplete: next 87 | }); 88 | }, 89 | out: function(next){ 90 | document.querySelector('#swup').style.opacity = 1; 91 | TweenLite.to(document.querySelector('#swup'), .5, { 92 | opacity: 0, 93 | onComplete: next 94 | }); 95 | } 96 | }, 97 | } 98 | } 99 | 100 | const swupjs = new Swupjs(options); 101 | ``` 102 | 103 | 104 | ## Choosing the animation 105 | As one may have noticed, the name of animation object in options is defined as `'*'`, which serves as a fallback or base set of animations used throughout the website. 106 | Custom animations can be defined for a transition between any pages, where the name is defined by `[starting route]>[final route]`. 107 | 108 | ```javascript 109 | ... 110 | 'homepage>documentation': { 111 | out: function (next) { 112 | next() 113 | }, 114 | in: function (next) { 115 | next() 116 | } 117 | } 118 | ... 119 | ``` 120 | 121 | The animation above would be executed for the transition between homepage (/) and documentation page (/documentation). 122 | Notice that for the lack of route, keyword "homepage" is used. 123 | Any of the two routes can also be defined by wildcard symbol (`homepage>*` or `*>documentation`). 124 | The most fitting animation is always chosen. 125 | 126 | ## Custom animation to dynamic pages 127 | Similarly to swup, where `data-swup-transition` attribute of the clicked link is used for assigning a special class to the html tag, swupjs uses the same attribute for choosing custom animation. 128 | In case the attribute is defined on clicked link, swupjs also tests the animation object for the content of the data attribute. 129 | So following attribute `data-swup-transition="post"` would end up in `*>post` being executed. 130 | 131 | ```javascript 132 | ... 133 | '*': { 134 | ... 135 | }, 136 | '*>documentation': { 137 | ... 138 | }, 139 | '*>post': { 140 | ... 141 | } 142 | ... 143 | ``` 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /dist/swupjs.min.js: -------------------------------------------------------------------------------- 1 | (function e(t,n){if(typeof exports==="object"&&typeof module==="object")module.exports=n();else if(typeof define==="function"&&define.amd)define([],n);else if(typeof exports==="object")exports["Swupjs"]=n();else t["Swupjs"]=n()})(window,function(){return function(e){var t={};function n(i){if(t[i]){return t[i].exports}var o=t[i]={i,l:false,exports:{}};e[i].call(o.exports,o,o.exports,n);o.l=true;return o.exports}n.m=e;n.c=t;n.d=function(e,t,i){if(!n.o(e,t)){Object.defineProperty(e,t,{configurable:false,enumerable:true,get:i})}};n.r=function(e){Object.defineProperty(e,"__esModule",{value:true})};n.n=function(e){var t=e&&e.__esModule?function t(){return e["default"]}:function t(){return e};n.d(t,"a",t);return t};n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};n.p="";return n(n.s=30)}([function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:true});t.query=i;t.queryAll=o;function i(e){var t=arguments.length>1&&arguments[1]!==undefined?arguments[1]:document;if(typeof e!=="string"){return e}return t.querySelector(e)}function o(e){var t=arguments.length>1&&arguments[1]!==undefined?arguments[1]:document;if(typeof e!=="string"){return e}return Array.prototype.slice.call(t.querySelectorAll(e))}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:true});var i=function(){function e(e,t){for(var n=0;n")){var a=n.split(">");var l=a[0];var u=a[1];if(u==e.to||u=="*"){s++}if(u==e.custom){s=s+2}if(l==e.from||l=="*"){s++}}if(s>r){r=s;o=n;i=t[n]}});if(i==null||r==1){i=t["*"];o="*"}return i[n]}},function(e,t,n){"use strict";var i=n(1);var o=r(i);function r(e){return e&&e.__esModule?e:{default:e}}var s=Array.prototype.forEach;e.exports=function(e,t){var n=this;document.documentElement.classList.remove("is-leaving");var i=new o.default;i.setPath(e.responseURL);if(window.location.pathname!==i.getPath()){window.history.replaceState({url:i.getPath(),random:Math.random(),source:"swup"},document.title,i.getPath())}if(!t||this.options.animateHistoryBrowsing){document.documentElement.classList.add("is-rendering")}this.triggerEvent("willReplaceContent");for(var r=0;r-1){this._handlers[t].splice(r,1)}}else{console.warn("Handler for event '"+t+"' no found.")}}else{this._handlers[t]=[]}}else{Object.keys(this._handlers).forEach(function(e){i._handlers[e]=[]})}}},function(e,t,n){"use strict";e.exports=function e(t,n){if(this._handlers[t]){this._handlers[t].push(n)}else{console.warn("Unsupported event "+t+".")}}},function(e,t,n){"use strict";var i=n(0);e.exports=function(e){var t=this;var n=0;for(var o=0;o2&&arguments[2]!==undefined?arguments[2]:this.options.animateScroll;var o=1-this.options.scrollFriction;var r=this.options.scrollAcceleration;var s=0;var a=0;var l=0;var u=0;var c=0;var d=null;function f(){return document.body.scrollTop||document.documentElement.scrollTop}var h=function e(){var t=p();m();if(c===1&&l>s||c===-1&&lt?-1:1;u=t+c;l=t;a=0;if(s!=l){h()}else{n.triggerEvent("scrollDone")}};this.triggerEvent("scrollStart");if(i==0){window.scrollTo(0,t);this.triggerEvent("scrollDone")}else{v(t)}}},function(e,t,n){"use strict";e.exports=function(){this.currentUrl=window.location.pathname+window.location.search}},function(e,t,n){"use strict";e.exports=function(e,t){if(this.options.debugMode&&t){console.groupCollapsed("%cswup:"+"%c"+e,"color: #343434","color: #009ACD");console.log(t);console.groupEnd()}else if(this.options.debugMode){console.log("%cswup:"+"%c"+e,"color: #343434","color: #009ACD")}this._handlers[e].forEach(function(e){try{e(t)}catch(e){console.error(e)}});var n=new CustomEvent("swup:"+e,{detail:e});document.dispatchEvent(n)}},function(e,t,n){"use strict";e.exports=function(e){window.history.pushState({url:e||window.location.href.split(window.location.hostname)[1],random:Math.random(),source:"swup"},document.getElementsByTagName("title")[0].innerText,e||window.location.href.split(window.location.hostname)[1])}},function(e,t,n){"use strict";var i=n(0);var o=n(1);var r=s(o);function s(e){return e&&e.__esModule?e:{default:e}}var a=Array.prototype.forEach;e.exports=function(e,t){var n=this;document.documentElement.classList.remove("is-leaving");var o=new r.default;o.setPath(e.responseURL);if(window.location.pathname!==o.getPath()){window.history.replaceState({url:o.getPath(),random:Math.random(),source:"swup"},document.title,o.getPath())}if(!t||this.options.animateHistoryBrowsing){document.documentElement.classList.add("is-rendering")}this.triggerEvent("willReplaceContent");for(var s=0;s","");var r=document.createElement("div");r.innerHTML=o;var s=[];for(var a=0;a1&&arguments[1]!==undefined?arguments[1]:false;var n={url:window.location.pathname+window.location.search,method:"GET",data:null};var o=i({},n,e);var r=new XMLHttpRequest;r.onreadystatechange=function(){if(r.readyState===4){if(r.status!==500){t(r.responseText,r)}else{t(null,r)}}};r.open(o.method,o.url,true);r.setRequestHeader("X-Requested-With","swup");r.send(o.data);return r}},function(e,t,n){"use strict";e.exports=function e(){var t=document.createElement("div");var n={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var i in n){if(t.style[i]!==undefined){return n[i]}}return false}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:true});var i=function(){function e(e,t){for(var n=0;n 1 && arguments[1] !== undefined ? arguments[1] : document; 96 | 97 | if (typeof selector !== 'string') { 98 | return selector; 99 | } 100 | 101 | return context.querySelector(selector); 102 | } 103 | 104 | function queryAll(selector) { 105 | var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document; 106 | 107 | if (typeof selector !== 'string') { 108 | return selector; 109 | } 110 | 111 | return Array.prototype.slice.call(context.querySelectorAll(selector)); 112 | } 113 | 114 | /***/ }), 115 | /* 1 */ 116 | /***/ (function(module, exports, __webpack_require__) { 117 | 118 | "use strict"; 119 | 120 | 121 | Object.defineProperty(exports, "__esModule", { 122 | value: true 123 | }); 124 | 125 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 126 | 127 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 128 | 129 | var Link = function () { 130 | function Link() { 131 | _classCallCheck(this, Link); 132 | 133 | this.link = document.createElement("a"); 134 | } 135 | 136 | _createClass(Link, [{ 137 | key: 'setPath', 138 | value: function setPath(href) { 139 | this.link.href = href; 140 | } 141 | }, { 142 | key: 'getPath', 143 | value: function getPath() { 144 | var path = this.link.pathname; 145 | if (path[0] != '/') { 146 | path = '/' + path; 147 | } 148 | return path; 149 | } 150 | }, { 151 | key: 'getAddress', 152 | value: function getAddress() { 153 | var path = this.link.pathname + this.link.search; 154 | if (path[0] != '/') { 155 | path = '/' + path; 156 | } 157 | return path; 158 | } 159 | }, { 160 | key: 'getHash', 161 | value: function getHash() { 162 | return this.link.hash; 163 | } 164 | }]); 165 | 166 | return Link; 167 | }(); 168 | 169 | exports.default = Link; 170 | 171 | /***/ }), 172 | /* 2 */ 173 | /***/ (function(module, exports, __webpack_require__) { 174 | 175 | "use strict"; 176 | 177 | 178 | module.exports = function (fn) { 179 | return new Promise(function (resolve) { 180 | fn(resolve); 181 | }); 182 | }; 183 | 184 | /***/ }), 185 | /* 3 */ 186 | /***/ (function(module, exports, __webpack_require__) { 187 | 188 | "use strict"; 189 | 190 | 191 | module.exports = function (transition, animations, type) { 192 | 193 | var animation = null; 194 | var animationName = null; 195 | var topRating = 0; 196 | 197 | Object.keys(animations).forEach(function (item) { 198 | var rating = 0; 199 | if (item.includes('>')) { 200 | var route = item.split('>'); 201 | var from = route[0]; 202 | var to = route[1]; 203 | 204 | // TO equals to TO 205 | if (to == transition.to || to == "*") { 206 | rating++; 207 | } 208 | 209 | // equals to CUSTOM animation 210 | if (to == transition.custom) { 211 | rating = rating + 2; 212 | } 213 | 214 | // FROM equals or is ANY 215 | if (from == transition.from || from == "*") { 216 | rating++; 217 | } 218 | } 219 | 220 | // set new final animation 221 | if (rating > topRating) { 222 | topRating = rating; 223 | animationName = item; 224 | animation = animations[item]; 225 | } 226 | }); 227 | 228 | if (animation == null || topRating == 1) { 229 | animation = animations['*']; 230 | animationName = '*'; 231 | } 232 | 233 | return animation[type]; 234 | }; 235 | 236 | /***/ }), 237 | /* 4 */ 238 | /***/ (function(module, exports, __webpack_require__) { 239 | 240 | "use strict"; 241 | 242 | 243 | var _Link = __webpack_require__(1); 244 | 245 | var _Link2 = _interopRequireDefault(_Link); 246 | 247 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 248 | 249 | var forEach = Array.prototype.forEach; 250 | 251 | 252 | module.exports = function (page, popstate) { 253 | var _this = this; 254 | 255 | document.documentElement.classList.remove('is-leaving'); 256 | 257 | // replace state in case the url was redirected 258 | var link = new _Link2.default(); 259 | link.setPath(page.responseURL); 260 | 261 | if (window.location.pathname !== link.getPath()) { 262 | window.history.replaceState({ 263 | url: link.getPath(), 264 | random: Math.random(), 265 | source: "swup" 266 | }, document.title, link.getPath()); 267 | } 268 | 269 | if (!popstate || this.options.animateHistoryBrowsing) { 270 | document.documentElement.classList.add('is-rendering'); 271 | } 272 | 273 | this.triggerEvent('willReplaceContent'); 274 | 275 | // replace blocks 276 | for (var i = 0; i < page.blocks.length; i++) { 277 | document.body.querySelector('[data-swup="' + i + '"]').outerHTML = page.blocks[i]; 278 | } 279 | 280 | // set title 281 | document.title = page.title; 282 | 283 | // handle classes after render 284 | // remove 285 | if (this.options.pageClassPrefix !== false) { 286 | document.body.className.split(' ').forEach(function (className) { 287 | // empty string for page class 288 | if (className != "" && className.includes(_this.options.pageClassPrefix)) { 289 | document.body.classList.remove(className); 290 | } 291 | }); 292 | } 293 | 294 | // add 295 | if (page.pageClass != "") { 296 | page.pageClass.split(' ').forEach(function (className) { 297 | if (className != "" && className.includes(_this.options.pageClassPrefix)) { 298 | document.body.classList.add(className); 299 | } 300 | }); 301 | } 302 | 303 | this.triggerEvent('contentReplaced'); 304 | this.triggerEvent('pageView'); 305 | 306 | if (!this.options.cache) { 307 | this.cache.empty(this.options.debugMode); 308 | } 309 | 310 | // scrolling 311 | if (!this.options.doScrollingRightAway || this.scrollToElement) { 312 | this.doScrolling(popstate); 313 | } 314 | 315 | // detect animation end 316 | var animationPromises = []; 317 | if (!popstate || this.options.animateHistoryBrowsing) { 318 | this.triggerEvent('animationInStart'); 319 | var animationPromise = this.createAnimationPromise(this.getAnimation(this.transition, this.animations, 'in')); 320 | animationPromises.push(animationPromise); 321 | } 322 | 323 | //preload pages if possible 324 | this.preloadPages(); 325 | 326 | if (!popstate || this.options.animateHistoryBrowsing) { 327 | Promise.all(animationPromises).then(function () { 328 | _this.triggerEvent('animationInDone'); 329 | // remove "to-{page}" classes 330 | document.documentElement.className.split(' ').forEach(function (classItem) { 331 | if (new RegExp("^to-").test(classItem) || classItem === "is-changing" || classItem === "is-rendering" || classItem === "is-popstate") { 332 | document.documentElement.classList.remove(classItem); 333 | } 334 | }); 335 | }); 336 | } 337 | 338 | // update current url 339 | this.getUrl(); 340 | // reset scroll-to element 341 | this.scrollToElement = null; 342 | }; 343 | 344 | /***/ }), 345 | /* 5 */ 346 | /***/ (function(module, exports, __webpack_require__) { 347 | 348 | "use strict"; 349 | 350 | 351 | module.exports = function (data, popstate) { 352 | var _this = this; 353 | 354 | // scrolling 355 | if (this.options.doScrollingRightAway && !this.scrollToElement) { 356 | this.doScrolling(popstate); 357 | } 358 | 359 | // create array for storing animation promises 360 | var animationPromises = []; 361 | 362 | // set transition object 363 | if (data.customTransition != null) { 364 | this.updateTransition(window.location.pathname, data.url, data.customTransition); 365 | document.documentElement.classList.add('to-' + this.classify(data.customTransition)); 366 | } else { 367 | this.updateTransition(window.location.pathname, data.url); 368 | } 369 | 370 | if (!popstate || this.options.animateHistoryBrowsing) { 371 | // start animation 372 | this.triggerEvent('animationOutStart'); 373 | document.documentElement.classList.add('is-changing'); 374 | document.documentElement.classList.add('is-leaving'); 375 | if (popstate) { 376 | document.documentElement.classList.add('is-popstate'); 377 | } 378 | document.documentElement.classList.add('to-' + this.classify(data.url)); 379 | 380 | // animation promise 381 | var animationPromise = this.createAnimationPromise(this.getAnimation(this.transition, this.animations, 'out')); 382 | animationPromises.push(animationPromise); 383 | 384 | Promise.all(animationPromises).then(function () { 385 | _this.triggerEvent('animationOutDone'); 386 | }); 387 | 388 | // create pop element with or without anchor 389 | if (this.scrollToElement != null) { 390 | var pop = data.url + this.scrollToElement; 391 | } else { 392 | var pop = data.url; 393 | } 394 | if (!popstate) this.createState(pop); 395 | } else { 396 | // proceed without animating 397 | this.triggerEvent('animationSkipped'); 398 | } 399 | 400 | if (this.cache.exists(data.url)) { 401 | var xhrPromise = new Promise(function (resolve) { 402 | resolve(); 403 | }); 404 | this.triggerEvent('pageRetrievedFromCache'); 405 | } else { 406 | if (!this.preloadPromise || this.preloadPromise.route != data.url) { 407 | var xhrPromise = new Promise(function (resolve, reject) { 408 | _this.getPage(data, function (response, request) { 409 | if (request.status === 500) { 410 | _this.triggerEvent('serverError'); 411 | reject(data.url); 412 | return; 413 | } else { 414 | // get json data 415 | var page = _this.getDataFromHtml(response, request); 416 | if (page != null) { 417 | page.url = data.url; 418 | } else { 419 | reject(data.url); 420 | return; 421 | } 422 | // render page 423 | _this.cache.cacheUrl(page, _this.options.debugMode); 424 | _this.triggerEvent('pageLoaded'); 425 | } 426 | resolve(); 427 | }); 428 | }); 429 | } else { 430 | var xhrPromise = this.preloadPromise; 431 | } 432 | } 433 | 434 | Promise.all(animationPromises.concat([xhrPromise])).then(function () { 435 | _this.renderPage(_this.cache.getPage(data.url), popstate); 436 | _this.preloadPromise = null; 437 | }).catch(function (errorUrl) { 438 | // rewrite the skipPopStateHandling function to redirect manually when the history.go is processed 439 | _this.options.skipPopStateHandling = function () { 440 | window.location = errorUrl; 441 | return true; 442 | }; 443 | 444 | // go back to the actual page were still at 445 | window.history.go(-1); 446 | }); 447 | }; 448 | 449 | /***/ }), 450 | /* 6 */ 451 | /***/ (function(module, exports, __webpack_require__) { 452 | 453 | "use strict"; 454 | 455 | 456 | module.exports = function (str) { 457 | if (this.options.debugMode) { 458 | console.log(str + '%c', 'color: #009ACD'); 459 | } 460 | }; 461 | 462 | /***/ }), 463 | /* 7 */ 464 | /***/ (function(module, exports, __webpack_require__) { 465 | 466 | "use strict"; 467 | 468 | 469 | module.exports = function (plugin, options) { 470 | var _this = this; 471 | 472 | options = Object.assign({}, plugin.options, options); 473 | 474 | plugin.options = options; 475 | 476 | var getCurrentPageHtml = function getCurrentPageHtml() { 477 | var page = _this.cache.getPage(window.location.pathname + window.location.search); 478 | var html = document.createElement('html'); 479 | html.innerHTML = page.originalContent; 480 | return html; 481 | }; 482 | 483 | this.plugins.push(plugin); 484 | plugin.exec(options, this, getCurrentPageHtml); 485 | return this.plugins; 486 | }; 487 | 488 | /***/ }), 489 | /* 8 */ 490 | /***/ (function(module, exports, __webpack_require__) { 491 | 492 | "use strict"; 493 | 494 | 495 | var _utils = __webpack_require__(0); 496 | 497 | module.exports = function () { 498 | var _this = this; 499 | 500 | if (this.options.preload) { 501 | (0, _utils.queryAll)('[data-swup-preload]').forEach(function (element) { 502 | _this.preloadPage(element.href); 503 | }); 504 | } 505 | }; 506 | 507 | /***/ }), 508 | /* 9 */ 509 | /***/ (function(module, exports, __webpack_require__) { 510 | 511 | "use strict"; 512 | 513 | 514 | var _Link = __webpack_require__(1); 515 | 516 | var _Link2 = _interopRequireDefault(_Link); 517 | 518 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 519 | 520 | module.exports = function (pathname) { 521 | var _this = this; 522 | 523 | var link = new _Link2.default(); 524 | link.setPath(pathname); 525 | return new Promise(function (resolve, reject) { 526 | if (link.getAddress() != _this.currentUrl && !_this.cache.exists(link.getAddress())) { 527 | _this.getPage({ url: link.getAddress() }, function (response, request) { 528 | if (request.status === 500) { 529 | _this.triggerEvent('serverError'); 530 | reject(); 531 | } else { 532 | // get json data 533 | var page = _this.getDataFromHtml(response, request); 534 | if (page != null) { 535 | page.url = link.getAddress(); 536 | _this.cache.cacheUrl(page, _this.options.debugMode); 537 | _this.triggerEvent('pagePreloaded'); 538 | } 539 | resolve(_this.cache.getPage(link.getAddress())); 540 | } 541 | }); 542 | } else { 543 | resolve(_this.cache.getPage(link.getAddress())); 544 | } 545 | }); 546 | }; 547 | 548 | /***/ }), 549 | /* 10 */ 550 | /***/ (function(module, exports, __webpack_require__) { 551 | 552 | "use strict"; 553 | 554 | 555 | module.exports = function (from, to, custom) { 556 | 557 | // homepage case 558 | if (from == "/") { 559 | from = "/homepage"; 560 | } 561 | if (to == "/") { 562 | to = "/homepage"; 563 | } 564 | 565 | // transition routes 566 | this.transition = { 567 | from: from.replace('/', ''), 568 | to: to.replace('/', '') 569 | }; 570 | 571 | if (custom) { 572 | this.transition.custom = custom; 573 | } 574 | }; 575 | 576 | /***/ }), 577 | /* 11 */ 578 | /***/ (function(module, exports, __webpack_require__) { 579 | 580 | "use strict"; 581 | 582 | 583 | module.exports = function off(event, handler) { 584 | var _this = this; 585 | 586 | if (event != null) { 587 | if (handler != null) { 588 | if (this._handlers[event] && this._handlers[event].filter(function (savedHandler) { 589 | return savedHandler === handler; 590 | }).length) { 591 | var toRemove = this._handlers[event].filter(function (savedHandler) { 592 | return savedHandler === handler; 593 | })[0]; 594 | var index = this._handlers[event].indexOf(toRemove); 595 | if (index > -1) { 596 | this._handlers[event].splice(index, 1); 597 | } 598 | } else { 599 | console.warn("Handler for event '" + event + "' no found."); 600 | } 601 | } else { 602 | this._handlers[event] = []; 603 | } 604 | } else { 605 | Object.keys(this._handlers).forEach(function (keys) { 606 | _this._handlers[keys] = []; 607 | }); 608 | } 609 | }; 610 | 611 | /***/ }), 612 | /* 12 */ 613 | /***/ (function(module, exports, __webpack_require__) { 614 | 615 | "use strict"; 616 | 617 | 618 | module.exports = function on(event, handler) { 619 | if (this._handlers[event]) { 620 | this._handlers[event].push(handler); 621 | } else { 622 | console.warn("Unsupported event " + event + "."); 623 | } 624 | }; 625 | 626 | /***/ }), 627 | /* 13 */ 628 | /***/ (function(module, exports, __webpack_require__) { 629 | 630 | "use strict"; 631 | 632 | 633 | var _utils = __webpack_require__(0); 634 | 635 | module.exports = function (element) { 636 | var _this = this; 637 | 638 | var blocks = 0; 639 | 640 | for (var i = 0; i < this.options.elements.length; i++) { 641 | if (element.querySelector(this.options.elements[i]) == null) { 642 | console.warn("Element " + this.options.elements[i] + " is not in current page."); 643 | } else { 644 | (0, _utils.queryAll)(this.options.elements[i]).forEach(function (item, index) { 645 | (0, _utils.queryAll)(_this.options.elements[i], element)[index].dataset.swup = blocks; 646 | blocks++; 647 | }); 648 | } 649 | } 650 | }; 651 | 652 | /***/ }), 653 | /* 14 */ 654 | /***/ (function(module, exports, __webpack_require__) { 655 | 656 | "use strict"; 657 | 658 | 659 | module.exports = function (popstate) { 660 | if (this.options.scroll && (!popstate || this.options.animateHistoryBrowsing)) { 661 | if (this.scrollToElement != null) { 662 | var element = document.querySelector(this.scrollToElement); 663 | if (element != null) { 664 | var top = element.getBoundingClientRect().top + window.pageYOffset; 665 | this.scrollTo(document.body, top); 666 | } else { 667 | console.warn("Element for offset not found (" + this.scrollToElement + ")"); 668 | } 669 | this.scrollToElement = null; 670 | } else { 671 | this.scrollTo(document.body, 0); 672 | } 673 | } 674 | }; 675 | 676 | /***/ }), 677 | /* 15 */ 678 | /***/ (function(module, exports, __webpack_require__) { 679 | 680 | "use strict"; 681 | 682 | 683 | module.exports = function (text) { 684 | var output = text.toString().toLowerCase().replace(/\s+/g, '-') // Replace spaces with - 685 | .replace(/\//g, '-') // Replace / with - 686 | .replace(/[^\w\-]+/g, '') // Remove all non-word chars 687 | .replace(/\-\-+/g, '-') // Replace multiple - with single - 688 | .replace(/^-+/, '') // Trim - from start of text 689 | .replace(/-+$/, ''); // Trim - from end of text 690 | if (output[0] == "/") output = output.splice(1); 691 | if (output == '') output = 'homepage'; 692 | return output; 693 | }; 694 | 695 | /***/ }), 696 | /* 16 */ 697 | /***/ (function(module, exports, __webpack_require__) { 698 | 699 | "use strict"; 700 | 701 | 702 | module.exports = function (element, to) { 703 | var _this = this; 704 | 705 | var animatedScroll = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this.options.animateScroll; 706 | 707 | var friction = 1 - this.options.scrollFriction; 708 | var acceleration = this.options.scrollAcceleration; 709 | 710 | var positionY = 0; 711 | var velocityY = 0; 712 | var targetPositionY = 0; 713 | var targetPositionYWithOffset = 0; 714 | var direction = 0; 715 | 716 | var raf = null; 717 | 718 | function getScrollTop() { 719 | return document.body.scrollTop || document.documentElement.scrollTop; 720 | } 721 | 722 | var animate = function animate() { 723 | var distance = update(); 724 | render(); 725 | 726 | if (direction === 1 && targetPositionY > positionY || direction === -1 && targetPositionY < positionY) { 727 | raf = requestAnimationFrame(animate); 728 | } else { 729 | window.scrollTo(0, targetPositionY); 730 | _this.triggerEvent('scrollDone'); 731 | } 732 | }; 733 | 734 | function update() { 735 | var distance = targetPositionYWithOffset - positionY; 736 | var attraction = distance * acceleration; 737 | 738 | applyForce(attraction); 739 | 740 | velocityY *= friction; 741 | positionY += velocityY; 742 | 743 | return distance; 744 | } 745 | 746 | var applyForce = function applyForce(force) { 747 | velocityY += force; 748 | }; 749 | 750 | var render = function render() { 751 | window.scrollTo(0, positionY); 752 | }; 753 | 754 | window.addEventListener('mousewheel', function (event) { 755 | if (raf) { 756 | cancelAnimationFrame(raf); 757 | raf = null; 758 | } 759 | }, { 760 | passive: true 761 | }); 762 | 763 | var scrollTo = function scrollTo(offset, callback) { 764 | positionY = getScrollTop(); 765 | direction = positionY > offset ? -1 : 1; 766 | targetPositionYWithOffset = offset + direction; 767 | targetPositionY = offset; 768 | velocityY = 0; 769 | if (positionY != targetPositionY) { 770 | animate(); 771 | } else { 772 | _this.triggerEvent('scrollDone'); 773 | } 774 | }; 775 | 776 | this.triggerEvent('scrollStart'); 777 | if (animatedScroll == 0) { 778 | window.scrollTo(0, to); 779 | this.triggerEvent('scrollDone'); 780 | } else { 781 | scrollTo(to); 782 | } 783 | }; 784 | 785 | /***/ }), 786 | /* 17 */ 787 | /***/ (function(module, exports, __webpack_require__) { 788 | 789 | "use strict"; 790 | 791 | 792 | module.exports = function () { 793 | this.currentUrl = window.location.pathname + window.location.search; 794 | }; 795 | 796 | /***/ }), 797 | /* 18 */ 798 | /***/ (function(module, exports, __webpack_require__) { 799 | 800 | "use strict"; 801 | 802 | 803 | module.exports = function (eventName, originalEvent) { 804 | if (this.options.debugMode && originalEvent) { 805 | console.groupCollapsed('%cswup:' + '%c' + eventName, 'color: #343434', 'color: #009ACD'); 806 | console.log(originalEvent); 807 | console.groupEnd(); 808 | } else if (this.options.debugMode) { 809 | console.log('%cswup:' + '%c' + eventName, 'color: #343434', 'color: #009ACD'); 810 | } 811 | 812 | // call saved handlers with "on" method and pass originalEvent object if available 813 | this._handlers[eventName].forEach(function (handler) { 814 | try { 815 | handler(originalEvent); 816 | } catch (error) { 817 | console.error(error); 818 | } 819 | }); 820 | 821 | // trigger event on document with prefix "swup:" 822 | var event = new CustomEvent('swup:' + eventName, { detail: eventName }); 823 | document.dispatchEvent(event); 824 | }; 825 | 826 | /***/ }), 827 | /* 19 */ 828 | /***/ (function(module, exports, __webpack_require__) { 829 | 830 | "use strict"; 831 | 832 | 833 | module.exports = function (url) { 834 | window.history.pushState({ 835 | url: url || window.location.href.split(window.location.hostname)[1], 836 | random: Math.random(), 837 | source: "swup" 838 | }, document.getElementsByTagName('title')[0].innerText, url || window.location.href.split(window.location.hostname)[1]); 839 | }; 840 | 841 | /***/ }), 842 | /* 20 */ 843 | /***/ (function(module, exports, __webpack_require__) { 844 | 845 | "use strict"; 846 | 847 | 848 | var _utils = __webpack_require__(0); 849 | 850 | var _Link = __webpack_require__(1); 851 | 852 | var _Link2 = _interopRequireDefault(_Link); 853 | 854 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 855 | 856 | var forEach = Array.prototype.forEach; 857 | 858 | 859 | module.exports = function (page, popstate) { 860 | var _this = this; 861 | 862 | document.documentElement.classList.remove('is-leaving'); 863 | 864 | // replace state in case the url was redirected 865 | var link = new _Link2.default(); 866 | link.setPath(page.responseURL); 867 | 868 | if (window.location.pathname !== link.getPath()) { 869 | window.history.replaceState({ 870 | url: link.getPath(), 871 | random: Math.random(), 872 | source: "swup" 873 | }, document.title, link.getPath()); 874 | } 875 | 876 | // only add for non-popstate transitions 877 | if (!popstate || this.options.animateHistoryBrowsing) { 878 | document.documentElement.classList.add('is-rendering'); 879 | } 880 | 881 | this.triggerEvent('willReplaceContent'); 882 | 883 | // replace blocks 884 | for (var i = 0; i < page.blocks.length; i++) { 885 | document.body.querySelector('[data-swup="' + i + '"]').outerHTML = page.blocks[i]; 886 | } 887 | 888 | // set title 889 | document.title = page.title; 890 | 891 | // handle classes after render 892 | // remove 893 | if (this.options.pageClassPrefix !== false) { 894 | document.body.className.split(' ').forEach(function (className) { 895 | // empty string for page class 896 | if (className != "" && className.includes(_this.options.pageClassPrefix)) { 897 | document.body.classList.remove(className); 898 | } 899 | }); 900 | } 901 | // add 902 | if (page.pageClass != "") { 903 | page.pageClass.split(' ').forEach(function (className) { 904 | if (className != "" && className.includes(_this.options.pageClassPrefix)) { 905 | document.body.classList.add(className); 906 | } 907 | }); 908 | } 909 | 910 | this.triggerEvent('contentReplaced'); 911 | this.triggerEvent('pageView'); 912 | if (!this.options.cache) { 913 | this.cache.empty(this.options.debugMode); 914 | } 915 | setTimeout(function () { 916 | if (!popstate || _this.options.animateHistoryBrowsing) { 917 | _this.triggerEvent('animationInStart'); 918 | document.documentElement.classList.remove('is-animating'); 919 | } 920 | }, 10); 921 | 922 | // scrolling 923 | if (!this.options.doScrollingRightAway || this.scrollToElement) { 924 | this.doScrolling(popstate); 925 | } 926 | 927 | // detect animation end 928 | var animatedElements = (0, _utils.queryAll)(this.options.animationSelector); 929 | var promises = []; 930 | forEach.call(animatedElements, function (element) { 931 | var promise = new Promise(function (resolve) { 932 | element.addEventListener(_this.transitionEndEvent, function (event) { 933 | if (element == event.target) { 934 | resolve(); 935 | } 936 | }); 937 | }); 938 | promises.push(promise); 939 | }); 940 | 941 | //preload pages if possible 942 | this.preloadPages(); 943 | 944 | if (!popstate || this.options.animateHistoryBrowsing) { 945 | Promise.all(promises).then(function () { 946 | _this.triggerEvent('animationInDone'); 947 | // remove "to-{page}" classes 948 | document.documentElement.className.split(' ').forEach(function (classItem) { 949 | if (new RegExp("^to-").test(classItem) || classItem === "is-changing" || classItem === "is-rendering" || classItem === "is-popstate") { 950 | document.documentElement.classList.remove(classItem); 951 | } 952 | }); 953 | }); 954 | } 955 | 956 | // update current url 957 | this.getUrl(); 958 | // reset scroll-to element 959 | this.scrollToElement = null; 960 | }; 961 | 962 | /***/ }), 963 | /* 21 */ 964 | /***/ (function(module, exports, __webpack_require__) { 965 | 966 | "use strict"; 967 | 968 | 969 | var _utils = __webpack_require__(0); 970 | 971 | var forEach = Array.prototype.forEach; 972 | 973 | 974 | module.exports = function (data, popstate) { 975 | var _this = this; 976 | 977 | // scrolling 978 | if (this.options.doScrollingRightAway && !this.scrollToElement) { 979 | this.doScrolling(popstate); 980 | } 981 | 982 | // create array for storing animation promises 983 | var animationPromises = []; 984 | 985 | // set transition object 986 | if (data.customTransition != null) { 987 | this.updateTransition(window.location.pathname, data.url, data.customTransition); 988 | document.documentElement.classList.add('to-' + this.classify(data.customTransition)); 989 | } else { 990 | this.updateTransition(window.location.pathname, data.url); 991 | } 992 | 993 | if (!popstate || this.options.animateHistoryBrowsing) { 994 | // start animation 995 | this.triggerEvent('animationOutStart'); 996 | document.documentElement.classList.add('is-changing'); 997 | document.documentElement.classList.add('is-leaving'); 998 | document.documentElement.classList.add('is-animating'); 999 | if (popstate) { 1000 | document.documentElement.classList.add('is-popstate'); 1001 | } 1002 | document.documentElement.classList.add('to-' + this.classify(data.url)); 1003 | 1004 | // detect animation end 1005 | var animatedElements = (0, _utils.queryAll)(this.options.animationSelector); 1006 | forEach.call(animatedElements, function (element) { 1007 | var promise = new Promise(function (resolve) { 1008 | element.addEventListener(_this.transitionEndEvent, function (event) { 1009 | if (element == event.target) { 1010 | resolve(); 1011 | } 1012 | }); 1013 | }); 1014 | animationPromises.push(promise); 1015 | }); 1016 | 1017 | Promise.all(animationPromises).then(function () { 1018 | _this.triggerEvent('animationOutDone'); 1019 | }); 1020 | 1021 | // create pop element with or without anchor 1022 | if (this.scrollToElement != null) { 1023 | var pop = data.url + this.scrollToElement; 1024 | } else { 1025 | var pop = data.url; 1026 | } 1027 | if (!popstate) this.createState(pop); 1028 | } else { 1029 | // proceed without animating 1030 | this.triggerEvent('animationSkipped'); 1031 | } 1032 | 1033 | if (this.cache.exists(data.url)) { 1034 | var xhrPromise = new Promise(function (resolve) { 1035 | resolve(); 1036 | }); 1037 | this.triggerEvent('pageRetrievedFromCache'); 1038 | } else { 1039 | if (!this.preloadPromise || this.preloadPromise.route != data.url) { 1040 | var xhrPromise = new Promise(function (resolve, reject) { 1041 | _this.getPage(data, function (response, request) { 1042 | if (request.status === 500) { 1043 | _this.triggerEvent('serverError'); 1044 | reject(data.url); 1045 | return; 1046 | } else { 1047 | // get json data 1048 | var page = _this.getDataFromHtml(response, request); 1049 | if (page != null) { 1050 | page.url = data.url; 1051 | } else { 1052 | reject(data.url); 1053 | return; 1054 | } 1055 | // render page 1056 | _this.cache.cacheUrl(page, _this.options.debugMode); 1057 | _this.triggerEvent('pageLoaded'); 1058 | } 1059 | resolve(); 1060 | }); 1061 | }); 1062 | } else { 1063 | var xhrPromise = this.preloadPromise; 1064 | } 1065 | } 1066 | 1067 | Promise.all(animationPromises.concat([xhrPromise])).then(function () { 1068 | // render page 1069 | _this.renderPage(_this.cache.getPage(data.url), popstate); 1070 | _this.preloadPromise = null; 1071 | }).catch(function (errorUrl) { 1072 | // rewrite the skipPopStateHandling function to redirect manually when the history.go is processed 1073 | _this.options.skipPopStateHandling = function () { 1074 | window.location = errorUrl; 1075 | return true; 1076 | }; 1077 | 1078 | // go back to the actual page were still at 1079 | window.history.go(-1); 1080 | }); 1081 | }; 1082 | 1083 | /***/ }), 1084 | /* 22 */ 1085 | /***/ (function(module, exports, __webpack_require__) { 1086 | 1087 | "use strict"; 1088 | 1089 | 1090 | var _utils = __webpack_require__(0); 1091 | 1092 | module.exports = function (html, request) { 1093 | var _this = this; 1094 | 1095 | var content = html.replace('', ''); 1096 | var fakeDom = document.createElement('div'); 1097 | fakeDom.innerHTML = content; 1098 | var blocks = []; 1099 | 1100 | for (var i = 0; i < this.options.elements.length; i++) { 1101 | if (fakeDom.querySelector(this.options.elements[i]) == null) { 1102 | console.warn('Element ' + this.options.elements[i] + ' is not found in cached page.'); 1103 | return null; 1104 | } else { 1105 | (0, _utils.queryAll)(this.options.elements[i]).forEach(function (item, index) { 1106 | (0, _utils.queryAll)(_this.options.elements[i], fakeDom)[index].dataset.swup = blocks.length; 1107 | blocks.push((0, _utils.queryAll)(_this.options.elements[i], fakeDom)[index].outerHTML); 1108 | }); 1109 | } 1110 | } 1111 | 1112 | var json = { 1113 | title: fakeDom.querySelector('title').innerText, 1114 | pageClass: fakeDom.querySelector('#swupBody').className, 1115 | originalContent: html, 1116 | blocks: blocks, 1117 | responseURL: request != null ? request.responseURL : window.location.href 1118 | }; 1119 | return json; 1120 | }; 1121 | 1122 | /***/ }), 1123 | /* 23 */ 1124 | /***/ (function(module, exports, __webpack_require__) { 1125 | 1126 | "use strict"; 1127 | 1128 | 1129 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 1130 | 1131 | module.exports = function (options) { 1132 | var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; 1133 | 1134 | var defaults = { 1135 | url: window.location.pathname + window.location.search, 1136 | method: "GET", 1137 | data: null 1138 | }; 1139 | 1140 | var data = _extends({}, defaults, options); 1141 | 1142 | var request = new XMLHttpRequest(); 1143 | 1144 | request.onreadystatechange = function () { 1145 | if (request.readyState === 4) { 1146 | if (request.status !== 500) { 1147 | callback(request.responseText, request); 1148 | } else { 1149 | callback(null, request); 1150 | } 1151 | } 1152 | }; 1153 | 1154 | request.open(data.method, data.url, true); 1155 | request.setRequestHeader("X-Requested-With", "swup"); 1156 | request.send(data.data); 1157 | return request; 1158 | }; 1159 | 1160 | /***/ }), 1161 | /* 24 */ 1162 | /***/ (function(module, exports, __webpack_require__) { 1163 | 1164 | "use strict"; 1165 | 1166 | 1167 | module.exports = function transitionEnd() { 1168 | var el = document.createElement('div'); 1169 | 1170 | var transEndEventNames = { 1171 | WebkitTransition: 'webkitTransitionEnd', 1172 | MozTransition: 'transitionend', 1173 | OTransition: 'oTransitionEnd otransitionend', 1174 | transition: 'transitionend' 1175 | }; 1176 | 1177 | for (var name in transEndEventNames) { 1178 | if (el.style[name] !== undefined) { 1179 | return transEndEventNames[name]; 1180 | } 1181 | } 1182 | 1183 | return false; 1184 | }; 1185 | 1186 | /***/ }), 1187 | /* 25 */ 1188 | /***/ (function(module, exports, __webpack_require__) { 1189 | 1190 | "use strict"; 1191 | 1192 | 1193 | Object.defineProperty(exports, "__esModule", { 1194 | value: true 1195 | }); 1196 | 1197 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1198 | 1199 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1200 | 1201 | var Cache = function () { 1202 | function Cache() { 1203 | _classCallCheck(this, Cache); 1204 | 1205 | this.pages = {}; 1206 | this.count = 0; 1207 | this.last = null; 1208 | } 1209 | 1210 | _createClass(Cache, [{ 1211 | key: 'cacheUrl', 1212 | value: function cacheUrl(page, displayCache) { 1213 | this.count++; 1214 | if (page.url in this.pages === false) { 1215 | this.pages[page.url] = page; 1216 | } 1217 | this.last = this.pages[page.url]; 1218 | if (displayCache) { 1219 | this.displayCache(); 1220 | } 1221 | } 1222 | }, { 1223 | key: 'getPage', 1224 | value: function getPage(url) { 1225 | return this.pages[url]; 1226 | } 1227 | }, { 1228 | key: 'displayCache', 1229 | value: function displayCache() { 1230 | console.groupCollapsed('Cache (' + Object.keys(this.pages).length + ')'); 1231 | for (var key in this.pages) { 1232 | console.log(this.pages[key]); 1233 | } 1234 | console.groupEnd(); 1235 | } 1236 | }, { 1237 | key: 'exists', 1238 | value: function exists(url) { 1239 | if (url in this.pages) return true; 1240 | return false; 1241 | } 1242 | }, { 1243 | key: 'empty', 1244 | value: function empty(showLog) { 1245 | this.pages = {}; 1246 | this.count = 0; 1247 | this.last = null; 1248 | if (showLog) { 1249 | console.log('Cache cleared'); 1250 | } 1251 | } 1252 | }, { 1253 | key: 'remove', 1254 | value: function remove(url) { 1255 | delete this.pages[url]; 1256 | } 1257 | }]); 1258 | 1259 | return Cache; 1260 | }(); 1261 | 1262 | exports.default = Cache; 1263 | 1264 | /***/ }), 1265 | /* 26 */ 1266 | /***/ (function(module, exports) { 1267 | 1268 | var DOCUMENT_NODE_TYPE = 9; 1269 | 1270 | /** 1271 | * A polyfill for Element.matches() 1272 | */ 1273 | if (typeof Element !== 'undefined' && !Element.prototype.matches) { 1274 | var proto = Element.prototype; 1275 | 1276 | proto.matches = proto.matchesSelector || 1277 | proto.mozMatchesSelector || 1278 | proto.msMatchesSelector || 1279 | proto.oMatchesSelector || 1280 | proto.webkitMatchesSelector; 1281 | } 1282 | 1283 | /** 1284 | * Finds the closest parent that matches a selector. 1285 | * 1286 | * @param {Element} element 1287 | * @param {String} selector 1288 | * @return {Function} 1289 | */ 1290 | function closest (element, selector) { 1291 | while (element && element.nodeType !== DOCUMENT_NODE_TYPE) { 1292 | if (typeof element.matches === 'function' && 1293 | element.matches(selector)) { 1294 | return element; 1295 | } 1296 | element = element.parentNode; 1297 | } 1298 | } 1299 | 1300 | module.exports = closest; 1301 | 1302 | 1303 | /***/ }), 1304 | /* 27 */ 1305 | /***/ (function(module, exports, __webpack_require__) { 1306 | 1307 | var closest = __webpack_require__(26); 1308 | 1309 | /** 1310 | * Delegates event to a selector. 1311 | * 1312 | * @param {Element} element 1313 | * @param {String} selector 1314 | * @param {String} type 1315 | * @param {Function} callback 1316 | * @param {Boolean} useCapture 1317 | * @return {Object} 1318 | */ 1319 | function delegate(element, selector, type, callback, useCapture) { 1320 | var listenerFn = listener.apply(this, arguments); 1321 | 1322 | element.addEventListener(type, listenerFn, useCapture); 1323 | 1324 | return { 1325 | destroy: function() { 1326 | element.removeEventListener(type, listenerFn, useCapture); 1327 | } 1328 | } 1329 | } 1330 | 1331 | /** 1332 | * Finds closest match and invokes callback. 1333 | * 1334 | * @param {Element} element 1335 | * @param {String} selector 1336 | * @param {String} type 1337 | * @param {Function} callback 1338 | * @return {Function} 1339 | */ 1340 | function listener(element, selector, type, callback) { 1341 | return function(e) { 1342 | e.delegateTarget = closest(e.target, selector); 1343 | 1344 | if (e.delegateTarget) { 1345 | callback.call(element, e); 1346 | } 1347 | } 1348 | } 1349 | 1350 | module.exports = delegate; 1351 | 1352 | 1353 | /***/ }), 1354 | /* 28 */ 1355 | /***/ (function(module, exports, __webpack_require__) { 1356 | 1357 | "use strict"; 1358 | 1359 | 1360 | Object.defineProperty(exports, "__esModule", { 1361 | value: true 1362 | }); 1363 | 1364 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 1365 | 1366 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1367 | 1368 | // helpers 1369 | 1370 | 1371 | // modules 1372 | 1373 | 1374 | var _delegate = __webpack_require__(27); 1375 | 1376 | var _delegate2 = _interopRequireDefault(_delegate); 1377 | 1378 | var _Cache = __webpack_require__(25); 1379 | 1380 | var _Cache2 = _interopRequireDefault(_Cache); 1381 | 1382 | var _Link = __webpack_require__(1); 1383 | 1384 | var _Link2 = _interopRequireDefault(_Link); 1385 | 1386 | var _transitionEnd = __webpack_require__(24); 1387 | 1388 | var _transitionEnd2 = _interopRequireDefault(_transitionEnd); 1389 | 1390 | var _request = __webpack_require__(23); 1391 | 1392 | var _request2 = _interopRequireDefault(_request); 1393 | 1394 | var _getDataFromHtml = __webpack_require__(22); 1395 | 1396 | var _getDataFromHtml2 = _interopRequireDefault(_getDataFromHtml); 1397 | 1398 | var _loadPage = __webpack_require__(21); 1399 | 1400 | var _loadPage2 = _interopRequireDefault(_loadPage); 1401 | 1402 | var _renderPage = __webpack_require__(20); 1403 | 1404 | var _renderPage2 = _interopRequireDefault(_renderPage); 1405 | 1406 | var _createState = __webpack_require__(19); 1407 | 1408 | var _createState2 = _interopRequireDefault(_createState); 1409 | 1410 | var _triggerEvent = __webpack_require__(18); 1411 | 1412 | var _triggerEvent2 = _interopRequireDefault(_triggerEvent); 1413 | 1414 | var _getUrl = __webpack_require__(17); 1415 | 1416 | var _getUrl2 = _interopRequireDefault(_getUrl); 1417 | 1418 | var _scrollTo = __webpack_require__(16); 1419 | 1420 | var _scrollTo2 = _interopRequireDefault(_scrollTo); 1421 | 1422 | var _classify = __webpack_require__(15); 1423 | 1424 | var _classify2 = _interopRequireDefault(_classify); 1425 | 1426 | var _doScrolling = __webpack_require__(14); 1427 | 1428 | var _doScrolling2 = _interopRequireDefault(_doScrolling); 1429 | 1430 | var _markSwupElements = __webpack_require__(13); 1431 | 1432 | var _markSwupElements2 = _interopRequireDefault(_markSwupElements); 1433 | 1434 | var _on = __webpack_require__(12); 1435 | 1436 | var _on2 = _interopRequireDefault(_on); 1437 | 1438 | var _off = __webpack_require__(11); 1439 | 1440 | var _off2 = _interopRequireDefault(_off); 1441 | 1442 | var _updateTransition = __webpack_require__(10); 1443 | 1444 | var _updateTransition2 = _interopRequireDefault(_updateTransition); 1445 | 1446 | var _preloadPage = __webpack_require__(9); 1447 | 1448 | var _preloadPage2 = _interopRequireDefault(_preloadPage); 1449 | 1450 | var _preloadPages = __webpack_require__(8); 1451 | 1452 | var _preloadPages2 = _interopRequireDefault(_preloadPages); 1453 | 1454 | var _usePlugin = __webpack_require__(7); 1455 | 1456 | var _usePlugin2 = _interopRequireDefault(_usePlugin); 1457 | 1458 | var _log = __webpack_require__(6); 1459 | 1460 | var _log2 = _interopRequireDefault(_log); 1461 | 1462 | var _utils = __webpack_require__(0); 1463 | 1464 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1465 | 1466 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1467 | 1468 | var Swup = function () { 1469 | function Swup(setOptions) { 1470 | _classCallCheck(this, Swup); 1471 | 1472 | // default options 1473 | var defaults = { 1474 | cache: true, 1475 | animationSelector: '[class*="transition-"]', 1476 | elements: ['#swup'], 1477 | pageClassPrefix: '', 1478 | debugMode: false, 1479 | scroll: true, 1480 | 1481 | doScrollingRightAway: false, 1482 | animateScroll: true, 1483 | scrollFriction: .3, 1484 | scrollAcceleration: .04, 1485 | 1486 | preload: true, 1487 | support: true, 1488 | plugins: [], 1489 | 1490 | skipPopStateHandling: function skipPopStateHandling(event) { 1491 | if (event.state && event.state.source == "swup") { 1492 | return false; 1493 | } 1494 | return true; 1495 | }, 1496 | animateHistoryBrowsing: false, 1497 | 1498 | LINK_SELECTOR: 'a[href^="' + window.location.origin + '"]:not([data-no-swup]), a[href^="/"]:not([data-no-swup]), a[href^="#"]:not([data-no-swup])', 1499 | FORM_SELECTOR: 'form[data-swup-form]' 1500 | 1501 | /** 1502 | * current transition object 1503 | */ 1504 | };this.transition = {}; 1505 | 1506 | var options = _extends({}, defaults, setOptions); 1507 | 1508 | /** 1509 | * handler arrays 1510 | */ 1511 | this._handlers = { 1512 | animationInDone: [], 1513 | animationInStart: [], 1514 | animationOutDone: [], 1515 | animationOutStart: [], 1516 | animationSkipped: [], 1517 | clickLink: [], 1518 | contentReplaced: [], 1519 | disabled: [], 1520 | enabled: [], 1521 | hoverLink: [], 1522 | openPageInNewTab: [], 1523 | pageLoaded: [], 1524 | pagePreloaded: [], 1525 | pageRetrievedFromCache: [], 1526 | pageView: [], 1527 | popState: [], 1528 | samePage: [], 1529 | samePageWithHash: [], 1530 | scrollDone: [], 1531 | scrollStart: [], 1532 | serverError: [], 1533 | submitForm: [], 1534 | willReplaceContent: [] 1535 | }; 1536 | 1537 | /** 1538 | * helper variables 1539 | */ 1540 | // id of element to scroll to after render 1541 | this.scrollToElement = null; 1542 | // promise used for preload, so no new loading of the same page starts while page is loading 1543 | this.preloadPromise = null; 1544 | // save options 1545 | this.options = options; 1546 | // plugins array 1547 | this.plugins = []; 1548 | 1549 | /** 1550 | * make modules accessible in instance 1551 | */ 1552 | this.getUrl = _getUrl2.default; 1553 | this.cache = new _Cache2.default(); 1554 | this.link = new _Link2.default(); 1555 | this.transitionEndEvent = (0, _transitionEnd2.default)(); 1556 | this.getDataFromHtml = _getDataFromHtml2.default; 1557 | this.getPage = _request2.default; 1558 | this.scrollTo = _scrollTo2.default; 1559 | this.loadPage = _loadPage2.default; 1560 | this.renderPage = _renderPage2.default; 1561 | this.createState = _createState2.default; 1562 | this.triggerEvent = _triggerEvent2.default; 1563 | this.classify = _classify2.default; 1564 | this.doScrolling = _doScrolling2.default; 1565 | this.markSwupElements = _markSwupElements2.default; 1566 | this.on = _on2.default; 1567 | this.off = _off2.default; 1568 | this.updateTransition = _updateTransition2.default; 1569 | this.preloadPage = _preloadPage2.default; 1570 | this.preloadPages = _preloadPages2.default; 1571 | this.usePlugin = _usePlugin2.default; 1572 | this.log = _log2.default; 1573 | this.enable = this.enable; 1574 | this.destroy = this.destroy; 1575 | 1576 | // attach instance to window in debug mode 1577 | if (this.options.debugMode) { 1578 | window.swup = this; 1579 | } 1580 | 1581 | this.getUrl(); 1582 | this.enable(); 1583 | } 1584 | 1585 | _createClass(Swup, [{ 1586 | key: 'enable', 1587 | value: function enable() { 1588 | var _this = this; 1589 | 1590 | /** 1591 | * support check 1592 | */ 1593 | if (this.options.support) { 1594 | // check pushState support 1595 | if (!('pushState' in window.history)) { 1596 | console.warn('pushState is not supported'); 1597 | return; 1598 | } 1599 | // check transitionEnd support 1600 | if ((0, _transitionEnd2.default)()) { 1601 | this.transitionEndEvent = (0, _transitionEnd2.default)(); 1602 | } else { 1603 | console.warn('transitionEnd detection is not supported'); 1604 | return; 1605 | } 1606 | // check Promise support 1607 | if (typeof Promise === "undefined" || Promise.toString().indexOf("[native code]") === -1) { 1608 | console.warn('Promise is not supported'); 1609 | return; 1610 | } 1611 | } 1612 | 1613 | // variable to keep event listeners from "delegate" 1614 | this.delegatedListeners = {}; 1615 | 1616 | /** 1617 | * link click handler 1618 | */ 1619 | this.delegatedListeners.click = (0, _delegate2.default)(document, this.options.LINK_SELECTOR, 'click', this.linkClickHandler.bind(this)); 1620 | 1621 | /** 1622 | * link mouseover handler (preload) 1623 | */ 1624 | this.delegatedListeners.mouseover = (0, _delegate2.default)(document.body, this.options.LINK_SELECTOR, 'mouseover', this.linkMouseoverHandler.bind(this)); 1625 | 1626 | /** 1627 | * form submit handler 1628 | */ 1629 | this.delegatedListeners.formSubmit = (0, _delegate2.default)(document, this.options.FORM_SELECTOR, 'submit', this.formSubmitHandler.bind(this)); 1630 | 1631 | /** 1632 | * popstate handler 1633 | */ 1634 | window.addEventListener('popstate', this.popStateHandler.bind(this)); 1635 | 1636 | /** 1637 | * initial save to cache 1638 | */ 1639 | var page = this.getDataFromHtml(document.documentElement.outerHTML); 1640 | page.url = this.currentUrl; 1641 | if (this.options.cache) { 1642 | this.cache.cacheUrl(page, this.options.debugMode); 1643 | } 1644 | 1645 | /** 1646 | * mark swup blocks in html 1647 | */ 1648 | this.markSwupElements(document.documentElement); 1649 | 1650 | /** 1651 | * enable plugins from options 1652 | */ 1653 | this.options.plugins.forEach(function (item) { 1654 | return _this.usePlugin(item); 1655 | }); 1656 | 1657 | /** 1658 | * modify initial history record 1659 | */ 1660 | window.history.replaceState(Object.assign({}, window.history.state, { 1661 | url: window.location.href, 1662 | random: Math.random(), 1663 | source: "swup" 1664 | }), document.title, window.location.href); 1665 | 1666 | /** 1667 | * Disable browser scroll control on popstates when animateHistoryBrowsing option is enabled 1668 | */ 1669 | if (this.options.animateHistoryBrowsing) { 1670 | window.history.scrollRestoration = "manual"; 1671 | } 1672 | 1673 | /** 1674 | * trigger enabled event 1675 | */ 1676 | this.triggerEvent('enabled'); 1677 | document.documentElement.classList.add('swup-enabled'); 1678 | 1679 | /** 1680 | * trigger page view event 1681 | */ 1682 | this.triggerEvent('pageView'); 1683 | 1684 | /** 1685 | * preload pages if possible 1686 | */ 1687 | this.preloadPages(); 1688 | } 1689 | }, { 1690 | key: 'destroy', 1691 | value: function destroy() { 1692 | // remove delegated listeners 1693 | this.delegatedListeners.click.destroy(); 1694 | this.delegatedListeners.mouseover.destroy(); 1695 | 1696 | // remove popstate listener 1697 | window.removeEventListener('popstate', this.popStateHandler.bind(this)); 1698 | 1699 | // empty cache 1700 | this.cache.empty(); 1701 | 1702 | // remove swup data atributes from blocks 1703 | (0, _utils.queryAll)('[data-swup]').forEach(function (element) { 1704 | delete element.dataset.swup; 1705 | }); 1706 | 1707 | // remove handlers 1708 | this.off(); 1709 | 1710 | this.triggerEvent('disabled'); 1711 | document.documentElement.classList.remove('swup-enabled'); 1712 | } 1713 | }, { 1714 | key: 'linkClickHandler', 1715 | value: function linkClickHandler(event) { 1716 | // no control key pressed 1717 | if (!event.metaKey && !event.ctrlKey && !event.shiftKey && !event.altKey) { 1718 | // index of pressed button needs to be checked because Firefox triggers click on all mouse buttons 1719 | if (event.button === 0) { 1720 | this.triggerEvent('clickLink', event); 1721 | var link = new _Link2.default(); 1722 | event.preventDefault(); 1723 | link.setPath(event.delegateTarget.href); 1724 | 1725 | if (link.getAddress() == this.currentUrl || link.getAddress() == '') { 1726 | // link to the same URL 1727 | if (link.getHash() != '') { 1728 | // link to the same URL with hash 1729 | this.triggerEvent('samePageWithHash', event); 1730 | var element = document.querySelector(link.getHash()); 1731 | if (element != null) { 1732 | // referenced element found 1733 | if (this.options.scroll) { 1734 | var top = element.getBoundingClientRect().top + window.pageYOffset; 1735 | this.scrollTo(document.body, top); 1736 | } 1737 | history.replaceState({ 1738 | url: link.getAddress() + link.getHash(), 1739 | random: Math.random(), 1740 | source: "swup" 1741 | }, document.title, link.getAddress() + link.getHash()); 1742 | } else { 1743 | // referenced element not found 1744 | console.warn('Element for offset not found (' + link.getHash() + ')'); 1745 | } 1746 | } else { 1747 | // link to the same URL without hash 1748 | this.triggerEvent('samePage', event); 1749 | if (this.options.scroll) { 1750 | this.scrollTo(document.body, 0, 1); 1751 | } 1752 | } 1753 | } else { 1754 | // link to different url 1755 | if (link.getHash() != '') { 1756 | this.scrollToElement = link.getHash(); 1757 | } 1758 | 1759 | // get custom transition from data 1760 | var customTransition = event.delegateTarget.dataset.swupTransition; 1761 | 1762 | // load page 1763 | this.loadPage({ url: link.getAddress(), customTransition: customTransition }, false); 1764 | } 1765 | } 1766 | } else { 1767 | // open in new tab (do nothing) 1768 | this.triggerEvent('openPageInNewTab', event); 1769 | } 1770 | } 1771 | }, { 1772 | key: 'linkMouseoverHandler', 1773 | value: function linkMouseoverHandler(event) { 1774 | var _this2 = this; 1775 | 1776 | this.triggerEvent('hoverLink', event); 1777 | if (this.options.preload) { 1778 | var link = new _Link2.default(); 1779 | link.setPath(event.delegateTarget.href); 1780 | if (link.getAddress() != this.currentUrl && !this.cache.exists(link.getAddress()) && this.preloadPromise == null) { 1781 | this.preloadPromise = new Promise(function (resolve, reject) { 1782 | _this2.getPage({ url: link.getAddress() }, function (response, request) { 1783 | if (request.status === 500) { 1784 | _this2.triggerEvent('serverError', event); 1785 | reject(link.getAddress()); 1786 | return; 1787 | } else { 1788 | // get json data 1789 | var page = _this2.getDataFromHtml(response, request); 1790 | if (page != null) { 1791 | page.url = link.getAddress(); 1792 | _this2.cache.cacheUrl(page, _this2.options.debugMode); 1793 | _this2.triggerEvent('pagePreloaded', event); 1794 | } else { 1795 | reject(link.getAddress()); 1796 | return; 1797 | } 1798 | } 1799 | resolve(); 1800 | _this2.preloadPromise = null; 1801 | }); 1802 | }); 1803 | this.preloadPromise.route = link.getAddress(); 1804 | } 1805 | } 1806 | } 1807 | }, { 1808 | key: 'formSubmitHandler', 1809 | value: function formSubmitHandler(event) { 1810 | // no control key pressed 1811 | if (!event.metaKey) { 1812 | this.triggerEvent('submitForm', event); 1813 | event.preventDefault(); 1814 | var form = event.target; 1815 | var formData = new FormData(form); 1816 | 1817 | var link = new _Link2.default(); 1818 | link.setPath(form.action); 1819 | 1820 | if (link.getHash() != '') { 1821 | this.scrollToElement = link.getHash(); 1822 | } 1823 | 1824 | if (form.method.toLowerCase() != "get") { 1825 | // remove page from cache 1826 | this.cache.remove(link.getAddress()); 1827 | 1828 | // send data 1829 | this.loadPage({ 1830 | url: link.getAddress(), 1831 | method: form.method, 1832 | data: formData 1833 | }); 1834 | } else { 1835 | // create base url 1836 | var url = link.getAddress() || window.location.href; 1837 | var inputs = (0, _utils.queryAll)('input, select', form); 1838 | if (url.indexOf('?') == -1) { 1839 | url += "?"; 1840 | } else { 1841 | url += "&"; 1842 | } 1843 | 1844 | // add form data to url 1845 | inputs.forEach(function (input) { 1846 | if (input.type == "checkbox" || input.type == "radio") { 1847 | if (input.checked) { 1848 | url += encodeURIComponent(input.name) + "=" + encodeURIComponent(input.value) + "&"; 1849 | } 1850 | } else { 1851 | url += encodeURIComponent(input.name) + "=" + encodeURIComponent(input.value) + "&"; 1852 | } 1853 | }); 1854 | 1855 | // remove last "&" 1856 | url = url.slice(0, -1); 1857 | 1858 | // remove page from cache 1859 | this.cache.remove(url); 1860 | 1861 | // send data 1862 | this.loadPage({ 1863 | url: url 1864 | }); 1865 | } 1866 | } else { 1867 | this.triggerEvent('openFormSubmitInNewTab', event); 1868 | } 1869 | } 1870 | }, { 1871 | key: 'popStateHandler', 1872 | value: function popStateHandler(event) { 1873 | var link = new _Link2.default(); 1874 | if (this.options.skipPopStateHandling(event)) return; 1875 | link.setPath(event.state ? event.state.url : window.location.pathname); 1876 | if (link.getHash() != '') { 1877 | this.scrollToElement = link.getHash(); 1878 | } else { 1879 | event.preventDefault(); 1880 | } 1881 | this.triggerEvent('popState', event); 1882 | this.loadPage({ url: link.getAddress() }, event); 1883 | } 1884 | }]); 1885 | 1886 | return Swup; 1887 | }(); 1888 | 1889 | exports.default = Swup; 1890 | 1891 | /***/ }), 1892 | /* 29 */ 1893 | /***/ (function(module, exports, __webpack_require__) { 1894 | 1895 | "use strict"; 1896 | 1897 | 1898 | Object.defineProperty(exports, "__esModule", { 1899 | value: true 1900 | }); 1901 | 1902 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 1903 | 1904 | var _swup = __webpack_require__(28); 1905 | 1906 | var _swup2 = _interopRequireDefault(_swup); 1907 | 1908 | var _loadPage = __webpack_require__(5); 1909 | 1910 | var _loadPage2 = _interopRequireDefault(_loadPage); 1911 | 1912 | var _renderPage = __webpack_require__(4); 1913 | 1914 | var _renderPage2 = _interopRequireDefault(_renderPage); 1915 | 1916 | var _getAnimation = __webpack_require__(3); 1917 | 1918 | var _getAnimation2 = _interopRequireDefault(_getAnimation); 1919 | 1920 | var _createAnimationPromise = __webpack_require__(2); 1921 | 1922 | var _createAnimationPromise2 = _interopRequireDefault(_createAnimationPromise); 1923 | 1924 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1925 | 1926 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1927 | 1928 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } 1929 | 1930 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } 1931 | 1932 | // modules 1933 | 1934 | 1935 | var Swupjs = function (_Swup) { 1936 | _inherits(Swupjs, _Swup); 1937 | 1938 | function Swupjs(setOptions) { 1939 | _classCallCheck(this, Swupjs); 1940 | 1941 | var defaults = { 1942 | animations: { 1943 | '*': { 1944 | out: function out(next) { 1945 | next(); 1946 | }, 1947 | in: function _in(next) { 1948 | next(); 1949 | } 1950 | } 1951 | } 1952 | }; 1953 | 1954 | var options = _extends({}, defaults, setOptions); 1955 | 1956 | var _this = _possibleConstructorReturn(this, (Swupjs.__proto__ || Object.getPrototypeOf(Swupjs)).call(this, options)); 1957 | 1958 | _this.loadPage = _loadPage2.default; 1959 | _this.renderPage = _renderPage2.default; 1960 | _this.getAnimation = _getAnimation2.default; 1961 | _this.createAnimationPromise = _createAnimationPromise2.default; 1962 | 1963 | 1964 | _this.animations = options.animations; 1965 | return _this; 1966 | } 1967 | 1968 | /** 1969 | * make modules accessible in instance 1970 | */ 1971 | 1972 | 1973 | return Swupjs; 1974 | }(_swup2.default); 1975 | 1976 | exports.default = Swupjs; 1977 | 1978 | /***/ }), 1979 | /* 30 */ 1980 | /***/ (function(module, exports, __webpack_require__) { 1981 | 1982 | "use strict"; 1983 | 1984 | 1985 | var _index = __webpack_require__(29); 1986 | 1987 | var _index2 = _interopRequireDefault(_index); 1988 | 1989 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 1990 | 1991 | module.exports = _index2.default; // this is here for webpack to expose Swupjs as window.Swupjs 1992 | 1993 | /***/ }) 1994 | /******/ ]); 1995 | }); --------------------------------------------------------------------------------