Pull To Refresh
Pull to refresh is a special component that can be used to initiate the refreshing of a page’s contents.
Pull To Refresh Layout
Let's look on how to integrate pull to refresh to page:
<div class="page">
<!-- Page content must have additional "ptr-content" class -->
<div class="page-content ptr-content" data-ptr-distance="55" data-ptr-mousewheel="true">
<!-- Default pull to refresh preloader-->
<div class="ptr-preloader">
<div class="preloader"></div>
<div class="ptr-arrow"></div>
</div>
<!-- usual content below -->
<div class="list">
...
</div>
<!-- nested scrollable element -->
<div class="my-scolling-content ptr-watch-scrollable">
...
</div>
<!-- another nested scrollable element -->
<div class="another-scolling-content ptr-ignore">
...
</div>
</div>
</div>
Where:
ptr-content
class. This is required to enable pull to refreshdiv class="ptr-preloader"
hidden layer with pull to refresh visual elements: preloader and arrowdata-ptr-distance="55"
additional attribute that allows to set custom pull to refresh trigger distance. By default (if not specified) it is 44pxdata-ptr-mousewheel="true"
additional attribute that enables pull to refresh with mousewheel (for desktop apps). Works only for PTR top.ptr-watch-scrollable
- additional class that must be added on nested scrollable elements to prevent pull to refresh on such elements scrollingptr-ignore
- additional class that must be added on nested scrollable elements or other elements that will to prevent pull to refresh on such elements scrolling or touchmove
Pull To Refresh From Bottom
It is also possible to make it work like pull from bottom. In this case we need to move ptr-preloader
element to the bottom of page content and add additional ptr-bottom
class to pull to refresh content:
<div class="page">
<!-- ptr-content must have additional "ptr-bottom" class -->
<div class="page-content ptr-content ptr-bottom">
<div class="list">
...
</div>
<!-- Pull to refresh preloader moves to bottom -->
<div class="ptr-preloader">
<div class="preloader"></div>
<div class="ptr-arrow"></div>
</div>
</div>
</div>
Pull To Refresh Sequence
When user starts to pull ptr-content down, then ptr-preloader will receive additional ptr-pull-down
class.
When user pulls down ptr-content on a distance more than 44px (when ptr-preloader will be fully visible), then ptr-preloader will receive additional ptr-pull-up
class which changes arrow rotation to notify user about refresh action on release.
When user release pull to refresh content when it is in "ptr-pull-up" state, then ptr-preloader will receive additional ptr-refreshing
class. In "refreshing" state arrow will be hidden and user will see preloader indicator. On this stage you probably need to do Ajax request and refresh page content.
Pull To Refresh App Methods
There are few App's methods that can be used with pull to refresh container:
app.ptr.create(el)- initialise PTR on specified HTML element container.
- el - HTMLElement or string (with CSS selector) - PTR element (
ptr-content
). Required.
Method returns created PTR instance
app.ptr.destroy(el)- remove PTR event listeners from the specified HTML element
- el - HTMLElement or string (with CSS selector) - PTR element (
ptr-content
). Required.
app.ptr.get(el)- get PTR instance by HTML element
- el - HTMLElement or string (with CSS Selector). PTR element (
ptr-content
).
Method returns PTR instance
app.ptr.done(el)- reset PTR state on specified PTR content element
- el - HTMLElement or string (with CSS Selector). PTR element (
ptr-content
). Required.
app.ptr.refresh(el)- trigger PTR on specified PTR content element
- el - HTMLElement or string (with CSS Selector). PTR element (
ptr-content
). Required.
Pull To Refresh Methods & Properties
If we created PTR manually or used app.ptr.get
method we will PTR initialized instance with useful methods and properties:
// init ptr manually
var ptr = app.ptr.create('.ptr-content');
// or using get to retrieve already created instance
var ptr = app.ptr.get('.ptr-content');
Properties | |
---|---|
ptr.app | Link to global app instance |
ptr.el | PTR HTML element (ptr-content ) |
ptr.$el | Dom7 instance with PTR HTML element (ptr-content ) |
Methods | |
ptr.done() | Reset PTR state |
ptr.refresh() | Trigger PTR |
ptr.destroy() | Destroy PTR instance and remove PTR event listeners from the specified HTML element |
Pull To Refresh Events
PTR will fire the following DOM events on popup element and events on app and popup instance:
DOM Events
Event | Target | Description |
---|---|---|
ptr:pullstart | Pull To Refresh content<div class="ptr-content"> | Event will be triggered when you start to move pull to refresh content |
ptr:pullmove | Pull To Refresh content<div class="ptr-content"> | Event will be triggered during you move pull to refresh content |
ptr:pullend | Pull To Refresh content<div class="ptr-content"> | Event will be triggered when you release pull to refresh content |
ptr:refresh | Pull To Refresh content<div class="ptr-content"> | Event will be triggered when pull to refresh enters in "refreshing" state. event.detail contain ptr.done method to reset its state after loading completed |
ptr:done | Pull To Refresh content<div class="ptr-content"> | Event will be triggered after pull to refresh is done and it is back to initial state (after calling ptr.done method) |
ptr:beforedestroy | Pull To Refresh content<div class="ptr-content"> | Event will be triggered right before PTR instance will be destroyed |
App and Pull To Refresh Instance Events
PTR instance emits events on both self instance and app instance. App instance events has same names prefixed with ptr
.
Event | Target | Arguments | Description |
---|---|---|---|
pullStart | ptr | (el) | Event will be triggered when you start to move pull to refresh content. As an argument event handler receives ptr element |
ptrPullStart | app | (el) | |
pullMove | ptr | (el, data) | Event will be triggered during you move pull to refresh content. As an argument event handler receives ptr element and ptr data containing the following properties:
|
ptrPullMove | app | (el, data) | |
pullEnd | ptr | (el, data) | Event will be triggered when you release pull to refresh content. As an argument event handler receives ptr element |
ptrPullEnd | app | (el, data) | |
refresh | ptr | (el, done) | Event will be triggered when pull to refresh enters in "refreshing" state. As an argument event handler receives ptr element and done function to reset PTR state |
ptrRefresh | app | (el, done) | |
done | ptr | (el) | Event will be triggered after pull to refresh is done and it is back to initial state (after calling ptr.done method). As an argument event handler receives ptr element |
ptrDone | app | (el) | |
beforeDestroy | ptr | (ptr) | Event will be triggered right before PTR instance will be destroyed. As an argument event handler receives PTR instance |
ptrBeforeDestroy | app | (ptr) |
CSS Variables
Below is the list of related CSS variables (CSS custom properties).
.ios {
--f7-ptr-preloader-size: 28px;
--f7-ptr-size: 44px;
}
.md {
--f7-ptr-preloader-size: 22px;
--f7-ptr-size: 40px;
}
.md,
.md .dark,
.md [class*='color-'] {
--f7-ptr-preloader-bg-color: var(--f7-md-surface-1);
--f7-ptr-preloader-color: var(--f7-md-primary);
}
Examples
Pull From Top
<template>
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner">
<div class="title">Pull To Refresh</div>
</div>
</div>
<div class="page-content ptr-content" @ptr:refresh=${loadMore}>
<div class="ptr-preloader">
<div class="preloader"></div>
<div class="ptr-arrow"></div>
</div>
<div class="list media-list">
<ul>
${items.map((item) => $h`
<li class="item-content">
<div class="item-media"><img src=${item.picURL} width="44" /></div>
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">${item.song}</div>
</div>
<div class="item-subtitle">${item.author}</div>
</div>
</li>
`)}
</ul>
</div>
</div>
</div>
</template>
<script>
export default (props, { $update }) => {
// Dummy Content
const songs = ['Yellow Submarine', 'Don\'t Stop Me Now', 'Billie Jean', 'Californication'];
const authors = ['Beatles', 'Queen', 'Michael Jackson', 'Red Hot Chili Peppers'];
let items = [
{
picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-1.jpg',
song: 'Yellow Submarine',
author: 'Beatles',
},
{
picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-2.jpg',
song: 'Don\'t Stop Me Now',
author: 'Queen',
},
{
picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-3.jpg',
song: 'Billie Jean',
author: 'Michael Jackson',
},
]
const loadMore = (e, done) => {
// Emulate 2s loading
setTimeout(() => {
const picURL = 'https://cdn.framework7.io/placeholder/abstract-88x88-' + (Math.floor(Math.random() * 10) + 1) + '.jpg';
const song = songs[Math.floor(Math.random() * songs.length)];
const author = authors[Math.floor(Math.random() * authors.length)];
// Add new item
items.push({
picURL,
song,
author,
});
// Update state to rerender
$update();
// When loading done, we need to reset it
done();
}, 2000);
}
return $render;
}
</script>
Pull From Bottom
<template>
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner">
<div class="title">Pull To Refresh Bottom</div>
</div>
</div>
<div class="page-content ptr-content ptr-bottom" @ptr:refresh=${loadMore}>
<div class="ptr-preloader">
<div class="preloader"></div>
<div class="ptr-arrow"></div>
</div>
<div class="list media-list">
<ul>
${items.map((item) => $h`
<li class="item-content">
<div class="item-media"><img src=${item.picURL} width="44" /></div>
<div class="item-inner">
<div class="item-title-row">
<div class="item-title">${item.song}</div>
</div>
<div class="item-subtitle">${item.author}</div>
</div>
</li>
`)}
</ul>
</div>
</div>
</div>
</template>
<script>
export default (props, { $update }) => {
// Dummy Content
const songs = ['Yellow Submarine', 'Don\'t Stop Me Now', 'Billie Jean', 'Californication'];
const authors = ['Beatles', 'Queen', 'Michael Jackson', 'Red Hot Chili Peppers'];
let items = [
{
picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-1.jpg',
song: 'Yellow Submarine',
author: 'Beatles',
},
{
picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-2.jpg',
song: 'Don\'t Stop Me Now',
author: 'Queen',
},
{
picURL: 'https://cdn.framework7.io/placeholder/abstract-88x88-3.jpg',
song: 'Billie Jean',
author: 'Michael Jackson',
},
]
const loadMore = (e, done) => {
// Emulate 2s loading
setTimeout(() => {
const picURL = 'https://cdn.framework7.io/placeholder/abstract-88x88-' + (Math.floor(Math.random() * 10) + 1) + '.jpg';
const song = songs[Math.floor(Math.random() * songs.length)];
const author = authors[Math.floor(Math.random() * authors.length)];
// Add new item
items.push({
picURL,
song,
author,
});
// Update state to rerender
$update();
// When loading done, we need to reset it
done();
}, 2000);
}
return $render;
}
</script>