aboutsummaryrefslogtreecommitdiffstats
path: root/web/src/js/components/common
diff options
context:
space:
mode:
authorJason <jason.daurus@gmail.com>2016-06-17 07:07:38 +0800
committerJason <jason.daurus@gmail.com>2016-06-17 07:07:38 +0800
commit7a78970d10ab2dfc9b86dd30a76fb1513f43dd35 (patch)
tree6d331d83866f6809cfad3b62a96b261c087394d4 /web/src/js/components/common
parent4ce7a9ba7728e7988f4455723ba5fed4fcd8d149 (diff)
downloadmitmproxy-7a78970d10ab2dfc9b86dd30a76fb1513f43dd35.tar.gz
mitmproxy-7a78970d10ab2dfc9b86dd30a76fb1513f43dd35.tar.bz2
mitmproxy-7a78970d10ab2dfc9b86dd30a76fb1513f43dd35.zip
[web] common
Diffstat (limited to 'web/src/js/components/common')
-rw-r--r--web/src/js/components/common/Button.jsx16
-rw-r--r--web/src/js/components/common/Splitter.jsx99
-rw-r--r--web/src/js/components/common/ToggleButton.jsx17
-rw-r--r--web/src/js/components/common/ToggleInputButton.jsx52
4 files changed, 184 insertions, 0 deletions
diff --git a/web/src/js/components/common/Button.jsx b/web/src/js/components/common/Button.jsx
new file mode 100644
index 00000000..cc2fe9dd
--- /dev/null
+++ b/web/src/js/components/common/Button.jsx
@@ -0,0 +1,16 @@
+import React, { PropTypes } from 'react'
+
+Button.propTypes = {
+ onClick: PropTypes.func.isRequired,
+ text: PropTypes.string.isRequired
+}
+
+export default function Button({ onClick, text, icon }) {
+ return (
+ <div className={"btn btn-default"} onClick={onClick}>
+ <i className={"fa fa-fw " + icon}/>
+ &nbsp;
+ {text}
+ </div>
+ )
+}
diff --git a/web/src/js/components/common/Splitter.jsx b/web/src/js/components/common/Splitter.jsx
new file mode 100644
index 00000000..9d22b6fd
--- /dev/null
+++ b/web/src/js/components/common/Splitter.jsx
@@ -0,0 +1,99 @@
+import React, { Component } from 'react'
+import ReactDOM from 'react-dom'
+import classnames from 'classnames'
+
+export default class Splitter extends Component {
+
+ static defaultProps = { axis: 'x' }
+
+ constructor(props, context) {
+ super(props, context)
+
+ this.state = { applied: false, startX: false, startY: false }
+
+ this.onMouseMove = this.onMouseMove.bind(this)
+ this.onMouseUp = this.onMouseUp.bind(this)
+ this.onDragEnd = this.onDragEnd.bind(this)
+ }
+
+ onMouseDown(e) {
+ this.setState({ startX: e.pageX, startY: e.pageY })
+
+ window.addEventListener('mousemove', this.onMouseMove)
+ window.addEventListener('mouseup', this.onMouseUp)
+ // Occasionally, only a dragEnd event is triggered, but no mouseUp.
+ window.addEventListener('dragend', this.onDragEnd)
+ }
+
+ onDragEnd() {
+ ReactDOM.findDOMNode(this).style.transform = ''
+
+ window.removeEventListener('dragend', this.onDragEnd)
+ window.removeEventListener('mouseup', this.onMouseUp)
+ window.removeEventListener('mousemove', this.onMouseMove)
+ }
+
+ onMouseUp(e) {
+ this.onDragEnd()
+
+ const node = ReactDOM.findDOMNode(this)
+ const prev = node.previousElementSibling
+
+ let flexBasis = prev.offsetHeight + e.pageY - this.state.startY
+
+ if (this.props.axis === 'x') {
+ flexBasis = prev.offsetWidth + e.pageX - this.state.startX
+ }
+
+ prev.style.flex = `0 0 ${Math.max(0, flexBasis)}px`
+ node.nextElementSibling.style.flex = '1 1 auto'
+
+ this.setState({ applied: true })
+ this.onResize()
+ }
+
+ onMouseMove(e) {
+ let dX = 0
+ let dY = 0
+ if (this.props.axis === 'x') {
+ dX = e.pageX - this.state.startX
+ } else {
+ dY = e.pageY - this.state.startY
+ }
+ ReactDOM.findDOMNode(this).style.transform = `translate(${dX}px, ${dY}px)`
+ }
+
+ onResize() {
+ // Trigger a global resize event. This notifies components that employ virtual scrolling
+ // that their viewport may have changed.
+ window.setTimeout(() => window.dispatchEvent(new CustomEvent('resize')), 1)
+ }
+
+ reset(willUnmount) {
+ if (!this.state.applied) {
+ return
+ }
+
+ const node = ReactDOM.findDOMNode(this)
+
+ node.previousElementSibling.style.flex = ''
+ node.nextElementSibling.style.flex = ''
+
+ if (!willUnmount) {
+ this.setState({ applied: false })
+ }
+ this.onResize()
+ }
+
+ componentWillUnmount() {
+ this.reset(true)
+ }
+
+ render() {
+ return (
+ <div className={classnames('splitter', this.props.axis === 'x' ? 'splitter-x' : 'splitter-y')}>
+ <div onMouseDown={this.onMouseDown} draggable="true"></div>
+ </div>
+ )
+ }
+}
diff --git a/web/src/js/components/common/ToggleButton.jsx b/web/src/js/components/common/ToggleButton.jsx
new file mode 100644
index 00000000..6027728b
--- /dev/null
+++ b/web/src/js/components/common/ToggleButton.jsx
@@ -0,0 +1,17 @@
+import React, { PropTypes } from 'react'
+
+ToggleButton.propTypes = {
+ checked: PropTypes.bool.isRequired,
+ onToggle: PropTypes.func.isRequired,
+ text: PropTypes.string.isRequired
+}
+
+export default function ToggleButton({ checked, onToggle, text }) {
+ return (
+ <div className={"btn btn-toggle " + (checked ? "btn-primary" : "btn-default")} onClick={onToggle}>
+ <i className={"fa fa-fw " + (checked ? "fa-check-square-o" : "fa-square-o")}/>
+ &nbsp;
+ {text}
+ </div>
+ )
+}
diff --git a/web/src/js/components/common/ToggleInputButton.jsx b/web/src/js/components/common/ToggleInputButton.jsx
new file mode 100644
index 00000000..25d620ae
--- /dev/null
+++ b/web/src/js/components/common/ToggleInputButton.jsx
@@ -0,0 +1,52 @@
+import React, { Component, PropTypes } from 'react'
+import classnames from 'classnames'
+import { Key } from '../../utils'
+
+export default class ToggleInputButton extends Component {
+
+ static propTypes = {
+ name: PropTypes.string.isRequired,
+ txt: PropTypes.string.isRequired,
+ onToggleChanged: PropTypes.func.isRequired
+ }
+
+ constructor(props) {
+ super(props)
+ this.state = { txt: props.txt }
+ }
+
+ onChange(e) {
+ this.setState({ txt: e.target.value })
+ }
+
+ onKeyDown(e) {
+ e.stopPropagation()
+ if (e.keyCode === Key.ENTER) {
+ this.props.onToggleChanged(this.state.txt)
+ }
+ }
+
+ render() {
+ return (
+ <div className="input-group toggle-input-btn">
+ <span className="input-group-btn"
+ onClick={() => this.props.onToggleChanged(this.state.txt)}>
+ <div className={classnames('btn', this.props.checked ? 'btn-primary' : 'btn-default')}>
+ <span className={classnames('fa', this.props.checked ? 'fa-check-square-o' : 'fa-square-o')}/>
+ &nbsp;
+ {this.props.name}
+ </div>
+ </span>
+ <input
+ className="form-control"
+ placeholder={this.props.placeholder}
+ disabled={this.props.checked}
+ value={this.state.txt}
+ type={this.props.inputType}
+ onChange={e => this.onChange(e)}
+ onKeyDown={e => this.onKeyDown(e)}
+ />
+ </div>
+ )
+ }
+}