generator-bingo-dig-h5
Version:
Bingo-dig-h5 generator by BINGO.DIG
300 lines (250 loc) • 7.99 kB
JSX
var React = require('react');
var KeyCode = require('../utils/key-code');
var Classable = require('../mixins/classable');
var UniqueId = require('../utils/unique-id');
var WindowListenable = require('../mixins/window-listenable');
var FocusRipple = require('./ripples/focus-ripple');
var TouchRipple = require('./ripples/touch-ripple');
var Paper = require('./paper');
var EnhancedSwitch = React.createClass({
mixins: [Classable, WindowListenable],
propTypes: {
id: React.PropTypes.string,
inputType: React.PropTypes.string.isRequired,
switchElement: React.PropTypes.element.isRequired,
iconClassName: React.PropTypes.string.isRequired,
name: React.PropTypes.string,
value: React.PropTypes.string,
label: React.PropTypes.string,
onSwitch: React.PropTypes.func,
required: React.PropTypes.bool,
disabled: React.PropTypes.bool,
defaultSwitched: React.PropTypes.bool,
labelPosition: React.PropTypes.oneOf(['left', 'right']),
disableFocusRipple: React.PropTypes.bool,
disableTouchRipple: React.PropTypes.bool
},
windowListeners: {
'keydown': '_handleWindowKeydown',
'keyup': '_handleWindowKeyup'
},
getDefaultProps: function() {
return {
iconClassName: ''
};
},
getInitialState: function() {
return {
switched: this.props.defaultSwitched || (this.props.valueLink && this.props.valueLink.value),
isKeyboardFocused: false
};
},
componentDidMount: function() {
var inputNode = this.refs.checkbox.getDOMNode();
this.setState({switched: inputNode.checked});
},
componentWillReceiveProps: function(nextProps) {
var hasCheckedLinkProp = nextProps.hasOwnProperty('checkedLink');
var hasCheckedProp = nextProps.hasOwnProperty('checked');
var hasToggledProp = nextProps.hasOwnProperty('toggled');
var hasNewDefaultProp = (nextProps.hasOwnProperty('defaultSwitched') && (nextProps.defaultSwitched != this.props.defaultSwitched));
var newState = {};
if (hasCheckedProp) {
newState.switched = nextProps.checked;
} else if (hasToggledProp) {
newState.switched = nextProps.toggled;
} else if (hasCheckedLinkProp) {
newState.switched = nextProps.checkedLink.value;
}
if (newState) {
this.setState(newState);
};
},
render: function() {
var {
type,
name,
value,
label,
onSwitch,
defaultSwitched,
onBlur,
onFocus,
onMouseUp,
onMouseDown,
onMouseOut,
onTouchStart,
onTouchEnd,
disableTouchRipple,
disableFocusRipple,
iconClassName,
...other
} = this.props;
var classes = this.getClasses('dig-enhanced-switch', {
'dig-is-switched': this.state.switched,
'dig-is-disabled': this.props.disabled,
'dig-is-required': this.props.required
});
var inputId = this.props.id || UniqueId.generate();
var labelElement = this.props.label ? (
<label className='dig-switch-label' htmlFor={inputId}>
{this.props.label}
</label>
) : null;
var inputProps = {
ref: "checkbox",
type: this.props.inputType,
name: this.props.name,
value: this.props.value,
defaultChecked: this.props.defaultSwitched,
onBlur: this._handleBlur,
onFocus: this._handleFocus
};
var hideTouchRipple = this.props.disabled || disableTouchRipple;
if (!hideTouchRipple) {
inputProps.onMouseUp = this._handleMouseUp;
inputProps.onMouseDown = this._handleMouseDown;
inputProps.onMouseOut = this._handleMouseOut;
inputProps.onTouchStart = this._handleTouchStart;
inputProps.onTouchEnd = this._handleTouchEnd;
};
if (!this.props.hasOwnProperty('checkedLink')) {
inputProps.onChange = this._handleChange;
}
var inputElement = (
<input
{...other}
{...inputProps}
className="dig-enhanced-switch-input" />
);
var touchRipple = (
<TouchRipple
ref="touchRipple"
key="touchRipple"
centerRipple={true} />
);
var focusRipple = (
<FocusRipple
key="focusRipple"
show={this.state.isKeyboardFocused} />
);
var ripples = [
hideTouchRipple ? null : touchRipple,
this.props.disabled || disableFocusRipple ? null : focusRipple
];
iconClassName += ' dig-enhanced-switch-wrap';
var switchElement = (this.props.iconClassName.indexOf("toggle") == -1) ? (
<div className={iconClassName}>
{this.props.switchElement}
{ripples}
</div>
) : (
<div className={iconClassName}>
<div className="dig-toggle-track" />
<Paper className="dig-toggle-thumb" zDepth={1}> {ripples} </Paper>
</div>
);
var labelPositionExist = this.props.labelPosition;
// Position is left if not defined or invalid.
var elementsInOrder = (labelPositionExist &&
(this.props.labelPosition.toUpperCase() === "RIGHT")) ? (
<div>
{switchElement}
{labelElement}
</div>
) : (
<div>
{labelElement}
{switchElement}
</div>
);
return (
<div className={classes}>
{inputElement}
{elementsInOrder}
</div>
);
},
isSwitched: function() {
return this.refs.checkbox.getDOMNode().checked;
},
// no callback here because there is no event
setSwitched: function(newSwitchedValue) {
if (!this.props.hasOwnProperty('checked') || this.props.checked === false) {
this.setState({switched: newSwitchedValue});
this.refs.checkbox.getDOMNode().checked = newSwitchedValue;
} else if (process.NODE_ENV !== 'production') {
var message = 'Cannot call set method while checked is defined as a property.';
console.error(message);
}
},
getValue: function() {
return this.refs.checkbox.getDOMNode().value;
},
isKeyboardFocused: function() {
return this.state.isKeyboardFocused;
},
_handleChange: function(e) {
this._tabPressed = false;
this.setState({
isKeyboardFocused: false
});
var isInputChecked = this.refs.checkbox.getDOMNode().checked;
if (!this.props.hasOwnProperty('checked')) this.setState({switched: isInputChecked});
if (this.props.onSwitch) this.props.onSwitch(e, isInputChecked);
},
/**
* Because both the ripples and the checkbox input cannot share pointer
* events, the checkbox input takes control of pointer events and calls
* ripple animations manually.
*/
// Checkbox inputs only use SPACE to change their state. Using ENTER will
// update the ui but not the input.
_handleWindowKeydown: function(e) {
if (e.keyCode == KeyCode.TAB) this._tabPressed = true;
if (e.keyCode == KeyCode.SPACE && this.state.isKeyboardFocused) {
this._handleChange(e);
}
},
_handleWindowKeyup: function(e) {
if (e.keyCode == KeyCode.SPACE && this.state.isKeyboardFocused) {
this._handleChange(e);
}
},
_handleMouseDown: function(e) {
//only listen to left clicks
if (e.button === 0) this.refs.touchRipple.start(e);
},
_handleMouseUp: function(e) {
this.refs.touchRipple.end();
},
_handleMouseOut: function(e) {
this.refs.touchRipple.end();
},
_handleTouchStart: function(e) {
this.refs.touchRipple.start(e);
},
_handleTouchEnd: function(e) {
this.refs.touchRipple.end();
},
_handleBlur: function(e) {
this.setState({
isKeyboardFocused: false
});
if (this.props.onBlur) this.props.onBlur(e);
},
_handleFocus: function(e) {
//setTimeout is needed becuase the focus event fires first
//Wait so that we can capture if this was a keyboard focus
//or touch focus
setTimeout(function() {
if (this._tabPressed) {
this.setState({
isKeyboardFocused: true
});
}
}.bind(this), 150);
if (this.props.onFocus) this.props.onFocus(e);
}
});
module.exports = EnhancedSwitch;