diff --git a/src/index.html b/src/index.html
index b5f156732..fef4465aa 100644
--- a/src/index.html
+++ b/src/index.html
@@ -19,7 +19,7 @@
.setters-container {
display: flex;
font-size: 75%;
- height: 25vh;
+ height: 10vh;
justify-content: space-around;
padding: 20px;
}
@@ -37,8 +37,8 @@
text-align: center;
}
- #preview-container {
- height: 75vh;
+ .preview-container {
+ height: 90vh;
width: 100vw;
}
diff --git a/src/lib/ThumbnailsSidebar.js b/src/lib/ThumbnailsSidebar.js
index 7c2ca09f3..e13b886a9 100644
--- a/src/lib/ThumbnailsSidebar.js
+++ b/src/lib/ThumbnailsSidebar.js
@@ -4,7 +4,6 @@ import BoundedCache from './BoundedCache';
const CLASS_BOX_PREVIEW_THUMBNAIL = 'bp-thumbnail';
const CLASS_BOX_PREVIEW_THUMBNAIL_NAV = 'bp-thumbnail-nav';
-const CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED = 'bp-thumbnails-closed';
const CLASS_BOX_PREVIEW_THUMBNAIL_IMAGE = 'bp-thumbnail-image';
const CLASS_BOX_PREVIEW_THUMBNAIL_IMAGE_LOADED = 'bp-thumbnail-image-loaded';
const CLASS_BOX_PREVIEW_THUMBNAIL_IS_SELECTED = 'bp-thumbnail-is-selected';
@@ -26,6 +25,9 @@ class ThumbnailsSidebar {
/** @property {Array} - The list of currently rendered thumbnail elements */
currentThumbnails;
+ /** @property {Boolean} - Whether the sidebar is open or not */
+ isOpen;
+
/** @property {PDfViewer} - The PDFJS viewer instance */
pdfViewer;
@@ -46,6 +48,7 @@ class ThumbnailsSidebar {
this.currentThumbnails = [];
this.pdfViewer = pdfViewer;
this.thumbnailImageCache = new BoundedCache();
+ this.isOpen = false;
this.createImageEl = this.createImageEl.bind(this);
this.createPlaceholderThumbnail = this.createPlaceholderThumbnail.bind(this);
@@ -404,31 +407,23 @@ class ThumbnailsSidebar {
return;
}
- if (!this.isOpen()) {
+ if (!this.isOpen) {
this.toggleOpen();
} else {
this.toggleClose();
}
}
- /**
- * Returns whether the sidebar is open or not
- * @return {boolean} true if the sidebar is open, false if not
- */
- isOpen() {
- return this.anchorEl && !this.anchorEl.classList.contains(CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED);
- }
-
/**
* Toggles the sidebar open. This will scroll the current page into view
* @return {void}
*/
toggleOpen() {
- if (!this.anchorEl) {
+ if (!this.virtualScroller) {
return;
}
- this.anchorEl.classList.remove(CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED);
+ this.isOpen = true;
this.virtualScroller.scrollIntoView(this.currentPage - 1);
}
@@ -438,11 +433,7 @@ class ThumbnailsSidebar {
* @return {void}
*/
toggleClose() {
- if (!this.anchorEl) {
- return;
- }
-
- this.anchorEl.classList.add(CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED);
+ this.isOpen = false;
}
/**
diff --git a/src/lib/__tests__/ThumbnailsSidebar-test.js b/src/lib/__tests__/ThumbnailsSidebar-test.js
index 0ef1478b4..9251abae0 100644
--- a/src/lib/__tests__/ThumbnailsSidebar-test.js
+++ b/src/lib/__tests__/ThumbnailsSidebar-test.js
@@ -431,7 +431,6 @@ describe('ThumbnailsSidebar', () => {
describe('toggle()', () => {
beforeEach(() => {
- stubs.isOpen = sandbox.stub(thumbnailsSidebar, 'isOpen');
stubs.toggleOpen = sandbox.stub(thumbnailsSidebar, 'toggleOpen');
stubs.toggleClose = sandbox.stub(thumbnailsSidebar, 'toggleClose');
});
@@ -441,7 +440,6 @@ describe('ThumbnailsSidebar', () => {
thumbnailsSidebar.toggle();
- expect(stubs.isOpen).not.to.be.called;
expect(stubs.toggleOpen).not.to.be.called;
expect(stubs.toggleClose).not.to.be.called;
@@ -449,21 +447,19 @@ describe('ThumbnailsSidebar', () => {
});
it('should toggle open if it was closed', () => {
- stubs.isOpen.returns(false);
+ thumbnailsSidebar.isOpen = false;
thumbnailsSidebar.toggle();
- expect(stubs.isOpen).to.be.called;
expect(stubs.toggleOpen).to.be.called;
expect(stubs.toggleClose).not.to.be.called;
});
it('should toggle closed if it was open', () => {
- stubs.isOpen.returns(true);
+ thumbnailsSidebar.isOpen = true;
thumbnailsSidebar.toggle();
- expect(stubs.isOpen).to.be.called;
expect(stubs.toggleOpen).not.to.be.called;
expect(stubs.toggleClose).to.be.called;
});
@@ -475,15 +471,14 @@ describe('ThumbnailsSidebar', () => {
thumbnailsSidebar.virtualScroller = virtualScroller;
});
- it('should do nothing if there is no anchorEl', () => {
- thumbnailsSidebar.anchorEl = null;
+ it('should do nothing if there is no virtualScroller', () => {
+ thumbnailsSidebar.virtualScroller = null;
+ thumbnailsSidebar.isOpen = false;
thumbnailsSidebar.toggleOpen();
- expect(stubs.removeClass).not.to.be.called;
+ expect(thumbnailsSidebar.isOpen).to.be.false;
expect(stubs.vsScrollIntoView).not.to.be.called;
-
- thumbnailsSidebar.anchorEl = anchorEl;
});
it('should remove the hidden class and scroll the page into view', () => {
@@ -491,30 +486,18 @@ describe('ThumbnailsSidebar', () => {
thumbnailsSidebar.toggleOpen();
- expect(stubs.removeClass).to.be.calledWith(CLASS_HIDDEN);
+ expect(thumbnailsSidebar.isOpen).to.be.true;
expect(stubs.vsScrollIntoView).to.be.calledWith(2);
});
});
describe('toggleClose()', () => {
- beforeEach(() => {
- stubs.addClass = sandbox.stub(thumbnailsSidebar.anchorEl.classList, 'add');
- });
-
- it('should do nothing if there is no anchorEl', () => {
- thumbnailsSidebar.anchorEl = null;
-
- thumbnailsSidebar.toggleClose();
-
- expect(stubs.addClass).not.to.be.called;
-
- thumbnailsSidebar.anchorEl = anchorEl;
- });
+ it('should set isOpen to false', () => {
+ thumbnailsSidebar.isOpen = true;
- it('should add the hidden class', () => {
thumbnailsSidebar.toggleClose();
- expect(stubs.addClass).to.be.calledWith(CLASS_HIDDEN);
+ expect(thumbnailsSidebar.isOpen).to.be.false;
});
});
});
diff --git a/src/lib/_common.scss b/src/lib/_common.scss
index f3cd21f6d..098b83318 100644
--- a/src/lib/_common.scss
+++ b/src/lib/_common.scss
@@ -147,16 +147,14 @@ $header-height: 48px;
.bp-content {
align-items: center;
+ bottom: 0;
display: flex;
flex: 1 1 auto;
+ left: 0;
outline: none;
- position: relative;
- // transition: left 300ms cubic-bezier(0.4, 0, 0.2, 1);
- // position: absolute;
- // bottom: 0;
- // left: 0;
- // right: 0;
- // top: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
}
.bp-content.bp-is-fullscreen {
@@ -165,6 +163,10 @@ $header-height: 48px;
}
}
+.bp.bp-loaded .bp-content {
+ transition: left 300ms cubic-bezier(.4, 0, .2, 1);
+}
+
.accessibility-hidden {
left: -9999px;
position: absolute;
diff --git a/src/lib/constants.js b/src/lib/constants.js
index 42090a76a..112d7d8b2 100644
--- a/src/lib/constants.js
+++ b/src/lib/constants.js
@@ -35,6 +35,7 @@ export const CLASS_BOX_PREVIEW_NOTIFICATION = 'bp-notification';
export const CLASS_BOX_PREVIEW_NOTIFICATION_WRAPPER = 'bp-notifications-wrapper';
export const CLASS_BOX_PREVIEW_TOGGLE_OVERLAY = 'bp-toggle-overlay';
export const CLASS_BOX_PREVIEW_THEME_DARK = 'bp-theme-dark';
+export const CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED = 'bp-thumbnails-closed';
export const CLASS_BOX_PREVIEW_THUMBNAILS_CONTAINER = 'bp-thumbnails-container';
export const CLASS_ELEM_KEYBOARD_FOCUS = 'bp-has-keyboard-focus';
export const CLASS_FULLSCREEN = 'bp-is-fullscreen';
diff --git a/src/lib/viewers/doc/DocBaseViewer.js b/src/lib/viewers/doc/DocBaseViewer.js
index 04963d894..a3dac817b 100644
--- a/src/lib/viewers/doc/DocBaseViewer.js
+++ b/src/lib/viewers/doc/DocBaseViewer.js
@@ -21,7 +21,8 @@ import {
QUERY_PARAM_ENCODING,
ENCODING_TYPES,
CLASS_BOX_PREVIEW_THUMBNAILS_CONTAINER,
- ANNOTATOR_EVENT
+ ANNOTATOR_EVENT,
+ CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED
} from '../../constants';
import { checkPermission, getRepresentation } from '../../file';
import { appendQueryParams, createAssetUrlCreator, getMidpoint, getDistance, getClosestPageToPinch } from '../../util';
@@ -39,24 +40,25 @@ import Timer from '../../Timer';
const CURRENT_PAGE_MAP_KEY = 'doc-current-page-map';
const DEFAULT_SCALE_DELTA = 1.1;
+const IS_SAFARI_CLASS = 'is-safari';
const LOAD_TIMEOUT_MS = 180000; // 3 min timeout
-const SAFARI_PRINT_TIMEOUT_MS = 1000; // Wait 1s before trying to print
-const PRINT_DIALOG_TIMEOUT_MS = 500;
-const MAX_SCALE = 10.0;
-const MIN_SCALE = 0.1;
const MAX_PINCH_SCALE_VALUE = 3;
-const MIN_PINCH_SCALE_VALUE = 0.25;
+const MAX_SCALE = 10.0;
const MIN_PINCH_SCALE_DELTA = 0.01;
-const IS_SAFARI_CLASS = 'is-safari';
-const SCROLL_EVENT_THROTTLE_INTERVAL = 200;
-const SCROLL_END_TIMEOUT = this.isMobile ? 500 : 250;
-const RANGE_REQUEST_CHUNK_SIZE_US = 1048576; // 1MB
-const RANGE_REQUEST_CHUNK_SIZE_NON_US = 524288; // 512KB
+const MIN_PINCH_SCALE_VALUE = 0.25;
+const MIN_SCALE = 0.1;
const MINIMUM_RANGE_REQUEST_FILE_SIZE_NON_US = 26214400; // 25MB
const MOBILE_MAX_CANVAS_SIZE = 2949120; // ~3MP 1920x1536
+const PAGES_UNIT_NAME = 'pages';
const PINCH_PAGE_CLASS = 'pinch-page';
const PINCHING_CLASS = 'pinching';
-const PAGES_UNIT_NAME = 'pages';
+const PRINT_DIALOG_TIMEOUT_MS = 500;
+const RANGE_REQUEST_CHUNK_SIZE_NON_US = 524288; // 512KB
+const RANGE_REQUEST_CHUNK_SIZE_US = 1048576; // 1MB
+const SAFARI_PRINT_TIMEOUT_MS = 1000; // Wait 1s before trying to print
+const SCROLL_END_TIMEOUT = this.isMobile ? 500 : 250;
+const SCROLL_EVENT_THROTTLE_INTERVAL = 200;
+const THUMBNAILS_SIDEBAR_TRANSITION_TIME = 300; // 300ms
// List of metrics to be emitted only once per session
const METRICS_WHITELIST = [
USER_DOCUMENT_THUMBNAIL_EVENTS.CLOSE,
@@ -126,8 +128,9 @@ class DocBaseViewer extends BaseViewer {
this.startPageNum = this.getStartPage(this.startAt);
if (this.options.enableThumbnailsSidebar) {
+ this.rootEl.classList.add(CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED);
this.thumbnailsSidebarEl = document.createElement('div');
- this.thumbnailsSidebarEl.className = `${CLASS_BOX_PREVIEW_THUMBNAILS_CONTAINER} bp-thumbnails-closed`;
+ this.thumbnailsSidebarEl.className = `${CLASS_BOX_PREVIEW_THUMBNAILS_CONTAINER}`;
this.thumbnailsSidebarEl.setAttribute('data-testid', 'thumbnails-sidebar');
this.containerEl.parentNode.insertBefore(this.thumbnailsSidebarEl, this.containerEl);
}
@@ -1329,10 +1332,12 @@ class DocBaseViewer extends BaseViewer {
let metricName;
let eventName;
- if (!this.thumbnailsSidebar.isOpen()) {
+ if (!this.thumbnailsSidebar.isOpen) {
+ this.rootEl.classList.add(CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED);
metricName = USER_DOCUMENT_THUMBNAIL_EVENTS.CLOSE;
eventName = 'thumbnailsClose';
} else {
+ this.rootEl.classList.remove(CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED);
metricName = USER_DOCUMENT_THUMBNAIL_EVENTS.OPEN;
eventName = 'thumbnailsOpen';
}
@@ -1340,7 +1345,7 @@ class DocBaseViewer extends BaseViewer {
this.emitMetric({ name: metricName, data: pagesCount });
this.emit(eventName);
- setTimeout(() => this.resize(), 200);
+ setTimeout(() => this.resize(), THUMBNAILS_SIDEBAR_TRANSITION_TIME);
}
/**
diff --git a/src/lib/viewers/doc/__tests__/DocBaseViewer-test.js b/src/lib/viewers/doc/__tests__/DocBaseViewer-test.js
index a27cb628f..640b34c50 100644
--- a/src/lib/viewers/doc/__tests__/DocBaseViewer-test.js
+++ b/src/lib/viewers/doc/__tests__/DocBaseViewer-test.js
@@ -21,7 +21,8 @@ import {
QUERY_PARAM_ENCODING,
ENCODING_TYPES,
SELECTOR_BOX_PREVIEW_CONTENT,
- CLASS_BOX_PREVIEW_THUMBNAILS_CONTAINER
+ CLASS_BOX_PREVIEW_THUMBNAILS_CONTAINER,
+ CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED
} from '../../../constants';
import {
ICON_PRINT_CHECKMARK,
@@ -72,6 +73,7 @@ describe('src/lib/viewers/doc/DocBaseViewer', () => {
fixture.load('viewers/doc/__tests__/DocBaseViewer-test.html');
containerEl = document.querySelector(SELECTOR_BOX_PREVIEW_CONTENT);
+ stubs = {};
docBase = new DocBaseViewer({
cache: {
set: () => {},
@@ -92,9 +94,19 @@ describe('src/lib/viewers/doc/DocBaseViewer', () => {
enableThumbnailsSidebar: true
});
Object.defineProperty(BaseViewer.prototype, 'setup', { value: sandbox.stub() });
+ stubs.classListAdd = sandbox.stub();
+ stubs.classListRemove = sandbox.stub();
+ const rootEl = {
+ classList: {
+ add: stubs.classListAdd,
+ remove: stubs.classListRemove
+ }
+ };
+
docBase.containerEl = containerEl;
+ docBase.rootEl = rootEl;
+
docBase.setup();
- stubs = {};
});
afterEach(() => {
@@ -2212,26 +2224,34 @@ describe('src/lib/viewers/doc/DocBaseViewer', () => {
describe('toggleThumbnails()', () => {
let thumbnailsSidebar;
+ let clock;
beforeEach(() => {
sandbox.stub(docBase, 'resize');
sandbox.stub(docBase, 'emitMetric');
sandbox.stub(docBase, 'emit');
+ clock = sinon.useFakeTimers();
+
stubs.toggleSidebar = sandbox.stub();
stubs.isSidebarOpen = sandbox.stub();
thumbnailsSidebar = {
toggle: stubs.toggleSidebar,
- isOpen: stubs.isSidebarOpen,
+ isOpen: false,
destroy: () => {}
};
});
+ afterEach(() => {
+ clock.restore();
+ });
+
it('should do nothing if thumbnails sidebar does not exist', () => {
docBase.thumbnailsSidebar = undefined;
docBase.toggleThumbnails();
+ clock.tick(300);
expect(docBase.resize).not.to.be.called;
});
@@ -2239,12 +2259,13 @@ describe('src/lib/viewers/doc/DocBaseViewer', () => {
it('should toggle open and resize the viewer', () => {
docBase.thumbnailsSidebar = thumbnailsSidebar;
docBase.pdfViewer = { pagesCount: 10 };
- stubs.isSidebarOpen.returns(true);
+ thumbnailsSidebar.isOpen = true;
docBase.toggleThumbnails();
+ clock.tick(300);
+ expect(stubs.classListRemove).to.be.calledWith(CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED);
expect(stubs.toggleSidebar).to.be.called;
- expect(stubs.isSidebarOpen).to.be.called;
expect(docBase.resize).to.be.called;
expect(docBase.emitMetric).to.be.calledWith({ name: USER_DOCUMENT_THUMBNAIL_EVENTS.OPEN, data: 10 });
expect(docBase.emit).to.be.calledWith('thumbnailsOpen');
@@ -2253,12 +2274,12 @@ describe('src/lib/viewers/doc/DocBaseViewer', () => {
it('should toggle close and resize the viewer', () => {
docBase.thumbnailsSidebar = thumbnailsSidebar;
docBase.pdfViewer = { pagesCount: 10 };
- stubs.isSidebarOpen.returns(false);
docBase.toggleThumbnails();
+ clock.tick(300);
+ expect(stubs.classListAdd).to.be.calledWith(CLASS_BOX_PREVIEW_THUMBNAILS_CLOSED);
expect(stubs.toggleSidebar).to.be.called;
- expect(stubs.isSidebarOpen).to.be.called;
expect(docBase.resize).to.be.called;
expect(docBase.emitMetric).to.be.calledWith({ name: USER_DOCUMENT_THUMBNAIL_EVENTS.CLOSE, data: 10 });
expect(docBase.emit).to.be.calledWith('thumbnailsClose');
diff --git a/src/lib/viewers/doc/_docBase.scss b/src/lib/viewers/doc/_docBase.scss
index 9f5f18569..7b78edac0 100644
--- a/src/lib/viewers/doc/_docBase.scss
+++ b/src/lib/viewers/doc/_docBase.scss
@@ -5,15 +5,18 @@ $thumbnail-border-radius: 4px;
.bp {
.bp-thumbnails-container {
border-right: solid 1px $seesee;
+ bottom: 0;
display: flex;
flex: 0 0 auto; // Accounts for the 1px border on the right so the remaining width is actually 180
- transition: width 300ms cubic-bezier(.4, 0, .2, 1);
+ left: 0;
+ position: absolute;
+ top: 0;
+ transition: left 300ms cubic-bezier(.4, 0, .2, 1);
width: 201px;
}
- .bp-thumbnails-container.bp-thumbnails-closed {
- width: 0;
- overflow: hidden;
+ &.bp-thumbnails-closed .bp-thumbnails-container {
+ left: -201px;
}
.bp-thumbnail {
@@ -73,6 +76,10 @@ $thumbnail-border-radius: 4px;
border-color: $black;
}
}
+
+ &:not(.bp-thumbnails-closed) .bp-content {
+ left: 201px;
+ }
}
.bp-theme-dark {