mithril-slider-tm

1.1.0-qc5 • Public • Published

Content Slider for Mithril on mobile and desktop

Handles series of pageable content. This code is a Mithril component wrapper around HammerJS, with additional features.

Compatible with Mithril 1.0.

Examples

Examples

Features

  • Elements can be swiped or dragged.
  • Content can be anything that can be shown with HTML: a single image, a card, and so on.
  • Elements can be grouped, for instance for series of thumbnails that are shown a group at a time.
  • Elements content can be lazily loaded (see example code).
  • The slider can be controlled with next/previous buttons and queried for state.
  • Right-to-left language support, using mirrored transitions.

Installation

As npm module:

npm install --save mithril-slider

Or download from Github

  • git clone https://github.com/ArthurClemens/mithril-slider.git
  • cd mithril-slider
  • Install Lerna globally: npm install -g lerna
  • npm install
  • lerna init
  • lerna bootstrap

To build the source:

  • cd packages/mithril-slider
  • npm run build

To run the examples:

Usage

import { slider } from 'mithril-slider';

Slider panel contents is called a "page". Call the slider as component, with (at least) options pageData and page:

m(slider, {
  pageData,
  page
})

For option pageData, create a function to fetch page data:

const getPageData = () =>
  m.request({
    method: 'GET',
    url: 'app/data/images.json',
    background: false
  });

The function needs to return a promise (which m.request does).

The data can be anything, as long as a list is passed in the end. For example:

[
  "images/1.jpg",
  "images/2.jpg"
]

or

[
  {
    "title": "Love Valley, Cappadocia",
    "image": "images/1.jpg"
  },
]

For option page, create a function that returns a Mithril object for each single data item:

const page = opts =>
  m('.page', {
    style: {
      backgroundImage: `url(${opts.data})`
    }
  });

This function will be called for all list items.

Optimizing with lazy loading

The page function is called for all items in the list, so in the current form all images will get downloaded. For longer sliders this is not ideal, especially not on mobile.

We can optimize this by only loading the current, next and previous image:

const page = opts => {
  const currentIndex = opts.currentIndex;
  const listIndex = opts.listIndex;
  const data = opts.data;
  const style = (Math.abs(currentIndex - listIndex) < 2)
    ? { backgroundImage: `url(${data})` }
    : null;
  return m('.page', {
    style: style
  });
};

Sliding multiple pages

When showing more than one "page", for instance a series of thumbnails, use option groupBy:

const mySlider = m(slider, {
  pageData,
  page,
  groupBy: 3
});

For responsive interfaces, the number of pages within a group may be set dynamically (for instance divide the window width by the number of items to show).

No additional HTML markup is created for groups.

Use CSS to set the proper page size for each element.

Slider controls

The above example is fine for simply interacting with the slider (swiping/dragging). For more advanced functionality - for instance to conditionally show next/previous buttons - we need to access the slider instance.

By passing option sliderController, we can get a reference to the slider controller. The option is actually a function reference, and we can use m.prop to store the controller for later reference:

const app = {
  view: vnode => {
    const mySlider = m(slider, {
      pageData,
      page,
      sliderController: ctrl => vnode.state.sliderController = ctrl,
      ...
    });
  }
};

Now we can access slider controller methods:

const sliderController = vnode.state.sliderController;
const nextButton = m("a.next", {
  class: sliderController.hasNext()
    ? "enabled"
    : "disabled",
  onclick: () => sliderController.goNext()
}, "Next")

Styling

Note: With horizontal orientation and position: absolute, the page must have a width; with vertical orientation and position: absolute, the page must have a height.

There is very little CSS involved. The simplest approach is to link to the CSS file dist/mithril-slider.css, or copy the few lines to your own project.

Alternatively, Mithril Slider comes with a JavaScript based CSS object that is prepared for j2c, but does not import j2c itself. In the examples the CSS object is used to add styles to head:

import { css } from "mithril-slider";
import { addStyle } from "../app/styler";
addStyle("slider", css);

Configuration options

Parameter Mandatory Type Default Description
page required Function :: ({data :: any, listIndex :: Number, currentIndex :: Number}) => Mithril Template or String Function that creates an page from data
pageData required Function :: () => Promise Function that fetches a list of page data; should return a promise; after resolving m.redraw is called
sliderController optional Function :: () => Function Receives the slider controller function
class optional String Extra CSS class appended to 'slider'
duration optional Number 200 Default transition duration in ms (when not dragging); when dragging, duration is dependent on dragging velocity, this setting is the maximum duration for slow drags
orientation optional String 'horizontal' Either 'horizontal', 'vertical' or 'all'; translates to HammerJS's direction
rtl optional Boolean false Right-to-left language support (for instance Arabic and Hebrew); set to true to mirror transitions
pageOffsetX optional Number 0 The offset when the page element is displayed with an x offset relative to the slider container
pageOffsetY optional Number 0 The offset when the page element is displayed with an y offset relative to the slider container
groupBy optional Number Number of items within a group
before optional Mithril template or component Content shown before the pages; has class before
after optional Mithril template or component Content shown after the pages; has class after
index optional Number 0 Starting page index
cancelDragFactor optional Number 1/5 Fraction of page width below which the transition is cancelled
getState optional Function(state {Object}) Callback function that accepts the slider state (Object with properties index {Number}, hasNext {Booleam}, hasPrevious {Boolean}, pageEl {HTMLElement})

Slider controller methods

Method Type Description
index index() => Number The current page (index of the page list)
hasNext hasNext() => Boolean True if the current page has a next page
hasPrevious hasPrevious() => Boolean True if the current page has a previous page
goTo goTo(index :: Number, duration :: Number) Change the current page to the given index; transition duration is optional
goCurrent goCurrent(duration :: Number) Go to current page; useful after resize; transition duration is optional
goNext goNext(duration :: Number) Change the current page to the next index; if no next index exists, index is unchanged; transition duration is optional
goPrevious goPrevious(duration :: Number) Change the current page to the previous index; if no previous index exists, index is unchanged; transition duration is optional

CSS classes

Element Key Class
slider slider mithril-slider
content content mithril-slider__content
before before mithril-slider__before
after after mithril-slider__after

Size

Minified and gzipped: 1.8 Kb

Dependencies

Licence

MIT

Package Sidebar

Install

npm i mithril-slider-tm

Weekly Downloads

1

Version

1.1.0-qc5

License

MIT

Unpacked Size

41.8 kB

Total Files

6

Last publish

Collaborators

  • timmensch