-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
325 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
node_modules | ||
dist | ||
lib | ||
package-lock.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2020, Aymeric Assier and Julien Martins Da Costa. | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"name": "@wide/pageflip", | ||
"version": "2.0.0", | ||
"description": "Handle page transition when navigating", | ||
"license": "MIT", | ||
"author": "Aymeric Assier (https://github.com/myeti)", | ||
"contributors": [ | ||
"Aymeric Assier (https://github.com/myeti)", | ||
"Julien Martins Da Costa (https://github.com/jdacosta)" | ||
], | ||
"repository": { | ||
"type" : "git", | ||
"url" : "https://github.com/wide/pageflip.git" | ||
}, | ||
"main": "lib", | ||
"engines": { | ||
"node": ">=10.13.0" | ||
}, | ||
"scripts": { | ||
"build": "babel src/ -d lib/ --presets babel-preset-es2015", | ||
"prepare": "rimraf lib/ && npm run build" | ||
}, | ||
"dependencies": { | ||
"pjax": "^0.2.8" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "6.26.0", | ||
"babel-preset-es2015": "6.24.1", | ||
"rimraf": "^3.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Pageflip | ||
|
||
Handle page transition when navigating, based on `pjax`. | ||
|
||
|
||
## Install | ||
|
||
``` | ||
npm install @wide/pageflip --save | ||
``` | ||
|
||
|
||
## Usage | ||
|
||
```js | ||
import pageflip from '@wide/pageflip' | ||
|
||
pageflip({ | ||
container: 'main', | ||
transition: 'fadeUp', | ||
transitions: { | ||
fadeUp: { | ||
from: el => fadeUpOut(el), | ||
to: el => fadeUpIn(el) | ||
} | ||
} | ||
}) | ||
``` | ||
|
||
- `container`: selector of the element to update when the next page is loaded, default `main` | ||
- `transition`: default transition to apply, default `noop` | ||
- `transitions`: collection of available transitions | ||
- `enter`: called when the next page is loading, must return a `Promise` | ||
- `leave`: called when `enter` is resolved **and** the next page is loaded, ready to swap | ||
|
||
### Default transitions | ||
|
||
Pageflip comme with 2 defaults transitions: | ||
- `noop` do absolutely nothing, swap directly the next page | ||
- `fade` a simple fade in/out of the page | ||
|
||
### Lifecycle and hooks | ||
|
||
Pageflip apply the following process: | ||
``` | ||
click -> onLoad() -> transition.enter() -> page is -> onSwap() -> transition.leave() | ||
on link loaded | ||
``` | ||
|
||
You can interact around `onLoad()` and `onSwap()` with these hooks : | ||
```js | ||
pageflip({ | ||
beforeLoad(), | ||
afterLoad(), | ||
beforeSwap(), | ||
afterSwap() | ||
}) | ||
``` | ||
|
||
|
||
## Libraries | ||
|
||
This package uses : | ||
- [`pjax`](https://github.com/MoOx/pjax) | ||
|
||
|
||
## Authors | ||
|
||
- **Aymeric Assier** - [github.com/myeti](https://github.com/myeti) | ||
- **Julien Martins Da Costa** - [github.com/jdacosta](https://github.com/jdacosta) | ||
|
||
|
||
## License | ||
|
||
This project is licensed under the MIT License - see the [licence](licence) file for details |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
import Pjax from 'pjax' | ||
import transitions from './transitions' | ||
|
||
|
||
/** | ||
* States | ||
*/ | ||
const STATES = { | ||
loading: '-page-loading', | ||
loaded: '-page-loaded' | ||
} | ||
|
||
|
||
/** | ||
* Props | ||
*/ | ||
const runtime = { | ||
pjax: null, | ||
container: null, | ||
fallback: null, | ||
transition: null, | ||
transitions: {}, | ||
loading: null | ||
} | ||
|
||
|
||
/** | ||
* Start pager instance | ||
* @param {Object} opts | ||
*/ | ||
export default function(opts = {}) { | ||
|
||
// singleton | ||
if(runtime.pjax) return; | ||
|
||
// do not load pjax if browse from local files | ||
if(location.protocol === 'file:') { | ||
console.error('cannot load PJax on file:// protocol, please setup a web server') | ||
return | ||
} | ||
|
||
// set props | ||
runtime.container = opts.container || 'main' | ||
runtime.fallback = opts.transition || 'noop' | ||
runtime.transitions = Object.assign(transitions, opts.transitions) | ||
|
||
// set hooks | ||
runtime.beforeLoad = opts.beforeLoad | ||
runtime.afterLoad = opts.afterLoad | ||
runtime.beforeSwap = opts.beforeSwap | ||
runtime.afterSwap = opts.afterSwap | ||
|
||
// load the page | ||
document.addEventListener('pjax:send', onLoad) | ||
|
||
// handle error | ||
document.addEventListener('pjax:error', err => { | ||
console.error(err) | ||
location.href = err.request.responseURL | ||
}) | ||
|
||
// instanciate pjax | ||
runtime.pjax = new Pjax({ | ||
elements: 'a[href]:not([data-transition\\.skip]), form[action]', | ||
selectors: ['title', runtime.container], | ||
switches: { | ||
[runtime.container]: onSwap | ||
}, | ||
cacheBust: false | ||
}) | ||
|
||
// add initial class on body | ||
document.body.classList.add(STATES.loaded) | ||
} | ||
|
||
|
||
/** | ||
* Hook called when the page is loading | ||
* @param {Object} e | ||
*/ | ||
function onLoad(e) { | ||
|
||
// call hook | ||
if(runtime.beforeLoad) { | ||
runtime.beforeLoad() | ||
} | ||
|
||
// change body classes | ||
document.body.classList.remove(STATES.loaded) | ||
document.body.classList.add(STATES.loading) | ||
|
||
// resolve transition name (from event.transition or [data-transition] attribute or fallback) | ||
let name = runtime.fallback | ||
if(e.transition) { | ||
name = e.transition | ||
} | ||
else if(e.triggerElement && e.triggerElement.dataset.transition) { | ||
name = e.triggerElement.dataset.transition | ||
} | ||
|
||
// resolve transition scenario | ||
runtime.transition = runtime.transitions[name] || runtime.transitions[runtime.fallback] | ||
|
||
// start transition (assume promise) | ||
const el = document.querySelector(runtime.container) | ||
runtime.loading = runtime.transition.enter(el) | ||
|
||
// call hook | ||
if(runtime.afterLoad) { | ||
runtime.afterLoad() | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Hook called to replace the DOM content | ||
* @param {HTMLElement} before | ||
* @param {HTMLElement} after | ||
* @return {Promise} | ||
*/ | ||
function onSwap(before, after) { | ||
|
||
// call hook | ||
if(runtime.beforeSwap) { | ||
runtime.beforeSwap() | ||
} | ||
|
||
// when loading transition is done | ||
return runtime.loading.then(() => { | ||
|
||
// swap content | ||
before.innerHTML = after.innerHTML | ||
runtime.pjax.onSwitch() | ||
|
||
// scroll top | ||
scrollTo({ top: 0 }) | ||
|
||
// change body classes | ||
document.body.classList.remove(STATES.loading) | ||
document.body.classList.add(STATES.loaded) | ||
|
||
// end transition (assume promise) | ||
const el = document.querySelector(runtime.container) | ||
return runtime.transition.leave(el).then(() => { | ||
|
||
// call hook | ||
if(runtime.afterSwap) { | ||
runtime.afterSwap() | ||
} | ||
}) | ||
}) | ||
} | ||
|
||
|
||
/** | ||
* Change url | ||
* @param {String} url | ||
* @param {Object} opts | ||
*/ | ||
export function go(url, opts) { | ||
if(pjax) pjax.loadUrl(url, opts) | ||
else location.href = url | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
|
||
/** | ||
* Promisified native animation | ||
* @param {HTMLElement} el | ||
* @param {Array} keyframes | ||
* @param {Number} duration | ||
* @return {Promise} | ||
*/ | ||
function animate(el, keyframes, duration = 300) { | ||
return new Promise(done => { | ||
const anim = el.animate(keyframes, { duration }) | ||
anim.onfinish = done | ||
}) | ||
} | ||
|
||
|
||
export default { | ||
|
||
// default transition, do nothing | ||
noop: { | ||
enter: el => Promise.resolve(), | ||
leave: el => Promise.resolve(), | ||
}, | ||
|
||
// simple fade effect | ||
fade: { | ||
enter: el => animate(el, [{ opacity: 1 }, { opacity: 0 }]), | ||
leave: el => animate(el, [{ opacity: 0 }, { opacity: 1 }]) | ||
} | ||
|
||
} |