Add next/prev chapter buttons for mobile devices

Also removes touch events as they interfere with continuous scrolling
This commit is contained in:
Daniyar Itegulov 2020-09-14 18:51:03 +10:00
parent 270f585b26
commit 14583cf18e
No known key found for this signature in database
GPG Key ID: 4DB862B7839037FD
2 changed files with 77 additions and 44 deletions

View File

@ -19,6 +19,8 @@ export class BookPlayer {
this.onDialogClosed = this.onDialogClosed.bind(this); this.onDialogClosed = this.onDialogClosed.bind(this);
this.openTableOfContents = this.openTableOfContents.bind(this); this.openTableOfContents = this.openTableOfContents.bind(this);
this.prevChapter = this.prevChapter.bind(this);
this.nextChapter = this.nextChapter.bind(this);
this.onWindowKeyUp = this.onWindowKeyUp.bind(this); this.onWindowKeyUp = this.onWindowKeyUp.bind(this);
} }
@ -123,26 +125,6 @@ export class BookPlayer {
} }
} }
onTouchStart(e) {
// TODO: depending on the event this can be the document or the rendition itself
const rendition = this._rendition || this;
const book = rendition.book;
// check that the event is from the book or the document
if (!book || this._loaded === false) return;
// epubjs stores pages off the screen or something for preloading
// get the modulus of the touch event to account for the increased width
if (!e.touches || e.touches.length === 0) return;
const touch = e.touches[0].clientX % dom.getWindowSize().innerWidth;
if (touch < dom.getWindowSize().innerWidth / 2) {
book.package.metadata.direction === 'rtl' ? rendition.next() : rendition.prev();
} else {
book.package.metadata.direction === 'rtl' ? rendition.prev() : rendition.next();
}
}
onDialogClosed() { onDialogClosed() {
this.stop(); this.stop();
} }
@ -151,27 +133,33 @@ export class BookPlayer {
const elem = this._mediaElement; const elem = this._mediaElement;
elem.addEventListener('close', this.onDialogClosed, {once: true}); elem.addEventListener('close', this.onDialogClosed, {once: true});
elem.querySelector('.btnBookplayerExit').addEventListener('click', this.onDialogClosed, {once: true}); elem.querySelector('#btnBookplayerExit').addEventListener('click', this.onDialogClosed, {once: true});
elem.querySelector('.btnBookplayerToc').addEventListener('click', this.openTableOfContents); elem.querySelector('#btnBookplayerToc').addEventListener('click', this.openTableOfContents);
if (browser.mobile) {
elem.querySelector('#btnBookplayerPrev').addEventListener('click', this.prevChapter);
elem.querySelector('#btnBookplayerNext').addEventListener('click', this.nextChapter);
}
} }
bindEvents() { bindEvents() {
this.bindMediaElementEvents(); this.bindMediaElementEvents();
document.addEventListener('keyup', this.onWindowKeyUp); document.addEventListener('keyup', this.onWindowKeyUp);
document.addEventListener('touchstart', this.onTouchStart);
// FIXME: I don't really get why document keyup event is not triggered when epub is in focus // FIXME: I don't really get why document keyup event is not triggered when epub is in focus
this._rendition.on('keyup', this.onWindowKeyUp); this._rendition.on('keyup', this.onWindowKeyUp);
this._rendition.on('touchstart', this.onTouchStart);
} }
unbindMediaElementEvents() { unbindMediaElementEvents() {
const elem = this._mediaElement; const elem = this._mediaElement;
elem.removeEventListener('close', this.onDialogClosed); elem.removeEventListener('close', this.onDialogClosed);
elem.querySelector('.btnBookplayerExit').removeEventListener('click', this.onDialogClosed); elem.querySelector('#btnBookplayerExit').removeEventListener('click', this.onDialogClosed);
elem.querySelector('.btnBookplayerToc').removeEventListener('click', this.openTableOfContents); elem.querySelector('#btnBookplayerToc').removeEventListener('click', this.openTableOfContents);
if (browser.mobile) {
elem.querySelector('#btnBookplayerPrev').removeEventListener('click', this.prevChapter);
elem.querySelector('#btnBookplayerNext').removeEventListener('click', this.nextChapter);
}
} }
unbindEvents() { unbindEvents() {
@ -180,11 +168,9 @@ export class BookPlayer {
} }
document.removeEventListener('keyup', this.onWindowKeyUp); document.removeEventListener('keyup', this.onWindowKeyUp);
document.removeEventListener('touchstart', this.onTouchStart);
if (this._rendition) { if (this._rendition) {
this._rendition.off('keyup', this.onWindowKeyUp); this._rendition.off('keyup', this.onWindowKeyUp);
this._rendition.off('touchstart', this.onTouchStart);
} }
} }
@ -194,6 +180,16 @@ export class BookPlayer {
} }
} }
prevChapter(e) {
this._rendition.prev();
e.preventDefault();
}
nextChapter(e) {
this._rendition.next();
e.preventDefault();
}
createMediaElement() { createMediaElement() {
let elem = this._mediaElement; let elem = this._mediaElement;
if (elem) { if (elem) {
@ -214,13 +210,22 @@ export class BookPlayer {
elem.id = 'bookPlayer'; elem.id = 'bookPlayer';
let html = ''; let html = '';
html += '<div class="topRightActionButtons">';
html += '<button is="paper-icon-button-light" class="autoSize bookplayerButton btnBookplayerExit hide-mouse-idle-tv" tabindex="-1"><i class="material-icons bookplayerButtonIcon close"></i></button>'; if (browser.mobile) {
html += '<div class="button-wrapper top-button"><button id="btnBookplayerPrev" is="paper-icon-button-light" class="autoSize bookplayerButton hide-mouse-idle-tv"><i class="material-icons bookplayerButtonIcon navigate_before"></i> Prev</button></div>';
}
html += '<div id="viewer">';
html += '<div class="topButtons">';
html += '<button is="paper-icon-button-light" id="btnBookplayerToc" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1"><i class="material-icons bookplayerButtonIcon toc"></i></button>';
html += '<button is="paper-icon-button-light" id="btnBookplayerExit" class="autoSize bookplayerButton hide-mouse-idle-tv" tabindex="-1"><i class="material-icons bookplayerButtonIcon close"></i></button>';
html += '</div>'; html += '</div>';
html += '<div class="topLeftActionButtons">';
html += '<button is="paper-icon-button-light" class="autoSize bookplayerButton btnBookplayerToc hide-mouse-idle-tv" tabindex="-1"><i class="material-icons bookplayerButtonIcon toc"></i></button>';
html += '</div>'; html += '</div>';
if (browser.mobile) {
html += '<div class="button-wrapper bottom-button"><button id="btnBookplayerNext" is="paper-icon-button-light" class="autoSize bookplayerButton hide-mouse-idle-tv">Next <i class="material-icons bookplayerButtonIcon navigate_next"></i></button></div>';
}
elem.innerHTML = html; elem.innerHTML = html;
dialogHelper.open(elem); dialogHelper.open(elem);
@ -236,9 +241,7 @@ export class BookPlayer {
return book.renderTo(elem, { return book.renderTo(elem, {
width: '100%', width: '100%',
height: '100%', height: '100%',
manager: 'continuous', flow: 'scrolled-doc'
flow: 'scrolled-doc',
offset: 0
}); });
} else { } else {
return book.renderTo(elem, { return book.renderTo(elem, {
@ -266,7 +269,7 @@ export class BookPlayer {
import('epubjs').then(({default: epubjs}) => { import('epubjs').then(({default: epubjs}) => {
const downloadHref = apiClient.getItemDownloadUrl(item.Id); const downloadHref = apiClient.getItemDownloadUrl(item.Id);
const book = epubjs(downloadHref, {openAs: 'epub'}); const book = epubjs(downloadHref, {openAs: 'epub'});
const rendition = this.render(elem, book); const rendition = this.render('viewer', book);
this._currentSrc = downloadHref; this._currentSrc = downloadHref;
this._rendition = rendition; this._rendition = rendition;

View File

@ -7,18 +7,20 @@
background: #fff; background: #fff;
} }
.topRightActionButtons { .topButtons {
right: 0.5vh;
top: 0.5vh; top: 0.5vh;
z-index: 1002; z-index: 1002;
position: absolute; position: sticky;
} }
.topLeftActionButtons { #btnBookplayerToc {
left: 0.5vh; float: left;
top: 0.5vh; margin-left: 2vw;
z-index: 1002; }
position: absolute;
#btnBookplayerExit {
float: right;
margin-right: 2vw;
} }
.bookplayerButtonIcon { .bookplayerButtonIcon {
@ -37,3 +39,31 @@
.bookplayerErrorMsg { .bookplayerErrorMsg {
text-align: center; text-align: center;
} }
#viewer {
align-items: flex-start;
}
#btnBookplayerPrev {
margin: 0.5vh 0.5vh;
color: black;
}
#btnBookplayerNext {
margin: 0.5vh 0.5vh;
color: black;
}
.button-wrapper {
text-align: center;
position: relative;
height: 0;
}
.top-button {
margin: 0.5vh 2em;
}
.bottom-button {
margin: 2em 0.5vh;
}