Skip to content
Draft
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
17 changes: 16 additions & 1 deletion BookReaderDemo/demo-internetarchive.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,12 @@

</head>

<body>
<body data-variant="attached">
<section class="theater" style="width: 100%; overflow: hidden; background-color: black;">
<ia-bookreader
baseHost="archive.org"
>
<!-- <div id="IABookReaderMessageWrapper" style="height: 55px" slot="header">Borrow Bar</div> -->
<div id="IABookReaderWrapper" slot="main">
<div id="BookReader" class="BookReader"></div>
</div>
Expand Down Expand Up @@ -202,6 +203,15 @@
</li>
</ul>
</details>
<div class="demo">
Variant:
<label>
<input type="radio" name="variant" value="floating"> Floating
</label>
<label>
<input type="radio" name="variant" value="attached" checked> Attached
</label>
</div>
<div class="demo">
<button id="toggle-loggedin">Toggle Logged in view</button>
<p>Features behind signed in gate: Bookmarks</p>
Expand Down Expand Up @@ -235,6 +245,11 @@ <h3>Placeholder div to allow scrolling</h3>
<!-- Certain features, like Bookmarks, use modal-manager to draw their interface -->
<modal-manager></modal-manager>
<script >
// Variant toggle
$('input[name="variant"]').on('change', (e) => {
const variant = e.target.value;
document.body.setAttribute('data-variant', variant);
});
// Set up demo things
const iaBR = document.querySelector('ia-bookreader');
const toggleLoginBtn = document.querySelector('#toggle-loggedin');
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"dependencies": {
"@internetarchive/bergamot-translator": "^0.4.9-ia.1",
"@internetarchive/ia-activity-indicator": "^0.0.4",
"@internetarchive/ia-item-navigator": "2.2.2",
"@internetarchive/ia-item-navigator": "2.3.0-0",
"@internetarchive/icon-bookmark": "^1.3.4",
"@internetarchive/icon-dl": "^1.3.4",
"@internetarchive/icon-edit-pencil": "^1.3.4",
Expand Down
50 changes: 42 additions & 8 deletions src/BookReader.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,32 @@ BookReader.prototype.setup = function(options) {
this.subPrefix = options.subPrefix;
/** @deprecated */
this.bookPath = options.bookPath;
this.fader = utils.debounce(
(source) => this.fader.hide(source),
2000,
(source) => this.fader.show(source),
{
tap: (source) => {
console.log('Show UI ...', source);
},
},
);
this.fader.show = (source) => {
console.log('Show UI');
$(document.body).removeClass('BRfaded');
};
this.fader.hide = (source) => {
console.log('Hide UI');
$(document.body).addClass('BRfaded');
};
this.fader.toggle = (source) => {
if ($(document.body).hasClass('BRfaded')) {
this.fader.show(source);
this.fader(source);
} else {
this.fader.hide(source);
}
};

// Construct the usual plugins first to get type hints
this.plugins = {
Expand Down Expand Up @@ -742,6 +768,17 @@ BookReader.prototype.init = function() {
}
}

// Init modes
for (const mode of Object.values(this._modes)) {
mode.init();
}

if (this.plugins.experiments?.isExperimentEnabled('hideable-chrome')) {
this.refs.$br.on('pointermove', utils.eventFilterMouseMove(ev => ev.pointerType != 'touch' && this.fader('pointermove')));
this.refs.$brContainer[0].addEventListener('scroll', utils.eventFilterScrollUp(() => this.fader('scroll')), { passive: true });
this.refs.$brContainer[0].addEventListener('touchstart', utils.eventFilterSameElement(() => this.fader('touchstart')), { passive: true });
}

this.init.initComplete = true;
this.trigger(BookReader.eventNames.PostInit);

Expand Down Expand Up @@ -1016,16 +1053,12 @@ BookReader.prototype.zoom = function(direction) {
* So resize isn't perceived sharp/jerky
*/
BookReader.prototype.resizeBRcontainer = function(animate) {
const top = this.getToolBarHeight();
const bottom = this.plugins.experiments?.isExperimentEnabled('hideable-chrome') ? 0 : this.getFooterHeight();
if (animate) {
this.refs.$brContainer.animate({
top: this.getToolBarHeight(),
bottom: this.getFooterHeight(),
}, this.constResizeAnimationDuration, 'linear');
this.refs.$brContainer.animate({ top, bottom }, this.constResizeAnimationDuration, 'linear');
} else {
this.refs.$brContainer.css({
top: this.getToolBarHeight(),
bottom: this.getFooterHeight(),
});
this.refs.$brContainer.css({ top, bottom });
}
};

Expand Down Expand Up @@ -1978,6 +2011,7 @@ BookReader.prototype.queryStringFromParams = function(

/**
* Helper to select within instance's elements
* @returns {JQuery<HTMLElement>}
*/
BookReader.prototype.$ = function(selector) {
return this.refs.$br.find(selector);
Expand Down
12 changes: 12 additions & 0 deletions src/BookReader/Mode1Up.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { Mode1UpLit } from './Mode1UpLit.js';
import { DragScrollable } from './DragScrollable.js';
import { ModeAbstract } from './ModeAbstract.js';
import { eventFilterScrollUp } from './utils.js';
/** @typedef {import('../BookReader.js').default} BookReader */
/** @typedef {import('./BookModel.js').BookModel} BookModel */
/** @typedef {import('./BookModel.js').PageIndex} PageIndex */
Expand Down Expand Up @@ -34,6 +35,17 @@ export class Mode1Up extends ModeAbstract {
/** @private */
get $brContainer() { return this.br.refs.$brContainer; }

get scrollContainer() {
return this.mode1UpLit;
}

init() {
if (this.br.plugins.experiments?.isExperimentEnabled('hideable-chrome')) {
this.$el[0].addEventListener('scroll', eventFilterScrollUp(() => this.br.fader('scroll')), { passive: true });
this.$el[0].addEventListener('click', () => this.br.fader('click'), { passive: true });
}
}

/**
* This is called when we switch to one page view
*/
Expand Down
16 changes: 16 additions & 0 deletions src/BookReader/Mode2Up.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@
import { Mode2UpLit } from './Mode2UpLit.js';
import { DragScrollable } from './DragScrollable.js';
import { ModeAbstract } from './ModeAbstract.js';
import { eventFilterSameElement, eventFilterScrollUp } from './utils.js';
/** @typedef {import('../BookReader.js').default} BookReader */
/** @typedef {import('./BookModel.js').BookModel} BookModel */
/** @typedef {import('./BookModel.js').PageIndex} PageIndex */

export class Mode2Up extends ModeAbstract {
name = '2up';

get scrollContainer() {
return this.mode2UpLit;
}

/**
* @param {BookReader} br
* @param {BookModel} bookModel
Expand All @@ -32,6 +37,17 @@ export class Mode2Up extends ModeAbstract {
this.everShown = false;
}

init() {
if (this.br.plugins.experiments?.isExperimentEnabled('hideable-chrome')) {
this.$el[0].addEventListener('scroll', eventFilterScrollUp(() => this.br.fader('scroll')), { passive: true });
this.$el[0].addEventListener('click', eventFilterSameElement(() => this.br.fader.toggle('click')));
this.$el.on('click', '.BRpagecontainer', () => {
if (this.$el.hasClass('BRpageFlipping')) return;
this.br.fader.toggle('click');
});
}
}

/**
* This is called when we switch into this mode
*/
Expand Down
5 changes: 3 additions & 2 deletions src/BookReader/Mode2UpLit.js
Original file line number Diff line number Diff line change
Expand Up @@ -680,9 +680,10 @@ export class Mode2UpLit extends LitElement {

const $page = $(ev.target).closest('.BRpagecontainer');
if (!$page.length) return;
if ($page.data('side') == 'L') {
const pageBoundingBox = $page[0].getBoundingClientRect();
if ($page.data('side') == 'L' && ev.clientX < pageBoundingBox.left + pageBoundingBox.width * 3 / 4) {
this.br.left();
} else if ($page.data('side') == 'R') {
} else if ($page.data('side') == 'R' && ev.clientX > pageBoundingBox.right - pageBoundingBox.width * 3 / 4) {
this.br.right();
}
}
Expand Down
8 changes: 8 additions & 0 deletions src/BookReader/ModeAbstract.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ export class ModeAbstract {
/** @type {BookModel} */
book;

/** @type {HTMLElement} */
get scrollContainer() {
throw new Error('Not implemented');
}

/**
* Get the page at the given index or direction
* @param {PageIndex | 'left' | 'right' | 'next' | 'prev'} indexOrDirection
Expand All @@ -40,4 +45,7 @@ export class ModeAbstract {
return this.book.getPage(indexOrDirection);
}
}

/** @abstract */
init() {}
}
4 changes: 4 additions & 0 deletions src/BookReader/ModeThumb.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import { ModeAbstract } from './ModeAbstract.js';
export class ModeThumb extends ModeAbstract {
name = 'thumb'

get scrollContainer() {
return this.br.refs.$brContainer[0];
}

/**
* @param {BookReader} br
* @param {BookModel} bookModel
Expand Down
93 changes: 89 additions & 4 deletions src/BookReader/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,22 +107,36 @@
*
* @param {T} func
* @param {number} wait
* @param {boolean} immediate
* @param {boolean | function} immediate If true, calls func on the leading edge. If a
* function is provided, that function is called on the leading edge instead of `func`.
* `func` is still called on the trailing edge.
* @param {Object} [options]
* @param {function | null} [options.tap] Function to tap the event stream -- eg not debounced
* @return {T}
*/
export function debounce(func, wait, immediate) {
export function debounce(func, wait, immediate, {tap = null} = {}) {
let timeout;
return function() {
const context = this;
const args = arguments;
const later = () => {
timeout = null;
if (!immediate) func.apply(context, args);
if (!immediate || typeof immediate === 'function') func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
if (callNow) {
if (typeof immediate === 'function') {
immediate.apply(context, args);
} else {
func.apply(context, args);
}
}

if (tap) {
tap.apply(context, args);
}
};
}

Expand Down Expand Up @@ -311,3 +325,74 @@
return aValue < bValue ? -1 : aValue > bValue ? 1 : 0;
});
}

/**
* @param {Function} callback
* @param {Object} options
* @param {number} [options.scrollDelay=20] How many pixels to scroll before triggering
* @returns {function(): void}
*/
export function eventFilterScrollUp(callback, {scrollDelay = 20} = {}) {
let lastScrollTop = 0;
let accumulatedScroll = 0;
return function(event) {
const st = this.scrollTop;
if (st < lastScrollTop) {
accumulatedScroll += lastScrollTop - st;
if (accumulatedScroll >= scrollDelay) {
callback(event);
accumulatedScroll = 0;
}
}
lastScrollTop = st;
};
}

/**
* Filters mousemove events to only call callback when the mouse has moved
* more than minDistance pixels.
* @param {Function} callback
* @param {Object} options
* @param {number} [options.minDistance=10]
*/
export function eventFilterMouseMove(callback, {minDistance = 10} = {}) {
let startX = null;
let startY = null;

// debounce resetting startX/startY to avoid issues with small jitters
const resetStart = debounce(() => {
startX = null;
startY = null;
}, 100);

return function(event) {
if (startX === null || startY === null) {
startX = event.clientX;
startY = event.clientY;
return;
}
const deltaX = event.clientX - startX;
const deltaY = event.clientY - startY;
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance >= minDistance) {
callback(event);
startX = event.clientX;
startY = event.clientY;
}
resetStart();
};
};

Check failure on line 384 in src/BookReader/utils.js

View workflow job for this annotation

GitHub Actions / tests

Unnecessary semicolon

/**
* Filters event if the target element is the same as the element the event is bound to.
* Useful for avoiding handling events from child elements.
* @param {Function} callback
* @returns {function(Event): void}
*/
export function eventFilterSameElement(callback) {
return function(event) {
if (event.target === event.currentTarget) {
callback(event);
}
};
}
3 changes: 2 additions & 1 deletion src/css/BookReader.scss
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ $searchResultText: $lightBlue;
$searchResultBG: $darkBlue;

@mixin brDarkControls {
background-color: $brColorDarkGreyBg;
background-color: rgba($brColorDarkGreyBg, 0.9);
backdrop-filter: blur(5px);
color: white;
a { color: white; }
}
Expand Down
Loading
Loading