Bespoke.js
DIY Presentation Micro-Framework
Bespoke.js is a super minimal (1KB min'd and gzipped), modular presentation library for modern browsers, designed to foster a rich plugin ecosystem.
The core library sets up the presentation, provides a simple control API and manages events. Any other functionality is implemented as a plugin.
Joining the Bespoke.js ecosystem is simple with the suite of official Yeoman generators:
Creating a Presentation
Due to the highly modular nature of Bespoke.js, the quickest way to get started is with Bespoke.js Generator, a Yeoman generator that scaffolds a boilerplate presentation with a Gulp build system.
Assuming you have Node.js installed, in a blank directory:
$ npm install -g generator-bespoke
$ yo bespoke
In your newly scaffolded project, you can use the following Gulp tasks:
$ gulp serve
to run a preview server with LiveReload.$ gulp deploy
to deploy to GitHub Pages.$ gulp
to compile static assets to 'public'.
For more detailed instructions, check out the Bespoke.js Generator repo.
If you'd prefer to craft a new presentation from scratch, you can install Bespoke.js from npm with npm install bespoke
, Bower with bower install bespoke.js
, or manually download either the production version or the development version. The Bespoke.js core is extremely lightweight, so you'll probably want to include some plugins.
Basic Usage
Loading Bespoke
Bespoke.js is shipped in a UMD format, meaning that bespoke
and its plugins are available as CommonJS/AMD modules or browser globals.
Markup
It's completely up to you which tags you use, but the following is a good starting point:
<article id="presentation">
<section>Slide 1</section>
<section>Slide 2</section>
<section>Slide 3</section>
</article>
JavaScript
To create a new presentation, Bespoke.js provides the from(selector[, plugins])
method, which takes a selector or element reference and an array of plugins, and returns a deck instance.
var deck = bespoke.from('#presentation', [plugins]);
deck.next();
deck.prev();
deck.slide(0);
deck.slide();
By default, all non-script child elements of the resolved parent element become slides.
Plugins
Official Plugins
All official plugins can be installed from npm or Bower, e.g. $ npm install bespoke-keys
or $ bower install bespoke-touch
All Plugins
You can view the full list of Bespoke.js plugins on npm by browsing the bespoke-plugin keyword.
Using Plugins
All official plugins are provided in a UMD format, meaning they are available as CommonJS/AMD modules or browser globals.
For example, if you're using CommonJS modules via browserify or webpack, it would look something like this:
var bespoke = require('bespoke'),
classes = require('bespoke-classes'),
keys = require('bespoke-keys'),
touch = require('bespoke-touch');
var deck = bespoke.from('#presentation', [
classes(),
keys(),
touch()
]);
If you're using browser globals, all official plugins are added to the bespoke.plugins
object, for example:
var deck = bespoke.from('#presentation', [
bespoke.plugins.classes(),
bespoke.plugins.keys(),
bespoke.plugins.touch()
]);
Themes
Official Themes
As with plugins, all official themes can be installed from npm or Bower, e.g. $ npm install bespoke-theme-cube
or $ bower install bespoke-theme-voltaire
All Themes
You can view the full list of Bespoke.js themes on npm by browsing the bespoke-theme keyword.
Using Themes
Themes are included just like any other plugin:
var bespoke = require('bespoke'),
cube = require('bespoke-theme-cube'),
keys = require('bespoke-keys'),
touch = require('bespoke-touch');
var deck = bespoke.from('#presentation', [
cube(),
keys(),
touch()
]);
If you're using browser globals, all official themes are added to the bespoke.themes
object, for example:
var deck = bespoke.from('#presentation', [
bespoke.themes.cube(),
bespoke.plugins.keys(),
bespoke.plugins.touch()
]);
Advanced Usage
From HTMLElement
If you already have a reference to a DOM node, you can pass it directly to the from
method.
bespoke.from(element);
Slide Selector
You can specify which elements become slides by passing an options Hash containing the key parent
and, optionally, the key slides
) to the from
method.
The value of either key can be a CSS selector or a DOM node.
bespoke.from({ parent: selectorOrElement, slides: selectorOrElementList });
For example:
bespoke.from({ parent: '#presentation', slides: '#presentation > section' });
This advanced usage allows you to include auxilary HTML inside the parent element, skip slides that don't match the selector or explicitly filter out slides before passing on the collection.
Deck Instances
Deck instances are provided to plugins and returned when instantiating a presentation. The following properties are available on each instance.
Note: The optional eventData
parameter is an object that will be merged with the event
object in subsequent event handlers.
next([eventData]) | Next slide. |
prev([eventData]) | Previous slide. |
slide([index[, eventData]]) | Get or set the active slide index. |
on(event, callback) | Attach event handlers |
off(event, callback) | Unbind event handlers |
fire(event[, eventData]) | Fire custom events. This method is primarily designed for plugin authors. |
parent | The deck's parent element |
slides | An array of slide elements |
Events
Binding Events
Events are bound via the deck instance. Each event is passed an event object containing a reference to the relevant slide and its index.
deck.on(eventName, function(event) {
event.slide;
event.index;
return false;
});
Standard Events
In most cases, you will only need to use these standard events.
activate | A slide has been activated. event.slide is the activated slide. |
deactivate | A slide has been deactivated. event.slide is the deactivated slide. |
Deck Interaction Events
These events are fired when the deck has been interacted with, but before the interaction has had any effect.
This allows you to intercept the default behaviour by returning false
from the event handler.
next | The next slide has been requested, even if last slide is active. event.slide is the current slide. |
prev | The previous slide has been requested, even if first slide is active. event.slide is the current slide. |
slide | A specific slide has been requested. event.slide is the requested slide. |
Unbinding events
When binding events, the on
method returns a function that can be used to remove the event handler.
var off = deck.on('activate', function() {
});
off();
You can also use the off
method. However, you must use the same function reference that was used when registering the event.
deck.on('activate', onActivate);
deck.off('activate', onActivate);
Creating Plugins
Want a boilerplate plugin? Use the official Bespoke.js Plugin Generator.
If you'd like to learn by example, check out the list of existing plugins.
Basic Plugins
Plugins are simply functions that are called when presentations are created. They are passed a deck instance which allows you to interact with the deck's state, bind events and modify its elements.
To be consistent with the suite of official Bespoke.js plugins, it is highly recommended that you implement your plugin as a function that takes configuration and returns a plugin function.
var myPlugin = function() {
return function() {
deck.on('activate', function(e) {
console.log('Activated slide ' + (e.index + 1) + ' of ' + deck.slides.length);
});
}
};
The plugin can now be provided in the plugins array when using the from(selector[, plugins])
method.
bespoke.from('#presentation', [
myPlugin()
]);
Plugins with Options
If your plugin needs some configurability, your plugin factory function can take options and return a configured plugin function.
var myPlugin = function(options) {
return function(deck) {
var showTotal = options && options.showTotal;
deck.on('activate', function(e) {
console.log('Activated slide ' + (e.index + 1) +
(showTotal ? ' of ' + deck.slides.length : ''));
});
}
};
bespoke.from('#presentation', [
myPlugin({ showTotal: true })
]);
Custom Event Data
Additional event data can be supplied to next
, prev
and slide
, which is merged with the final event
object in subsequent event handlers.
This functionality is particularly useful if you need to differentiate between events caused by your plugin, and those caused by your end users or other plugins.
var myPlugin = function() {
return function(deck) {
deck.on('activate', function(event) {
if (event.foo === 'bar') {
} else {
}
});
deck.next({
foo: 'bar'
});
};
}
Creating Themes
Themes are essentially just plugins that also happen to insert styles into the page.
You can quickly scaffold a boilerplate theme project with the official Bespoke.js Theme Generator.
Presentations
Made a presentation with Bespoke.js? Let me know.
Questions?
Contact me on GitHub or Twitter: @markdalgleish
License
MIT License