Alejandro Sellero
2015-04-23 aca70af6e6cdbb4cceef16b3fad848663beed824
- Bugfix selecting days from previous or next month from the current viewed month.
- Bugfix adding keys to children in year and month view.
- Feature adding different modes to be able to have datepicker, timepicker, or datetimepicker.
1 files added
8 files modified
243 ■■■■■ changed files
examples/basic/basic.jsx 104 ●●●●● patch | view | raw | blame | history
src/Constants.jsx 5 ●●●●● patch | view | raw | blame | history
src/DateTimeField.jsx 60 ●●●●● patch | view | raw | blame | history
src/DateTimePicker.jsx 17 ●●●● patch | view | raw | blame | history
src/DateTimePickerHours.jsx 16 ●●●●● patch | view | raw | blame | history
src/DateTimePickerMinutes.jsx 16 ●●●●● patch | view | raw | blame | history
src/DateTimePickerMonths.jsx 2 ●●● patch | view | raw | blame | history
src/DateTimePickerTime.jsx 21 ●●●●● patch | view | raw | blame | history
src/DateTimePickerYears.jsx 2 ●●● patch | view | raw | blame | history
examples/basic/basic.jsx
@@ -4,52 +4,70 @@
var Basic = React.createClass({
    render: function() {
        return <div className="container">
                        <div className="row">
                            <div className="col-xs-12">
                                <h1>React Bootstrap DateTimePicker</h1>
                                This project is a port of <a href="https://github.com/Eonasdan/bootstrap-datetimepicker">https://github.com/Eonasdan/bootstrap-datetimepicker</a> for React.js
                            </div>
                        </div>
                        <div className="row">
                            <div className="col-xs-12">
                                Default Basic Example
                                <DateTimeField />
                                <pre> {'<DateTimeField />'} </pre>
                            </div>
                        </div>
                        <div className="row">
                            <div className="col-xs-12">
                                Example with default Text
                                <DateTimeField
                                    defaultText="Please select a date"
                                />
                                <pre> {'<DateTimeField defaultText="Please select a date" />'} </pre>
                            </div>
                        </div>
                        <div className="row">
                            <div className="col-xs-12">
                            ViewMode set to years view with custom inputFormat
                            <DateTimeField
                                inputFormat='DD-MM-YYYY'
                                viewMode='years'
        return (
            <div className="container">
                <div className="row">
                    <div className="col-xs-12">
                        <h1>React Bootstrap DateTimePicker</h1>
                        This project is a port of <a href="https://github.com/Eonasdan/bootstrap-datetimepicker">https://github.com/Eonasdan/bootstrap-datetimepicker</a> for React.js
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-12">
                        Default Basic Example
                        <DateTimeField />
                        <pre> {'<DateTimeField />'} </pre>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-12">
                        Example with default Text
                        <DateTimeField
                            defaultText="Please select a date"
                            />
                            <pre> {'<DateTimeField viewMode="years" inputFormat="DD-MM-YYYY" />'} </pre>
                            </div>
                        </div>
                        <div className="row">
                            <div className="col-xs-12">
                            daysOfWeekDisabled
                            <DateTimeField
                                daysOfWeekDisabled={[0,1,2]}
                        <pre> {'<DateTimeField defaultText="Please select a date" />'} </pre>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-12">
                        ViewMode set to years view with custom inputFormat
                        <DateTimeField
                            inputFormat='DD-MM-YYYY'
                            viewMode='years'
                            />
                            <pre> {'<DateTimeField daysOfWeekDisabled={[0,1,2]} />'} </pre>
                        </div>
                        </div>
                    </div>;
                        <pre> {'<DateTimeField viewMode="years" inputFormat="DD-MM-YYYY" />'} </pre>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-12">
                        daysOfWeekDisabled
                        <DateTimeField
                            daysOfWeekDisabled={[0,1,2]}
                            />
                        <pre> {'<DateTimeField daysOfWeekDisabled={[0,1,2]} />'} </pre>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-12">
                        daysOfWeekDisabled
                        <DateTimeField
                            mode="time"
                            />
                        <pre> {'<DateTimeField mode="time" />'} </pre>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-12">
                        daysOfWeekDisabled
                        <DateTimeField
                            mode="date"
                            />
                        <pre> {'<DateTimeField mode="date" />'} </pre>
                    </div>
                </div>
            </div>
        );
    }
});
src/Constants.jsx
New file
@@ -0,0 +1,5 @@
module.exports = {
    MODE_DATE: 'date',
    MODE_DATETIME: 'datetime',
    MODE_TIME: 'time'
};
src/DateTimeField.jsx
@@ -8,32 +8,46 @@
Glyphicon = require('react-bootstrap').Glyphicon;
Constants = require('./Constants');
DateTimeField = React.createClass({
  propTypes: {
    dateTime: React.PropTypes.string,
    onChange: React.PropTypes.func,
    format: React.PropTypes.string,
    inputFormat: React.PropTypes.string,
    inputProps: React.PropTypes.object,
    defaultText: React.PropTypes.string
    inputFormat: React.PropTypes.string,
    defaultText: React.PropTypes.string,
    mode: React.PropTypes.oneOf([Constants.MODE_DATE, Constants.MODE_DATETIME, Constants.MODE_TIME])
  },
  getDefaultProps: function() {
    return {
      dateTime: moment().format('x'),
      format: 'x',
      inputFormat: "MM/DD/YY h:mm A",
      showToday: true,
      viewMode: 'days',
      daysOfWeekDisabled: [],
      onChange: function (x) {
        console.log(x);
      }
      mode: Constants.MODE_DATETIME,
      onChange: function (x) {}
    };
  },
  resolvePropsInputFormat: function() {
    if(this.props.inputFormat) return this.props.inputFormat;
    switch(this.props.mode) {
      case Constants.MODE_TIME:
        return "h:mm A";
      case Constants.MODE_DATE:
        return "MM/DD/YY";
      default:
        return "MM/DD/YY h:mm A";
    }
  },
  getInitialState: function() {
    return {
      showDatePicker: true,
      showTimePicker: false,
      showDatePicker: this.props.mode !== Constants.MODE_TIME,
      showTimePicker: this.props.mode === Constants.MODE_TIME,
      inputFormat: this.resolvePropsInputFormat(),
      buttonIcon: this.props.mode === Constants.MODE_TIME ? "time" : "calendar",
      widgetStyle: {
        display: 'block',
        position: 'absolute',
@@ -42,7 +56,7 @@
      },
      viewDate: moment(this.props.dateTime, this.props.format, true).startOf("month"),
      selectedDate: moment(this.props.dateTime, this.props.format, true),
      inputValue: typeof this.props.defaultText != 'undefined' ?  this.props.defaultText : moment(this.props.dateTime, this.props.format, true).format(this.props.inputFormat)
      inputValue: typeof this.props.defaultText != 'undefined' ?  this.props.defaultText : moment(this.props.dateTime, this.props.format, true).format(this.resolvePropsInputFormat())
    };
  },
  componentWillReceiveProps: function(nextProps) {
@@ -56,28 +70,33 @@
  },
  onChange: function(event) {
    var value = event.target == null ? event : event.target.value;
    if (moment(value, this.props.inputFormat, true).isValid()) {
    if (moment(value, this.state.inputFormat, true).isValid()) {
      this.setState({
        selectedDate: moment(value, this.props.inputFormat, true),
        viewDate: moment(value, this.props.inputFormat, true).startOf("month")
        selectedDate: moment(value, this.state.inputFormat, true),
        viewDate: moment(value, this.state.inputFormat, true).startOf("month")
      });
    }
    return this.setState({
      inputValue: value
    }, function() {
      return this.props.onChange(moment(this.state.inputValue, this.props.inputFormat, true).format(this.props.format));
      return this.props.onChange(moment(this.state.inputValue, this.state.inputFormat, true).format(this.props.format));
    });
  },
  setSelectedDate: function(e) {
    var target = e.target;
    var month;
    if(target.className.includes("new")) month = this.state.viewDate.month() + 1;
    else if(target.className.includes("old")) month = this.state.viewDate.month() - 1;
    else month = this.state.viewDate.month();
    return this.setState({
      selectedDate: this.state.viewDate.clone().date(parseInt(e.target.innerHTML)).hour(this.state.selectedDate.hours()).minute(this.state.selectedDate.minutes())
      selectedDate: this.state.viewDate.clone().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.props.inputFormat)
        inputValue: this.state.selectedDate.format(this.state.inputFormat)
      });
    });
  },
@@ -88,7 +107,7 @@
      this.closePicker();
      this.props.onChange(this.state.selectedDate.format(this.props.format));
      return this.setState({
        inputValue: this.state.selectedDate.format(this.props.inputFormat)
        inputValue: this.state.selectedDate.format(this.state.inputFormat)
      });
    });
  },
@@ -99,7 +118,7 @@
      this.closePicker();
      this.props.onChange(this.state.selectedDate.format(this.props.format));
      return this.setState({
        inputValue: this.state.selectedDate.format(this.props.inputFormat)
        inputValue: this.state.selectedDate.format(this.state.inputFormat)
      });
    });
  },
@@ -173,9 +192,9 @@
  },
  togglePeriod: function() {
    if (this.state.selectedDate.hour() > 12) {
      return this.onChange(this.state.selectedDate.clone().subtract(12, 'hours').format(this.props.inputFormat));
      return this.onChange(this.state.selectedDate.clone().subtract(12, 'hours').format(this.state.inputFormat));
    } else {
      return this.onChange(this.state.selectedDate.clone().add(12, 'hours').format(this.props.inputFormat));
      return this.onChange(this.state.selectedDate.clone().add(12, 'hours').format(this.state.inputFormat));
    }
  },
  togglePicker: function() {
@@ -268,6 +287,7 @@
                  showToday={this.props.showToday}
                  viewMode={this.props.viewMode}
                  daysOfWeekDisabled={this.props.daysOfWeekDisabled}
                  mode={this.props.mode}
                  addDecade={this.addDecade}
                  addYear={this.addYear}
                  addMonth={this.addMonth}
@@ -288,7 +308,7 @@
            />
            <div className="input-group date" ref="datetimepicker">
              <input type="text" className="form-control" onChange={this.onChange} value={this.state.inputValue} {...this.props.inputProps}/>
              <span className="input-group-addon" onClick={this.onClick} onBlur={this.onBlur} ref="dtpbutton"><Glyphicon glyph="calendar" /></span>
              <span className="input-group-addon" onClick={this.onClick} onBlur={this.onBlur} ref="dtpbutton"><Glyphicon glyph={this.state.buttonIcon} /></span>
            </div>
          </div>
    );
src/DateTimePicker.jsx
@@ -8,6 +8,8 @@
Glyphicon = require('react-bootstrap').Glyphicon;
Constants = require('./Constants');
DateTimePicker = React.createClass({
  propTypes: {
    showDatePicker: React.PropTypes.bool,
@@ -21,6 +23,7 @@
      React.PropTypes.string,
      React.PropTypes.number
    ]),
    mode: React.PropTypes.oneOf([Constants.MODE_DATE, Constants.MODE_DATETIME, Constants.MODE_TIME]),
    daysOfWeekDisabled: React.PropTypes.array,
    setSelectedDate: React.PropTypes.func.isRequired,
    subtractYear: React.PropTypes.func.isRequired,
@@ -73,10 +76,20 @@
              addMinute={this.props.addMinute}
              subtractMinute={this.props.subtractMinute}
              togglePeriod={this.props.togglePeriod}
              mode={this.props.mode}
        />
      </li>
      );
    }
  },
  renderSwitchButton: function() {
      return this.props.mode === Constants.MODE_DATETIME ?
          (
              <li>
                <span className="btn picker-switch" style={{width:'100%'}} onClick={this.props.togglePicker}><Glyphicon glyph={this.props.showTimePicker ? 'calendar' : 'time'} /></span>
              </li>
          ) :
          null;
  },
  render: function() {
    return (
@@ -86,9 +99,7 @@
          {this.renderDatePicker()}
          <li>
            <span className="btn picker-switch" style={{width:'100%'}} onClick={this.props.togglePicker}><Glyphicon glyph={this.props.showTimePicker ? 'calendar' : 'time'} /></span>
          </li>
          {this.renderSwitchButton()}
          {this.renderTimePicker()}
src/DateTimePickerHours.jsx
@@ -1,14 +1,28 @@
var DateTimePickerHours, React;
React = require('react');
Glyphicon = require('react-bootstrap').Glyphicon;
DateTimePickerHours = React.createClass({
  propTypes: {
    setSelectedHour: React.PropTypes.func.isRequired
    setSelectedHour: React.PropTypes.func.isRequired,
    onSwitch: React.PropTypes.func.isRequired
  },
  renderSwitchButton: function() {
    return this.props.mode === Constants.MODE_TIME ?
        (
            <ul className="list-unstyled">
              <li>
                <span className="btn picker-switch" style={{width:'100%'}} onClick={this.props.onSwitch}><Glyphicon glyph="time" /></span>
              </li>
            </ul>
        ) :
        null;
  },
  render: function() {
    return (
      <div className="timepicker-hours" data-action="selectHour" style={{display: 'block'}}>
        {this.renderSwitchButton()}
        <table className="table-condensed">
          <tbody>
            <tr>
src/DateTimePickerMinutes.jsx
@@ -1,14 +1,28 @@
var DateTimePickerMinutes, React;
React = require('react');
Glyphicon = require('react-bootstrap').Glyphicon;
DateTimePickerMinutes = React.createClass({
  propTypes: {
    setSelectedMinute: React.PropTypes.func.isRequired
    setSelectedMinute: React.PropTypes.func.isRequired,
    onSwitch: React.PropTypes.func.isRequired
  },
  renderSwitchButton: function() {
    return this.props.mode === Constants.MODE_TIME ?
        (
            <ul className="list-unstyled">
              <li>
                <span className="btn picker-switch" style={{width:'100%'}} onClick={this.props.onSwitch}><Glyphicon glyph="time" /></span>
              </li>
            </ul>
        ) :
        null;
  },
  render: function() {
    return (
      <div className="timepicker-minutes" data-action="selectMinute" style={{display: 'block'}}>
        {this.renderSwitchButton()}
        <table className="table-condensed">
          <tbody>
            <tr>
src/DateTimePickerMonths.jsx
@@ -24,7 +24,7 @@
        month: true,
        'active': i === month && this.props.viewDate.year() === this.props.selectedDate.year()
      };
      months.push(<span className={React.addons.classSet(classes)} onClick={this.props.setViewMonth}>{monthsShort[i]}</span>);
      months.push(<span key={i} className={React.addons.classSet(classes)} onClick={this.props.setViewMonth}>{monthsShort[i]}</span>);
      i++;
    }
    return months;
src/DateTimePickerTime.jsx
@@ -8,6 +8,8 @@
Glyphicon = require('react-bootstrap').Glyphicon;
Constants = require('./Constants');
DateTimePickerTime = React.createClass({
  propTypes: {
    setSelectedHour: React.PropTypes.func.isRequired,
@@ -18,13 +20,20 @@
    addMinute: React.PropTypes.func.isRequired,
    viewDate: React.PropTypes.object.isRequired,
    selectedDate: React.PropTypes.object.isRequired,
    togglePeriod: React.PropTypes.func.isRequired
    togglePeriod: React.PropTypes.func.isRequired,
    mode: React.PropTypes.oneOf([Constants.MODE_DATE, Constants.MODE_DATETIME, Constants.MODE_TIME])
  },
  getInitialState: function() {
    return {
      minutesDisplayed: false,
      hoursDisplayed: false
    };
  },
  goBack: function() {
    return this.setState({
      minutesDisplayed: false,
      hoursDisplayed: false
    });
  },
  showMinutes: function() {
    return this.setState({
@@ -38,20 +47,14 @@
  },
  renderMinutes: function() {
    if (this.state.minutesDisplayed) {
      return (<DateTimePickerMinutes
            setSelectedMinute={this.props.setSelectedMinute}
       />
       );
      return <DateTimePickerMinutes {...this.props} onSwitch={this.goBack} />;
    } else {
      return null;
    }
  },
  renderHours: function() {
    if (this.state.hoursDisplayed) {
      return (<DateTimePickerHours
            setSelectedHour={this.props.setSelectedHour}
      />
      );
      return <DateTimePickerHours {...this.props} onSwitch={this.goBack} />;
    } else {
      return null;
    }
src/DateTimePickerYears.jsx
@@ -22,7 +22,7 @@
        old: i === -1 | i === 10,
        active: this.props.selectedDate.year() === year
      };
      years.push(<span className={React.addons.classSet(classes)} onClick={this.props.setViewYear}>{year}</span>);
      years.push(<span key={year} className={React.addons.classSet(classes)} onClick={this.props.setViewYear}>{year}</span>);
      year++;
      i++;
    }