diff --git a/src/lib/Controls.js b/src/lib/Controls.js index f499011a5..58d9b22d0 100644 --- a/src/lib/Controls.js +++ b/src/lib/Controls.js @@ -8,6 +8,8 @@ const CONTROLS_PAGE_NUM_INPUT_CLASS = 'bp-page-num-input'; const CONTROLS_PAGE_NUM_WRAPPER_CLASS = 'bp-page-num-wrapper'; const CONTROLS_AUTO_HIDE_TIMEOUT_IN_MILLIS = 2000; +export const CLASS_BOX_CONTROLS_GROUP_BUTTON = 'bp-controls-group-btn'; + class Controls { /** @property {HTMLElement} - Controls container element */ containerEl; @@ -191,9 +193,12 @@ class Controls { * @param {string} [classList] - optional class list * @param {string} [content] - Optional content HTML * @param {string} [tag] - Optional html tag, defaults to 'button' + * @param {HTMLElement} [parent] - Optional parent tag, defaults to the controls element * @return {HTMLElement} The created HTMLElement inserted into the control */ - add(text, handler, classList = '', content = '', tag = 'button') { + add(text, handler, classList = '', content = '', tag = 'button', parent = this.controlsEl) { + const parentElement = this.controlsEl.contains(parent) ? parent : this.controlsEl; + const cell = document.createElement('div'); cell.className = 'bp-controls-cell'; @@ -214,7 +219,7 @@ class Controls { } cell.appendChild(element); - this.controlsEl.appendChild(cell); + parentElement.appendChild(cell); if (handler) { // Maintain a reference for cleanup @@ -227,6 +232,22 @@ class Controls { return element; } + /** + * Add div for a group of controls + * + * @public + * @param {string} classNames - optional class names + * @return {HTMLElement} The created HTMLElement for a group of controls + */ + addGroup(classNames = '') { + const group = document.createElement('div'); + group.className = `bp-controls-group ${classNames}`; + + this.controlsEl.appendChild(group); + + return group; + } + /** * Enables the controls. * diff --git a/src/lib/Controls.scss b/src/lib/Controls.scss index 81835a76f..b5ea4a18e 100644 --- a/src/lib/Controls.scss +++ b/src/lib/Controls.scss @@ -10,8 +10,7 @@ .bp-controls { position: relative; left: -50%; - display: table; - table-layout: fixed; + display: flex; background: fade-out($twos, .05); border-radius: 3px; opacity: 0; @@ -81,6 +80,12 @@ visibility: visible; } } + + .bp-zoom-btn { + display: flex; + align-items: center; + justify-content: center; + } } .box-show-preview-controls .bp-controls { @@ -155,6 +160,23 @@ } .bp-zoom-current-scale { + min-width: 48px; color: $white; font-size: 14px; + text-align: center; +} + +.bp-controls-group { + display: flex; + align-items: center; + margin-right: 4px; + margin-left: 4px; + + .bp-controls-group-btn { + width: 32px; + } + + & + .bp-controls-cell { + margin-left: 4px; + } } diff --git a/src/lib/PageControls.js b/src/lib/PageControls.js index 84f0686aa..b2a9a7972 100644 --- a/src/lib/PageControls.js +++ b/src/lib/PageControls.js @@ -4,6 +4,7 @@ import Browser from './Browser'; import { BROWSERS } from './constants'; import { decodeKeydown } from './util'; import { ICON_DROP_DOWN, ICON_DROP_UP } from './icons/icons'; +import { CLASS_BOX_CONTROLS_GROUP_BUTTON } from './Controls'; const SHOW_PAGE_NUM_INPUT_CLASS = 'show-page-number-input'; const CONTROLS_PAGE_NUM_WRAPPER_CLASS = 'bp-page-num-wrapper'; @@ -72,14 +73,32 @@ class PageControls extends EventEmitter { * @return {void} */ add(currentPageNumber, pagesCount) { + const groupElement = this.controls.addGroup(); + // const groupElement = undefined; this.controls.add( __('previous_page'), this.setPreviousPage, - `bp-previous-page-icon ${PREV_PAGE}`, + `${CLASS_BOX_CONTROLS_GROUP_BUTTON} bp-previous-page-icon ${PREV_PAGE}`, ICON_DROP_UP, + undefined, + groupElement, + ); + this.controls.add( + __('enter_page_num'), + this.showPageNumInput, + PAGE_NUM, + pageNumTemplate, + undefined, + groupElement, + ); + this.controls.add( + __('next_page'), + this.setNextPage, + `${CLASS_BOX_CONTROLS_GROUP_BUTTON} bp-next-page-icon ${NEXT_PAGE}`, + ICON_DROP_DOWN, + undefined, + groupElement, ); - this.controls.add(__('enter_page_num'), this.showPageNumInput, PAGE_NUM, pageNumTemplate); - this.controls.add(__('next_page'), this.setNextPage, `bp-next-page-icon ${NEXT_PAGE}`, ICON_DROP_DOWN); const pageNumEl = this.controlsEl.querySelector(`.${PAGE_NUM}`); this.totalPagesEl = pageNumEl.querySelector(`.${CONTROLS_TOTAL_PAGES}`); diff --git a/src/lib/ZoomControls.js b/src/lib/ZoomControls.js index eb85505d2..767db517a 100644 --- a/src/lib/ZoomControls.js +++ b/src/lib/ZoomControls.js @@ -1,11 +1,12 @@ import isFinite from 'lodash/isFinite'; import noop from 'lodash/noop'; import { ICON_ZOOM_IN, ICON_ZOOM_OUT } from './icons/icons'; -import Controls from './Controls'; +import Controls, { CLASS_BOX_CONTROLS_GROUP_BUTTON } from './Controls'; const CLASS_ZOOM_CURRENT_SCALE = 'bp-zoom-current-scale'; const CLASS_ZOOM_IN_BUTTON = 'bp-zoom-in-btn'; const CLASS_ZOOM_OUT_BUTTON = 'bp-zoom-out-btn'; +const CLASS_ZOOM_BUTTON = 'bp-zoom-btn'; class ZoomControls { /** @property {Controls} - Controls object */ @@ -67,15 +68,31 @@ class ZoomControls { this.maxZoom = Math.round(this.validateZoom(maxZoom, Number.POSITIVE_INFINITY) * 100); this.minZoom = Math.round(Math.max(this.validateZoom(minZoom, 0), 0) * 100); - this.controls.add(__('zoom_out'), onZoomOut, `${CLASS_ZOOM_OUT_BUTTON} ${zoomOutClassName}`, ICON_ZOOM_OUT); + const groupElement = this.controls.addGroup(); this.controls.add( - __('zoom_current_scale'), + __('zoom_out'), + onZoomOut, + `${CLASS_BOX_CONTROLS_GROUP_BUTTON} ${CLASS_ZOOM_BUTTON} ${CLASS_ZOOM_OUT_BUTTON} ${zoomOutClassName}`, + ICON_ZOOM_OUT, undefined, + groupElement, + ); + this.controls.add( + __('zoom_current_scale'), undefined, - `100%`, + CLASS_ZOOM_CURRENT_SCALE, + '100%', 'div', + groupElement, + ); + this.controls.add( + __('zoom_in'), + onZoomIn, + `${CLASS_BOX_CONTROLS_GROUP_BUTTON} ${CLASS_ZOOM_BUTTON} ${CLASS_ZOOM_IN_BUTTON} ${zoomInClassName}`, + ICON_ZOOM_IN, + undefined, + groupElement, ); - this.controls.add(__('zoom_in'), onZoomIn, `${CLASS_ZOOM_IN_BUTTON} ${zoomInClassName}`, ICON_ZOOM_IN); this.currentScaleElement = this.controlsElement.querySelector(`.${CLASS_ZOOM_CURRENT_SCALE}`); this.setCurrentScale(currentScale); diff --git a/src/lib/__tests__/Controls-test.js b/src/lib/__tests__/Controls-test.js index 1695e2c10..82cfabf6a 100644 --- a/src/lib/__tests__/Controls-test.js +++ b/src/lib/__tests__/Controls-test.js @@ -284,6 +284,20 @@ describe('lib/Controls', () => { expect(span.parentNode.parentNode).to.equal(controls.controlsEl); expect(controls.buttonRefs.push).not.to.be.called; }); + + it('should append the controls to the provided element', () => { + const div = controls.addGroup('test-group'); + const btn = controls.add('test button', sandbox.stub(), 'test1', 'test content', undefined, div); + expect(btn.parentNode.parentNode).to.equal(div); + }); + }); + + describe('addGroup()', () => { + it('should create a controls group within the controls element', () => { + const div = controls.addGroup('test-group'); + expect(div.parentNode).to.equal(controls.controlsEl); + expect(div.classList.contains('test-group')); + }); }); describe('enable()', () => { diff --git a/src/lib/__tests__/ZoomControls-test.js b/src/lib/__tests__/ZoomControls-test.js index 53411002c..163bfd2fe 100644 --- a/src/lib/__tests__/ZoomControls-test.js +++ b/src/lib/__tests__/ZoomControls-test.js @@ -48,15 +48,30 @@ describe('lib/ZoomControls', () => { it('should add the controls', () => { zoomControls.init(0.5, { onZoomIn: stubs.onZoomIn, onZoomOut: stubs.onZoomOut }); - expect(stubs.add).to.be.calledWith(__('zoom_out'), stubs.onZoomOut, 'bp-zoom-out-btn ', ICON_ZOOM_OUT); expect(stubs.add).to.be.calledWith( - __('zoom_current_scale'), + __('zoom_out'), + stubs.onZoomOut, + 'bp-controls-group-btn bp-zoom-btn bp-zoom-out-btn ', + ICON_ZOOM_OUT, undefined, + sinon.match.any, + ); + expect(stubs.add).to.be.calledWith( + __('zoom_current_scale'), undefined, + 'bp-zoom-current-scale', sinon.match.string, 'div', + sinon.match.any, + ); + expect(stubs.add).to.be.calledWith( + __('zoom_in'), + stubs.onZoomIn, + 'bp-controls-group-btn bp-zoom-btn bp-zoom-in-btn ', + ICON_ZOOM_IN, + undefined, + sinon.match.any, ); - expect(stubs.add).to.be.calledWith(__('zoom_in'), stubs.onZoomIn, 'bp-zoom-in-btn ', ICON_ZOOM_IN); expect(zoomControls.currentScaleElement).not.to.be.undefined; expect(stubs.setCurrentScale).to.be.calledWith(0.5); expect(zoomControls.maxZoom).to.be.equal(Number.POSITIVE_INFINITY); @@ -102,21 +117,26 @@ describe('lib/ZoomControls', () => { expect(stubs.add).to.be.calledWith( __('zoom_out'), stubs.onZoomOut, - 'bp-zoom-out-btn zoom-out-classname', + 'bp-controls-group-btn bp-zoom-btn bp-zoom-out-btn zoom-out-classname', ICON_ZOOM_OUT, + undefined, + sinon.match.any, ); expect(stubs.add).to.be.calledWith( __('zoom_current_scale'), undefined, - undefined, + 'bp-zoom-current-scale', sinon.match.string, 'div', + sinon.match.any, ); expect(stubs.add).to.be.calledWith( __('zoom_in'), stubs.onZoomIn, - 'bp-zoom-in-btn zoom-in-classname', + 'bp-controls-group-btn bp-zoom-btn bp-zoom-in-btn zoom-in-classname', ICON_ZOOM_IN, + undefined, + sinon.match.any, ); }); }); diff --git a/src/lib/icons/search.svg b/src/lib/icons/search.svg index 6b4ce0e09..e497efe42 100644 --- a/src/lib/icons/search.svg +++ b/src/lib/icons/search.svg @@ -1,4 +1,4 @@ - + diff --git a/src/lib/icons/thumbnails-toggle-icon.svg b/src/lib/icons/thumbnails-toggle-icon.svg index f7644db48..e8292bc9a 100644 --- a/src/lib/icons/thumbnails-toggle-icon.svg +++ b/src/lib/icons/thumbnails-toggle-icon.svg @@ -1 +1 @@ - + diff --git a/src/lib/icons/zoom_in.svg b/src/lib/icons/zoom_in.svg index 8a4f5f460..ab345c490 100644 --- a/src/lib/icons/zoom_in.svg +++ b/src/lib/icons/zoom_in.svg @@ -1,4 +1,4 @@ - + diff --git a/src/lib/icons/zoom_out.svg b/src/lib/icons/zoom_out.svg index 4f04ceccd..908c12379 100644 --- a/src/lib/icons/zoom_out.svg +++ b/src/lib/icons/zoom_out.svg @@ -1,4 +1,4 @@ - +