Skip to content

Commit

Permalink
Bump 2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
myeti committed May 29, 2020
1 parent d9e627f commit 5072674
Show file tree
Hide file tree
Showing 6 changed files with 325 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
dist
lib
package-lock.json
21 changes: 21 additions & 0 deletions licence
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.
31 changes: 31 additions & 0 deletions package.json
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"
}
}
75 changes: 75 additions & 0 deletions readme.md
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
163 changes: 163 additions & 0 deletions src/index.js
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
}
31 changes: 31 additions & 0 deletions src/transitions.js
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 }])
}

}

0 comments on commit 5072674

Please sign in to comment.