Giter Club home page Giter Club logo

pageable's Introduction

Pageable

Maintenance Code Climate maintainability npm license GitHub release npm GitHub issues GitHub issues

Pageable transforms a web page into a full page scrolling presentation.

  • Lightweight (less than 3kb gzipped)
  • Responsive
  • Performant
  • Touch support
  • Easy to set up
  • IE10+

Demos


If this project helps you then you can grab me a coffee or beer to say thanks.

paypal


Contents


Install

npm

npm install pageable --save

Browser

Grab the file from one of the CDNs and include it in your page:

https://unpkg.com/pageable@latest/dist/pageable.min.js

You can replace latest with the required release number if needed.

You can also include the optional stylesheet that applies styling to the nav pips and buttons:

https://unpkg.com/pageable@latest/dist/pageable.min.css

Set up

Define a container element that has at least one descendant element with the data-anchor attribute.

HTML

<div id="container">
    <div data-anchor="Page 1"></div>
    <div data-anchor="Page 2"></div>
    <div data-anchor="Page 3"></div>
    <div data-anchor="Page 4"></div>
    ....
</div>

Instantiate Pageable and pass a reference to the container in the constructor:

JS

new Pageable("#container");

The HTML will be transformed in the following way:

<div class="pg-wrapper">
    <div id="container" class="pg-container">
        <!-- pages -->
        <div data-anchor="page-1" id="page-1" class="pg-page pg-active"></div>
        <div data-anchor="page-2" id="page-2" class="pg-page"></div>
        <div data-anchor="page-3" id="page-3" class="pg-page"></div>
        <div data-anchor="page-4" id="page-4" class="pg-page"></div>
        ...
    </div>
    <!-- pips will go here -->
</div>

If you don't set the [data-anchor] attribute then you must set the anchors with the anchors option.

If pips are enabled, their HTML will be appended to the .pg-wrapper element after the .pg-container element.

The defined anchors will be 'slugified' and used as the page's id - e.g. My Page 1 will be converted to my-page-1

Take care not to have another element with a duplicate id


You can pass an object as the second paramater to customise the instance:

JS

new Pageable("#container", {
    childSelector: "[data-anchor]" // CSS3 selector string for the pages
    anchors: [], // define the page anchors
    pips: true, // display the pips
    animation: 300, // the duration in ms of the scroll animation
    delay: 0, // the delay in ms before the scroll animation starts
    throttle: 50, // the interval in ms that the resize callback is fired
    orientation: "vertical", // or horizontal
    swipeThreshold: 50, // swipe / mouse drag distance (px) before firing the page change event
    freeScroll: false, // allow manual scrolling when dragging instead of automatically moving to next page
    navPrevEl: false, // define an element to use to scroll to the previous page (CSS3 selector string or Element reference)
    navNextEl: false, // define an element to use to scroll to the next page (CSS3 selector string or Element reference)
    infinite: false, // enable infinite scrolling (from 0.4.0)
    slideshow: { // enable slideshow that cycles through your pages automatically (from 0.4.0)
        interval: 3000, // time in ms between page change,
        delay: 0 // delay in ms after the interval has ended and before changing page
    },
    events: {
        wheel: true, // enable / disable mousewheel scrolling
        mouse: true, // enable / disable mouse drag scrolling
        touch: true, // enable / disable touch / swipe scrolling
        keydown: true, // enable / disable keyboard navigation
    },
    easing: function(currentTime, startPos, endPos, interval) {
        // the easing function used for the scroll animation
        return -endPos * (currentTime /= interval) * (currentTime - 2) + startPos;
    },
    onInit: function() {
        // do something when the instance is ready
    },
    onUpdate: function() {
        // do something when the instance updates
    },    
    onBeforeStart: function() {
        // do something before scrolling begins
    },
    onStart: function() {
        // do something when scrolling begins
    },
    onScroll: function() {
        // do something during scroll
    },
    onFinish: function() {
        // do something when scrolling ends
    },
});

Anchors

Any anchor on your page that has a hash that matches the ones in the current Pageable instance will trigger scrolling. This allows you to add navigation links without needing to define event listeners or callbacks to get them to trigger a scroll.


API Reference


Options

childSelector

type: Boolean
default: true

A CSS3 selector string for selecting the nodes to be used as pages


anchors

type: Array
default: undefined

An array of strings to use as the page anchors. Make sure the number of anchors used is equal to the number of pages.


pips

type: Boolean
default: true

Displays the navigation pips.


animation

type: Number
default: 300

Sets the scroll animation duration. Set to 0 to disable animation.

NOTE: This option was known as interval in versions prior to v0.5.0


delay

type: Number
default: 0

Sets the delay in ms before the scroll animation starts.


swipeThreshold

type: Number
default: 50

Sets the swipe / mouse drag distance in px before firing the page change event. If drag / swipe distance is below this threshold then scrolling will not activate.


freeScroll

type: Boolean
default: false

Sets the ability to drag / scroll freely instead of snapping to the next page.


infinite

type: Boolean
default: false

Allow seamless continuous scrolling.


orientation

type: String
default: 'vertical'

Sets the orientation of the instance. Either 'vertical' or 'horizontal'.


throttle

type: Number
default: 50

Sets the interval in ms that the resize callback is fired.


navPrevEl

type: String|HTMLElement
default: false

Define an element to use to scroll to the previous page. A valid CSS3 selector string or Element reference.


navNextEl

type: String|HTMLElement
default: false

Define an element to use to scroll to the next page. A valid CSS3 selector string or Element reference.


slideshow

type: Object
default: false

Enables the slideshow function that cycles through your pages automatically.

The object has two properties to further customise the slidewhow:

  • interval - length of time in ms to display each page.
  • delay - delay in ms after the interval has ended and before changing page.

events

type: Object

Define the allowed events.

  • wheel - enable / disable mousewheel scrolling
  • mouse - enable / disable mouse drag scrolling
  • touch - enable / disable touch / swipe scrolling
  • keydown - enable / disable keyboard navigation

All properties are set to true by default.


easing

type: Function

Define the easing function used for the scroll animation.

The function takes four arguments:

function(currentTime, startPos, endPos, interval) {
    // the default easing function
    return -endPos * (currentTime /= interval) * (currentTime - 2) + startPos;
}
  • currentTime - The current time in ms
  • startPos - The start position in px
  • endPos - The end position in px
  • interval - The duration of the animation in ms

onInit

type: Function
default: noop

Define a callback to be called when the instance is fully rendered and ready for use.

The function takes a single argument that returns the data object (See Custom Events)

new Pageable("#container", {
    onInit: function(data) {
        // data.index, data.scrolled, data.max
    }
});

onUpdate

type: Function
default: noop

Define a callback to be called when the instance updates.

The function takes a single argument that returns the data object (See Custom Events)


onBeforeStart

type: Function
default: noop

Define a callback to be called before scrolling begins.

The function takes a single argument that returns the data object (See Custom Events)


onStart

type: Function
default: noop

Define a callback to be called when scrolling begins.

The function takes a single argument that returns the data object (See Custom Events)


onScroll

type: Function
default: noop

Define a callback to be called while scrolling.

The function takes a single argument that returns the data object (See Custom Events)


onFinish

type: Function
default: noop

Define a callback to be called when scrolling finishes.

The function takes a single argument that returns the data object (See Custom Events)


Methods

destroy()

Destroy the instance.

This will remove all event listeners and return the DOM to it's initial state.

pageable.destroy();

init()

Initialise the instance after destroying.

pageable.init();

next()

Scroll to next page.

pageable.next();

prev()

Scroll to previous page.

pageable.prev();

scrollToPage([page])

Scroll to defined page number.

// scroll to page 3
pageable.scrollToPage(3);

scrollToAnchor([anchor])

Scroll to defined anchor.

pageable.scrollToAnchor("#myanchor");

orientate([orientation])

Orientate the instance to either vertical or horizontal.

pageable.orientate("horizontal");
// or
pageable.orientate("vertical");

slideshow()

Returns an instance of the slideshow. This requires the slideshow option to be set to true (v0.4.0 and above).

The sideshow instance has two methods:

  • start() - starts / resumes the slideshow
  • stop() - stops / pauses the slideshow
// stop / pause slideshow
pageable.slideshow().stop();

// start / resume slideshow
pageable.slideshow().start();

on([event, [callback]])

Add custom event listener. See Custom Events


off([event, [callback]])

remove custom event listener. See Custom Events


Custom Events

You can listen to Pageable's custom events with the on(type, callback) method.

The callback has one argument which returns the data object:

{
    index: // the current page index
    scrolled: // the current scroll offset
    max: // the maximum scroll amount possible
    percent: // the scroll position as a percentage of the maximum scroll (v0.6.7 and above)
}

The percent property can be helpful when adding progress indicators (see Adding Progress Bars).

Examples

const pages = new Pageable("#container");

pages.on("init", data => {
    // do something when the instance is ready
});

pages.on("update", data => {
    // do something when the instance is updated
    
    // this event also fires when the screen size changes
});

pages.on("scroll.before", data => {
    // do something before scrolling starts
    
    // this event will fire when the defined delay begins
    
    // e.g. if the delay is set to 400, this event will
    // fire 400ms BEFORE the "scroll.start" event fires    
});

pages.on("scroll.start", data => {
    // do something when scrolling starts
    
    // this event will fire when the defined delay ends
    
    // e.g. if the delay is set to 400, this event will
    // fire 400ms AFTER the "scroll.before" event fires
});

pages.on("scroll", data => {
    // do something during scroll
});

pages.on("scroll.end", data => {
    // do something when scrolling ends
});

If this project helps you then you can grab me a coffee or beer to say thanks.

paypal


Copyright © 2018 Karl Saunders | BSD & MIT license

pageable's People

Contributors

mobius1 avatar wigzen avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pageable's Issues

Option to disable the keydown event?

Hi,

Thanks for the great plugin!

Is it possible to add in an option to disable the keydown event?

This appears to be hijacking other keydown events I have on the page - like with inputs.

Something like

events: {
    keydown: false,
}

Colorbox Issue

Hi

I use Pageable as a slideshow, and some slides use Colorbox to pop up or pop out images
I wish to show something.

Whilst viewing inside Colorbox, Pageable will scroll away from the original slide.

Is there a way to prevent this scrolling?

Using Windows7, Firefox 69.0.2 (32-bit)

pips: true,
animation: 100,
delay: 300,
throttle: 150,
orientation: "horizontal",
easing: function easing(t, b, c, d, s) {
return -c * (t /= d) * (t - 2) + b;
},
onInit: noop,
onUpdate: noop,
onBeforeStart: noop,
onStart: noop,
onScroll: noop,
onFinish: noop,
swipeThreshold: 50,
freeScroll: false,
slideshow: false,
infinite: false,
childSelector: '[data-anchor]',
events: {
wheel: true,
mouse: true,
touch: true,
keydown: true
}

Proposal regarding the window size

Hi Mobius1,
thanks a lot for creating this! I'm playing with it these days and I started wondering about the window size.
I see that you are defining it using the window's inner dimensions:
width: window.innerWidth,
height: window.innerHeight

I wonder whether, especially for mobile, it wouldn't be better to use something else. For example I'm getting more consistent results using the body's dimensions:
width: document.body.clientWidth,
height: document.body.clientHeight

The issue with using window's dimensions on mobile is that most of the time part of the window is covered by the address bar (on Chrome at least) and even using innerWidth/innerHeight as you are doing, it doesn't seem to consistently return the available space, but rather the dimensions of the whole window. At least for me this makes the content quite often look not centered and it even goes out of the view.

Would you consider making this configurable somehow?

Again, thanks a lot for this library.

Resizing Issue

After resizing the browser window when again maximize the window. it remains in same size with scroll bar.
screenshot from 2018-10-25 16-47-36

events not working

Can't disable events in settings
events: { wheel: false, // enable / disable mousewheel scrolling mouse: false, // enable / disable mouse drag scrolling touch: false, // enable / disable touch / swipe scrolling keydown: false, // enable / disable keyboard navigation },

Important Issue!

It points to a file that does not have a main value in the package.json file.

package.json 파일의 main 값이 없는 파일을 가리키고 있습니다.

Normal scrolling works during animation on mobile Chrome

Normal scrolling works during animation, that offsets position if swiped during it and animation ends up being offset. Next switch is abrupt since predicted position is incorrect. Project demos have that issue as well.

Tested on mobile Chrome 80.0.3987.132

pips not visible

I am using pageable in a react app and I am not able to see navigation pips by default

Links inside pages not working with touch devices

Hi!

I noticed that with a touch input (either with a mobile device or Chrome responsive emulation) clicking on a link doesn't work unless you "double touch" it.

However, this doesn't happen if you set touch events to false on initialisation, so I thought this was caused by Pageable catching the touch to swipe thus preventing to trigger the link's.

This behaviour can be replicated in the playground by replacing a page text with a link while in responsive mode in chrome.

If anyone else reading this is affected by this issue and looking for a temporary solution : I fixed it with some JS by adding a listener on the affected links that redirects to their url but that isn't ideal

Array.from(document.querySelectorAll('.myLink')).forEach((el) => {
  el.addEventListener('touchend', () => {
    window.location.href = el.href;
  });
});

on leave?

like Fullpage, I want to use function 'onLeave'

Possible to use with React?

Hello do you know if it's possible to use this within a react app and if so how? I have tried integrating it in a few different ways but it does not seem to work.

Pageable instance destroy function not working.

I'm trying to destroy the instance as shown

...
  useEffect(() => {
    return () => {
      if (window.pageable) {
        window.pageable.destroy();
      }
    }
  }, [])
...

but this is not working,
In spa when I'm navigating to another route I'm still facing the full page snap scroll working.
Not able to get back to the normal scroll state for different pages in my application.

Please help!

[bug] window resize event

Before the window resize event is over, your event is running. (matching width and height)
That part is as follows.

'window.addEventListener ("resize", this.callbacks.update, false);

Pageable.prototype.update = function () {
  ...
};

I'm not good enough, I need your help. I cheer you. Thank you.

How can I show more content in one Pageable?

It is a very cool script, but I want it to use responsive.
If I resize my window, the content-high in the box will be greater. Or if my content-high greater than the Pageable-High ... the user has no chance to scroll in this box!
Is there an opinion that the user can scroll in this box, if the content higher as the Pageable .. or (better) is there an opinion that the Pageable will be greater (higher) that the user can scroll to the end and than he jump to the next Pageable?
Thank you very much.
Greetings

How to deal with an updating container?

I have an API returning results back into the container. Unfortunately, it doesn't seem to pick up the new data-anchors on those elements. Is there a way to tell pageable to reevaluate the container?

Drag and swipe distance before trigger event

Hello,
Is it possible to put a custom distance before the drag or swipe event is fired ?
Now it's like 1px down or up trigger the related event but I added a slider inside with swipe/drag and if i don't do a perfect line left or right then it change page and don't slide.

Trackpad continued scrolling

I've noticed that when scrolling on a trackpad that Pageable has a tendency to scroll through two or more pages (depending on how "aggressive" the scroll gesture was). This is something that I've been able to replicate in multiple browsers (Chrome/Firefox/Safari) and on both Mac and PC.

Should also note that adjusting the swipeThreshold doesn't seem to affect this behavior, and that it is still possible to only scroll one page at a time (albeit with significantly and unnaturally small swipe gestures on the trackpad).

Floating Button per page

Hi
Struggling with CSS. I'd like to place a different button per page bottom right, like the ones in material-design of android. But no matter what they overlap each other and are not sticky to it's page.

To be clear, this is not a bug, this is just a question of somebody unable to do proper CSS :)

https://jsfiddle.net/chlehmann/nt8eq5x0/

Any help would be much apreciated!!

[bug] events inside box doesn`t works

Events inside box doesn`t works on mobile chrome browser.
Chrome 77.0.3865.116

	const options = {
		pips: true,
		infinite: true,
		easing: function(currentTime, startPos, endPos, interval) {
			// the easing function used for the scroll animation
			return -endPos * (currentTime /= interval) * (currentTime - 2) + startPos;
		},
	}

Безымянный

More:

Plugin works well only in the web version on a real mobile device works like shit. Why does pugin try to render a block every time? he doesn’t succeed, the layout floats loaded for a long time. Why can't you make a dumb scroll from block to block only?
This is not ready for production, please correct the errors or do not mislead people so that there is no waste of time

How to use with nextjs

I tried multiple ways, from hooks to class components, but none seem to be working for nextjs, can someone please provide a proper example or explanation on how to integrate this with next.js.

i'd really really love to use this but im not able to

Pageable: The container could not be found.

I created React app and when I use Pageable its thrown a error: App.jsx:9 Pageable: The container could not be found.

Code example:

import { useState } from 'react'
import Pageable from 'pageable'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'

function App() {
  const [count, setCount] = useState(0)
  const pageable = new Pageable('#container', {
    childSelector: "[data-anchor]",
    anchors: [],
    animation: 700,
  });

  return (
    <> 
      <div id="container">
        <div data-anchor="Page 1" className='section'>
                    <div>
                      <a href="https://vitejs.dev">
                        <img src={viteLogo} className="logo" alt="Vite logo" />
                      </a>
                      <a href="https://react.dev">
                        <img src={reactLogo} className="logo react" alt="React logo" />
                      </a>
                    </div>
                    <h1>Vite + React</h1>
                    <div className="card">
                      <button onClick={() => setCount((count) => count + 1)}>
                        count is {count}
                      </button>
                      <p>
                        Edit <code>src/App.jsx</code> and save to test HMR
                      </p>
                    </div>
                    <p className="read-the-docs">
                      Click on the Vite and React logos to learn more
                    </p>
        </div>
        <div data-anchor="Page 2" className='section'>
                    <div>
                      <a href="https://vitejs.dev">
                        <img src={viteLogo} className="logo" alt="Vite logo" />
                      </a>
                      <a href="https://react.dev">
                        <img src={reactLogo} className="logo react" alt="React logo" />
                      </a>
                    </div>
                    <h1>Vite + React</h1>
                    <div className="card">
                      <button onClick={() => setCount((count) => count + 1)}>
                        count is {count}
                      </button>
                      <p>
                        Edit <code>src/App.jsx</code> and save to test HMR
                      </p>
                    </div>
                    <p className="read-the-docs">
                      Click on the Vite and React logos to learn more
                    </p>
        </div>
        <div data-anchor="Page 3" className='section'>
                    <div>
                      <a href="https://vitejs.dev">
                        <img src={viteLogo} className="logo" alt="Vite logo" />
                      </a>
                      <a href="https://react.dev">
                        <img src={reactLogo} className="logo react" alt="React logo" />
                      </a>
                    </div>
                    <h1>Vite + React</h1>
                    <div className="card">
                      <button onClick={() => setCount((count) => count + 1)}>
                        count is {count}
                      </button>
                      <p>
                        Edit <code>src/App.jsx</code> and save to test HMR
                      </p>
                    </div>
                    <p className="read-the-docs">
                      Click on the Vite and React logos to learn more
                    </p>
        </div>
      </div>

    </>
  )
}

export default App

Free Scroll inside container with overflow-y scroll

Not sure where to ask this.
Scrolling inside container doesn't freescroll. Scrolling anywhere on container executes pageable full page scroll animation. I realize that is by design, but is there anyway to set freescroll to true when scrolling inside a container on the page that has overflow-y set to scroll?

<section>
  *scroll here full page scroll
  <div class="overflow-y-scroll">
       A container with overflowed content meant to have default scroll or touch drag behavior
   </div>
</section>
*scroll here full page scroll
<section>
*scroll here full page scroll
</section

Any help with this would be appreciated.

chrome horizontal scroll on pg-wrapper when box-sizing: border-box;

There's a problem on Chrome Version 75.0.3770.142 (Official Build) (64-bit) / Wiindows10.

When pg-wrapper element has box-sizing: border-box; which I have because of globally applying css reset (including) border-box setting to all elements, horizontal scroll appears (and stays) on pg-wrapper after the script init, overwriting this setting by:

.pg-wrapper {
  box-sizing: content-box;
}

solves the issue.
This problem appears only on Chrome.

Adding horizontal page scroll to vertical.

I have a vertical scroll initiated which is working great. Now I initiated another horizontal scroll with as container a div within the second page of the vertical scroll and other names for the data-anchors.
Since swiping/scrolling would be too glitch/risky I disabled those and use a button. So when I press the button everything works fine until the end of the animation. When the animation seems to stop the page is on the next page but then 'glitches' back to the first horizontal page. The active classes are on the right divs however.
Making a comment of
that.container.style.transform = "";
in _scrollBy makes it work for the 1st and 2nd page but not others. And that also doesn't make vertical animations work well.

It's not working in Chrome & FF (didn't test other browsers).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.