Skip to content

Commit

Permalink
fix(zoom): Add zoom min/max limits for image and text files (#1107)
Browse files Browse the repository at this point in the history
  • Loading branch information
jstoffan authored and mergify[bot] committed Nov 25, 2019
1 parent 8b31ec0 commit 1e84a70
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 54 deletions.
21 changes: 6 additions & 15 deletions src/lib/ZoomControls.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ const CLASS_ZOOM_CURRENT_SCALE_VALUE = 'bp-zoom-current-scale-value';
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';
const ZOOM_MAX = Number.POSITIVE_INFINITY;
const ZOOM_MIN = 0.1;

class ZoomControls {
/** @property {Controls} - Controls object */
Expand Down Expand Up @@ -60,14 +62,14 @@ class ZoomControls {
{
zoomOutClassName = '',
zoomInClassName = '',
minZoom = 0,
maxZoom = Number.POSITIVE_INFINITY,
minZoom = ZOOM_MIN,
maxZoom = ZOOM_MAX,
onZoomIn = noop,
onZoomOut = noop,
} = {},
) {
this.maxZoom = Math.round(this.validateZoom(maxZoom, Number.POSITIVE_INFINITY) * 100);
this.minZoom = Math.round(Math.max(this.validateZoom(minZoom, 0), 0) * 100);
this.maxZoom = Math.round((isFinite(maxZoom) && maxZoom <= ZOOM_MAX ? maxZoom : ZOOM_MAX) * 100);
this.minZoom = Math.round((isFinite(minZoom) && minZoom >= ZOOM_MIN ? minZoom : ZOOM_MIN) * 100);

const groupElement = this.controls.addGroup();
this.controls.add(
Expand Down Expand Up @@ -99,17 +101,6 @@ class ZoomControls {
this.setCurrentScale(currentScale);
}

/**
* Validates the zoom valid to ensure it is a number
*
* @param {number} zoomValue - Zoom value to validate
* @param {number} defaultZoomValue - Default zoom value
* @returns {number} The validated zoom value or the default value
*/
validateZoom(zoomValue, defaultZoomValue = 0) {
return isFinite(zoomValue) ? zoomValue : defaultZoomValue;
}

/**
* Sets the current scale
*
Expand Down
12 changes: 6 additions & 6 deletions src/lib/__tests__/ZoomControls-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ describe('lib/ZoomControls', () => {
expect(zoomControls.currentScaleElement).not.to.be.undefined;
expect(stubs.setCurrentScale).to.be.calledWith(0.5);
expect(zoomControls.maxZoom).to.be.equal(Number.POSITIVE_INFINITY);
expect(zoomControls.minZoom).to.be.equal(0);
expect(zoomControls.minZoom).to.be.equal(10);
});

it('should set the min and max zooms if specified', () => {
Expand All @@ -86,17 +86,17 @@ describe('lib/ZoomControls', () => {
});

it('should set the min zoom to 0 if negative is provided', () => {
zoomControls.init(0.5, { minZoom: -0.1, maxZoom: 5 });
zoomControls.init(0.5, { minZoom: -0.2, maxZoom: 5 });

expect(zoomControls.maxZoom).to.be.equal(500);
expect(zoomControls.minZoom).to.be.equal(0);
expect(zoomControls.minZoom).to.be.equal(10);
});

it('should set the min zoom to 0 if number is not provided', () => {
zoomControls.init(0.5, { minZoom: '0.1', maxZoom: 5 });
it('should set the min zoom to 0.1 if number is not provided', () => {
zoomControls.init(0.5, { minZoom: '0.2', maxZoom: 5 });

expect(zoomControls.maxZoom).to.be.equal(500);
expect(zoomControls.minZoom).to.be.equal(0);
expect(zoomControls.minZoom).to.be.equal(10);
});

it('should set the max zoom to Number.POSITIVE_INFINITY if number is not provided', () => {
Expand Down
53 changes: 28 additions & 25 deletions src/lib/viewers/text/TextBaseViewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@ import Controls from '../../Controls';
import ZoomControls from '../../ZoomControls';
import { checkPermission } from '../../file';
import { CLASS_IS_PRINTABLE, CLASS_IS_SELECTABLE, PERMISSION_DOWNLOAD } from '../../constants';

import { ICON_FULLSCREEN_IN, ICON_FULLSCREEN_OUT } from '../../icons/icons';

const ZOOM_DEFAULT = 1.0;
const ZOOM_MAX = 10;
const ZOOM_MIN = 0.1;
const ZOOM_STEP = 0.1;

class TextBaseViewer extends BaseViewer {
/**
* @inheritdoc
Expand All @@ -14,6 +18,8 @@ class TextBaseViewer extends BaseViewer {
super(options);

this.api = options.api;
this.scale = ZOOM_DEFAULT;

// Bind context for handlers;
this.zoomOut = this.zoomOut.bind(this);
this.zoomIn = this.zoomIn.bind(this);
Expand Down Expand Up @@ -47,36 +53,31 @@ class TextBaseViewer extends BaseViewer {
/**
* Zooms by increasing or decreasing font size
* @public
* @param {string} inOrOut - in or out
* @param {string} type - in, out, reset
* @return {void}
*/
zoom(inOrOut) {
const el = this.containerEl.querySelector('.bp-text');
const size = this.getFontSize();
let newFontSize = 0;

if (inOrOut === 'in') {
newFontSize = size + 10;
} else if (inOrOut === 'out') {
newFontSize = size - 10;
zoom(type) {
let newScale = ZOOM_DEFAULT;

if (type === 'in') {
newScale = this.scale + ZOOM_STEP;
newScale = newScale <= ZOOM_MAX ? newScale : ZOOM_MAX;
} else if (type === 'out') {
newScale = this.scale - ZOOM_STEP;
newScale = newScale >= ZOOM_MIN ? newScale : ZOOM_MIN;
}

el.style.fontSize = `${newFontSize}%`;
// Convert the decimal scale to a percentage font size for text content
this.containerEl.querySelector('.bp-text').style.fontSize = `${Math.round(newScale * 100)}%`;

this.emit('zoom', {
zoom: newFontSize,
canZoomIn: true,
canZoomOut: true,
zoom: newScale,
});
this.zoomControls.setCurrentScale(newFontSize / 100);
}

/**
* Gets the font size applied to the text
* @returns {number} The font size as a number
*/
getFontSize() {
const el = this.containerEl.querySelector('.bp-text');
return parseInt(el.style.fontSize, 10) || 100;
this.scale = newScale;
this.zoomControls.setCurrentScale(newScale);
}

/**
Expand Down Expand Up @@ -124,11 +125,13 @@ class TextBaseViewer extends BaseViewer {
loadUI() {
this.controls = new Controls(this.containerEl);
this.zoomControls = new ZoomControls(this.controls);
this.zoomControls.init(this.getFontSize() / 100, {
zoomInClassName: 'bp-text-zoom-in-icon',
zoomOutClassName: 'bp-text-zoom-out-icon',
this.zoomControls.init(this.scale, {
maxZoom: ZOOM_MAX,
minZoom: ZOOM_MIN,
onZoomIn: this.zoomIn,
onZoomOut: this.zoomOut,
zoomInClassName: 'bp-text-zoom-in-icon',
zoomOutClassName: 'bp-text-zoom-out-icon',
});

this.controls.add(
Expand Down
13 changes: 5 additions & 8 deletions src/lib/viewers/text/__tests__/TextBaseViewer-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('lib/viewers/text/TextBaseViewer', () => {
sandbox.stub(textBase, 'emit');
textBase.zoom();
expect(textBase.emit).to.be.calledWith('zoom');
expect(textBase.zoomControls.setCurrentScale).to.be.calledWith(0);
expect(textBase.zoomControls.setCurrentScale).to.be.calledWith(1.0);
});

it('should increase font size when zooming in', () => {
Expand Down Expand Up @@ -146,10 +146,6 @@ describe('lib/viewers/text/TextBaseViewer', () => {
const addFunc = Controls.prototype.add;
const zoomInitFunc = ZoomControls.prototype.init;

beforeEach(() => {
sandbox.stub(textBase, 'getFontSize');
});

afterEach(() => {
Object.defineProperty(Controls.prototype, 'add', { value: addFunc });
Object.defineProperty(ZoomControls.prototype, 'init', { value: zoomInitFunc });
Expand All @@ -158,7 +154,6 @@ describe('lib/viewers/text/TextBaseViewer', () => {
it('should setup controls and add click handlers', () => {
Object.defineProperty(Controls.prototype, 'add', { value: sandbox.stub() });
Object.defineProperty(ZoomControls.prototype, 'init', { value: sandbox.stub() });
textBase.getFontSize.returns(100);

textBase.loadUI();
expect(textBase.controls instanceof Controls).to.be.true;
Expand All @@ -172,10 +167,12 @@ describe('lib/viewers/text/TextBaseViewer', () => {

expect(textBase.zoomControls instanceof ZoomControls).to.be.true;
expect(ZoomControls.prototype.init).to.be.calledWith(1, {
zoomInClassName: 'bp-text-zoom-in-icon',
zoomOutClassName: 'bp-text-zoom-out-icon',
maxZoom: 10,
minZoom: 0.1,
onZoomIn: textBase.zoomIn,
onZoomOut: textBase.zoomOut,
zoomInClassName: 'bp-text-zoom-in-icon',
zoomOutClassName: 'bp-text-zoom-out-icon',
});
});
});
Expand Down

0 comments on commit 1e84a70

Please sign in to comment.