Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
63 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,84 @@ | ||
'use strict'; | ||
|
||
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; } | ||
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | ||
|
||
var React = require('react'); | ||
var ReactDOM = require('react-dom'); | ||
|
||
function checkbox(name, checkedValues, onChange) { | ||
return function Checkbox(props) { | ||
var checked = checkedValues.indexOf(props.value) >= 0; | ||
onChange = onChange.bind(null, props.value); | ||
|
||
return React.createElement('input', _extends({}, props, { | ||
type: 'checkbox', | ||
name: name, | ||
checked: checked, | ||
onChange: onChange | ||
})); | ||
}; | ||
} | ||
|
||
module.exports = React.createClass({ | ||
displayName: 'CheckboxGroup', | ||
getInitialState: function getInitialState() { | ||
return { defaultValue: this.props.defaultValue || [] }; | ||
}, | ||
|
||
componentDidMount: function componentDidMount() { | ||
this.setCheckboxNames(); | ||
this.setCheckedBoxes(); | ||
}, | ||
|
||
componentDidUpdate: function componentDidUpdate() { | ||
this.setCheckboxNames(); | ||
this.setCheckedBoxes(); | ||
return { | ||
value: this.props.value || this.props.defaultValue || [], | ||
firstRender: true // for defaultValue | ||
}; | ||
}, | ||
|
||
render: function render() { | ||
var _props = this.props; | ||
var name = _props.name; | ||
var value = _props.value; | ||
var defaultValue = _props.defaultValue; | ||
|
||
var otherProps = _objectWithoutProperties(_props, ['name', 'value', 'defaultValue']); | ||
|
||
return React.createElement( | ||
'div', | ||
otherProps, | ||
this.props.children | ||
); | ||
isControlledComponent: function isControlledComponent() { | ||
return !!this.props.value; | ||
}, | ||
|
||
setCheckboxNames: function setCheckboxNames() { | ||
// stay DRY and don't put the same `name` on all checkboxes manually. Put it on | ||
// the tag and it'll be done here | ||
var $checkboxes = this.getCheckboxes(); | ||
for (var i = 0, length = $checkboxes.length; i < length; i++) { | ||
$checkboxes[i].setAttribute('name', this.props.name); | ||
componentWillReceiveProps: function componentWillReceiveProps(newProps) { | ||
if (newProps.value) { | ||
this.setState({ value: newProps.value }); | ||
} | ||
}, | ||
|
||
getCheckboxes: function getCheckboxes() { | ||
return ReactDOM.findDOMNode(this).querySelectorAll('input[type="checkbox"]'); | ||
componentDidMount: function componentDidMount() { | ||
// TODO: this seems wrong, is there a better way?? | ||
this.setState({ | ||
firstRender: false | ||
}); | ||
}, | ||
onCheckboxChange: function onCheckboxChange(checkboxValue, event) { | ||
var newValue; | ||
if (event.target.checked) { | ||
newValue = this.state.value.concat(checkboxValue); | ||
} else { | ||
newValue = this.state.value.filter(function (v) { | ||
return v !== checkboxValue; | ||
}); | ||
} | ||
|
||
setCheckedBoxes: function setCheckedBoxes() { | ||
var $checkboxes = this.getCheckboxes(); | ||
// if `value` is passed from parent, always use that value. This is similar | ||
// to React's controlled component. If `defaultValue` is used instead, | ||
// subsequent updates to defaultValue are ignored. Note: when `defaultValue` | ||
// and `value` are both passed, the latter takes precedence, just like in | ||
// a controlled component | ||
var destinationValue = this.props.value != null ? this.props.value : this.state.defaultValue; | ||
|
||
for (var i = 0, length = $checkboxes.length; i < length; i++) { | ||
var $checkbox = $checkboxes[i]; | ||
if (!this.isControlledComponent()) { | ||
this.setState({ value: newValue }); | ||
} else { | ||
this.setState({ value: this.props.value }); | ||
} | ||
|
||
// intentionally use implicit conversion for those who accidentally used, | ||
// say, `valueToChange` of 1 (integer) to compare it with `value` of "1" | ||
// (auto conversion to valid html value from React) | ||
if (destinationValue.indexOf($checkbox.value) >= 0) { | ||
$checkbox.checked = true; | ||
} | ||
if (typeof this.props.onChange === 'function') { | ||
this.props.onChange(newValue); | ||
} | ||
}, | ||
getValue: function getValue() { | ||
return this.state.value; | ||
}, | ||
render: function render() { | ||
var _props = this.props; | ||
var name = _props.name; | ||
var value = _props.value; | ||
var children = _props.children; | ||
|
||
getCheckedValues: function getCheckedValues() { | ||
var $checkboxes = this.getCheckboxes(); | ||
|
||
var checked = []; | ||
for (var i = 0, length = $checkboxes.length; i < length; i++) { | ||
if ($checkboxes[i].checked) { | ||
checked.push($checkboxes[i].value); | ||
} | ||
var checkedValues; | ||
if (!this.isControlledComponent()) { | ||
checkedValues = this.state.value; | ||
} else { | ||
checkedValues = value; | ||
} | ||
|
||
return checked; | ||
var renderedChildren = children(checkbox(name, checkedValues, this.onCheckboxChange)); | ||
return renderedChildren && React.Children.only(renderedChildren); | ||
} | ||
}); |