diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 00000000..0db15815
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,43 @@
+# Change Log
+All notable changes to this project will be documented in this file.
+This project adheres to [Semantic Versioning](http://semver.org/).
+This change log adheres to standards from [Keep a CHANGELOG](http://keepachangelog.com).
+
+## [0.7.0] - 2017-08-25
+### Changed
+* Allowed the dateTime property to accept an existing Moment instance, to allow preservation of UTC flag.
+
+## [0.6.0] - 2017-03-23
+### Changed
+* Do not format inputValue when onChange to solve [issue](https://github.com/MYOB-Technology/myob_widgets/issues/460)
+[0.6.0]: https://github.com/MYOB-Technology/react-bootstrap-datetimepicker/compare/v0.5.2...v0.6.0
+
+## [0.5.2] - 2017-01-25
+### Changed
+* Made min and max dates soft disable fields such that they will still be greyed out but but still be able to be clicked
+[0.5.2]: https://github.com/MYOB-Technology/react-bootstrap-datetimepicker/compare/v0.4.2...v0.5.2
+
+## [0.4.2] - 2016-11-11
+### Fixed
+* Initialise the DateTimeField's inputValue to dateTime, even if defaultText is set
+
+[0.4.2]: https://github.com/MYOB-Technology/react-bootstrap-datetimepicker/compare/v0.4.0...v0.4.2
+
+## [0.2.3] - 2016-06-07
+### Changed
+* Removed the assumption that dates typed in the input field will be separated by either a ‘/’ for date mode and a space for month mode.
+
+[0.2.3]: https://github.com/MYOB-Technology/react-bootstrap-datetimepicker/compare/v0.2.2...v0.2.3
+
+## [0.2.0] - 2016-04-22
+### Added
+* 'onBlur', 'onEnterKeyDown', 'name', and 'tabIndex' props to DateTimeField
+
+### Fixed
+* When selecting a month, it does not reset the error styles of the input
+* Auto-evaluates year at 2 digits when both YY and YYYY formats are accepted
+
+### Changed
+* The DateTimeField now assumes that dates typed in the input field will be separated by either a ‘/’ or a space.
+
+[0.2.0]: https://github.com/MYOB-Technology/react-bootstrap-datetimepicker/compare/v0.1.0...v0.2.0
diff --git a/README.md b/README.md
index d3960fc4..eb77f1f1 100644
--- a/README.md
+++ b/README.md
@@ -6,15 +6,17 @@ This project is a port of https://github.com/Eonasdan/bootstrap-datetimepicker f
Usage
===============================
-Installation :
-```
-npm install react-bootstrap-datetimepicker
-```
+Installation : `npm install --save @myob/react-bootstrap-datetimepicker`
Then
+
```javascript
+//ES5
var DateTimeField = require('react-bootstrap-datetimepicker');
+//ES6
+import DateTimeField from "react-bootstrap-datetimepicker"
+
...
render: function() {
@@ -31,28 +33,72 @@ DateTimeField
| Name | Type | Default | Description |
| ------------ | ------- | ------- | ----------- |
-| **dateTime** | string | moment().format('x') | Represents the inital dateTime, this string is then parsed by moment.js |
+| **dateTime** | string or moment | moment().format('x') | Represents the initial dateTime. If this is a string it will be parsed by moment.js using **format**, otherwise an existing moment instance may be used. |
| **format** | string | "x" | Defines the format moment.js should use to parse and output the date to onChange |
-| **inputFormat** | string | "MM/DD/YY h:mm A" | Defines the way the date is represented in the HTML input. It must be a format understanable by moment.js |
+| **inputFormat** | string or array | *see default format table below* | Defines the *accepted* date formats in the HTML input. It must be a format understandable by moment.js |
+| **inputDisplayFormat** | string | When there is **_no inputFormat given_**: *see default format table below*.
When an **_inputFormat_** is given and it is a **string**: it takes the inputFormat.
When the **_inputFormat_** is an **array**: it takes the first inputFormat. | Defines the *display* format of the date in the HTML input. It must be a format understandable by moment.js.
If there is an **_inputFormat_** given, the inputDisplayFormat must be one of the formats listed in the inputFormat|
| **onChange** | function | x => console.log(x) | Callback trigger when the date changes. `x` is the new datetime value. |
+| **onBlur** | function | () => {} | Callback trigger when the date field blurs. |
+| **onEnterKeyDown** | function | () => {} | Callback trigger when the Enter key is pressed. |
| **showToday** | boolean | true | Highlights today's date |
| **size** | string | "md" | Changes the size of the date picker input field. Sizes: "sm", "md", "lg" |
| **daysOfWeekDisabled** | array of integer | [] | Disables clicking on some days. Goes from 0 (Sunday) to 6 (Saturday). |
| **viewMode** | string or number | 'days' | The default view to display when the picker is shown. ('years', 'months', 'days') |
| **inputProps** | object | undefined | Defines additional attributes for the input element of the component. |
+| **inputRef** | string or function | inputDateTime | Allows a custom reference to be passed to the input field. |
| **minDate** | moment | undefined | The earliest date allowed for entry in the calendar view. |
| **maxDate** | moment | undefined | The latest date allowed for entry in the calendar view. |
-| **mode** | string | undefined | Allows to selectively display only the time picker ('time') or the date picker ('date') |
-| **defaultText** | string | {dateTime} | Sets the initial value. Could be an empty string, or helper text. |
+| **mode** | string | undefined | Allows to selectively display only the time picker ('time'), date picker ('date'), or month picker ('month') |
+| **defaultText** | string | undefined | Sets the input's placeholder value. Could be an empty string, or helper text. |
+| **name** | string | undefined | Sets the name of the input element. |
+| **tabIndex** | string | undefined | Sets the tabIndex of the input element. |
+
+
+Default Format Based on Mode
+========
+
+| Mode | Format |
+| ------------ | ------- |
+| **time** | "h:mm A" |
+| **date** | "MM/DD/YY" |
+| **month** | "MM/YY" |
+| *none given* | "MM/DD/YY h:mm A" |
+
+Release Process
+========
+Once your pull request has been merged to master:
+
+1. Make sure you have the latest changes by running `git pull` on the master branch.
+2. *(Optional)* Check that your changes are reflected in the lib/react-bootstrap-datetimepicker.js file by running `npm run build-npm` and checking the file manually from the lib folder.
+3. When you're happy with your changes, run on your console:
+
+ npm run patch-release
+ #OR
+ npm run minor-release
+ #OR
+ npm run major-release
+
+Please respect [semantic versioning](http://semver.org/)!
+
+If the release command fails, then please read what the release command does (see `package.json`), and figure out which step of the process went wrong, so that you can re-try just that bit. If you get stuck, ping #ex-myob-widgets for help!
+
+Local linking to another project
+========
+1. Run `npm run build-npm` from the react-bootstrap-datetimepicker console.
+2. In your other project's **package.json**,
+Use `"@myob/react-bootstrap-datetimepicker": "#{local_path}/react-bootstrap-datetimepicker"` instead of `"@myob/react-bootstrap-datetimepicker": "0.0.25"` in the dependency list.
+3. Run `npm install @myob/react-bootstrap-datetimepicker` from the same folder level as the package.json.
Update Warning
===============================
Starting from 0.0.6, the 3 github repositories `react-bootstrap-datetimepicker`, `react-bootstrap-datetimepicker-npm` and `react-bootstrap-datetimepicker-bower` are merged in a single one. The build process changed but the API is the same.
However now the package exports DateTimeField directly, no need to do :
+
```javascript
var DateTimeField = require('react-bootstrap-datetimepicker').DateTimeField;
```
instead use :
+
```javascript
var DateTimeField = require('react-bootstrap-datetimepicker');
```
diff --git a/bower.json b/bower.json
index 36d867b6..cc91b190 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "react-bootstrap-datetimepicker",
- "version": "0.0.22",
+ "version": "0.0.23",
"main": [
"./dist/react-bootstrap-datetimepicker.min.js"
],
diff --git a/dist/react-bootstrap-datetimepicker.js b/dist/react-bootstrap-datetimepicker.js
index 6fa6d9d3..4ac8e9c5 100644
--- a/dist/react-bootstrap-datetimepicker.js
+++ b/dist/react-bootstrap-datetimepicker.js
@@ -7,7 +7,7 @@
exports["ReactBootstrapDatetimepicker"] = factory(require("React"), require("moment"));
else
root["ReactBootstrapDatetimepicker"] = factory(root["React"], root["moment"]);
-})(this, function(__WEBPACK_EXTERNAL_MODULE_38__, __WEBPACK_EXTERNAL_MODULE_39__) {
+})(this, function(__WEBPACK_EXTERNAL_MODULE_38__, __WEBPACK_EXTERNAL_MODULE_180__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
@@ -83,90 +83,115 @@ return /******/ (function(modules) { // webpackBootstrap
var _react2 = _interopRequireDefault(_react);
- var _moment = __webpack_require__(39);
+ var _reactDom = __webpack_require__(39);
+
+ var _reactDom2 = _interopRequireDefault(_reactDom);
+
+ var _moment = __webpack_require__(180);
var _moment2 = _interopRequireDefault(_moment);
- var _classnames = __webpack_require__(40);
+ var _classnames = __webpack_require__(181);
var _classnames2 = _interopRequireDefault(_classnames);
- var _DateTimePickerJs = __webpack_require__(41);
+ var _DateTimePickerJs = __webpack_require__(182);
var _DateTimePickerJs2 = _interopRequireDefault(_DateTimePickerJs);
- var _ConstantsJs = __webpack_require__(51);
+ var _ConstantsJs = __webpack_require__(189);
var _ConstantsJs2 = _interopRequireDefault(_ConstantsJs);
var DateTimeField = (function (_Component) {
_inherits(DateTimeField, _Component);
- function DateTimeField() {
+ _createClass(DateTimeField, null, [{
+ key: "defaultProps",
+ value: {
+ dateTime: (0, _moment2["default"])().format("x"),
+ format: "x",
+ showToday: true,
+ viewMode: "days",
+ daysOfWeekDisabled: [],
+ inputRef: 'inputDateTime',
+ size: _ConstantsJs2["default"].SIZE_MEDIUM,
+ mode: _ConstantsJs2["default"].MODE_DATETIME,
+ onChange: function onChange(x) {
+ console.log(x);
+ }
+ },
+ enumerable: true
+ }]);
+
+ function DateTimeField(props) {
var _this = this;
_classCallCheck(this, DateTimeField);
- _get(Object.getPrototypeOf(DateTimeField.prototype), "constructor", this).apply(this, arguments);
+ _get(Object.getPrototypeOf(DateTimeField.prototype), "constructor", this).call(this, props);
- this.resolvePropsInputFormat = function () {
- if (_this.props.inputFormat) {
- return _this.props.inputFormat;
- }
+ this.getDefaultDateFormat = function () {
switch (_this.props.mode) {
case _ConstantsJs2["default"].MODE_TIME:
return "h:mm A";
case _ConstantsJs2["default"].MODE_DATE:
return "MM/DD/YY";
+ case _ConstantsJs2["default"].MODE_MONTH:
+ return "MM/YY";
default:
return "MM/DD/YY h:mm A";
}
};
- this.state = {
- showDatePicker: this.props.mode !== _ConstantsJs2["default"].MODE_TIME,
- showTimePicker: this.props.mode === _ConstantsJs2["default"].MODE_TIME,
- inputFormat: this.resolvePropsInputFormat(),
- buttonIcon: this.props.mode === _ConstantsJs2["default"].MODE_TIME ? "glyphicon-time" : "glyphicon-calendar",
- widgetStyle: {
- display: "block",
- position: "absolute",
- left: -9999,
- zIndex: "9999 !important"
- },
- viewDate: (0, _moment2["default"])(this.props.dateTime, this.props.format, true).startOf("month"),
- selectedDate: (0, _moment2["default"])(this.props.dateTime, this.props.format, true),
- inputValue: typeof this.props.defaultText !== "undefined" ? this.props.defaultText : (0, _moment2["default"])(this.props.dateTime, this.props.format, true).format(this.resolvePropsInputFormat())
+ this.resolvePropsInputDisplayFormat = function () {
+ var props = arguments.length <= 0 || arguments[0] === undefined ? _this.props : arguments[0];
+
+ if (props.inputDisplayFormat) {
+ return props.inputDisplayFormat;
+ } else if (props.inputFormat && typeof props.inputFormat === 'string') {
+ return props.inputFormat;
+ } else if (props.inputFormat && Array.isArray(props.inputFormat)) {
+ return props.inputFormat[0];
+ }
+ return _this.getDefaultDateFormat();
+ };
+
+ this.resolvePropsInputFormat = function () {
+ if (_this.props.inputFormat) {
+ return _this.props.inputFormat;
+ }
+ return _this.getDefaultDateFormat();
};
this.componentWillReceiveProps = function (nextProps) {
+
var state = {};
- if (nextProps.inputFormat !== _this.props.inputFormat) {
- state.inputFormat = nextProps.inputFormat;
- state.inputValue = (0, _moment2["default"])(nextProps.dateTime, nextProps.format, true).format(nextProps.inputFormat);
- }
+ state.inputDisplayFormat = _this.resolvePropsInputDisplayFormat(nextProps);
- if (nextProps.dateTime !== _this.props.dateTime && (0, _moment2["default"])(nextProps.dateTime, nextProps.format, true).isValid()) {
+ if ((0, _moment2["default"])(nextProps.dateTime, nextProps.format, true).isValid()) {
state.viewDate = (0, _moment2["default"])(nextProps.dateTime, nextProps.format, true).startOf("month");
state.selectedDate = (0, _moment2["default"])(nextProps.dateTime, nextProps.format, true);
- state.inputValue = (0, _moment2["default"])(nextProps.dateTime, nextProps.format, true).format(nextProps.inputFormat ? nextProps.inputFormat : _this.state.inputFormat);
+ state.inputValue = (0, _moment2["default"])(nextProps.dateTime, nextProps.format, true).format(state.inputDisplayFormat);
}
return _this.setState(state);
};
this.onChange = function (event) {
- var value = event.target == null ? event : event.target.value;
- if ((0, _moment2["default"])(value, _this.state.inputFormat, true).isValid()) {
- _this.setState({
- selectedDate: (0, _moment2["default"])(value, _this.state.inputFormat, true),
- viewDate: (0, _moment2["default"])(value, _this.state.inputFormat, true).startOf("month")
- });
- }
+ _this.formatValueForEvent('onChange', event);
+ };
+
+ this.onBlur = function (event) {
+ _this.formatValueForEvent('onBlur', event);
+ };
+
+ this.checkIsValid = function (value) {
+ return (0, _moment2["default"])(value, _this.state.inputFormat, true).isValid() || value === _this.props.defaultText || value === '';
+ };
+ this.setIsValid = function (isValid) {
return _this.setState({
- inputValue: value
- }, function () {
- return this.props.onChange((0, _moment2["default"])(this.state.inputValue, this.state.inputFormat, true).format(this.props.format), value);
+ isValid: isValid
});
};
@@ -174,44 +199,63 @@ return /******/ (function(modules) { // webpackBootstrap
return (0, _moment2["default"])(_this.state.inputValue, _this.props.inputFormat, true).format(_this.props.format);
};
+ this.setSelectedMonth = function (e) {
+ var target = e.target;
+
+ if (target.className && !target.className.match(/disabled/g)) {
+ return _this.setState({
+ selectedDate: (0, _moment2["default"])(_this.state.viewDate.clone().toDate()).month(e.target.innerHTML).date(1).hour(_this.state.selectedDate.hours()).minute(_this.state.selectedDate.minutes())
+ }, function () {
+ this.closePicker();
+ this.props.onChange(this.state.selectedDate.format(this.props.format));
+ return this.setState({
+ inputValue: this.state.selectedDate.format(this.state.inputDisplayFormat)
+ });
+ });
+ }
+ };
+
this.setSelectedDate = function (e) {
var target = e.target;
if (target.className && !target.className.match(/disabled/g)) {
+ _this.setIsValid(true);
var month = undefined;
if (target.className.indexOf("new") >= 0) month = _this.state.viewDate.month() + 1;else if (target.className.indexOf("old") >= 0) month = _this.state.viewDate.month() - 1;else month = _this.state.viewDate.month();
return _this.setState({
- selectedDate: _this.state.viewDate.clone().month(month).date(parseInt(e.target.innerHTML)).hour(_this.state.selectedDate.hours()).minute(_this.state.selectedDate.minutes())
+ selectedDate: (0, _moment2["default"])(_this.state.viewDate.clone().toDate()).month(month).date(parseInt(e.target.innerHTML)).hour(_this.state.selectedDate.hours()).minute(_this.state.selectedDate.minutes())
}, function () {
this.closePicker();
this.props.onChange(this.state.selectedDate.format(this.props.format));
return this.setState({
- inputValue: this.state.selectedDate.format(this.state.inputFormat)
+ inputValue: this.state.selectedDate.format(this.state.inputDisplayFormat)
});
});
}
};
this.setSelectedHour = function (e) {
+ _this.setIsValid(true);
return _this.setState({
selectedDate: _this.state.selectedDate.clone().hour(parseInt(e.target.innerHTML)).minute(_this.state.selectedDate.minutes())
}, function () {
this.closePicker();
this.props.onChange(this.state.selectedDate.format(this.props.format));
return this.setState({
- inputValue: this.state.selectedDate.format(this.state.inputFormat)
+ inputValue: this.state.selectedDate.format(this.state.inputDisplayFormat)
});
});
};
this.setSelectedMinute = function (e) {
+ _this.setIsValid(true);
return _this.setState({
selectedDate: _this.state.selectedDate.clone().hour(_this.state.selectedDate.hours()).minute(parseInt(e.target.innerHTML))
}, function () {
this.closePicker();
this.props.onChange(this.state.selectedDate.format(this.props.format));
return this.setState({
- inputValue: this.state.selectedDate.format(this.state.inputFormat)
+ inputValue: this.state.selectedDate.format(this.state.inputDisplayFormat)
});
});
};
@@ -234,7 +278,7 @@ return /******/ (function(modules) { // webpackBootstrap
}, function () {
this.props.onChange(this.state.selectedDate.format(this.props.format));
return this.setState({
- inputValue: this.state.selectedDate.format(this.resolvePropsInputFormat())
+ inputValue: this.state.selectedDate.format(this.resolvePropsInputDisplayFormat())
});
});
};
@@ -245,7 +289,7 @@ return /******/ (function(modules) { // webpackBootstrap
}, function () {
this.props.onChange(this.state.selectedDate.format(this.props.format));
return this.setState({
- inputValue: this.state.selectedDate.format(this.resolvePropsInputFormat())
+ inputValue: this.state.selectedDate.format(this.resolvePropsInputDisplayFormat())
});
});
};
@@ -274,7 +318,7 @@ return /******/ (function(modules) { // webpackBootstrap
}, function () {
_this.props.onChange(_this.state.selectedDate.format(_this.props.format));
return _this.setState({
- inputValue: _this.state.selectedDate.format(_this.resolvePropsInputFormat())
+ inputValue: _this.state.selectedDate.format(_this.resolvePropsInputDisplayFormat())
});
});
};
@@ -285,7 +329,7 @@ return /******/ (function(modules) { // webpackBootstrap
}, function () {
_this.props.onChange(_this.state.selectedDate.format(_this.props.format));
return _this.setState({
- inputValue: _this.state.selectedDate.format(_this.resolvePropsInputFormat())
+ inputValue: _this.state.selectedDate.format(_this.resolvePropsInputDisplayFormat())
});
});
};
@@ -310,9 +354,9 @@ return /******/ (function(modules) { // webpackBootstrap
this.togglePeriod = function () {
if (_this.state.selectedDate.hour() > 12) {
- return _this.onChange(_this.state.selectedDate.clone().subtract(12, "hours").format(_this.state.inputFormat));
+ return _this.onChange(_this.state.selectedDate.clone().subtract(12, "hours").format(_this.state.inputDisplayFormat));
} else {
- return _this.onChange(_this.state.selectedDate.clone().add(12, "hours").format(_this.state.inputFormat));
+ return _this.onChange(_this.state.selectedDate.clone().add(12, "hours").format(_this.state.inputDisplayFormat));
}
};
@@ -323,60 +367,97 @@ return /******/ (function(modules) { // webpackBootstrap
});
};
- this.onClick = function () {
+ this.setToday = function () {
+ var today = (0, _moment2["default"])();
+ _this.setIsValid(true);
+ return _this.setState({
+ selectedDate: today
+ }, function () {
+ this.closePicker();
+ this.props.onChange(today);
+ return this.setState({
+ inputValue: this.state.selectedDate.format(this.resolvePropsInputDisplayFormat())
+ });
+ });
+ };
+
+ this.calculatePosition = function (options) {
var classes = undefined,
gBCR = undefined,
offset = undefined,
placePosition = undefined,
scrollTop = undefined,
- styles = undefined;
+ styles = undefined,
+ widgetOffsetHeight = undefined,
+ clientHeight = undefined,
+ height = undefined;
+
+ classes = {};
+ if (options) {
+ classes["months"] = options.monthsDisplayed;
+ classes["years"] = options.yearsDisplayed;
+ classes["days"] = options.daysDisplayed;
+ classes["time"] = options.timeDisplayed;
+ }
+ gBCR = _this.refs.dtpbutton.getBoundingClientRect();
+
+ offset = {
+ top: gBCR.top + window.pageYOffset - document.documentElement.clientTop,
+ left: 0
+ };
+ offset.top = offset.top + _this.refs.datetimepicker.offsetHeight;
+ //Support for both old version of react and new version (v1.4.2) of react
+ //The new version of react return the child refs as a component rather than a DomNode
+ widgetOffsetHeight = _this.refs.widget.offsetHeight || _reactDom2["default"].findDOMNode(_this.refs.widget).offsetHeight;
+ clientHeight = _this.refs.widget.clientHeight || _reactDom2["default"].findDOMNode(_this.refs.widget).clientHeight;
+ height = _this.refs.widget.height || _reactDom2["default"].findDOMNode(_this.refs.widget).height;
+
+ scrollTop = window.pageYOffset !== undefined ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
+ placePosition = _this.props.direction === "up" ? "top" : _this.props.direction === "bottom" ? "bottom" : _this.props.direction === "auto" ? offset.top + widgetOffsetHeight > window.offsetHeight + scrollTop && widgetOffsetHeight + _this.refs.datetimepicker.offsetHeight > offset.top ? "top" : "bottom" : void 0;
+ if (placePosition === "top") {
+ offset.top = -widgetOffsetHeight - 2;
+ classes.top = true;
+ classes.bottom = false;
+ } else {
+ offset.top = 35;
+ classes.top = false;
+ classes.bottom = true;
+ }
+ styles = {
+ display: "block",
+ position: "absolute",
+ top: offset.top,
+ left: offset.left,
+ right: 40
+ };
+ return _this.setState({
+ widgetStyle: styles,
+ widgetClasses: classes
+ });
+ };
+
+ this.onClick = function () {
+ var displayOptions = {};
+
if (_this.state.showPicker) {
return _this.closePicker();
} else {
_this.setState({
showPicker: true
});
- gBCR = _this.refs.dtpbutton.getBoundingClientRect();
- classes = {
- "bootstrap-datetimepicker-widget": true,
- "dropdown-menu": true
- };
- offset = {
- top: gBCR.top + window.pageYOffset - document.documentElement.clientTop,
- left: gBCR.left + window.pageXOffset - document.documentElement.clientLeft
- };
- offset.top = offset.top + _this.refs.datetimepicker.offsetHeight;
- scrollTop = window.pageYOffset !== undefined ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
- placePosition = _this.props.direction === "up" ? "top" : _this.props.direction === "bottom" ? "bottom" : _this.props.direction === "auto" ? offset.top + _this.refs.widget.offsetHeight > window.offsetHeight + scrollTop && _this.refs.widget.offsetHeight + _this.refs.datetimepicker.offsetHeight > offset.top ? "top" : "bottom" : void 0;
- if (placePosition === "top") {
- offset.top = -_this.refs.widget.offsetHeight - _this.clientHeight - 2;
- classes.top = true;
- classes.bottom = false;
- classes["pull-right"] = true;
- } else {
- offset.top = 40;
- classes.top = false;
- classes.bottom = true;
- classes["pull-right"] = true;
- }
- styles = {
- display: "block",
- position: "absolute",
- top: offset.top,
- left: "auto",
- right: 40
- };
- return _this.setState({
- widgetStyle: styles,
- widgetClasses: classes
- });
+ displayOptions.yearsDisplayed = _this.props.mode === 'year';
+ displayOptions.monthsDisplayed = _this.props.mode === 'month';
+ displayOptions.daysDisplayed = _this.props.mode === 'date';
+ displayOptions.timeDisplayed = _this.props.mode === 'time';
+
+ _this.calculatePosition(displayOptions);
}
};
this.closePicker = function () {
var style = _extends({}, _this.state.widgetStyle);
style.left = -9999;
- style.display = "none";
+ style.display = "block";
return _this.setState({
showPicker: false,
widgetStyle: style
@@ -409,14 +490,56 @@ return /******/ (function(modules) { // webpackBootstrap
return _react2["default"].createElement("span", null);
}
};
+
+ var dateTime = props.dateTime ? props.dateTime : (0, _moment2["default"])().format(props.format);
+ this.state = {
+ showDatePicker: props.mode !== _ConstantsJs2["default"].MODE_TIME,
+ showTimePicker: props.mode === _ConstantsJs2["default"].MODE_TIME,
+ inputDisplayFormat: this.resolvePropsInputDisplayFormat(),
+ inputFormat: this.resolvePropsInputFormat(),
+ buttonIcon: props.mode === _ConstantsJs2["default"].MODE_TIME ? "glyphicon-time" : "glyphicon-calendar",
+ widgetStyle: {
+ display: "block",
+ position: "absolute",
+ left: -9999,
+ zIndex: "9999 !important"
+ },
+ viewDate: (0, _moment2["default"])(dateTime, props.format, true).startOf("month"),
+ selectedDate: (0, _moment2["default"])(dateTime, props.format, true),
+ inputValue: typeof props.defaultText !== "undefined" ? undefined : (0, _moment2["default"])(dateTime, props.format, true).format(this.resolvePropsInputDisplayFormat()),
+ isValid: true
+ };
}
_createClass(DateTimeField, [{
+ key: "formatValueForEvent",
+ value: function formatValueForEvent(eventName, event) {
+ var value = event.target == null ? event : event.target.value;
+
+ this.setIsValid(this.checkIsValid(value));
+ if ((0, _moment2["default"])(value, this.state.inputFormat, true).isValid()) {
+ this.setState({
+ selectedDate: (0, _moment2["default"])(value, this.state.inputFormat, true),
+ viewDate: (0, _moment2["default"])(value, this.state.inputFormat, true).startOf("month")
+ });
+ }
+
+ if ((0, _moment2["default"])(value, this.state.inputFormat, true).isValid()) {
+ value = (0, _moment2["default"])(value, this.state.inputFormat, true).format(this.state.inputDisplayFormat);
+ }
+
+ return this.setState({
+ inputValue: value
+ }, function () {
+ return this.props[eventName]((0, _moment2["default"])(this.state.inputValue, this.state.inputFormat, true).format(this.props.format), value);
+ });
+ }
+ }, {
key: "render",
value: function render() {
return _react2["default"].createElement(
"div",
- null,
+ { className: "bootstrap-datetimepicker-wrap" },
this.renderOverlay(),
_react2["default"].createElement(_DateTimePickerJs2["default"], {
addDecade: this.addDecade,
@@ -430,11 +553,13 @@ return /******/ (function(modules) { // webpackBootstrap
mode: this.props.mode,
ref: "widget",
selectedDate: this.state.selectedDate,
+ setSelectedMonth: this.setSelectedMonth,
setSelectedDate: this.setSelectedDate,
setSelectedHour: this.setSelectedHour,
setSelectedMinute: this.setSelectedMinute,
setViewMonth: this.setViewMonth,
setViewYear: this.setViewYear,
+ setToday: this.setToday,
showDatePicker: this.state.showDatePicker,
showTimePicker: this.state.showTimePicker,
showToday: this.props.showToday,
@@ -448,12 +573,13 @@ return /******/ (function(modules) { // webpackBootstrap
viewDate: this.state.viewDate,
viewMode: this.props.viewMode,
widgetClasses: this.state.widgetClasses,
- widgetStyle: this.state.widgetStyle
+ widgetStyle: this.state.widgetStyle,
+ calculatePosition: this.calculatePosition
}),
_react2["default"].createElement(
"div",
- { className: "input-group date " + this.size(), ref: "datetimepicker" },
- _react2["default"].createElement("input", _extends({ className: "form-control", onChange: this.onChange, type: "text", value: this.state.inputValue }, this.props.inputProps)),
+ { className: (0, _classnames2["default"])("input-group date " + this.size(), { "has-error": !this.state.isValid }), ref: "datetimepicker" },
+ _react2["default"].createElement("input", _extends({ className: "form-control", onChange: this.onChange, onBlur: this.onBlur, type: "text", value: this.state.inputValue }, this.props.inputProps, { ref: this.props.inputRef, placeholder: this.props.defaultText })),
_react2["default"].createElement(
"span",
{ className: "input-group-addon", onBlur: this.onBlur, onClick: this.onClick, ref: "dtpbutton" },
@@ -463,37 +589,24 @@ return /******/ (function(modules) { // webpackBootstrap
);
}
}], [{
- key: "defaultProps",
- value: {
- dateTime: (0, _moment2["default"])().format("x"),
- format: "x",
- showToday: true,
- viewMode: "days",
- daysOfWeekDisabled: [],
- size: _ConstantsJs2["default"].SIZE_MEDIUM,
- mode: _ConstantsJs2["default"].MODE_DATETIME,
- onChange: function onChange(x) {
- console.log(x);
- }
- },
- enumerable: true
- }, {
key: "propTypes",
value: {
dateTime: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.number]),
onChange: _react.PropTypes.func,
format: _react.PropTypes.string,
inputProps: _react.PropTypes.object,
- inputFormat: _react.PropTypes.string,
+ inputFormat: _react.PropTypes.oneOfType([_react.PropTypes.string, _react.PropTypes.arrayOf(_react.PropTypes.string)]),
+ inputDisplayFormat: _react.PropTypes.string,
defaultText: _react.PropTypes.string,
- mode: _react.PropTypes.oneOf([_ConstantsJs2["default"].MODE_DATE, _ConstantsJs2["default"].MODE_DATETIME, _ConstantsJs2["default"].MODE_TIME]),
+ mode: _react.PropTypes.oneOf([_ConstantsJs2["default"].MODE_DATE, _ConstantsJs2["default"].MODE_MONTH, _ConstantsJs2["default"].MODE_DATETIME, _ConstantsJs2["default"].MODE_TIME]),
minDate: _react.PropTypes.object,
maxDate: _react.PropTypes.object,
direction: _react.PropTypes.string,
showToday: _react.PropTypes.bool,
viewMode: _react.PropTypes.string,
size: _react.PropTypes.oneOf([_ConstantsJs2["default"].SIZE_SMALL, _ConstantsJs2["default"].SIZE_MEDIUM, _ConstantsJs2["default"].SIZE_LARGE]),
- daysOfWeekDisabled: _react.PropTypes.arrayOf(_react.PropTypes.number)
+ daysOfWeekDisabled: _react.PropTypes.arrayOf(_react.PropTypes.number),
+ isValid: _react.PropTypes.bool
},
enumerable: true
}]);
@@ -865,207 +978,18140 @@ return /******/ (function(modules) { // webpackBootstrap
};
/***/ },
-/* 25 */
-/***/ function(module, exports) {
+/* 25 */
+/***/ function(module, exports) {
+
+ module.exports = function(it){
+ return typeof it === 'object' ? it !== null : typeof it === 'function';
+ };
+
+/***/ },
+/* 26 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var isObject = __webpack_require__(25);
+ module.exports = function(it){
+ if(!isObject(it))throw TypeError(it + ' is not an object!');
+ return it;
+ };
+
+/***/ },
+/* 27 */
+/***/ function(module, exports, __webpack_require__) {
+
+ "use strict";
+
+ var _Object$defineProperty = __webpack_require__(28)["default"];
+
+ exports["default"] = (function () {
+ function defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+
+ _Object$defineProperty(target, descriptor.key, descriptor);
+ }
+ }
+
+ return function (Constructor, protoProps, staticProps) {
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) defineProperties(Constructor, staticProps);
+ return Constructor;
+ };
+ })();
+
+ exports.__esModule = true;
+
+/***/ },
+/* 28 */
+/***/ function(module, exports, __webpack_require__) {
+
+ module.exports = { "default": __webpack_require__(29), __esModule: true };
+
+/***/ },
+/* 29 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var $ = __webpack_require__(5);
+ module.exports = function defineProperty(it, key, desc){
+ return $.setDesc(it, key, desc);
+ };
+
+/***/ },
+/* 30 */
+/***/ function(module, exports) {
+
+ "use strict";
+
+ exports["default"] = function (instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+ };
+
+ exports.__esModule = true;
+
+/***/ },
+/* 31 */
+/***/ function(module, exports, __webpack_require__) {
+
+ "use strict";
+
+ var _Object$assign = __webpack_require__(32)["default"];
+
+ exports["default"] = _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;
+ };
+
+ exports.__esModule = true;
+
+/***/ },
+/* 32 */
+/***/ function(module, exports, __webpack_require__) {
+
+ module.exports = { "default": __webpack_require__(33), __esModule: true };
+
+/***/ },
+/* 33 */
+/***/ function(module, exports, __webpack_require__) {
+
+ __webpack_require__(34);
+ module.exports = __webpack_require__(14).Object.assign;
+
+/***/ },
+/* 34 */
+/***/ function(module, exports, __webpack_require__) {
+
+ // 19.1.3.1 Object.assign(target, source)
+ var $export = __webpack_require__(12);
+
+ $export($export.S + $export.F, 'Object', {assign: __webpack_require__(35)});
+
+/***/ },
+/* 35 */
+/***/ function(module, exports, __webpack_require__) {
+
+ // 19.1.2.1 Object.assign(target, source, ...)
+ var $ = __webpack_require__(5)
+ , toObject = __webpack_require__(36)
+ , IObject = __webpack_require__(8);
+
+ // should work with symbols and should have deterministic property order (V8 bug)
+ module.exports = __webpack_require__(17)(function(){
+ var a = Object.assign
+ , A = {}
+ , B = {}
+ , S = Symbol()
+ , K = 'abcdefghijklmnopqrst';
+ A[S] = 7;
+ K.split('').forEach(function(k){ B[k] = k; });
+ return a({}, A)[S] != 7 || Object.keys(a({}, B)).join('') != K;
+ }) ? function assign(target, source){ // eslint-disable-line no-unused-vars
+ var T = toObject(target)
+ , $$ = arguments
+ , $$len = $$.length
+ , index = 1
+ , getKeys = $.getKeys
+ , getSymbols = $.getSymbols
+ , isEnum = $.isEnum;
+ while($$len > index){
+ var S = IObject($$[index++])
+ , keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S)
+ , length = keys.length
+ , j = 0
+ , key;
+ while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key];
+ }
+ return T;
+ } : Object.assign;
+
+/***/ },
+/* 36 */
+/***/ function(module, exports, __webpack_require__) {
+
+ // 7.1.13 ToObject(argument)
+ var defined = __webpack_require__(10);
+ module.exports = function(it){
+ return Object(defined(it));
+ };
+
+/***/ },
+/* 37 */
+/***/ function(module, exports) {
+
+ "use strict";
+
+ exports["default"] = function (obj) {
+ return obj && obj.__esModule ? obj : {
+ "default": obj
+ };
+ };
+
+ exports.__esModule = true;
+
+/***/ },
+/* 38 */
+/***/ function(module, exports) {
+
+ module.exports = __WEBPACK_EXTERNAL_MODULE_38__;
+
+/***/ },
+/* 39 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ module.exports = __webpack_require__(40);
+
+
+/***/ },
+/* 40 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactDOM
+ */
+
+ /* globals __REACT_DEVTOOLS_GLOBAL_HOOK__*/
+
+ 'use strict';
+
+ var ReactCurrentOwner = __webpack_require__(41);
+ var ReactDOMTextComponent = __webpack_require__(42);
+ var ReactDefaultInjection = __webpack_require__(107);
+ var ReactInstanceHandles = __webpack_require__(81);
+ var ReactMount = __webpack_require__(64);
+ var ReactPerf = __webpack_require__(54);
+ var ReactReconciler = __webpack_require__(86);
+ var ReactUpdates = __webpack_require__(90);
+ var ReactVersion = __webpack_require__(178);
+
+ var findDOMNode = __webpack_require__(127);
+ var renderSubtreeIntoContainer = __webpack_require__(179);
+ var warning = __webpack_require__(61);
+
+ ReactDefaultInjection.inject();
+
+ var render = ReactPerf.measure('React', 'render', ReactMount.render);
+
+ var React = {
+ findDOMNode: findDOMNode,
+ render: render,
+ unmountComponentAtNode: ReactMount.unmountComponentAtNode,
+ version: ReactVersion,
+
+ /* eslint-disable camelcase */
+ unstable_batchedUpdates: ReactUpdates.batchedUpdates,
+ unstable_renderSubtreeIntoContainer: renderSubtreeIntoContainer
+ };
+
+ // Inject the runtime into a devtools global hook regardless of browser.
+ // Allows for debugging when the hook is injected on the page.
+ /* eslint-enable camelcase */
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== 'undefined' && typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.inject === 'function') {
+ __REACT_DEVTOOLS_GLOBAL_HOOK__.inject({
+ CurrentOwner: ReactCurrentOwner,
+ InstanceHandles: ReactInstanceHandles,
+ Mount: ReactMount,
+ Reconciler: ReactReconciler,
+ TextComponent: ReactDOMTextComponent
+ });
+ }
+
+ if (false) {
+ var ExecutionEnvironment = require('fbjs/lib/ExecutionEnvironment');
+ if (ExecutionEnvironment.canUseDOM && window.top === window.self) {
+
+ // First check if devtools is not installed
+ if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') {
+ // If we're in Chrome or Firefox, provide a download link if not installed.
+ if (navigator.userAgent.indexOf('Chrome') > -1 && navigator.userAgent.indexOf('Edge') === -1 || navigator.userAgent.indexOf('Firefox') > -1) {
+ console.debug('Download the React DevTools for a better development experience: ' + 'https://fb.me/react-devtools');
+ }
+ }
+
+ // If we're in IE8, check to see if we are in compatibility mode and provide
+ // information on preventing compatibility mode
+ var ieCompatibilityMode = document.documentMode && document.documentMode < 8;
+
+ process.env.NODE_ENV !== 'production' ? warning(!ieCompatibilityMode, 'Internet Explorer is running in compatibility mode; please add the ' + 'following tag to your HTML to prevent this from happening: ' + '') : undefined;
+
+ var expectedFeatures = [
+ // shims
+ Array.isArray, Array.prototype.every, Array.prototype.forEach, Array.prototype.indexOf, Array.prototype.map, Date.now, Function.prototype.bind, Object.keys, String.prototype.split, String.prototype.trim,
+
+ // shams
+ Object.create, Object.freeze];
+
+ for (var i = 0; i < expectedFeatures.length; i++) {
+ if (!expectedFeatures[i]) {
+ console.error('One or more ES5 shim/shams expected by React are not available: ' + 'https://fb.me/react-warning-polyfills');
+ break;
+ }
+ }
+ }
+ }
+
+ module.exports = React;
+
+/***/ },
+/* 41 */
+/***/ function(module, exports) {
+
+ /**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactCurrentOwner
+ */
+
+ 'use strict';
+
+ /**
+ * Keeps track of the current owner.
+ *
+ * The current owner is the component who should own any components that are
+ * currently being constructed.
+ */
+ var ReactCurrentOwner = {
+
+ /**
+ * @internal
+ * @type {ReactComponent}
+ */
+ current: null
+
+ };
+
+ module.exports = ReactCurrentOwner;
+
+/***/ },
+/* 42 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule ReactDOMTextComponent
+ * @typechecks static-only
+ */
+
+ 'use strict';
+
+ var DOMChildrenOperations = __webpack_require__(43);
+ var DOMPropertyOperations = __webpack_require__(58);
+ var ReactComponentBrowserEnvironment = __webpack_require__(62);
+ var ReactMount = __webpack_require__(64);
+
+ var assign = __webpack_require__(75);
+ var escapeTextContentForBrowser = __webpack_require__(57);
+ var setTextContent = __webpack_require__(56);
+ var validateDOMNesting = __webpack_require__(106);
+
+ /**
+ * Text nodes violate a couple assumptions that React makes about components:
+ *
+ * - When mounting text into the DOM, adjacent text nodes are merged.
+ * - Text nodes cannot be assigned a React root ID.
+ *
+ * This component is used to wrap strings in elements so that they can undergo
+ * the same reconciliation that is applied to elements.
+ *
+ * TODO: Investigate representing React components in the DOM with text nodes.
+ *
+ * @class ReactDOMTextComponent
+ * @extends ReactComponent
+ * @internal
+ */
+ var ReactDOMTextComponent = function (props) {
+ // This constructor and its argument is currently used by mocks.
+ };
+
+ assign(ReactDOMTextComponent.prototype, {
+
+ /**
+ * @param {ReactText} text
+ * @internal
+ */
+ construct: function (text) {
+ // TODO: This is really a ReactText (ReactNode), not a ReactElement
+ this._currentElement = text;
+ this._stringText = '' + text;
+
+ // Properties
+ this._rootNodeID = null;
+ this._mountIndex = 0;
+ },
+
+ /**
+ * Creates the markup for this text node. This node is not intended to have
+ * any features besides containing text content.
+ *
+ * @param {string} rootID DOM ID of the root node.
+ * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction
+ * @return {string} Markup for this text node.
+ * @internal
+ */
+ mountComponent: function (rootID, transaction, context) {
+ if (false) {
+ if (context[validateDOMNesting.ancestorInfoContextKey]) {
+ validateDOMNesting('span', null, context[validateDOMNesting.ancestorInfoContextKey]);
+ }
+ }
+
+ this._rootNodeID = rootID;
+ if (transaction.useCreateElement) {
+ var ownerDocument = context[ReactMount.ownerDocumentContextKey];
+ var el = ownerDocument.createElement('span');
+ DOMPropertyOperations.setAttributeForID(el, rootID);
+ // Populate node cache
+ ReactMount.getID(el);
+ setTextContent(el, this._stringText);
+ return el;
+ } else {
+ var escapedText = escapeTextContentForBrowser(this._stringText);
+
+ if (transaction.renderToStaticMarkup) {
+ // Normally we'd wrap this in a `span` for the reasons stated above, but
+ // since this is a situation where React won't take over (static pages),
+ // we can simply return the text as it is.
+ return escapedText;
+ }
+
+ return '' + escapedText + '';
+ }
+ },
+
+ /**
+ * Updates this component by updating the text content.
+ *
+ * @param {ReactText} nextText The next text content
+ * @param {ReactReconcileTransaction} transaction
+ * @internal
+ */
+ receiveComponent: function (nextText, transaction) {
+ if (nextText !== this._currentElement) {
+ this._currentElement = nextText;
+ var nextStringText = '' + nextText;
+ if (nextStringText !== this._stringText) {
+ // TODO: Save this as pending props and use performUpdateIfNecessary
+ // and/or updateComponent to do the actual update for consistency with
+ // other component types?
+ this._stringText = nextStringText;
+ var node = ReactMount.getNode(this._rootNodeID);
+ DOMChildrenOperations.updateTextContent(node, nextStringText);
+ }
+ }
+ },
+
+ unmountComponent: function () {
+ ReactComponentBrowserEnvironment.unmountIDFromEnvironment(this._rootNodeID);
+ }
+
+ });
+
+ module.exports = ReactDOMTextComponent;
+
+/***/ },
+/* 43 */
+/***/ function(module, exports, __webpack_require__) {
+
+ /**
+ * Copyright 2013-2015, Facebook, Inc.
+ * All rights reserved.
+ *
+ * This source code is licensed under the BSD-style license found in the
+ * LICENSE file in the root directory of this source tree. An additional grant
+ * of patent rights can be found in the PATENTS file in the same directory.
+ *
+ * @providesModule DOMChildrenOperations
+ * @typechecks static-only
+ */
+
+ 'use strict';
+
+ var Danger = __webpack_require__(44);
+ var ReactMultiChildUpdateTypes = __webpack_require__(52);
+ var ReactPerf = __webpack_require__(54);
+
+ var setInnerHTML = __webpack_require__(55);
+ var setTextContent = __webpack_require__(56);
+ var invariant = __webpack_require__(49);
+
+ /**
+ * Inserts `childNode` as a child of `parentNode` at the `index`.
+ *
+ * @param {DOMElement} parentNode Parent node in which to insert.
+ * @param {DOMElement} childNode Child node to insert.
+ * @param {number} index Index at which to insert the child.
+ * @internal
+ */
+ function insertChildAt(parentNode, childNode, index) {
+ // By exploiting arrays returning `undefined` for an undefined index, we can
+ // rely exclusively on `insertBefore(node, null)` instead of also using
+ // `appendChild(node)`. However, using `undefined` is not allowed by all
+ // browsers so we must replace it with `null`.
+
+ // fix render order error in safari
+ // IE8 will throw error when index out of list size.
+ var beforeChild = index >= parentNode.childNodes.length ? null : parentNode.childNodes.item(index);
+
+ parentNode.insertBefore(childNode, beforeChild);
+ }
+
+ /**
+ * Operations for updating with DOM children.
+ */
+ var DOMChildrenOperations = {
+
+ dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,
+
+ updateTextContent: setTextContent,
+
+ /**
+ * Updates a component's children by processing a series of updates. The
+ * update configurations are each expected to have a `parentNode` property.
+ *
+ * @param {array