174 lines
3.8 KiB
JavaScript
174 lines
3.8 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||
|
||
"use strict";
|
||
|
||
const { DOM: dom, createClass, PropTypes } =
|
||
require("devtools/client/shared/vendor/react");
|
||
|
||
const Constants = require("../constants");
|
||
const Types = require("../types");
|
||
|
||
module.exports = createClass({
|
||
displayName: "ViewportDimension",
|
||
|
||
propTypes: {
|
||
viewport: PropTypes.shape(Types.viewport).isRequired,
|
||
onRemoveDevice: PropTypes.func.isRequired,
|
||
onResizeViewport: PropTypes.func.isRequired,
|
||
},
|
||
|
||
getInitialState() {
|
||
let { width, height } = this.props.viewport;
|
||
|
||
return {
|
||
width,
|
||
height,
|
||
isEditing: false,
|
||
isInvalid: false,
|
||
};
|
||
},
|
||
|
||
componentWillReceiveProps(nextProps) {
|
||
let { width, height } = nextProps.viewport;
|
||
|
||
this.setState({
|
||
width,
|
||
height,
|
||
});
|
||
},
|
||
|
||
validateInput(value) {
|
||
let isInvalid = true;
|
||
|
||
// Check the value is a number and greater than MIN_VIEWPORT_DIMENSION
|
||
if (/^\d{3,4}$/.test(value) &&
|
||
parseInt(value, 10) >= Constants.MIN_VIEWPORT_DIMENSION) {
|
||
isInvalid = false;
|
||
}
|
||
|
||
this.setState({
|
||
isInvalid,
|
||
});
|
||
},
|
||
|
||
onInputBlur() {
|
||
let { width, height } = this.props.viewport;
|
||
|
||
if (this.state.width != width || this.state.height != height) {
|
||
this.onInputSubmit();
|
||
}
|
||
|
||
this.setState({
|
||
isEditing: false,
|
||
inInvalid: false,
|
||
});
|
||
},
|
||
|
||
onInputChange({ target }) {
|
||
if (target.value.length > 4) {
|
||
return;
|
||
}
|
||
|
||
if (this.refs.widthInput == target) {
|
||
this.setState({ width: target.value });
|
||
this.validateInput(target.value);
|
||
}
|
||
|
||
if (this.refs.heightInput == target) {
|
||
this.setState({ height: target.value });
|
||
this.validateInput(target.value);
|
||
}
|
||
},
|
||
|
||
onInputFocus() {
|
||
this.setState({
|
||
isEditing: true,
|
||
});
|
||
},
|
||
|
||
onInputKeyUp({ target, keyCode }) {
|
||
// On Enter, submit the input
|
||
if (keyCode == 13) {
|
||
this.onInputSubmit();
|
||
}
|
||
|
||
// On Esc, blur the target
|
||
if (keyCode == 27) {
|
||
target.blur();
|
||
}
|
||
},
|
||
|
||
onInputSubmit() {
|
||
if (this.state.isInvalid) {
|
||
let { width, height } = this.props.viewport;
|
||
|
||
this.setState({
|
||
width,
|
||
height,
|
||
isInvalid: false,
|
||
});
|
||
|
||
return;
|
||
}
|
||
|
||
// Change the device selector back to an unselected device
|
||
// TODO: Bug 1332754: Logic like this probably belongs in the action creator.
|
||
if (this.props.viewport.device) {
|
||
this.props.onRemoveDevice();
|
||
}
|
||
this.props.onResizeViewport(parseInt(this.state.width, 10),
|
||
parseInt(this.state.height, 10));
|
||
},
|
||
|
||
render() {
|
||
let editableClass = "viewport-dimension-editable";
|
||
let inputClass = "viewport-dimension-input";
|
||
|
||
if (this.state.isEditing) {
|
||
editableClass += " editing";
|
||
inputClass += " editing";
|
||
}
|
||
|
||
if (this.state.isInvalid) {
|
||
editableClass += " invalid";
|
||
}
|
||
|
||
return dom.div(
|
||
{
|
||
className: "viewport-dimension",
|
||
},
|
||
dom.div(
|
||
{
|
||
className: editableClass,
|
||
},
|
||
dom.input({
|
||
ref: "widthInput",
|
||
className: inputClass,
|
||
size: 4,
|
||
value: this.state.width,
|
||
onBlur: this.onInputBlur,
|
||
onChange: this.onInputChange,
|
||
onFocus: this.onInputFocus,
|
||
onKeyUp: this.onInputKeyUp,
|
||
}),
|
||
dom.span({
|
||
className: "viewport-dimension-separator",
|
||
}, "×"),
|
||
dom.input({
|
||
ref: "heightInput",
|
||
className: inputClass,
|
||
size: 4,
|
||
value: this.state.height,
|
||
onBlur: this.onInputBlur,
|
||
onChange: this.onInputChange,
|
||
onFocus: this.onInputFocus,
|
||
onKeyUp: this.onInputKeyUp,
|
||
})
|
||
)
|
||
);
|
||
},
|
||
|
||
});
|