Skip to content

Next release #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 20 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ A Keynote-inspired presentation app written with Mithril

3. Using a browser, go to `http://localhost:8000` and you'll see example slides.

4. To add or edit slides, make changes to the `slides.json` file and reload your browser.
4. To add or edit slides, make changes to the `slides.json` file and reload your
browser.

## Keyboard shortcuts
Shortcuts for navigating slides are listed below.
Expand All @@ -38,25 +39,34 @@ Quit presentation mode | <kbd>Esc</kbd> or <kbd>Q</kbd>
Show or hide the pointer | <kbd>C</kbd>
Change presentation theme | <kbd>T</kbd>

## Touch gestures
Gestures for navigating slides on touchscreen devices.

Action | Gesture
------------------------- | --------------------------------------------
Advance to the next slide | Tap on the right side of the slide
Go to previous slide | Tap on the left side of the slide
Change presentation theme | Touch and hold

## Offline mode
mithril-slides requires an internet connection to work. If you are to present in a
place without one. You can still use mithril-slides by checking out `offline` branch
before starting a web server:
mithril-slides requires an internet connection to work. If you are to present in
a place without one. You can still use mithril-slides by checking out `offline`
branch before starting a web server:

$ git checkout offline
$ python -m SimpleHTTPServer 8000 # Python 2
$ python -m http.server 8000 # Python 3

You also need to change src properties of all image and embed objects in your
`slides.json` file to local files.
You also need to point the `src` property of all images and embed objects in
your `slides.json` file to local files.

## Known issues
Some websites can not be embedded because they have secure HTTP headers (either
`X-Frame-Options` or `Content-Security-Policy`) set in their responses. To remove
those headers, you need a browser extension. For Google Chrome, install
`X-Frame-Options` or `Content-Security-Policy`) set in their responses. To
remove those headers, you need a browser extension. For Google Chrome, install
[ModHeader][1] extension and add response headers for above headers with empty
values. For Firefox, install [Modify Response Headers][2] add-on and add filters for
those headers. The following slide can be used to test your setup:
values. For Firefox, install [Modify Response Headers][2] add-on and add filters
for those headers. The following slide can be used to test your setup:

{
"embed": {
Expand Down
63 changes: 52 additions & 11 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<title>mithril-slides</title>
<style>
/* base */
Expand Down Expand Up @@ -130,8 +130,9 @@
<script src="//unpkg.com/mithril@^1.1.6/mithril.js"></script>
<script>
// setup
var Touch = {LEFT: 0, RIGHT: 1};
var Theme = {BLACK: 0, WHITE: 1, GRADIENT: 2, SHOWROOM: 3};
var TouchDirection = {LEFT: 0, CENTER: 1, RIGHT: 2};
var TouchType = {TAP: 0, PRESS: 1, HOLD: 2};

var Fullscreen = {
isEnabled: function() {
Expand Down Expand Up @@ -170,7 +171,7 @@
index: 0,
pointer: true,
theme: Theme.GRADIENT,
touch: null,
touch: {direction: null, start: null},

setIndex: function(value) {
if (value >= 0 && value < state.slides.length) {
Expand All @@ -188,16 +189,18 @@
}
},
setTouch: function(value) {
if (value in Object.values(Touch)) {
state.touch = value;
if (value in Object.values(TouchDirection)) {
state.touch.direction = value;
state.touch.start = Date.now();
}
},

backward: function() {
state.setIndex(state.index - 1);
},
clearTouch: function() {
state.touch = null;
state.touch.direction = null;
state.touch.start = null;
},
currentSlide: function() {
return state.slides.length > 0 ? state.slides[state.index] : {};
Expand All @@ -210,6 +213,31 @@
return Theme[key] === value;
});
},
getTouchDirection: function(x, width) {
if (!x || !width) {
return null;
}
if (x > width * 2 / 3) {
return TouchDirection.RIGHT;
} else if (x > width / 3) {
return TouchDirection.CENTER;
} else {
return TouchDirection.LEFT;
}
},
getTouchType: function() {
if (!state.touch.start) {
return null;
}
var elapsedTime = Date.now() - state.touch.start;
if (elapsedTime > 500) {
return TouchType.HOLD;
} else if (elapsedTime > 250) {
return TouchType.PRESS;
} else {
return TouchType.TAP;
}
},
loadSlides: function(url) {
return m.request({method: 'GET', url: url}).
then(state.setSlides).
Expand Down Expand Up @@ -245,6 +273,7 @@
style: {cursor: vnode.attrs.pointer ? 'default' : 'none'},
onclick: vnode.attrs.onclick,
ontouchstart: vnode.attrs.ontouchstart,
ontouchmove: vnode.attrs.ontouchmove,
ontouchend: vnode.attrs.ontouchend
}, [
m('#objects', [
Expand All @@ -266,19 +295,30 @@
var Presentation = {
handleTouchstart: function(event) {
event.preventDefault();
var firstTouch = event.touches[0];
var pageCenter = document.body.clientWidth / 2;
state.setTouch(firstTouch.pageX < pageCenter ? Touch.LEFT : Touch.RIGHT);
if (event.touches.length > 1) {
return;
}
var touch = event.touches[0];
var direction = state.getTouchDirection(touch.pageX, document.body.clientWidth);
state.setTouch(direction);
},
handleTouchmove: function(event) {
event.preventDefault();
state.clearTouch();
},
handleTouchend: function(event) {
event.preventDefault();
if (event.touches.length > 0) {
return;
}
if (state.touch === Touch.LEFT) {
var type = state.getTouchType();
var direction = state.touch.direction;
if (type === TouchType.HOLD) {
state.nextTheme();
} else if (type === TouchType.TAP && direction === TouchDirection.LEFT) {
this.play(state.backward);
m.redraw();
} else if (state.touch === Touch.RIGHT) {
} else if (type === TouchType.TAP && direction === TouchDirection.RIGHT) {
this.play(state.forward);
}
state.clearTouch();
Expand Down Expand Up @@ -348,6 +388,7 @@
theme: state.theme,
onclick: this.handleClick.bind(this),
ontouchstart: this.handleTouchstart.bind(this),
ontouchmove: this.handleTouchmove.bind(this),
ontouchend: this.handleTouchend.bind(this),
oncontextmenu: this.handleContextmenu.bind(this),
onkeydown: this.handleKeydown.bind(this)
Expand Down