2018-08-23 01:49:33 +08:00
|
|
|
import React, { Component } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import { FormattedMessage } from 'react-intl';
|
|
|
|
import Button from '/imports/ui/components/button/component';
|
|
|
|
import { styles } from '../styles.scss';
|
2018-09-28 22:42:07 +08:00
|
|
|
import HoldButton from './holdButton/component';
|
2018-08-23 01:49:33 +08:00
|
|
|
|
2018-08-29 00:09:52 +08:00
|
|
|
const DELAY_MILLISECONDS = 200;
|
2018-08-23 01:49:33 +08:00
|
|
|
const STEP_TIME = 100;
|
|
|
|
|
|
|
|
export default class ZoomTool extends Component {
|
|
|
|
static renderAriaLabelsDescs() {
|
|
|
|
return (
|
2018-08-29 00:09:52 +08:00
|
|
|
<div hidden key="hidden-div">
|
|
|
|
{/* Zoom in button aria */}
|
2018-08-23 01:49:33 +08:00
|
|
|
<div id="zoomInLabel">
|
|
|
|
<FormattedMessage
|
|
|
|
id="app.presentation.presentationToolbar.zoomInLabel"
|
|
|
|
description="Aria label for when switching to previous slide"
|
|
|
|
defaultMessage="Previous slide"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<div id="zoomInDesc">
|
|
|
|
<FormattedMessage
|
|
|
|
id="app.presentation.presentationToolbar.zoomInDesc"
|
|
|
|
description="Aria description for when switching to previous slide"
|
|
|
|
defaultMessage="Change the presentation to the previous slide"
|
|
|
|
/>
|
|
|
|
</div>
|
2018-08-29 00:09:52 +08:00
|
|
|
{/* Zoom out button aria */}
|
2018-08-23 01:49:33 +08:00
|
|
|
<div id="zoomOutLabel">
|
|
|
|
<FormattedMessage
|
|
|
|
id="app.presentation.presentationToolbar.zoomOutLabel"
|
|
|
|
description="Aria label for when switching to next slide"
|
|
|
|
defaultMessage="Next slide"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<div id="zoomOutDesc">
|
|
|
|
<FormattedMessage
|
|
|
|
id="app.presentation.presentationToolbar.zoomOutDesc"
|
|
|
|
description="Aria description for when switching to next slide"
|
|
|
|
defaultMessage="Change the presentation to the next slide"
|
|
|
|
/>
|
|
|
|
</div>
|
2018-08-29 00:09:52 +08:00
|
|
|
{/* Zoom indicator aria */}
|
2018-08-23 01:49:33 +08:00
|
|
|
<div id="zoomIndicator">
|
|
|
|
<FormattedMessage
|
|
|
|
id="app.presentation.presentationToolbar.zoomIndicator"
|
|
|
|
description="Aria label for when switching to a specific slide"
|
|
|
|
defaultMessage="Skip slide"
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
this.increment = this.increment.bind(this);
|
|
|
|
this.decrement = this.decrement.bind(this);
|
|
|
|
this.mouseDownHandler = this.mouseDownHandler.bind(this);
|
|
|
|
this.mouseUpHandler = this.mouseUpHandler.bind(this);
|
|
|
|
this.execInterval = this.execInterval.bind(this);
|
|
|
|
this.onChanger = this.onChanger.bind(this);
|
|
|
|
this.setInt = 0;
|
|
|
|
this.state = {
|
|
|
|
value: props.value,
|
|
|
|
mouseHolding: false,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
componentDidUpdate() {
|
|
|
|
const isDifferent = this.props.value !== this.state.value;
|
|
|
|
if (isDifferent) this.onChanger(this.props.value);
|
|
|
|
}
|
|
|
|
|
|
|
|
onChanger(value) {
|
|
|
|
const {
|
|
|
|
maxBound,
|
|
|
|
minBound,
|
|
|
|
change,
|
|
|
|
} = this.props;
|
|
|
|
let newValue = value;
|
|
|
|
const isDifferent = newValue !== this.state.value;
|
|
|
|
|
|
|
|
if (newValue <= minBound) {
|
|
|
|
newValue = minBound;
|
|
|
|
} else if (newValue >= maxBound) {
|
|
|
|
newValue = maxBound;
|
|
|
|
}
|
|
|
|
|
|
|
|
const propsIsDifferente = this.props.value !== newValue;
|
|
|
|
if (isDifferent && propsIsDifferente) {
|
|
|
|
this.setState({ value: newValue }, () => {
|
|
|
|
change(newValue);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
if (isDifferent && !propsIsDifferente) this.setState({ value: newValue });
|
|
|
|
}
|
|
|
|
|
|
|
|
increment() {
|
|
|
|
const {
|
|
|
|
step,
|
|
|
|
} = this.props;
|
|
|
|
const increaseZoom = this.state.value + step;
|
|
|
|
this.onChanger(increaseZoom);
|
|
|
|
}
|
|
|
|
decrement() {
|
|
|
|
const {
|
|
|
|
step,
|
|
|
|
} = this.props;
|
|
|
|
const decreaseZoom = this.state.value - step;
|
|
|
|
this.onChanger(decreaseZoom);
|
|
|
|
}
|
|
|
|
|
|
|
|
execInterval(inc) {
|
|
|
|
const exec = inc ? this.increment : this.decrement;
|
|
|
|
|
|
|
|
const interval = () => {
|
|
|
|
clearInterval(this.setInt);
|
|
|
|
this.setInt = setInterval(exec, STEP_TIME);
|
|
|
|
};
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
if (this.state.mouseHolding) {
|
|
|
|
interval();
|
|
|
|
}
|
|
|
|
}, DELAY_MILLISECONDS);
|
|
|
|
}
|
|
|
|
|
|
|
|
mouseDownHandler(bool) {
|
|
|
|
this.setState({
|
|
|
|
...this.state,
|
|
|
|
mouseHolding: true,
|
|
|
|
}, () => {
|
|
|
|
this.execInterval(bool);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
mouseUpHandler() {
|
|
|
|
this.setState({
|
|
|
|
...this.state,
|
|
|
|
mouseHolding: false,
|
|
|
|
}, () => clearInterval(this.setInt));
|
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const {
|
|
|
|
value,
|
|
|
|
minBound,
|
|
|
|
maxBound,
|
|
|
|
} = this.props;
|
|
|
|
return (
|
|
|
|
[
|
|
|
|
ZoomTool.renderAriaLabelsDescs(),
|
2018-09-28 22:42:07 +08:00
|
|
|
(
|
|
|
|
<HoldButton
|
|
|
|
key="zoom-tool-1"
|
|
|
|
exec={this.decrement}
|
|
|
|
value={value}
|
|
|
|
minBound={minBound}
|
|
|
|
>
|
|
|
|
<Button
|
|
|
|
key="zoom-tool-1"
|
|
|
|
aria-labelledby="zoomInLabel"
|
|
|
|
aria-describedby="zoomInDesc"
|
|
|
|
role="button"
|
|
|
|
label="-"
|
|
|
|
icon="minus"
|
|
|
|
disabled={(value <= minBound)}
|
|
|
|
className={styles.prevSlide}
|
|
|
|
hideLabel
|
|
|
|
/>
|
|
|
|
</HoldButton>
|
|
|
|
),
|
2018-08-23 01:49:33 +08:00
|
|
|
(
|
|
|
|
<span
|
|
|
|
key="zoom-tool-2"
|
|
|
|
aria-labelledby="prevSlideLabel"
|
|
|
|
aria-describedby={this.state.value}
|
|
|
|
className={styles.zoomPercentageDisplay}
|
|
|
|
>
|
|
|
|
{`${this.state.value}%`}
|
|
|
|
</span>
|
|
|
|
),
|
2018-09-28 22:42:07 +08:00
|
|
|
(
|
|
|
|
<HoldButton
|
|
|
|
key="zoom-tool-3"
|
|
|
|
exec={this.increment}
|
|
|
|
value={value}
|
|
|
|
maxBound={maxBound}
|
|
|
|
>
|
|
|
|
<Button
|
|
|
|
key="zoom-tool-3"
|
|
|
|
aria-labelledby="zoomOutLabel"
|
|
|
|
aria-describedby="zoomOutDesc"
|
|
|
|
role="button"
|
|
|
|
label="+"
|
|
|
|
icon="plus"
|
|
|
|
disabled={(value >= maxBound)}
|
|
|
|
className={styles.skipSlide}
|
|
|
|
hideLabel
|
|
|
|
/>
|
|
|
|
</HoldButton>
|
|
|
|
),
|
2018-08-23 01:49:33 +08:00
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const propTypes = {
|
|
|
|
value: PropTypes.number.isRequired,
|
|
|
|
change: PropTypes.func.isRequired,
|
|
|
|
minBound: PropTypes.number.isRequired,
|
|
|
|
maxBound: PropTypes.number.isRequired,
|
|
|
|
step: PropTypes.number.isRequired,
|
|
|
|
};
|
|
|
|
|
|
|
|
ZoomTool.propTypes = propTypes;
|