From bdd7fffaf207d1021394af874677e067b84ca9e2 Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 11:04:46 +0100
Subject: [PATCH 01/20] add `grunt:webpack` tasks for building
---
gruntfile.js | 38 ++++++++++++++++++++++++++++++++++++++
package.json | 9 +++++++--
webpack.config.js | 42 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 87 insertions(+), 2 deletions(-)
create mode 100644 webpack.config.js
diff --git a/gruntfile.js b/gruntfile.js
index a8434a4fb..7a8f46380 100644
--- a/gruntfile.js
+++ b/gruntfile.js
@@ -1,3 +1,20 @@
+'use strict';
+
+var _ = require('lodash');
+var webpack = require('webpack');
+
+var mergeWebpackConfig = function (destination) {
+ // Load webpackConfig only when using `grunt:webpack`
+ // load of grunt tasks is faster
+ var webpackConfig = require('./webpack.config');
+
+ return _.merge(destination, webpackConfig, function (a, b) {
+ if (_.isArray(a)) {
+ return a.concat(b);
+ }
+ });
+};
+
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
@@ -70,6 +87,26 @@ module.exports = function(grunt) {
options: {
eqnull: true
}
+ },
+
+ webpack: {
+ unmin: mergeWebpackConfig({
+ output: {
+ filename: 'react-datepicker.js'
+ }
+ }),
+ min: mergeWebpackConfig({
+ output: {
+ filename: 'react-datepicker.min.js'
+ },
+ plugins: [
+ new webpack.optimize.UglifyJsPlugin({
+ compressor: {
+ warnings: false
+ }
+ })
+ ]
+ })
}
});
@@ -77,6 +114,7 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-scss-lint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-jsxhint');
+ grunt.loadNpmTasks('grunt-webpack');
grunt.registerTask('default', ['watch', 'scsslint']);
grunt.registerTask('travis', ['jshint', 'jest', 'scsslint']);
diff --git a/package.json b/package.json
index 379c89083..3c7ac5dbc 100644
--- a/package.json
+++ b/package.json
@@ -21,19 +21,24 @@
"url": "https://github.com/Hacker0x01/react-datepicker/issues"
},
"devDependencies": {
+ "babel-core": "^4.7.3",
+ "babel-loader": "^4.1.0",
"browserify": "9.0.3",
"browserify-shim": "3.8.3",
"grunt": "0.4.5",
"grunt-cli": "0.1.13",
"grunt-contrib-sass": "0.9.2",
"grunt-contrib-watch": "0.6.1",
- "jest-cli": "0.4.0",
"grunt-jsxhint": "0.5.0",
"grunt-scss-lint": "^0.3.4",
+ "grunt-webpack": "^1.0.8",
+ "jest-cli": "0.4.0",
"lodash": "^3.3.0",
"react": "^0.12",
"react-tools": "0.12.2",
- "reactify": "^1.0"
+ "reactify": "^1.0",
+ "webpack": "^1.7.2",
+ "webpack-dev-server": "^1.7.0"
},
"peerDependencies": {
"react": "^0.12"
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 000000000..8c975b9df
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,42 @@
+var webpack = require('webpack');
+
+module.exports = {
+ entry: './src/datepicker',
+ output: {
+ libraryTarget: 'umd',
+ library: 'DatePicker'
+ },
+ module: {
+ loaders: [
+ {test: /\.js/, loaders: ['babel-loader'], exclude: /node_modules/}
+ ]
+ },
+ resolve: {
+ extensions: ['', '.js', '.jsx']
+ },
+ externals: [
+ {
+ 'react': {
+ root: 'React',
+ commonjs2: 'react',
+ commonjs: 'react',
+ amd: 'react'
+ }
+ },
+ {
+ 'react/addons': {
+ root: 'React',
+ commonjs2: 'react',
+ commonjs: 'react',
+ amd: 'react'
+ }
+ }
+ ],
+ node: {Buffer: false},
+ plugins: [
+ new webpack.optimize.DedupePlugin(),
+ new webpack.DefinePlugin({
+ 'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV)
+ })
+ ]
+};
From cd2c4b5e9c638a33a119f9316817675dc8742a18 Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 11:10:33 +0100
Subject: [PATCH 02/20] remove every dependancies in build
---
webpack.config.js | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/webpack.config.js b/webpack.config.js
index 8c975b9df..88ce21f1f 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -4,7 +4,8 @@ module.exports = {
entry: './src/datepicker',
output: {
libraryTarget: 'umd',
- library: 'DatePicker'
+ library: 'DatePicker',
+ path: './dist/'
},
module: {
loaders: [
@@ -30,6 +31,22 @@ module.exports = {
commonjs: 'react',
amd: 'react'
}
+ },
+ {
+ 'moment': {
+ root: 'moment',
+ commonjs2: 'moment',
+ commonjs: 'moment',
+ amd: 'moment'
+ }
+ },
+ {
+ 'react-onclickoutside': {
+ root: 'OnClickOutside',
+ commonjs2: 'react-onclickoutside',
+ commonjs: 'react-onclickoutside',
+ amd: 'react-onclickoutside'
+ }
}
],
node: {Buffer: false},
From b8195be42ef3b3e0c2f32eeed9d4d122292feccf Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 12:30:12 +0100
Subject: [PATCH 03/20] add dist forlder for builds, update path
---
bower.json | 5 ++---
package.json | 2 +-
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/bower.json b/bower.json
index db857c09f..a39085a9f 100644
--- a/bower.json
+++ b/bower.json
@@ -12,9 +12,8 @@
},
"license": "MIT",
"main": [
- "react-datepicker.js",
- "react-datepicker.css",
- "react-datepicker.css.map"
+ "dist/react-datepicker.min.js",
+ "dist/react-datepicker.css"
],
"keywords": [
"react",
diff --git a/package.json b/package.json
index 3c7ac5dbc..01a7dd89d 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,7 @@
"version": "0.5.1",
"license": "MIT",
"homepage": "https://github.com/Hacker0x01/react-datepicker",
- "main": "src/datepicker.js",
+ "main": "dist/datepicker.min.js",
"keywords": [
"react",
"datepicker",
From 254cd0568c47e51a4ccd5d49ee7bf3ab95e30898 Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 12:36:34 +0100
Subject: [PATCH 04/20] add build task, unmin and min styles
---
gruntfile.js | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/gruntfile.js b/gruntfile.js
index 7a8f46380..9a5990cbd 100644
--- a/gruntfile.js
+++ b/gruntfile.js
@@ -19,14 +19,23 @@ module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
sass: {
- dist: {
+ min: {
files: {
- 'react-datepicker.css' : 'src/stylesheets/datepicker.scss'
+ 'dist/react-datepicker.css': 'src/stylesheets/datepicker.scss'
+ },
+ options: {
+ sourcemap: 'none',
+ style: 'expanded'
}
},
- options: {
- sourcemap: 'none',
- style: 'expanded'
+ unmin: {
+ files: {
+ 'dist/react-datepicker.min.css': 'src/stylesheets/datepicker.scss'
+ },
+ options: {
+ sourcemap: 'none',
+ style: 'compressed'
+ }
}
},
@@ -118,6 +127,7 @@ module.exports = function(grunt) {
grunt.registerTask('default', ['watch', 'scsslint']);
grunt.registerTask('travis', ['jshint', 'jest', 'scsslint']);
+ grunt.registerTask('build', ['jshint', 'scsslint', 'webpack', 'sass']);
grunt.registerMultiTask('browserify', require('./grunt/tasks/browserify'));
grunt.registerTask('jest', require('./grunt/tasks/jest'));
From 4f91637c8565ca963bba4d3d9256480048f39fbd Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 12:36:53 +0100
Subject: [PATCH 05/20] update build files
---
dist/react-datepicker.css | 142 ++++++++
dist/react-datepicker.js | 621 ++++++++++++++++++++++++++++++++++
dist/react-datepicker.min.css | 1 +
dist/react-datepicker.min.js | 1 +
react-datepicker.js | 515 ----------------------------
5 files changed, 765 insertions(+), 515 deletions(-)
create mode 100644 dist/react-datepicker.css
create mode 100644 dist/react-datepicker.js
create mode 100644 dist/react-datepicker.min.css
create mode 100644 dist/react-datepicker.min.js
delete mode 100644 react-datepicker.js
diff --git a/dist/react-datepicker.css b/dist/react-datepicker.css
new file mode 100644
index 000000000..1fa1f943a
--- /dev/null
+++ b/dist/react-datepicker.css
@@ -0,0 +1,142 @@
+.datepicker__triangle {
+ margin-top: -8px;
+ margin-left: -8px;
+}
+.datepicker__triangle, .datepicker__triangle:before {
+ box-sizing: content-box;
+ position: absolute;
+ border: 8px solid transparent;
+ height: 0;
+ width: 1px;
+ border-top: none;
+ border-bottom-color: #f0f0f0;
+}
+.datepicker__triangle:before {
+ content: "";
+ z-index: -1;
+ border-width: 8px;
+ top: -1px;
+ left: -8px;
+ border-bottom-color: #aeaeae;
+}
+
+.datepicker {
+ font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 11px;
+ background-color: #fff;
+ color: #000;
+ border: 1px solid #aeaeae;
+ border-radius: 4px;
+ display: inline-block;
+ position: relative;
+}
+
+.datepicker__container {
+ position: absolute;
+ display: inline-block;
+ z-index: 2147483647;
+}
+
+.datepicker__triangle {
+ position: absolute;
+ left: 50px;
+}
+
+.datepicker__header {
+ text-align: center;
+ background-color: #f0f0f0;
+ border-bottom: 1px solid #aeaeae;
+ border-top-left-radius: 4px;
+ border-top-right-radius: 4px;
+ padding-top: 8px;
+ position: relative;
+}
+
+.datepicker__current-month {
+ color: black;
+ font-weight: bold;
+ font-size: 13px;
+}
+
+.datepicker__navigation {
+ line-height: 24px;
+ text-align: center;
+ cursor: pointer;
+ position: absolute;
+ top: 10px;
+ width: 0;
+ border: 6px solid transparent;
+}
+.datepicker__navigation--previous {
+ left: 10px;
+ border-right-color: #ccc;
+}
+.datepicker__navigation--previous:hover {
+ border-right-color: #b3b3b3;
+}
+.datepicker__navigation--next {
+ right: 10px;
+ border-left-color: #ccc;
+}
+.datepicker__navigation--next:hover {
+ border-left-color: #b3b3b3;
+}
+
+.datepicker__week-day {
+ color: #ccc;
+ display: inline-block;
+ width: 28px;
+ line-height: 24px;
+}
+
+.datepicker__month {
+ margin: 5px;
+ text-align: center;
+}
+
+.datepicker__day {
+ color: #000;
+ display: inline-block;
+ width: 24px;
+ line-height: 24px;
+ text-align: center;
+ margin: 2px;
+ cursor: pointer;
+}
+.datepicker__day:hover {
+ border-radius: 4px;
+ background-color: #f0f0f0;
+}
+.datepicker__day--today {
+ font-weight: bold;
+}
+.datepicker__day--selected {
+ border-radius: 4px;
+ background-color: #216ba5;
+ color: #fff;
+}
+.datepicker__day--selected:hover {
+ background-color: #1d5d90;
+}
+.datepicker__day--disabled {
+ cursor: default;
+ color: #ccc;
+}
+.datepicker__day--disabled:hover {
+ background-color: transparent;
+}
+
+.datepicker__input {
+ position: relative;
+ font-size: 13px;
+ border-radius: 4px;
+ box-shadow: inset 0 2px 2px #e9e9e9;
+ border: 1px solid #aeaeae;
+ line-height: 16px;
+ padding: 6px 10px 5px;
+}
+.datepicker__input:focus {
+ outline: none;
+ border-color: #aeaeae;
+ box-shadow: inset 0 2px 2px #e9e9e9, 0 0 10px 0 rgba(73, 107, 125, 0.3);
+}
diff --git a/dist/react-datepicker.js b/dist/react-datepicker.js
new file mode 100644
index 000000000..d9dfb6fdd
--- /dev/null
+++ b/dist/react-datepicker.js
@@ -0,0 +1,621 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("react"), require("moment"), require("react-onclickoutside"));
+ else if(typeof define === 'function' && define.amd)
+ define(["react", "moment", "react-onclickoutside"], factory);
+ else if(typeof exports === 'object')
+ exports["DatePicker"] = factory(require("react"), require("moment"), require("react-onclickoutside"));
+ else
+ root["DatePicker"] = factory(root["React"], root["moment"], root["OnClickOutside"]);
+})(this, function(__WEBPACK_EXTERNAL_MODULE_1__, __WEBPACK_EXTERNAL_MODULE_6__, __WEBPACK_EXTERNAL_MODULE_7__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId])
+/******/ return installedModules[moduleId].exports;
+
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ exports: {},
+/******/ id: moduleId,
+/******/ loaded: false
+/******/ };
+
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ // Flag the module as loaded
+/******/ module.loaded = true;
+
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+
+
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ function(module, exports, __webpack_require__) {
+
+ "use strict";
+
+ var React = __webpack_require__(1);
+ var Popover = __webpack_require__(2);
+ var DateUtil = __webpack_require__(3);
+ var Calendar = __webpack_require__(4);
+ var DateInput = __webpack_require__(5);
+
+ var DatePicker = React.createClass({
+ displayName: "DatePicker",
+
+ getInitialState: function getInitialState() {
+ return {
+ focus: false
+ };
+ },
+
+ handleFocus: function handleFocus() {
+ this.setState({
+ focus: true
+ });
+ },
+
+ hideCalendar: function hideCalendar() {
+ setTimeout((function () {
+ this.setState({
+ focus: false
+ });
+ }).bind(this), 0);
+ },
+
+ handleSelect: function handleSelect(date) {
+ this.setSelected(date);
+
+ setTimeout((function () {
+ this.hideCalendar();
+ }).bind(this), 200);
+ },
+
+ setSelected: function setSelected(date) {
+ this.props.onChange(date.moment());
+ },
+
+ onInputClick: function onInputClick() {
+ this.setState({
+ focus: true
+ });
+ },
+
+ calendar: function calendar() {
+ if (this.state.focus) {
+ return React.createElement(
+ Popover,
+ null,
+ React.createElement(Calendar, {
+ selected: this.props.selected,
+ onSelect: this.handleSelect,
+ hideCalendar: this.hideCalendar,
+ minDate: this.props.minDate,
+ maxDate: this.props.maxDate })
+ );
+ }
+ },
+
+ render: function render() {
+
+ return React.createElement(
+ "div",
+ null,
+ React.createElement(DateInput, {
+ date: this.props.selected,
+ dateFormat: this.props.dateFormat,
+ focus: this.state.focus,
+ onFocus: this.handleFocus,
+ handleClick: this.onInputClick,
+ handleEnter: this.hideCalendar,
+ setSelected: this.setSelected,
+ hideCalendar: this.hideCalendar,
+ placeholderText: this.props.placeholderText }),
+ this.calendar()
+ );
+ }
+ });
+
+ module.exports = DatePicker;
+
+/***/ },
+/* 1 */
+/***/ function(module, exports, __webpack_require__) {
+
+ module.exports = __WEBPACK_EXTERNAL_MODULE_1__;
+
+/***/ },
+/* 2 */
+/***/ function(module, exports, __webpack_require__) {
+
+ "use strict";
+
+ var React = __webpack_require__(1);
+
+ var Popover = React.createClass({
+ displayName: "Popover",
+
+ componentWillMount: function componentWillMount() {
+ popoverContainer = document.createElement("span");
+ popoverContainer.className = "datepicker__container";
+
+ this._popoverElement = popoverContainer;
+
+ document.querySelector("body").appendChild(this._popoverElement);
+ },
+
+ componentDidMount: function componentDidMount() {
+ this._renderPopover();
+ },
+
+ componentDidUpdate: function componentDidUpdate() {
+ this._renderPopover();
+ },
+
+ _popoverComponent: function _popoverComponent() {
+ var className = this.props.className;
+ return React.createElement(
+ "div",
+ { className: className },
+ this.props.children
+ );
+ },
+
+ _tetherOptions: function _tetherOptions() {
+ return {
+ element: this._popoverElement,
+ target: this.getDOMNode().parentElement,
+ attachment: "top left",
+ targetAttachment: "bottom left",
+ targetOffset: "10px 0",
+ optimizations: {
+ moveElement: false // always moves to
anyway!
+ },
+ constraints: [{
+ to: "scrollParent",
+ attachment: "together",
+ pin: true
+ }]
+ };
+ },
+
+ _renderPopover: function _renderPopover() {
+ React.render(this._popoverComponent(), this._popoverElement);
+
+ if (this._tether != null) {
+ this._tether.setOptions(this._tetherOptions());
+ } else {
+ this._tether = new Tether(this._tetherOptions());
+ }
+ },
+
+ componentWillUnmount: function componentWillUnmount() {
+ this._tether.destroy();
+ React.unmountComponentAtNode(this._popoverElement);
+ if (this._popoverElement.parentNode) {
+ this._popoverElement.parentNode.removeChild(this._popoverElement);
+ }
+ },
+
+ render: function render() {
+ return React.createElement("span", null);
+ }
+ });
+
+ module.exports = Popover;
+
+/***/ },
+/* 3 */
+/***/ function(module, exports, __webpack_require__) {
+
+ "use strict";
+
+ function DateUtil(date) {
+ this._date = date;
+ }
+
+ DateUtil.prototype.isBefore = function (other) {
+ return this._date.isBefore(other._date, "day");
+ };
+
+ DateUtil.prototype.isAfter = function (other) {
+ return this._date.isAfter(other._date, "day");
+ };
+
+ DateUtil.prototype.sameDay = function (other) {
+ return this._date.isSame(other._date, "day");
+ };
+
+ DateUtil.prototype.sameMonth = function (other) {
+ return this._date.isSame(other._date, "month");
+ };
+
+ DateUtil.prototype.day = function () {
+ return this._date.date();
+ };
+
+ DateUtil.prototype.mapDaysInWeek = function (callback) {
+ var week = [];
+ var firstDay = this._date.clone().startOf("isoWeek");
+
+ for (var i = 0; i < 7; i++) {
+ var day = new DateUtil(firstDay.clone().add(i, "days"));
+
+ week[i] = callback(day, i);
+ }
+
+ return week;
+ };
+
+ DateUtil.prototype.mapWeeksInMonth = function (callback) {
+ var month = [];
+ var firstDay = this._date.clone().startOf("month").startOf("isoWeek");
+
+ for (var i = 0; i < 6; i++) {
+ var weekStart = new DateUtil(firstDay.clone().add(i, "weeks"));
+
+ month[i] = callback(weekStart, i);
+ }
+
+ return month;
+ };
+
+ DateUtil.prototype.weekInMonth = function (other) {
+ var firstDayInWeek = this._date.clone();
+ var lastDayInWeek = this._date.clone().isoWeekday(7);
+
+ return firstDayInWeek.isSame(other._date, "month") || lastDayInWeek.isSame(other._date, "month");
+ };
+
+ DateUtil.prototype.format = function () {
+ return this._date.format.apply(this._date, arguments);
+ };
+
+ DateUtil.prototype.addMonth = function () {
+ return new DateUtil(this._date.clone().add(1, "month"));
+ };
+
+ DateUtil.prototype.subtractMonth = function () {
+ return new DateUtil(this._date.clone().subtract(1, "month"));
+ };
+
+ DateUtil.prototype.clone = function () {
+ return new DateUtil(this._date.clone());
+ };
+
+ DateUtil.prototype.safeClone = function (alternative) {
+ if (!!this._date) return this.clone();
+
+ if (alternative === undefined) alternative = null;
+ return new DateUtil(alternative);
+ };
+
+ DateUtil.prototype.moment = function () {
+ return this._date;
+ };
+
+ module.exports = DateUtil;
+
+/***/ },
+/* 4 */
+/***/ function(module, exports, __webpack_require__) {
+
+ "use strict";
+
+ var React = __webpack_require__(1);
+ var Day = __webpack_require__(8);
+ var DateUtil = __webpack_require__(3);
+ var moment = __webpack_require__(6);
+
+ var Calendar = React.createClass({
+ displayName: "Calendar",
+
+ mixins: [__webpack_require__(7)],
+
+ handleClickOutside: function handleClickOutside() {
+ this.props.hideCalendar();
+ },
+
+ getInitialState: function getInitialState() {
+ return {
+ date: new DateUtil(this.props.selected).safeClone(moment())
+ };
+ },
+
+ componentWillReceiveProps: function componentWillReceiveProps(nextProps) {
+ // When the selected date changed
+ if (nextProps.selected !== this.props.selected) {
+ this.setState({
+ date: new DateUtil(nextProps.selected).clone()
+ });
+ }
+ },
+
+ increaseMonth: function increaseMonth() {
+ this.setState({
+ date: this.state.date.addMonth()
+ });
+ },
+
+ decreaseMonth: function decreaseMonth() {
+ this.setState({
+ date: this.state.date.subtractMonth()
+ });
+ },
+
+ weeks: function weeks() {
+ return this.state.date.mapWeeksInMonth(this.renderWeek);
+ },
+
+ handleDayClick: function handleDayClick(day) {
+ this.props.onSelect(day);
+ },
+
+ renderWeek: function renderWeek(weekStart, key) {
+ if (!weekStart.weekInMonth(this.state.date)) {
+ return;
+ }
+
+ return React.createElement(
+ "div",
+ { key: key },
+ this.days(weekStart)
+ );
+ },
+
+ renderDay: function renderDay(day, key) {
+ var minDate = new DateUtil(this.props.minDate).safeClone(),
+ maxDate = new DateUtil(this.props.maxDate).safeClone(),
+ disabled = day.isBefore(minDate) || day.isAfter(maxDate);
+
+ return React.createElement(Day, {
+ key: key,
+ day: day,
+ date: this.state.date,
+ onClick: this.handleDayClick.bind(this, day),
+ selected: new DateUtil(this.props.selected),
+ disabled: disabled });
+ },
+
+ days: function days(weekStart) {
+ return weekStart.mapDaysInWeek(this.renderDay);
+ },
+
+ render: function render() {
+ return React.createElement(
+ "div",
+ { className: "datepicker" },
+ React.createElement("div", { className: "datepicker__triangle" }),
+ React.createElement(
+ "div",
+ { className: "datepicker__header" },
+ React.createElement("a", { className: "datepicker__navigation datepicker__navigation--previous",
+ onClick: this.decreaseMonth }),
+ React.createElement(
+ "span",
+ { className: "datepicker__current-month" },
+ this.state.date.format("MMMM YYYY")
+ ),
+ React.createElement("a", { className: "datepicker__navigation datepicker__navigation--next",
+ onClick: this.increaseMonth }),
+ React.createElement(
+ "div",
+ null,
+ React.createElement(
+ "div",
+ { className: "datepicker__day" },
+ "Mo"
+ ),
+ React.createElement(
+ "div",
+ { className: "datepicker__day" },
+ "Tu"
+ ),
+ React.createElement(
+ "div",
+ { className: "datepicker__day" },
+ "We"
+ ),
+ React.createElement(
+ "div",
+ { className: "datepicker__day" },
+ "Th"
+ ),
+ React.createElement(
+ "div",
+ { className: "datepicker__day" },
+ "Fr"
+ ),
+ React.createElement(
+ "div",
+ { className: "datepicker__day" },
+ "Sa"
+ ),
+ React.createElement(
+ "div",
+ { className: "datepicker__day" },
+ "Su"
+ )
+ )
+ ),
+ React.createElement(
+ "div",
+ { className: "datepicker__month" },
+ this.weeks()
+ )
+ );
+ }
+ });
+
+ module.exports = Calendar;
+
+/***/ },
+/* 5 */
+/***/ function(module, exports, __webpack_require__) {
+
+ "use strict";
+
+ var React = __webpack_require__(1);
+ var DateUtil = __webpack_require__(3);
+ var moment = __webpack_require__(6);
+
+ var DateInput = React.createClass({
+ displayName: "DateInput",
+
+ getDefaultProps: function getDefaultProps() {
+ return {
+ dateFormat: "YYYY-MM-DD"
+ };
+ },
+
+ getInitialState: function getInitialState() {
+ return {
+ value: this.safeDateFormat(this.props.date)
+ };
+ },
+
+ componentDidMount: function componentDidMount() {
+ this.toggleFocus(this.props.focus);
+ },
+
+ componentWillReceiveProps: function componentWillReceiveProps(newProps) {
+ this.toggleFocus(newProps.focus);
+
+ this.setState({
+ value: this.safeDateFormat(newProps.date)
+ });
+ },
+
+ toggleFocus: function toggleFocus(focus) {
+ if (focus) {
+ this.refs.input.getDOMNode().focus();
+ } else {
+ this.refs.input.getDOMNode().blur();
+ }
+ },
+
+ handleChange: function handleChange(event) {
+ var date = moment(event.target.value, this.props.dateFormat, true);
+
+ this.setState({
+ value: event.target.value
+ });
+
+ if (this.isValueAValidDate()) {
+ this.props.setSelected(new DateUtil(date));
+ }
+ },
+
+ safeDateFormat: function safeDateFormat(date) {
+ return !!date ? date.format(this.props.dateFormat) : null;
+ },
+
+ isValueAValidDate: function isValueAValidDate() {
+ var date = moment(event.target.value, this.props.dateFormat, true);
+
+ return date.isValid();
+ },
+
+ handleKeyDown: function handleKeyDown(event) {
+ switch (event.key) {
+ case "Enter":
+ event.preventDefault();
+ this.props.handleEnter();
+ break;
+ }
+ },
+
+ handleClick: function handleClick(event) {
+ this.props.handleClick(event);
+ },
+
+ render: function render() {
+ return React.createElement("input", {
+ ref: "input",
+ type: "text",
+ value: this.state.value,
+ onClick: this.handleClick,
+ onKeyDown: this.handleKeyDown,
+ onFocus: this.props.onFocus,
+ onChange: this.handleChange,
+ className: "datepicker__input",
+ placeholder: this.props.placeholderText });
+ }
+ });
+
+ module.exports = DateInput;
+
+/***/ },
+/* 6 */
+/***/ function(module, exports, __webpack_require__) {
+
+ module.exports = __WEBPACK_EXTERNAL_MODULE_6__;
+
+/***/ },
+/* 7 */
+/***/ function(module, exports, __webpack_require__) {
+
+ module.exports = __WEBPACK_EXTERNAL_MODULE_7__;
+
+/***/ },
+/* 8 */
+/***/ function(module, exports, __webpack_require__) {
+
+ "use strict";
+
+ var React = __webpack_require__(1);
+ var moment = __webpack_require__(6);
+
+ var Day = React.createClass({
+ displayName: "Day",
+
+ handleClick: function handleClick(event) {
+ if (this.props.disabled) {
+ return;
+ }this.props.onClick(event);
+ },
+
+ render: function render() {
+ classes = React.addons.classSet({
+ datepicker__day: true,
+ "datepicker__day--disabled": this.props.disabled,
+ "datepicker__day--selected": this.props.day.sameDay(this.props.selected),
+ "datepicker__day--today": this.props.day.sameDay(moment())
+ });
+
+ return React.createElement(
+ "div",
+ { className: classes, onClick: this.handleClick },
+ this.props.day.day()
+ );
+ }
+ });
+
+ module.exports = Day;
+
+/***/ }
+/******/ ])
+});
+;
\ No newline at end of file
diff --git a/dist/react-datepicker.min.css b/dist/react-datepicker.min.css
new file mode 100644
index 000000000..aa7fdb8e6
--- /dev/null
+++ b/dist/react-datepicker.min.css
@@ -0,0 +1 @@
+.datepicker__triangle{margin-top:-8px;margin-left:-8px}.datepicker__triangle,.datepicker__triangle:before{box-sizing:content-box;position:absolute;border:8px solid transparent;height:0;width:1px;border-top:none;border-bottom-color:#f0f0f0}.datepicker__triangle:before{content:"";z-index:-1;border-width:8px;top:-1px;left:-8px;border-bottom-color:#aeaeae}.datepicker{font-family:"Helvetica Neue", Helvetica, Arial, sans-serif;font-size:11px;background-color:#fff;color:#000;border:1px solid #aeaeae;border-radius:4px;display:inline-block;position:relative}.datepicker__container{position:absolute;display:inline-block;z-index:2147483647}.datepicker__triangle{position:absolute;left:50px}.datepicker__header{text-align:center;background-color:#f0f0f0;border-bottom:1px solid #aeaeae;border-top-left-radius:4px;border-top-right-radius:4px;padding-top:8px;position:relative}.datepicker__current-month{color:black;font-weight:bold;font-size:13px}.datepicker__navigation{line-height:24px;text-align:center;cursor:pointer;position:absolute;top:10px;width:0;border:6px solid transparent}.datepicker__navigation--previous{left:10px;border-right-color:#ccc}.datepicker__navigation--previous:hover{border-right-color:#b3b3b3}.datepicker__navigation--next{right:10px;border-left-color:#ccc}.datepicker__navigation--next:hover{border-left-color:#b3b3b3}.datepicker__week-day{color:#ccc;display:inline-block;width:28px;line-height:24px}.datepicker__month{margin:5px;text-align:center}.datepicker__day{color:#000;display:inline-block;width:24px;line-height:24px;text-align:center;margin:2px;cursor:pointer}.datepicker__day:hover{border-radius:4px;background-color:#f0f0f0}.datepicker__day--today{font-weight:bold}.datepicker__day--selected{border-radius:4px;background-color:#216ba5;color:#fff}.datepicker__day--selected:hover{background-color:#1d5d90}.datepicker__day--disabled{cursor:default;color:#ccc}.datepicker__day--disabled:hover{background-color:transparent}.datepicker__input{position:relative;font-size:13px;border-radius:4px;box-shadow:inset 0 2px 2px #e9e9e9;border:1px solid #aeaeae;line-height:16px;padding:6px 10px 5px}.datepicker__input:focus{outline:none;border-color:#aeaeae;box-shadow:inset 0 2px 2px #e9e9e9,0 0 10px 0 rgba(73,107,125,0.3)}
diff --git a/dist/react-datepicker.min.js b/dist/react-datepicker.min.js
new file mode 100644
index 000000000..f125b6324
--- /dev/null
+++ b/dist/react-datepicker.min.js
@@ -0,0 +1 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("moment"),require("react-onclickoutside")):"function"==typeof define&&define.amd?define(["react","moment","react-onclickoutside"],t):"object"==typeof exports?exports.DatePicker=t(require("react"),require("moment"),require("react-onclickoutside")):e.DatePicker=t(e.React,e.moment,e.OnClickOutside)}(this,function(e,t,n){return function(e){function t(a){if(n[a])return n[a].exports;var o=n[a]={exports:{},id:a,loaded:!1};return e[a].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";var a=n(1),o=n(2),s=(n(3),n(4)),i=n(5),r=a.createClass({displayName:"DatePicker",getInitialState:function(){return{focus:!1}},handleFocus:function(){this.setState({focus:!0})},hideCalendar:function(){setTimeout(function(){this.setState({focus:!1})}.bind(this),0)},handleSelect:function(e){this.setSelected(e),setTimeout(function(){this.hideCalendar()}.bind(this),200)},setSelected:function(e){this.props.onChange(e.moment())},onInputClick:function(){this.setState({focus:!0})},calendar:function(){return this.state.focus?a.createElement(o,null,a.createElement(s,{selected:this.props.selected,onSelect:this.handleSelect,hideCalendar:this.hideCalendar,minDate:this.props.minDate,maxDate:this.props.maxDate})):void 0},render:function(){return a.createElement("div",null,a.createElement(i,{date:this.props.selected,dateFormat:this.props.dateFormat,focus:this.state.focus,onFocus:this.handleFocus,handleClick:this.onInputClick,handleEnter:this.hideCalendar,setSelected:this.setSelected,hideCalendar:this.hideCalendar,placeholderText:this.props.placeholderText}),this.calendar())}});e.exports=r},function(t){t.exports=e},function(e,t,n){"use strict";var a=n(1),o=a.createClass({displayName:"Popover",componentWillMount:function(){popoverContainer=document.createElement("span"),popoverContainer.className="datepicker__container",this._popoverElement=popoverContainer,document.querySelector("body").appendChild(this._popoverElement)},componentDidMount:function(){this._renderPopover()},componentDidUpdate:function(){this._renderPopover()},_popoverComponent:function(){var e=this.props.className;return a.createElement("div",{className:e},this.props.children)},_tetherOptions:function(){return{element:this._popoverElement,target:this.getDOMNode().parentElement,attachment:"top left",targetAttachment:"bottom left",targetOffset:"10px 0",optimizations:{moveElement:!1},constraints:[{to:"scrollParent",attachment:"together",pin:!0}]}},_renderPopover:function(){a.render(this._popoverComponent(),this._popoverElement),null!=this._tether?this._tether.setOptions(this._tetherOptions()):this._tether=new Tether(this._tetherOptions())},componentWillUnmount:function(){this._tether.destroy(),a.unmountComponentAtNode(this._popoverElement),this._popoverElement.parentNode&&this._popoverElement.parentNode.removeChild(this._popoverElement)},render:function(){return a.createElement("span",null)}});e.exports=o},function(e){"use strict";function t(e){this._date=e}t.prototype.isBefore=function(e){return this._date.isBefore(e._date,"day")},t.prototype.isAfter=function(e){return this._date.isAfter(e._date,"day")},t.prototype.sameDay=function(e){return this._date.isSame(e._date,"day")},t.prototype.sameMonth=function(e){return this._date.isSame(e._date,"month")},t.prototype.day=function(){return this._date.date()},t.prototype.mapDaysInWeek=function(e){for(var n=[],a=this._date.clone().startOf("isoWeek"),o=0;7>o;o++){var s=new t(a.clone().add(o,"days"));n[o]=e(s,o)}return n},t.prototype.mapWeeksInMonth=function(e){for(var n=[],a=this._date.clone().startOf("month").startOf("isoWeek"),o=0;6>o;o++){var s=new t(a.clone().add(o,"weeks"));n[o]=e(s,o)}return n},t.prototype.weekInMonth=function(e){var t=this._date.clone(),n=this._date.clone().isoWeekday(7);return t.isSame(e._date,"month")||n.isSame(e._date,"month")},t.prototype.format=function(){return this._date.format.apply(this._date,arguments)},t.prototype.addMonth=function(){return new t(this._date.clone().add(1,"month"))},t.prototype.subtractMonth=function(){return new t(this._date.clone().subtract(1,"month"))},t.prototype.clone=function(){return new t(this._date.clone())},t.prototype.safeClone=function(e){return this._date?this.clone():(void 0===e&&(e=null),new t(e))},t.prototype.moment=function(){return this._date},e.exports=t},function(e,t,n){"use strict";var a=n(1),o=n(8),s=n(3),i=n(6),r=a.createClass({displayName:"Calendar",mixins:[n(7)],handleClickOutside:function(){this.props.hideCalendar()},getInitialState:function(){return{date:new s(this.props.selected).safeClone(i())}},componentWillReceiveProps:function(e){e.selected!==this.props.selected&&this.setState({date:new s(e.selected).clone()})},increaseMonth:function(){this.setState({date:this.state.date.addMonth()})},decreaseMonth:function(){this.setState({date:this.state.date.subtractMonth()})},weeks:function(){return this.state.date.mapWeeksInMonth(this.renderWeek)},handleDayClick:function(e){this.props.onSelect(e)},renderWeek:function(e,t){return e.weekInMonth(this.state.date)?a.createElement("div",{key:t},this.days(e)):void 0},renderDay:function(e,t){var n=new s(this.props.minDate).safeClone(),i=new s(this.props.maxDate).safeClone(),r=e.isBefore(n)||e.isAfter(i);return a.createElement(o,{key:t,day:e,date:this.state.date,onClick:this.handleDayClick.bind(this,e),selected:new s(this.props.selected),disabled:r})},days:function(e){return e.mapDaysInWeek(this.renderDay)},render:function(){return a.createElement("div",{className:"datepicker"},a.createElement("div",{className:"datepicker__triangle"}),a.createElement("div",{className:"datepicker__header"},a.createElement("a",{className:"datepicker__navigation datepicker__navigation--previous",onClick:this.decreaseMonth}),a.createElement("span",{className:"datepicker__current-month"},this.state.date.format("MMMM YYYY")),a.createElement("a",{className:"datepicker__navigation datepicker__navigation--next",onClick:this.increaseMonth}),a.createElement("div",null,a.createElement("div",{className:"datepicker__day"},"Mo"),a.createElement("div",{className:"datepicker__day"},"Tu"),a.createElement("div",{className:"datepicker__day"},"We"),a.createElement("div",{className:"datepicker__day"},"Th"),a.createElement("div",{className:"datepicker__day"},"Fr"),a.createElement("div",{className:"datepicker__day"},"Sa"),a.createElement("div",{className:"datepicker__day"},"Su"))),a.createElement("div",{className:"datepicker__month"},this.weeks()))}});e.exports=r},function(e,t,n){"use strict";var a=n(1),o=n(3),s=n(6),i=a.createClass({displayName:"DateInput",getDefaultProps:function(){return{dateFormat:"YYYY-MM-DD"}},getInitialState:function(){return{value:this.safeDateFormat(this.props.date)}},componentDidMount:function(){this.toggleFocus(this.props.focus)},componentWillReceiveProps:function(e){this.toggleFocus(e.focus),this.setState({value:this.safeDateFormat(e.date)})},toggleFocus:function(e){e?this.refs.input.getDOMNode().focus():this.refs.input.getDOMNode().blur()},handleChange:function(e){var t=s(e.target.value,this.props.dateFormat,!0);this.setState({value:e.target.value}),this.isValueAValidDate()&&this.props.setSelected(new o(t))},safeDateFormat:function(e){return e?e.format(this.props.dateFormat):null},isValueAValidDate:function(){var e=s(event.target.value,this.props.dateFormat,!0);return e.isValid()},handleKeyDown:function(e){switch(e.key){case"Enter":e.preventDefault(),this.props.handleEnter()}},handleClick:function(e){this.props.handleClick(e)},render:function(){return a.createElement("input",{ref:"input",type:"text",value:this.state.value,onClick:this.handleClick,onKeyDown:this.handleKeyDown,onFocus:this.props.onFocus,onChange:this.handleChange,className:"datepicker__input",placeholder:this.props.placeholderText})}});e.exports=i},function(e){e.exports=t},function(e){e.exports=n},function(e,t,n){"use strict";var a=n(1),o=n(6),s=a.createClass({displayName:"Day",handleClick:function(e){this.props.disabled||this.props.onClick(e)},render:function(){return classes=a.addons.classSet({datepicker__day:!0,"datepicker__day--disabled":this.props.disabled,"datepicker__day--selected":this.props.day.sameDay(this.props.selected),"datepicker__day--today":this.props.day.sameDay(o())}),a.createElement("div",{className:classes,onClick:this.handleClick},this.props.day.day())}});e.exports=s}])});
\ No newline at end of file
diff --git a/react-datepicker.js b/react-datepicker.js
deleted file mode 100644
index 265f2046f..000000000
--- a/react-datepicker.js
+++ /dev/null
@@ -1,515 +0,0 @@
-(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.DatePicker = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o anyway!
- },
- constraints: [
- {
- to: 'scrollParent',
- attachment: 'together',
- pin: true
- }
- ]
- };
- },
-
- _renderPopover: function() {
- React.render(this._popoverComponent(), this._popoverElement);
-
- if (this._tether != null) {
- this._tether.setOptions(this._tetherOptions());
- } else {
- this._tether = new Tether(this._tetherOptions());
- }
- },
-
- componentWillUnmount: function() {
- this._tether.destroy();
- React.unmountComponentAtNode(this._popoverElement);
- if (this._popoverElement.parentNode) {
- this._popoverElement.parentNode.removeChild(this._popoverElement);
- }
- },
-
- render: function() {
- return React.createElement("span", null);
- }
-});
-
-module.exports = Popover;
-
-
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],6:[function(require,module,exports){
-function DateUtil(date) {
- this._date = date;
-}
-
-DateUtil.prototype.isBefore = function(other) {
- return this._date.isBefore(other._date, 'day');
-};
-
-DateUtil.prototype.isAfter = function(other) {
- return this._date.isAfter(other._date, 'day');
-};
-
-DateUtil.prototype.sameDay = function(other) {
- return this._date.isSame(other._date, 'day');
-};
-
-DateUtil.prototype.sameMonth = function(other) {
- return this._date.isSame(other._date, 'month');
-};
-
-DateUtil.prototype.day = function() {
- return this._date.date();
-};
-
-DateUtil.prototype.mapDaysInWeek = function(callback) {
- var week = [];
- var firstDay = this._date.clone().startOf('isoWeek');
-
- for(var i = 0; i < 7; i++) {
- var day = new DateUtil(firstDay.clone().add(i, 'days'));
-
- week[i] = callback(day, i);
- }
-
- return week;
-};
-
-DateUtil.prototype.mapWeeksInMonth = function(callback) {
- var month = [];
- var firstDay = this._date.clone().startOf('month').startOf('isoWeek');
-
- for(var i = 0; i < 6; i++) {
- var weekStart = new DateUtil(firstDay.clone().add(i, 'weeks'));
-
- month[i] = callback(weekStart, i);
- }
-
- return month;
-};
-
-DateUtil.prototype.weekInMonth = function(other) {
- var firstDayInWeek = this._date.clone();
- var lastDayInWeek = this._date.clone().isoWeekday(7);
-
- return firstDayInWeek.isSame(other._date, 'month') ||
- lastDayInWeek.isSame(other._date, 'month');
-};
-
-DateUtil.prototype.format = function() {
- return this._date.format.apply(this._date, arguments);
-};
-
-DateUtil.prototype.addMonth = function() {
- return new DateUtil(this._date.clone().add(1, 'month'));
-};
-
-DateUtil.prototype.subtractMonth = function() {
- return new DateUtil(this._date.clone().subtract(1, 'month'));
-};
-
-DateUtil.prototype.clone = function() {
- return new DateUtil(this._date.clone());
-};
-
-DateUtil.prototype.safeClone = function(alternative) {
- if (!! this._date) return this.clone();
-
- if (alternative === undefined) alternative = null;
- return new DateUtil(alternative);
-};
-
-DateUtil.prototype.moment = function() {
- return this._date;
-};
-
-module.exports = DateUtil;
-
-
-
-},{}]},{},[1])(1)
-});
\ No newline at end of file
From be00a975e5cbd16b8d92f250337e6813bd020c4d Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 12:40:56 +0100
Subject: [PATCH 06/20] remove old references to browserify, reactify
---
grunt/tasks/browserify.js | 25 -------------------------
gruntfile.js | 29 +++--------------------------
package.json | 14 --------------
3 files changed, 3 insertions(+), 65 deletions(-)
delete mode 100644 grunt/tasks/browserify.js
diff --git a/grunt/tasks/browserify.js b/grunt/tasks/browserify.js
deleted file mode 100644
index d54be9238..000000000
--- a/grunt/tasks/browserify.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var browserify = require('browserify');
-var grunt = require('grunt');
-var _ = require('lodash');
-
-module.exports = function() {
- var config = this.data;
- var done = this.async();
- var bundle = browserify(config.browserifyOptions);
-
- _.forEach(config.transform, function(transform){
- bundle.transform(require(transform));
- });
-
- bundle.bundle(function(err, buf) {
- if (err) {
- grunt.log.error(err);
- return done(false);
- }
-
- var src = buf.toString();
-
- grunt.file.write(config.dest, src);
- done();
- });
-};
diff --git a/gruntfile.js b/gruntfile.js
index 9a5990cbd..a7730dd96 100644
--- a/gruntfile.js
+++ b/gruntfile.js
@@ -41,7 +41,7 @@ module.exports = function(grunt) {
watch: {
jshint: {
- files: 'src/**/*.js',
+ files: ['src/**/*.js', 'src/**/*.jsx'],
tasks: ['jshint']
},
@@ -55,8 +55,8 @@ module.exports = function(grunt) {
tasks: ['sass']
},
- browserify: {
- files: ['src/**/*.js'],
+ webpack: {
+ files: ['src/**/*.js', 'src/**/*.jsx'],
tasks: ['browserify']
}
},
@@ -66,28 +66,6 @@ module.exports = function(grunt) {
options: {
config: '.scss-lint.yml',
colorizeOutput: true
- },
- },
-
- browserify: {
- all: {
- dest: 'react-datepicker.js',
- transform: [
- 'reactify',
- 'browserify-shim'
- ],
- browserifyOptions: {
- entries: './src/datepicker.js',
- standalone: 'DatePicker',
- bundleExternal: false
- }
- },
-
- example : {
- dest: 'example/bundle.js',
- browserifyOptions: {
- entries: './example/boot.jsx'
- }
}
},
@@ -129,6 +107,5 @@ module.exports = function(grunt) {
grunt.registerTask('travis', ['jshint', 'jest', 'scsslint']);
grunt.registerTask('build', ['jshint', 'scsslint', 'webpack', 'sass']);
- grunt.registerMultiTask('browserify', require('./grunt/tasks/browserify'));
grunt.registerTask('jest', require('./grunt/tasks/jest'));
};
diff --git a/package.json b/package.json
index 01a7dd89d..eb91502fc 100644
--- a/package.json
+++ b/package.json
@@ -23,8 +23,6 @@
"devDependencies": {
"babel-core": "^4.7.3",
"babel-loader": "^4.1.0",
- "browserify": "9.0.3",
- "browserify-shim": "3.8.3",
"grunt": "0.4.5",
"grunt-cli": "0.1.13",
"grunt-contrib-sass": "0.9.2",
@@ -35,8 +33,6 @@
"jest-cli": "0.4.0",
"lodash": "^3.3.0",
"react": "^0.12",
- "react-tools": "0.12.2",
- "reactify": "^1.0",
"webpack": "^1.7.2",
"webpack-dev-server": "^1.7.0"
},
@@ -51,16 +47,6 @@
"scripts": {
"test": "grunt travis --verbose"
},
- "browserify": {
- "transform": [
- "reactify"
- ]
- },
- "browserify-shim": {
- "react/addons": "global:React",
- "moment": "global:moment",
- "react-onclickoutside": "global:OnClickOutside"
- },
"jest": {
"testDirectoryName": "test",
"scriptPreprocessor": "/jestPreprocessor.js",
From a961a2df1b607f7ccb6239563608f18c907fd6aa Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 12:41:42 +0100
Subject: [PATCH 07/20] run tests when `.jsx` file changed too
---
gruntfile.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gruntfile.js b/gruntfile.js
index a7730dd96..d22d06957 100644
--- a/gruntfile.js
+++ b/gruntfile.js
@@ -46,7 +46,7 @@ module.exports = function(grunt) {
},
jest: {
- files: ['src/**/*.js', 'test/**/*.js'],
+ files: ['src/**/*.jsx', 'src/**/*.js', 'test/**/*.js'],
tasks: ['jest']
},
From ba1d57b9c9fd40393ed36cbb97eda62bd9ffbf46 Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 12:43:57 +0100
Subject: [PATCH 08/20] main file for bower should be `.min.x`
---
bower.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bower.json b/bower.json
index a39085a9f..3c2ecf8e8 100644
--- a/bower.json
+++ b/bower.json
@@ -13,7 +13,7 @@
"license": "MIT",
"main": [
"dist/react-datepicker.min.js",
- "dist/react-datepicker.css"
+ "dist/react-datepicker.min.css"
],
"keywords": [
"react",
From e75640cbedbffa197a6f9f00ec760030a0c0317a Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 12:44:15 +0100
Subject: [PATCH 09/20] switch jest preprocessor to `babel-jest`
---
jestPreprocessor.js | 6 ------
package.json | 3 ++-
2 files changed, 2 insertions(+), 7 deletions(-)
delete mode 100644 jestPreprocessor.js
diff --git a/jestPreprocessor.js b/jestPreprocessor.js
deleted file mode 100644
index 48c3a625b..000000000
--- a/jestPreprocessor.js
+++ /dev/null
@@ -1,6 +0,0 @@
-var ReactTools = require('react-tools');
-module.exports = {
- process: function(src) {
- return ReactTools.transform(src);
- }
-};
diff --git a/package.json b/package.json
index eb91502fc..fd2cd3790 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
},
"devDependencies": {
"babel-core": "^4.7.3",
+ "babel-jest": "^4.0.0",
"babel-loader": "^4.1.0",
"grunt": "0.4.5",
"grunt-cli": "0.1.13",
@@ -49,7 +50,7 @@
},
"jest": {
"testDirectoryName": "test",
- "scriptPreprocessor": "/jestPreprocessor.js",
+ "scriptPreprocessor": "/node_modules/babel-jest",
"unmockedModulePathPatterns": [
"/node_modules/react"
]
From 056292fdba0c5d26e2e6f33a19b1b0627e947691 Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 12:44:42 +0100
Subject: [PATCH 10/20] remove old dist file
---
react-datepicker.css | 142 -------------------------------------------
1 file changed, 142 deletions(-)
delete mode 100644 react-datepicker.css
diff --git a/react-datepicker.css b/react-datepicker.css
deleted file mode 100644
index 1fa1f943a..000000000
--- a/react-datepicker.css
+++ /dev/null
@@ -1,142 +0,0 @@
-.datepicker__triangle {
- margin-top: -8px;
- margin-left: -8px;
-}
-.datepicker__triangle, .datepicker__triangle:before {
- box-sizing: content-box;
- position: absolute;
- border: 8px solid transparent;
- height: 0;
- width: 1px;
- border-top: none;
- border-bottom-color: #f0f0f0;
-}
-.datepicker__triangle:before {
- content: "";
- z-index: -1;
- border-width: 8px;
- top: -1px;
- left: -8px;
- border-bottom-color: #aeaeae;
-}
-
-.datepicker {
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
- font-size: 11px;
- background-color: #fff;
- color: #000;
- border: 1px solid #aeaeae;
- border-radius: 4px;
- display: inline-block;
- position: relative;
-}
-
-.datepicker__container {
- position: absolute;
- display: inline-block;
- z-index: 2147483647;
-}
-
-.datepicker__triangle {
- position: absolute;
- left: 50px;
-}
-
-.datepicker__header {
- text-align: center;
- background-color: #f0f0f0;
- border-bottom: 1px solid #aeaeae;
- border-top-left-radius: 4px;
- border-top-right-radius: 4px;
- padding-top: 8px;
- position: relative;
-}
-
-.datepicker__current-month {
- color: black;
- font-weight: bold;
- font-size: 13px;
-}
-
-.datepicker__navigation {
- line-height: 24px;
- text-align: center;
- cursor: pointer;
- position: absolute;
- top: 10px;
- width: 0;
- border: 6px solid transparent;
-}
-.datepicker__navigation--previous {
- left: 10px;
- border-right-color: #ccc;
-}
-.datepicker__navigation--previous:hover {
- border-right-color: #b3b3b3;
-}
-.datepicker__navigation--next {
- right: 10px;
- border-left-color: #ccc;
-}
-.datepicker__navigation--next:hover {
- border-left-color: #b3b3b3;
-}
-
-.datepicker__week-day {
- color: #ccc;
- display: inline-block;
- width: 28px;
- line-height: 24px;
-}
-
-.datepicker__month {
- margin: 5px;
- text-align: center;
-}
-
-.datepicker__day {
- color: #000;
- display: inline-block;
- width: 24px;
- line-height: 24px;
- text-align: center;
- margin: 2px;
- cursor: pointer;
-}
-.datepicker__day:hover {
- border-radius: 4px;
- background-color: #f0f0f0;
-}
-.datepicker__day--today {
- font-weight: bold;
-}
-.datepicker__day--selected {
- border-radius: 4px;
- background-color: #216ba5;
- color: #fff;
-}
-.datepicker__day--selected:hover {
- background-color: #1d5d90;
-}
-.datepicker__day--disabled {
- cursor: default;
- color: #ccc;
-}
-.datepicker__day--disabled:hover {
- background-color: transparent;
-}
-
-.datepicker__input {
- position: relative;
- font-size: 13px;
- border-radius: 4px;
- box-shadow: inset 0 2px 2px #e9e9e9;
- border: 1px solid #aeaeae;
- line-height: 16px;
- padding: 6px 10px 5px;
-}
-.datepicker__input:focus {
- outline: none;
- border-color: #aeaeae;
- box-shadow: inset 0 2px 2px #e9e9e9, 0 0 10px 0 rgba(73, 107, 125, 0.3);
-}
From 189d5de988c62fd023e0b9dd92e997afe0bb3cbb Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 12:53:35 +0100
Subject: [PATCH 11/20] fixing node engines for `jest`
---
package.json | 3 +++
1 file changed, 3 insertions(+)
diff --git a/package.json b/package.json
index fd2cd3790..2181460ad 100644
--- a/package.json
+++ b/package.json
@@ -6,6 +6,9 @@
"license": "MIT",
"homepage": "https://github.com/Hacker0x01/react-datepicker",
"main": "dist/datepicker.min.js",
+ "engines": {
+ "node": ">= 0.10 < 0.12"
+ },
"keywords": [
"react",
"datepicker",
From 43450968a9efcdaf5548b1f92d15fc6188342b9e Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 12:53:49 +0100
Subject: [PATCH 12/20] `grunt-jsxhint` require `react-tools`
---
package.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/package.json b/package.json
index 2181460ad..de7880de7 100644
--- a/package.json
+++ b/package.json
@@ -37,6 +37,7 @@
"jest-cli": "0.4.0",
"lodash": "^3.3.0",
"react": "^0.12",
+ "react-tools": "^0.12.2",
"webpack": "^1.7.2",
"webpack-dev-server": "^1.7.0"
},
From 852ecc24fb8e7be5180048d6bf6e03753e502e7a Mon Sep 17 00:00:00 2001
From: Maxime Tyler <127086@supinfo.com>
Date: Mon, 9 Mar 2015 13:18:30 +0100
Subject: [PATCH 13/20] add `grunt webpack:example` for building example
---
example/bundle.js | 23717 -------------------------------------------
example/example.js | 713 ++
example/index.html | 10 +-
gruntfile.js | 13 +-
4 files changed, 730 insertions(+), 23723 deletions(-)
delete mode 100644 example/bundle.js
create mode 100644 example/example.js
diff --git a/example/bundle.js b/example/bundle.js
deleted file mode 100644
index bc07264eb..000000000
--- a/example/bundle.js
+++ /dev/null
@@ -1,23717 +0,0 @@
-(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o ['10', '00'] or '-1530' > ['-', '15', '30']
- parseTimezoneChunker = /([\+\-]|\d\d)/gi,
-
- // getter and setter names
- proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
- unitMillisecondFactors = {
- 'Milliseconds' : 1,
- 'Seconds' : 1e3,
- 'Minutes' : 6e4,
- 'Hours' : 36e5,
- 'Days' : 864e5,
- 'Months' : 2592e6,
- 'Years' : 31536e6
- },
-
- unitAliases = {
- ms : 'millisecond',
- s : 'second',
- m : 'minute',
- h : 'hour',
- d : 'day',
- D : 'date',
- w : 'week',
- W : 'isoWeek',
- M : 'month',
- Q : 'quarter',
- y : 'year',
- DDD : 'dayOfYear',
- e : 'weekday',
- E : 'isoWeekday',
- gg: 'weekYear',
- GG: 'isoWeekYear'
- },
-
- camelFunctions = {
- dayofyear : 'dayOfYear',
- isoweekday : 'isoWeekday',
- isoweek : 'isoWeek',
- weekyear : 'weekYear',
- isoweekyear : 'isoWeekYear'
- },
-
- // format function strings
- formatFunctions = {},
-
- // default relative time thresholds
- relativeTimeThresholds = {
- s: 45, // seconds to minute
- m: 45, // minutes to hour
- h: 22, // hours to day
- d: 26, // days to month
- M: 11 // months to year
- },
-
- // tokens to ordinalize and pad
- ordinalizeTokens = 'DDD w W M D d'.split(' '),
- paddedTokens = 'M D H h m s w W'.split(' '),
-
- formatTokenFunctions = {
- M : function () {
- return this.month() + 1;
- },
- MMM : function (format) {
- return this.localeData().monthsShort(this, format);
- },
- MMMM : function (format) {
- return this.localeData().months(this, format);
- },
- D : function () {
- return this.date();
- },
- DDD : function () {
- return this.dayOfYear();
- },
- d : function () {
- return this.day();
- },
- dd : function (format) {
- return this.localeData().weekdaysMin(this, format);
- },
- ddd : function (format) {
- return this.localeData().weekdaysShort(this, format);
- },
- dddd : function (format) {
- return this.localeData().weekdays(this, format);
- },
- w : function () {
- return this.week();
- },
- W : function () {
- return this.isoWeek();
- },
- YY : function () {
- return leftZeroFill(this.year() % 100, 2);
- },
- YYYY : function () {
- return leftZeroFill(this.year(), 4);
- },
- YYYYY : function () {
- return leftZeroFill(this.year(), 5);
- },
- YYYYYY : function () {
- var y = this.year(), sign = y >= 0 ? '+' : '-';
- return sign + leftZeroFill(Math.abs(y), 6);
- },
- gg : function () {
- return leftZeroFill(this.weekYear() % 100, 2);
- },
- gggg : function () {
- return leftZeroFill(this.weekYear(), 4);
- },
- ggggg : function () {
- return leftZeroFill(this.weekYear(), 5);
- },
- GG : function () {
- return leftZeroFill(this.isoWeekYear() % 100, 2);
- },
- GGGG : function () {
- return leftZeroFill(this.isoWeekYear(), 4);
- },
- GGGGG : function () {
- return leftZeroFill(this.isoWeekYear(), 5);
- },
- e : function () {
- return this.weekday();
- },
- E : function () {
- return this.isoWeekday();
- },
- a : function () {
- return this.localeData().meridiem(this.hours(), this.minutes(), true);
- },
- A : function () {
- return this.localeData().meridiem(this.hours(), this.minutes(), false);
- },
- H : function () {
- return this.hours();
- },
- h : function () {
- return this.hours() % 12 || 12;
- },
- m : function () {
- return this.minutes();
- },
- s : function () {
- return this.seconds();
- },
- S : function () {
- return toInt(this.milliseconds() / 100);
- },
- SS : function () {
- return leftZeroFill(toInt(this.milliseconds() / 10), 2);
- },
- SSS : function () {
- return leftZeroFill(this.milliseconds(), 3);
- },
- SSSS : function () {
- return leftZeroFill(this.milliseconds(), 3);
- },
- Z : function () {
- var a = this.utcOffset(),
- b = '+';
- if (a < 0) {
- a = -a;
- b = '-';
- }
- return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2);
- },
- ZZ : function () {
- var a = this.utcOffset(),
- b = '+';
- if (a < 0) {
- a = -a;
- b = '-';
- }
- return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
- },
- z : function () {
- return this.zoneAbbr();
- },
- zz : function () {
- return this.zoneName();
- },
- x : function () {
- return this.valueOf();
- },
- X : function () {
- return this.unix();
- },
- Q : function () {
- return this.quarter();
- }
- },
-
- deprecations = {},
-
- lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'],
-
- updateInProgress = false;
-
- // Pick the first defined of two or three arguments. dfl comes from
- // default.
- function dfl(a, b, c) {
- switch (arguments.length) {
- case 2: return a != null ? a : b;
- case 3: return a != null ? a : b != null ? b : c;
- default: throw new Error('Implement me');
- }
- }
-
- function hasOwnProp(a, b) {
- return hasOwnProperty.call(a, b);
- }
-
- function defaultParsingFlags() {
- // We need to deep clone this object, and es5 standard is not very
- // helpful.
- return {
- empty : false,
- unusedTokens : [],
- unusedInput : [],
- overflow : -2,
- charsLeftOver : 0,
- nullInput : false,
- invalidMonth : null,
- invalidFormat : false,
- userInvalidated : false,
- iso: false
- };
- }
-
- function printMsg(msg) {
- if (moment.suppressDeprecationWarnings === false &&
- typeof console !== 'undefined' && console.warn) {
- console.warn('Deprecation warning: ' + msg);
- }
- }
-
- function deprecate(msg, fn) {
- var firstTime = true;
- return extend(function () {
- if (firstTime) {
- printMsg(msg);
- firstTime = false;
- }
- return fn.apply(this, arguments);
- }, fn);
- }
-
- function deprecateSimple(name, msg) {
- if (!deprecations[name]) {
- printMsg(msg);
- deprecations[name] = true;
- }
- }
-
- function padToken(func, count) {
- return function (a) {
- return leftZeroFill(func.call(this, a), count);
- };
- }
- function ordinalizeToken(func, period) {
- return function (a) {
- return this.localeData().ordinal(func.call(this, a), period);
- };
- }
-
- function monthDiff(a, b) {
- // difference in months
- var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
- // b is in (anchor - 1 month, anchor + 1 month)
- anchor = a.clone().add(wholeMonthDiff, 'months'),
- anchor2, adjust;
-
- if (b - anchor < 0) {
- anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
- // linear across the month
- adjust = (b - anchor) / (anchor - anchor2);
- } else {
- anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
- // linear across the month
- adjust = (b - anchor) / (anchor2 - anchor);
- }
-
- return -(wholeMonthDiff + adjust);
- }
-
- while (ordinalizeTokens.length) {
- i = ordinalizeTokens.pop();
- formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
- }
- while (paddedTokens.length) {
- i = paddedTokens.pop();
- formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
- }
- formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
-
-
- function meridiemFixWrap(locale, hour, meridiem) {
- var isPm;
-
- if (meridiem == null) {
- // nothing to do
- return hour;
- }
- if (locale.meridiemHour != null) {
- return locale.meridiemHour(hour, meridiem);
- } else if (locale.isPM != null) {
- // Fallback
- isPm = locale.isPM(meridiem);
- if (isPm && hour < 12) {
- hour += 12;
- }
- if (!isPm && hour === 12) {
- hour = 0;
- }
- return hour;
- } else {
- // thie is not supposed to happen
- return hour;
- }
- }
-
- /************************************
- Constructors
- ************************************/
-
- function Locale() {
- }
-
- // Moment prototype object
- function Moment(config, skipOverflow) {
- if (skipOverflow !== false) {
- checkOverflow(config);
- }
- copyConfig(this, config);
- this._d = new Date(+config._d);
- // Prevent infinite loop in case updateOffset creates new moment
- // objects.
- if (updateInProgress === false) {
- updateInProgress = true;
- moment.updateOffset(this);
- updateInProgress = false;
- }
- }
-
- // Duration Constructor
- function Duration(duration) {
- var normalizedInput = normalizeObjectUnits(duration),
- years = normalizedInput.year || 0,
- quarters = normalizedInput.quarter || 0,
- months = normalizedInput.month || 0,
- weeks = normalizedInput.week || 0,
- days = normalizedInput.day || 0,
- hours = normalizedInput.hour || 0,
- minutes = normalizedInput.minute || 0,
- seconds = normalizedInput.second || 0,
- milliseconds = normalizedInput.millisecond || 0;
-
- // representation for dateAddRemove
- this._milliseconds = +milliseconds +
- seconds * 1e3 + // 1000
- minutes * 6e4 + // 1000 * 60
- hours * 36e5; // 1000 * 60 * 60
- // Because of dateAddRemove treats 24 hours as different from a
- // day when working around DST, we need to store them separately
- this._days = +days +
- weeks * 7;
- // It is impossible translate months into days without knowing
- // which months you are are talking about, so we have to store
- // it separately.
- this._months = +months +
- quarters * 3 +
- years * 12;
-
- this._data = {};
-
- this._locale = moment.localeData();
-
- this._bubble();
- }
-
- /************************************
- Helpers
- ************************************/
-
-
- function extend(a, b) {
- for (var i in b) {
- if (hasOwnProp(b, i)) {
- a[i] = b[i];
- }
- }
-
- if (hasOwnProp(b, 'toString')) {
- a.toString = b.toString;
- }
-
- if (hasOwnProp(b, 'valueOf')) {
- a.valueOf = b.valueOf;
- }
-
- return a;
- }
-
- function copyConfig(to, from) {
- var i, prop, val;
-
- if (typeof from._isAMomentObject !== 'undefined') {
- to._isAMomentObject = from._isAMomentObject;
- }
- if (typeof from._i !== 'undefined') {
- to._i = from._i;
- }
- if (typeof from._f !== 'undefined') {
- to._f = from._f;
- }
- if (typeof from._l !== 'undefined') {
- to._l = from._l;
- }
- if (typeof from._strict !== 'undefined') {
- to._strict = from._strict;
- }
- if (typeof from._tzm !== 'undefined') {
- to._tzm = from._tzm;
- }
- if (typeof from._isUTC !== 'undefined') {
- to._isUTC = from._isUTC;
- }
- if (typeof from._offset !== 'undefined') {
- to._offset = from._offset;
- }
- if (typeof from._pf !== 'undefined') {
- to._pf = from._pf;
- }
- if (typeof from._locale !== 'undefined') {
- to._locale = from._locale;
- }
-
- if (momentProperties.length > 0) {
- for (i in momentProperties) {
- prop = momentProperties[i];
- val = from[prop];
- if (typeof val !== 'undefined') {
- to[prop] = val;
- }
- }
- }
-
- return to;
- }
-
- function absRound(number) {
- if (number < 0) {
- return Math.ceil(number);
- } else {
- return Math.floor(number);
- }
- }
-
- // left zero fill a number
- // see http://jsperf.com/left-zero-filling for performance comparison
- function leftZeroFill(number, targetLength, forceSign) {
- var output = '' + Math.abs(number),
- sign = number >= 0;
-
- while (output.length < targetLength) {
- output = '0' + output;
- }
- return (sign ? (forceSign ? '+' : '') : '-') + output;
- }
-
- function positiveMomentsDifference(base, other) {
- var res = {milliseconds: 0, months: 0};
-
- res.months = other.month() - base.month() +
- (other.year() - base.year()) * 12;
- if (base.clone().add(res.months, 'M').isAfter(other)) {
- --res.months;
- }
-
- res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
-
- return res;
- }
-
- function momentsDifference(base, other) {
- var res;
- other = makeAs(other, base);
- if (base.isBefore(other)) {
- res = positiveMomentsDifference(base, other);
- } else {
- res = positiveMomentsDifference(other, base);
- res.milliseconds = -res.milliseconds;
- res.months = -res.months;
- }
-
- return res;
- }
-
- // TODO: remove 'name' arg after deprecation is removed
- function createAdder(direction, name) {
- return function (val, period) {
- var dur, tmp;
- //invert the arguments, but complain about it
- if (period !== null && !isNaN(+period)) {
- deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
- tmp = val; val = period; period = tmp;
- }
-
- val = typeof val === 'string' ? +val : val;
- dur = moment.duration(val, period);
- addOrSubtractDurationFromMoment(this, dur, direction);
- return this;
- };
- }
-
- function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) {
- var milliseconds = duration._milliseconds,
- days = duration._days,
- months = duration._months;
- updateOffset = updateOffset == null ? true : updateOffset;
-
- if (milliseconds) {
- mom._d.setTime(+mom._d + milliseconds * isAdding);
- }
- if (days) {
- rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding);
- }
- if (months) {
- rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding);
- }
- if (updateOffset) {
- moment.updateOffset(mom, days || months);
- }
- }
-
- // check if is an array
- function isArray(input) {
- return Object.prototype.toString.call(input) === '[object Array]';
- }
-
- function isDate(input) {
- return Object.prototype.toString.call(input) === '[object Date]' ||
- input instanceof Date;
- }
-
- // compare two arrays, return the number of differences
- function compareArrays(array1, array2, dontConvert) {
- var len = Math.min(array1.length, array2.length),
- lengthDiff = Math.abs(array1.length - array2.length),
- diffs = 0,
- i;
- for (i = 0; i < len; i++) {
- if ((dontConvert && array1[i] !== array2[i]) ||
- (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
- diffs++;
- }
- }
- return diffs + lengthDiff;
- }
-
- function normalizeUnits(units) {
- if (units) {
- var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
- units = unitAliases[units] || camelFunctions[lowered] || lowered;
- }
- return units;
- }
-
- function normalizeObjectUnits(inputObject) {
- var normalizedInput = {},
- normalizedProp,
- prop;
-
- for (prop in inputObject) {
- if (hasOwnProp(inputObject, prop)) {
- normalizedProp = normalizeUnits(prop);
- if (normalizedProp) {
- normalizedInput[normalizedProp] = inputObject[prop];
- }
- }
- }
-
- return normalizedInput;
- }
-
- function makeList(field) {
- var count, setter;
-
- if (field.indexOf('week') === 0) {
- count = 7;
- setter = 'day';
- }
- else if (field.indexOf('month') === 0) {
- count = 12;
- setter = 'month';
- }
- else {
- return;
- }
-
- moment[field] = function (format, index) {
- var i, getter,
- method = moment._locale[field],
- results = [];
-
- if (typeof format === 'number') {
- index = format;
- format = undefined;
- }
-
- getter = function (i) {
- var m = moment().utc().set(setter, i);
- return method.call(moment._locale, m, format || '');
- };
-
- if (index != null) {
- return getter(index);
- }
- else {
- for (i = 0; i < count; i++) {
- results.push(getter(i));
- }
- return results;
- }
- };
- }
-
- function toInt(argumentForCoercion) {
- var coercedNumber = +argumentForCoercion,
- value = 0;
-
- if (coercedNumber !== 0 && isFinite(coercedNumber)) {
- if (coercedNumber >= 0) {
- value = Math.floor(coercedNumber);
- } else {
- value = Math.ceil(coercedNumber);
- }
- }
-
- return value;
- }
-
- function daysInMonth(year, month) {
- return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
- }
-
- function weeksInYear(year, dow, doy) {
- return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week;
- }
-
- function daysInYear(year) {
- return isLeapYear(year) ? 366 : 365;
- }
-
- function isLeapYear(year) {
- return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
- }
-
- function checkOverflow(m) {
- var overflow;
- if (m._a && m._pf.overflow === -2) {
- overflow =
- m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
- m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
- m._a[HOUR] < 0 || m._a[HOUR] > 24 ||
- (m._a[HOUR] === 24 && (m._a[MINUTE] !== 0 ||
- m._a[SECOND] !== 0 ||
- m._a[MILLISECOND] !== 0)) ? HOUR :
- m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
- m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
- m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
- -1;
-
- if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
- overflow = DATE;
- }
-
- m._pf.overflow = overflow;
- }
- }
-
- function isValid(m) {
- if (m._isValid == null) {
- m._isValid = !isNaN(m._d.getTime()) &&
- m._pf.overflow < 0 &&
- !m._pf.empty &&
- !m._pf.invalidMonth &&
- !m._pf.nullInput &&
- !m._pf.invalidFormat &&
- !m._pf.userInvalidated;
-
- if (m._strict) {
- m._isValid = m._isValid &&
- m._pf.charsLeftOver === 0 &&
- m._pf.unusedTokens.length === 0 &&
- m._pf.bigHour === undefined;
- }
- }
- return m._isValid;
- }
-
- function normalizeLocale(key) {
- return key ? key.toLowerCase().replace('_', '-') : key;
- }
-
- // pick the locale from the array
- // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
- // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
- function chooseLocale(names) {
- var i = 0, j, next, locale, split;
-
- while (i < names.length) {
- split = normalizeLocale(names[i]).split('-');
- j = split.length;
- next = normalizeLocale(names[i + 1]);
- next = next ? next.split('-') : null;
- while (j > 0) {
- locale = loadLocale(split.slice(0, j).join('-'));
- if (locale) {
- return locale;
- }
- if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
- //the next array item is better than a shallower substring of this one
- break;
- }
- j--;
- }
- i++;
- }
- return null;
- }
-
- function loadLocale(name) {
- var oldLocale = null;
- if (!locales[name] && hasModule) {
- try {
- oldLocale = moment.locale();
- require('./locale/' + name);
- // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales
- moment.locale(oldLocale);
- } catch (e) { }
- }
- return locales[name];
- }
-
- // Return a moment from input, that is local/utc/utcOffset equivalent to
- // model.
- function makeAs(input, model) {
- var res, diff;
- if (model._isUTC) {
- res = model.clone();
- diff = (moment.isMoment(input) || isDate(input) ?
- +input : +moment(input)) - (+res);
- // Use low-level api, because this fn is low-level api.
- res._d.setTime(+res._d + diff);
- moment.updateOffset(res, false);
- return res;
- } else {
- return moment(input).local();
- }
- }
-
- /************************************
- Locale
- ************************************/
-
-
- extend(Locale.prototype, {
-
- set : function (config) {
- var prop, i;
- for (i in config) {
- prop = config[i];
- if (typeof prop === 'function') {
- this[i] = prop;
- } else {
- this['_' + i] = prop;
- }
- }
- // Lenient ordinal parsing accepts just a number in addition to
- // number + (possibly) stuff coming from _ordinalParseLenient.
- this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + /\d{1,2}/.source);
- },
-
- _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
- months : function (m) {
- return this._months[m.month()];
- },
-
- _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
- monthsShort : function (m) {
- return this._monthsShort[m.month()];
- },
-
- monthsParse : function (monthName, format, strict) {
- var i, mom, regex;
-
- if (!this._monthsParse) {
- this._monthsParse = [];
- this._longMonthsParse = [];
- this._shortMonthsParse = [];
- }
-
- for (i = 0; i < 12; i++) {
- // make the regex if we don't have it already
- mom = moment.utc([2000, i]);
- if (strict && !this._longMonthsParse[i]) {
- this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
- this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
- }
- if (!strict && !this._monthsParse[i]) {
- regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
- this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
- }
- // test the regex
- if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
- return i;
- } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
- return i;
- } else if (!strict && this._monthsParse[i].test(monthName)) {
- return i;
- }
- }
- },
-
- _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
- weekdays : function (m) {
- return this._weekdays[m.day()];
- },
-
- _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
- weekdaysShort : function (m) {
- return this._weekdaysShort[m.day()];
- },
-
- _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
- weekdaysMin : function (m) {
- return this._weekdaysMin[m.day()];
- },
-
- weekdaysParse : function (weekdayName) {
- var i, mom, regex;
-
- if (!this._weekdaysParse) {
- this._weekdaysParse = [];
- }
-
- for (i = 0; i < 7; i++) {
- // make the regex if we don't have it already
- if (!this._weekdaysParse[i]) {
- mom = moment([2000, 1]).day(i);
- regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
- this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
- }
- // test the regex
- if (this._weekdaysParse[i].test(weekdayName)) {
- return i;
- }
- }
- },
-
- _longDateFormat : {
- LTS : 'h:mm:ss A',
- LT : 'h:mm A',
- L : 'MM/DD/YYYY',
- LL : 'MMMM D, YYYY',
- LLL : 'MMMM D, YYYY LT',
- LLLL : 'dddd, MMMM D, YYYY LT'
- },
- longDateFormat : function (key) {
- var output = this._longDateFormat[key];
- if (!output && this._longDateFormat[key.toUpperCase()]) {
- output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
- return val.slice(1);
- });
- this._longDateFormat[key] = output;
- }
- return output;
- },
-
- isPM : function (input) {
- // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
- // Using charAt should be more compatible.
- return ((input + '').toLowerCase().charAt(0) === 'p');
- },
-
- _meridiemParse : /[ap]\.?m?\.?/i,
- meridiem : function (hours, minutes, isLower) {
- if (hours > 11) {
- return isLower ? 'pm' : 'PM';
- } else {
- return isLower ? 'am' : 'AM';
- }
- },
-
-
- _calendar : {
- sameDay : '[Today at] LT',
- nextDay : '[Tomorrow at] LT',
- nextWeek : 'dddd [at] LT',
- lastDay : '[Yesterday at] LT',
- lastWeek : '[Last] dddd [at] LT',
- sameElse : 'L'
- },
- calendar : function (key, mom, now) {
- var output = this._calendar[key];
- return typeof output === 'function' ? output.apply(mom, [now]) : output;
- },
-
- _relativeTime : {
- future : 'in %s',
- past : '%s ago',
- s : 'a few seconds',
- m : 'a minute',
- mm : '%d minutes',
- h : 'an hour',
- hh : '%d hours',
- d : 'a day',
- dd : '%d days',
- M : 'a month',
- MM : '%d months',
- y : 'a year',
- yy : '%d years'
- },
-
- relativeTime : function (number, withoutSuffix, string, isFuture) {
- var output = this._relativeTime[string];
- return (typeof output === 'function') ?
- output(number, withoutSuffix, string, isFuture) :
- output.replace(/%d/i, number);
- },
-
- pastFuture : function (diff, output) {
- var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
- return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
- },
-
- ordinal : function (number) {
- return this._ordinal.replace('%d', number);
- },
- _ordinal : '%d',
- _ordinalParse : /\d{1,2}/,
-
- preparse : function (string) {
- return string;
- },
-
- postformat : function (string) {
- return string;
- },
-
- week : function (mom) {
- return weekOfYear(mom, this._week.dow, this._week.doy).week;
- },
-
- _week : {
- dow : 0, // Sunday is the first day of the week.
- doy : 6 // The week that contains Jan 1st is the first week of the year.
- },
-
- firstDayOfWeek : function () {
- return this._week.dow;
- },
-
- firstDayOfYear : function () {
- return this._week.doy;
- },
-
- _invalidDate: 'Invalid date',
- invalidDate: function () {
- return this._invalidDate;
- }
- });
-
- /************************************
- Formatting
- ************************************/
-
-
- function removeFormattingTokens(input) {
- if (input.match(/\[[\s\S]/)) {
- return input.replace(/^\[|\]$/g, '');
- }
- return input.replace(/\\/g, '');
- }
-
- function makeFormatFunction(format) {
- var array = format.match(formattingTokens), i, length;
-
- for (i = 0, length = array.length; i < length; i++) {
- if (formatTokenFunctions[array[i]]) {
- array[i] = formatTokenFunctions[array[i]];
- } else {
- array[i] = removeFormattingTokens(array[i]);
- }
- }
-
- return function (mom) {
- var output = '';
- for (i = 0; i < length; i++) {
- output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
- }
- return output;
- };
- }
-
- // format date using native date object
- function formatMoment(m, format) {
- if (!m.isValid()) {
- return m.localeData().invalidDate();
- }
-
- format = expandFormat(format, m.localeData());
-
- if (!formatFunctions[format]) {
- formatFunctions[format] = makeFormatFunction(format);
- }
-
- return formatFunctions[format](m);
- }
-
- function expandFormat(format, locale) {
- var i = 5;
-
- function replaceLongDateFormatTokens(input) {
- return locale.longDateFormat(input) || input;
- }
-
- localFormattingTokens.lastIndex = 0;
- while (i >= 0 && localFormattingTokens.test(format)) {
- format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
- localFormattingTokens.lastIndex = 0;
- i -= 1;
- }
-
- return format;
- }
-
-
- /************************************
- Parsing
- ************************************/
-
-
- // get the regex to find the next token
- function getParseRegexForToken(token, config) {
- var a, strict = config._strict;
- switch (token) {
- case 'Q':
- return parseTokenOneDigit;
- case 'DDDD':
- return parseTokenThreeDigits;
- case 'YYYY':
- case 'GGGG':
- case 'gggg':
- return strict ? parseTokenFourDigits : parseTokenOneToFourDigits;
- case 'Y':
- case 'G':
- case 'g':
- return parseTokenSignedNumber;
- case 'YYYYYY':
- case 'YYYYY':
- case 'GGGGG':
- case 'ggggg':
- return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
- case 'S':
- if (strict) {
- return parseTokenOneDigit;
- }
- /* falls through */
- case 'SS':
- if (strict) {
- return parseTokenTwoDigits;
- }
- /* falls through */
- case 'SSS':
- if (strict) {
- return parseTokenThreeDigits;
- }
- /* falls through */
- case 'DDD':
- return parseTokenOneToThreeDigits;
- case 'MMM':
- case 'MMMM':
- case 'dd':
- case 'ddd':
- case 'dddd':
- return parseTokenWord;
- case 'a':
- case 'A':
- return config._locale._meridiemParse;
- case 'x':
- return parseTokenOffsetMs;
- case 'X':
- return parseTokenTimestampMs;
- case 'Z':
- case 'ZZ':
- return parseTokenTimezone;
- case 'T':
- return parseTokenT;
- case 'SSSS':
- return parseTokenDigits;
- case 'MM':
- case 'DD':
- case 'YY':
- case 'GG':
- case 'gg':
- case 'HH':
- case 'hh':
- case 'mm':
- case 'ss':
- case 'ww':
- case 'WW':
- return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits;
- case 'M':
- case 'D':
- case 'd':
- case 'H':
- case 'h':
- case 'm':
- case 's':
- case 'w':
- case 'W':
- case 'e':
- case 'E':
- return parseTokenOneOrTwoDigits;
- case 'Do':
- return strict ? config._locale._ordinalParse : config._locale._ordinalParseLenient;
- default :
- a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i'));
- return a;
- }
- }
-
- function utcOffsetFromString(string) {
- string = string || '';
- var possibleTzMatches = (string.match(parseTokenTimezone) || []),
- tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
- parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
- minutes = +(parts[1] * 60) + toInt(parts[2]);
-
- return parts[0] === '+' ? minutes : -minutes;
- }
-
- // function to convert string input to date
- function addTimeToArrayFromToken(token, input, config) {
- var a, datePartArray = config._a;
-
- switch (token) {
- // QUARTER
- case 'Q':
- if (input != null) {
- datePartArray[MONTH] = (toInt(input) - 1) * 3;
- }
- break;
- // MONTH
- case 'M' : // fall through to MM
- case 'MM' :
- if (input != null) {
- datePartArray[MONTH] = toInt(input) - 1;
- }
- break;
- case 'MMM' : // fall through to MMMM
- case 'MMMM' :
- a = config._locale.monthsParse(input, token, config._strict);
- // if we didn't find a month name, mark the date as invalid.
- if (a != null) {
- datePartArray[MONTH] = a;
- } else {
- config._pf.invalidMonth = input;
- }
- break;
- // DAY OF MONTH
- case 'D' : // fall through to DD
- case 'DD' :
- if (input != null) {
- datePartArray[DATE] = toInt(input);
- }
- break;
- case 'Do' :
- if (input != null) {
- datePartArray[DATE] = toInt(parseInt(
- input.match(/\d{1,2}/)[0], 10));
- }
- break;
- // DAY OF YEAR
- case 'DDD' : // fall through to DDDD
- case 'DDDD' :
- if (input != null) {
- config._dayOfYear = toInt(input);
- }
-
- break;
- // YEAR
- case 'YY' :
- datePartArray[YEAR] = moment.parseTwoDigitYear(input);
- break;
- case 'YYYY' :
- case 'YYYYY' :
- case 'YYYYYY' :
- datePartArray[YEAR] = toInt(input);
- break;
- // AM / PM
- case 'a' : // fall through to A
- case 'A' :
- config._meridiem = input;
- // config._isPm = config._locale.isPM(input);
- break;
- // HOUR
- case 'h' : // fall through to hh
- case 'hh' :
- config._pf.bigHour = true;
- /* falls through */
- case 'H' : // fall through to HH
- case 'HH' :
- datePartArray[HOUR] = toInt(input);
- break;
- // MINUTE
- case 'm' : // fall through to mm
- case 'mm' :
- datePartArray[MINUTE] = toInt(input);
- break;
- // SECOND
- case 's' : // fall through to ss
- case 'ss' :
- datePartArray[SECOND] = toInt(input);
- break;
- // MILLISECOND
- case 'S' :
- case 'SS' :
- case 'SSS' :
- case 'SSSS' :
- datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
- break;
- // UNIX OFFSET (MILLISECONDS)
- case 'x':
- config._d = new Date(toInt(input));
- break;
- // UNIX TIMESTAMP WITH MS
- case 'X':
- config._d = new Date(parseFloat(input) * 1000);
- break;
- // TIMEZONE
- case 'Z' : // fall through to ZZ
- case 'ZZ' :
- config._useUTC = true;
- config._tzm = utcOffsetFromString(input);
- break;
- // WEEKDAY - human
- case 'dd':
- case 'ddd':
- case 'dddd':
- a = config._locale.weekdaysParse(input);
- // if we didn't get a weekday name, mark the date as invalid
- if (a != null) {
- config._w = config._w || {};
- config._w['d'] = a;
- } else {
- config._pf.invalidWeekday = input;
- }
- break;
- // WEEK, WEEK DAY - numeric
- case 'w':
- case 'ww':
- case 'W':
- case 'WW':
- case 'd':
- case 'e':
- case 'E':
- token = token.substr(0, 1);
- /* falls through */
- case 'gggg':
- case 'GGGG':
- case 'GGGGG':
- token = token.substr(0, 2);
- if (input) {
- config._w = config._w || {};
- config._w[token] = toInt(input);
- }
- break;
- case 'gg':
- case 'GG':
- config._w = config._w || {};
- config._w[token] = moment.parseTwoDigitYear(input);
- }
- }
-
- function dayOfYearFromWeekInfo(config) {
- var w, weekYear, week, weekday, dow, doy, temp;
-
- w = config._w;
- if (w.GG != null || w.W != null || w.E != null) {
- dow = 1;
- doy = 4;
-
- // TODO: We need to take the current isoWeekYear, but that depends on
- // how we interpret now (local, utc, fixed offset). So create
- // a now version of current config (take local/utc/offset flags, and
- // create now).
- weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year);
- week = dfl(w.W, 1);
- weekday = dfl(w.E, 1);
- } else {
- dow = config._locale._week.dow;
- doy = config._locale._week.doy;
-
- weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year);
- week = dfl(w.w, 1);
-
- if (w.d != null) {
- // weekday -- low day numbers are considered next week
- weekday = w.d;
- if (weekday < dow) {
- ++week;
- }
- } else if (w.e != null) {
- // local weekday -- counting starts from begining of week
- weekday = w.e + dow;
- } else {
- // default to begining of week
- weekday = dow;
- }
- }
- temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow);
-
- config._a[YEAR] = temp.year;
- config._dayOfYear = temp.dayOfYear;
- }
-
- // convert an array to a date.
- // the array should mirror the parameters below
- // note: all values past the year are optional and will default to the lowest possible value.
- // [year, month, day , hour, minute, second, millisecond]
- function dateFromConfig(config) {
- var i, date, input = [], currentDate, yearToUse;
-
- if (config._d) {
- return;
- }
-
- currentDate = currentDateArray(config);
-
- //compute day of the year from weeks and weekdays
- if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
- dayOfYearFromWeekInfo(config);
- }
-
- //if the day of the year is set, figure out what it is
- if (config._dayOfYear) {
- yearToUse = dfl(config._a[YEAR], currentDate[YEAR]);
-
- if (config._dayOfYear > daysInYear(yearToUse)) {
- config._pf._overflowDayOfYear = true;
- }
-
- date = makeUTCDate(yearToUse, 0, config._dayOfYear);
- config._a[MONTH] = date.getUTCMonth();
- config._a[DATE] = date.getUTCDate();
- }
-
- // Default to current date.
- // * if no year, month, day of month are given, default to today
- // * if day of month is given, default month and year
- // * if month is given, default only year
- // * if year is given, don't default anything
- for (i = 0; i < 3 && config._a[i] == null; ++i) {
- config._a[i] = input[i] = currentDate[i];
- }
-
- // Zero out whatever was not defaulted, including time
- for (; i < 7; i++) {
- config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
- }
-
- // Check for 24:00:00.000
- if (config._a[HOUR] === 24 &&
- config._a[MINUTE] === 0 &&
- config._a[SECOND] === 0 &&
- config._a[MILLISECOND] === 0) {
- config._nextDay = true;
- config._a[HOUR] = 0;
- }
-
- config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
- // Apply timezone offset from input. The actual utcOffset can be changed
- // with parseZone.
- if (config._tzm != null) {
- config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
- }
-
- if (config._nextDay) {
- config._a[HOUR] = 24;
- }
- }
-
- function dateFromObject(config) {
- var normalizedInput;
-
- if (config._d) {
- return;
- }
-
- normalizedInput = normalizeObjectUnits(config._i);
- config._a = [
- normalizedInput.year,
- normalizedInput.month,
- normalizedInput.day || normalizedInput.date,
- normalizedInput.hour,
- normalizedInput.minute,
- normalizedInput.second,
- normalizedInput.millisecond
- ];
-
- dateFromConfig(config);
- }
-
- function currentDateArray(config) {
- var now = new Date();
- if (config._useUTC) {
- return [
- now.getUTCFullYear(),
- now.getUTCMonth(),
- now.getUTCDate()
- ];
- } else {
- return [now.getFullYear(), now.getMonth(), now.getDate()];
- }
- }
-
- // date from string and format string
- function makeDateFromStringAndFormat(config) {
- if (config._f === moment.ISO_8601) {
- parseISO(config);
- return;
- }
-
- config._a = [];
- config._pf.empty = true;
-
- // This array is used to make a Date, either with `new Date` or `Date.UTC`
- var string = '' + config._i,
- i, parsedInput, tokens, token, skipped,
- stringLength = string.length,
- totalParsedInputLength = 0;
-
- tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
-
- for (i = 0; i < tokens.length; i++) {
- token = tokens[i];
- parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
- if (parsedInput) {
- skipped = string.substr(0, string.indexOf(parsedInput));
- if (skipped.length > 0) {
- config._pf.unusedInput.push(skipped);
- }
- string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
- totalParsedInputLength += parsedInput.length;
- }
- // don't parse if it's not a known token
- if (formatTokenFunctions[token]) {
- if (parsedInput) {
- config._pf.empty = false;
- }
- else {
- config._pf.unusedTokens.push(token);
- }
- addTimeToArrayFromToken(token, parsedInput, config);
- }
- else if (config._strict && !parsedInput) {
- config._pf.unusedTokens.push(token);
- }
- }
-
- // add remaining unparsed input length to the string
- config._pf.charsLeftOver = stringLength - totalParsedInputLength;
- if (string.length > 0) {
- config._pf.unusedInput.push(string);
- }
-
- // clear _12h flag if hour is <= 12
- if (config._pf.bigHour === true && config._a[HOUR] <= 12) {
- config._pf.bigHour = undefined;
- }
- // handle meridiem
- config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR],
- config._meridiem);
- dateFromConfig(config);
- checkOverflow(config);
- }
-
- function unescapeFormat(s) {
- return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
- return p1 || p2 || p3 || p4;
- });
- }
-
- // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
- function regexpEscape(s) {
- return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
- }
-
- // date from string and array of format strings
- function makeDateFromStringAndArray(config) {
- var tempConfig,
- bestMoment,
-
- scoreToBeat,
- i,
- currentScore;
-
- if (config._f.length === 0) {
- config._pf.invalidFormat = true;
- config._d = new Date(NaN);
- return;
- }
-
- for (i = 0; i < config._f.length; i++) {
- currentScore = 0;
- tempConfig = copyConfig({}, config);
- if (config._useUTC != null) {
- tempConfig._useUTC = config._useUTC;
- }
- tempConfig._pf = defaultParsingFlags();
- tempConfig._f = config._f[i];
- makeDateFromStringAndFormat(tempConfig);
-
- if (!isValid(tempConfig)) {
- continue;
- }
-
- // if there is any input that was not parsed add a penalty for that format
- currentScore += tempConfig._pf.charsLeftOver;
-
- //or tokens
- currentScore += tempConfig._pf.unusedTokens.length * 10;
-
- tempConfig._pf.score = currentScore;
-
- if (scoreToBeat == null || currentScore < scoreToBeat) {
- scoreToBeat = currentScore;
- bestMoment = tempConfig;
- }
- }
-
- extend(config, bestMoment || tempConfig);
- }
-
- // date from iso format
- function parseISO(config) {
- var i, l,
- string = config._i,
- match = isoRegex.exec(string);
-
- if (match) {
- config._pf.iso = true;
- for (i = 0, l = isoDates.length; i < l; i++) {
- if (isoDates[i][1].exec(string)) {
- // match[5] should be 'T' or undefined
- config._f = isoDates[i][0] + (match[6] || ' ');
- break;
- }
- }
- for (i = 0, l = isoTimes.length; i < l; i++) {
- if (isoTimes[i][1].exec(string)) {
- config._f += isoTimes[i][0];
- break;
- }
- }
- if (string.match(parseTokenTimezone)) {
- config._f += 'Z';
- }
- makeDateFromStringAndFormat(config);
- } else {
- config._isValid = false;
- }
- }
-
- // date from iso format or fallback
- function makeDateFromString(config) {
- parseISO(config);
- if (config._isValid === false) {
- delete config._isValid;
- moment.createFromInputFallback(config);
- }
- }
-
- function map(arr, fn) {
- var res = [], i;
- for (i = 0; i < arr.length; ++i) {
- res.push(fn(arr[i], i));
- }
- return res;
- }
-
- function makeDateFromInput(config) {
- var input = config._i, matched;
- if (input === undefined) {
- config._d = new Date();
- } else if (isDate(input)) {
- config._d = new Date(+input);
- } else if ((matched = aspNetJsonRegex.exec(input)) !== null) {
- config._d = new Date(+matched[1]);
- } else if (typeof input === 'string') {
- makeDateFromString(config);
- } else if (isArray(input)) {
- config._a = map(input.slice(0), function (obj) {
- return parseInt(obj, 10);
- });
- dateFromConfig(config);
- } else if (typeof(input) === 'object') {
- dateFromObject(config);
- } else if (typeof(input) === 'number') {
- // from milliseconds
- config._d = new Date(input);
- } else {
- moment.createFromInputFallback(config);
- }
- }
-
- function makeDate(y, m, d, h, M, s, ms) {
- //can't just apply() to create a date:
- //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
- var date = new Date(y, m, d, h, M, s, ms);
-
- //the date constructor doesn't accept years < 1970
- if (y < 1970) {
- date.setFullYear(y);
- }
- return date;
- }
-
- function makeUTCDate(y) {
- var date = new Date(Date.UTC.apply(null, arguments));
- if (y < 1970) {
- date.setUTCFullYear(y);
- }
- return date;
- }
-
- function parseWeekday(input, locale) {
- if (typeof input === 'string') {
- if (!isNaN(input)) {
- input = parseInt(input, 10);
- }
- else {
- input = locale.weekdaysParse(input);
- if (typeof input !== 'number') {
- return null;
- }
- }
- }
- return input;
- }
-
- /************************************
- Relative Time
- ************************************/
-
-
- // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
- function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
- return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
- }
-
- function relativeTime(posNegDuration, withoutSuffix, locale) {
- var duration = moment.duration(posNegDuration).abs(),
- seconds = round(duration.as('s')),
- minutes = round(duration.as('m')),
- hours = round(duration.as('h')),
- days = round(duration.as('d')),
- months = round(duration.as('M')),
- years = round(duration.as('y')),
-
- args = seconds < relativeTimeThresholds.s && ['s', seconds] ||
- minutes === 1 && ['m'] ||
- minutes < relativeTimeThresholds.m && ['mm', minutes] ||
- hours === 1 && ['h'] ||
- hours < relativeTimeThresholds.h && ['hh', hours] ||
- days === 1 && ['d'] ||
- days < relativeTimeThresholds.d && ['dd', days] ||
- months === 1 && ['M'] ||
- months < relativeTimeThresholds.M && ['MM', months] ||
- years === 1 && ['y'] || ['yy', years];
-
- args[2] = withoutSuffix;
- args[3] = +posNegDuration > 0;
- args[4] = locale;
- return substituteTimeAgo.apply({}, args);
- }
-
-
- /************************************
- Week of Year
- ************************************/
-
-
- // firstDayOfWeek 0 = sun, 6 = sat
- // the day of the week that starts the week
- // (usually sunday or monday)
- // firstDayOfWeekOfYear 0 = sun, 6 = sat
- // the first week is the week that contains the first
- // of this day of the week
- // (eg. ISO weeks use thursday (4))
- function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
- var end = firstDayOfWeekOfYear - firstDayOfWeek,
- daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
- adjustedMoment;
-
-
- if (daysToDayOfWeek > end) {
- daysToDayOfWeek -= 7;
- }
-
- if (daysToDayOfWeek < end - 7) {
- daysToDayOfWeek += 7;
- }
-
- adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd');
- return {
- week: Math.ceil(adjustedMoment.dayOfYear() / 7),
- year: adjustedMoment.year()
- };
- }
-
- //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
- function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
- var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
-
- d = d === 0 ? 7 : d;
- weekday = weekday != null ? weekday : firstDayOfWeek;
- daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
- dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
-
- return {
- year: dayOfYear > 0 ? year : year - 1,
- dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
- };
- }
-
- /************************************
- Top Level Functions
- ************************************/
-
- function makeMoment(config) {
- var input = config._i,
- format = config._f,
- res;
-
- config._locale = config._locale || moment.localeData(config._l);
-
- if (input === null || (format === undefined && input === '')) {
- return moment.invalid({nullInput: true});
- }
-
- if (typeof input === 'string') {
- config._i = input = config._locale.preparse(input);
- }
-
- if (moment.isMoment(input)) {
- return new Moment(input, true);
- } else if (format) {
- if (isArray(format)) {
- makeDateFromStringAndArray(config);
- } else {
- makeDateFromStringAndFormat(config);
- }
- } else {
- makeDateFromInput(config);
- }
-
- res = new Moment(config);
- if (res._nextDay) {
- // Adding is smart enough around DST
- res.add(1, 'd');
- res._nextDay = undefined;
- }
-
- return res;
- }
-
- moment = function (input, format, locale, strict) {
- var c;
-
- if (typeof(locale) === 'boolean') {
- strict = locale;
- locale = undefined;
- }
- // object construction must be done this way.
- // https://github.com/moment/moment/issues/1423
- c = {};
- c._isAMomentObject = true;
- c._i = input;
- c._f = format;
- c._l = locale;
- c._strict = strict;
- c._isUTC = false;
- c._pf = defaultParsingFlags();
-
- return makeMoment(c);
- };
-
- moment.suppressDeprecationWarnings = false;
-
- moment.createFromInputFallback = deprecate(
- 'moment construction falls back to js Date. This is ' +
- 'discouraged and will be removed in upcoming major ' +
- 'release. Please refer to ' +
- 'https://github.com/moment/moment/issues/1407 for more info.',
- function (config) {
- config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
- }
- );
-
- // Pick a moment m from moments so that m[fn](other) is true for all
- // other. This relies on the function fn to be transitive.
- //
- // moments should either be an array of moment objects or an array, whose
- // first element is an array of moment objects.
- function pickBy(fn, moments) {
- var res, i;
- if (moments.length === 1 && isArray(moments[0])) {
- moments = moments[0];
- }
- if (!moments.length) {
- return moment();
- }
- res = moments[0];
- for (i = 1; i < moments.length; ++i) {
- if (moments[i][fn](res)) {
- res = moments[i];
- }
- }
- return res;
- }
-
- moment.min = function () {
- var args = [].slice.call(arguments, 0);
-
- return pickBy('isBefore', args);
- };
-
- moment.max = function () {
- var args = [].slice.call(arguments, 0);
-
- return pickBy('isAfter', args);
- };
-
- // creating with utc
- moment.utc = function (input, format, locale, strict) {
- var c;
-
- if (typeof(locale) === 'boolean') {
- strict = locale;
- locale = undefined;
- }
- // object construction must be done this way.
- // https://github.com/moment/moment/issues/1423
- c = {};
- c._isAMomentObject = true;
- c._useUTC = true;
- c._isUTC = true;
- c._l = locale;
- c._i = input;
- c._f = format;
- c._strict = strict;
- c._pf = defaultParsingFlags();
-
- return makeMoment(c).utc();
- };
-
- // creating with unix timestamp (in seconds)
- moment.unix = function (input) {
- return moment(input * 1000);
- };
-
- // duration
- moment.duration = function (input, key) {
- var duration = input,
- // matching against regexp is expensive, do it on demand
- match = null,
- sign,
- ret,
- parseIso,
- diffRes;
-
- if (moment.isDuration(input)) {
- duration = {
- ms: input._milliseconds,
- d: input._days,
- M: input._months
- };
- } else if (typeof input === 'number') {
- duration = {};
- if (key) {
- duration[key] = input;
- } else {
- duration.milliseconds = input;
- }
- } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
- sign = (match[1] === '-') ? -1 : 1;
- duration = {
- y: 0,
- d: toInt(match[DATE]) * sign,
- h: toInt(match[HOUR]) * sign,
- m: toInt(match[MINUTE]) * sign,
- s: toInt(match[SECOND]) * sign,
- ms: toInt(match[MILLISECOND]) * sign
- };
- } else if (!!(match = isoDurationRegex.exec(input))) {
- sign = (match[1] === '-') ? -1 : 1;
- parseIso = function (inp) {
- // We'd normally use ~~inp for this, but unfortunately it also
- // converts floats to ints.
- // inp may be undefined, so careful calling replace on it.
- var res = inp && parseFloat(inp.replace(',', '.'));
- // apply sign while we're at it
- return (isNaN(res) ? 0 : res) * sign;
- };
- duration = {
- y: parseIso(match[2]),
- M: parseIso(match[3]),
- d: parseIso(match[4]),
- h: parseIso(match[5]),
- m: parseIso(match[6]),
- s: parseIso(match[7]),
- w: parseIso(match[8])
- };
- } else if (duration == null) {// checks for null or undefined
- duration = {};
- } else if (typeof duration === 'object' &&
- ('from' in duration || 'to' in duration)) {
- diffRes = momentsDifference(moment(duration.from), moment(duration.to));
-
- duration = {};
- duration.ms = diffRes.milliseconds;
- duration.M = diffRes.months;
- }
-
- ret = new Duration(duration);
-
- if (moment.isDuration(input) && hasOwnProp(input, '_locale')) {
- ret._locale = input._locale;
- }
-
- return ret;
- };
-
- // version number
- moment.version = VERSION;
-
- // default format
- moment.defaultFormat = isoFormat;
-
- // constant that refers to the ISO standard
- moment.ISO_8601 = function () {};
-
- // Plugins that add properties should also add the key here (null value),
- // so we can properly clone ourselves.
- moment.momentProperties = momentProperties;
-
- // This function will be called whenever a moment is mutated.
- // It is intended to keep the offset in sync with the timezone.
- moment.updateOffset = function () {};
-
- // This function allows you to set a threshold for relative time strings
- moment.relativeTimeThreshold = function (threshold, limit) {
- if (relativeTimeThresholds[threshold] === undefined) {
- return false;
- }
- if (limit === undefined) {
- return relativeTimeThresholds[threshold];
- }
- relativeTimeThresholds[threshold] = limit;
- return true;
- };
-
- moment.lang = deprecate(
- 'moment.lang is deprecated. Use moment.locale instead.',
- function (key, value) {
- return moment.locale(key, value);
- }
- );
-
- // This function will load locale and then set the global locale. If
- // no arguments are passed in, it will simply return the current global
- // locale key.
- moment.locale = function (key, values) {
- var data;
- if (key) {
- if (typeof(values) !== 'undefined') {
- data = moment.defineLocale(key, values);
- }
- else {
- data = moment.localeData(key);
- }
-
- if (data) {
- moment.duration._locale = moment._locale = data;
- }
- }
-
- return moment._locale._abbr;
- };
-
- moment.defineLocale = function (name, values) {
- if (values !== null) {
- values.abbr = name;
- if (!locales[name]) {
- locales[name] = new Locale();
- }
- locales[name].set(values);
-
- // backwards compat for now: also set the locale
- moment.locale(name);
-
- return locales[name];
- } else {
- // useful for testing
- delete locales[name];
- return null;
- }
- };
-
- moment.langData = deprecate(
- 'moment.langData is deprecated. Use moment.localeData instead.',
- function (key) {
- return moment.localeData(key);
- }
- );
-
- // returns locale data
- moment.localeData = function (key) {
- var locale;
-
- if (key && key._locale && key._locale._abbr) {
- key = key._locale._abbr;
- }
-
- if (!key) {
- return moment._locale;
- }
-
- if (!isArray(key)) {
- //short-circuit everything else
- locale = loadLocale(key);
- if (locale) {
- return locale;
- }
- key = [key];
- }
-
- return chooseLocale(key);
- };
-
- // compare moment object
- moment.isMoment = function (obj) {
- return obj instanceof Moment ||
- (obj != null && hasOwnProp(obj, '_isAMomentObject'));
- };
-
- // for typechecking Duration objects
- moment.isDuration = function (obj) {
- return obj instanceof Duration;
- };
-
- for (i = lists.length - 1; i >= 0; --i) {
- makeList(lists[i]);
- }
-
- moment.normalizeUnits = function (units) {
- return normalizeUnits(units);
- };
-
- moment.invalid = function (flags) {
- var m = moment.utc(NaN);
- if (flags != null) {
- extend(m._pf, flags);
- }
- else {
- m._pf.userInvalidated = true;
- }
-
- return m;
- };
-
- moment.parseZone = function () {
- return moment.apply(null, arguments).parseZone();
- };
-
- moment.parseTwoDigitYear = function (input) {
- return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
- };
-
- moment.isDate = isDate;
-
- /************************************
- Moment Prototype
- ************************************/
-
-
- extend(moment.fn = Moment.prototype, {
-
- clone : function () {
- return moment(this);
- },
-
- valueOf : function () {
- return +this._d - ((this._offset || 0) * 60000);
- },
-
- unix : function () {
- return Math.floor(+this / 1000);
- },
-
- toString : function () {
- return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
- },
-
- toDate : function () {
- return this._offset ? new Date(+this) : this._d;
- },
-
- toISOString : function () {
- var m = moment(this).utc();
- if (0 < m.year() && m.year() <= 9999) {
- if ('function' === typeof Date.prototype.toISOString) {
- // native implementation is ~50x faster, use it when we can
- return this.toDate().toISOString();
- } else {
- return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
- }
- } else {
- return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
- }
- },
-
- toArray : function () {
- var m = this;
- return [
- m.year(),
- m.month(),
- m.date(),
- m.hours(),
- m.minutes(),
- m.seconds(),
- m.milliseconds()
- ];
- },
-
- isValid : function () {
- return isValid(this);
- },
-
- isDSTShifted : function () {
- if (this._a) {
- return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
- }
-
- return false;
- },
-
- parsingFlags : function () {
- return extend({}, this._pf);
- },
-
- invalidAt: function () {
- return this._pf.overflow;
- },
-
- utc : function (keepLocalTime) {
- return this.utcOffset(0, keepLocalTime);
- },
-
- local : function (keepLocalTime) {
- if (this._isUTC) {
- this.utcOffset(0, keepLocalTime);
- this._isUTC = false;
-
- if (keepLocalTime) {
- this.subtract(this._dateUtcOffset(), 'm');
- }
- }
- return this;
- },
-
- format : function (inputString) {
- var output = formatMoment(this, inputString || moment.defaultFormat);
- return this.localeData().postformat(output);
- },
-
- add : createAdder(1, 'add'),
-
- subtract : createAdder(-1, 'subtract'),
-
- diff : function (input, units, asFloat) {
- var that = makeAs(input, this),
- zoneDiff = (that.utcOffset() - this.utcOffset()) * 6e4,
- anchor, diff, output, daysAdjust;
-
- units = normalizeUnits(units);
-
- if (units === 'year' || units === 'month' || units === 'quarter') {
- output = monthDiff(this, that);
- if (units === 'quarter') {
- output = output / 3;
- } else if (units === 'year') {
- output = output / 12;
- }
- } else {
- diff = this - that;
- output = units === 'second' ? diff / 1e3 : // 1000
- units === 'minute' ? diff / 6e4 : // 1000 * 60
- units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
- units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
- units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
- diff;
- }
- return asFloat ? output : absRound(output);
- },
-
- from : function (time, withoutSuffix) {
- return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
- },
-
- fromNow : function (withoutSuffix) {
- return this.from(moment(), withoutSuffix);
- },
-
- calendar : function (time) {
- // We want to compare the start of today, vs this.
- // Getting start-of-today depends on whether we're locat/utc/offset
- // or not.
- var now = time || moment(),
- sod = makeAs(now, this).startOf('day'),
- diff = this.diff(sod, 'days', true),
- format = diff < -6 ? 'sameElse' :
- diff < -1 ? 'lastWeek' :
- diff < 0 ? 'lastDay' :
- diff < 1 ? 'sameDay' :
- diff < 2 ? 'nextDay' :
- diff < 7 ? 'nextWeek' : 'sameElse';
- return this.format(this.localeData().calendar(format, this, moment(now)));
- },
-
- isLeapYear : function () {
- return isLeapYear(this.year());
- },
-
- isDST : function () {
- return (this.utcOffset() > this.clone().month(0).utcOffset() ||
- this.utcOffset() > this.clone().month(5).utcOffset());
- },
-
- day : function (input) {
- var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
- if (input != null) {
- input = parseWeekday(input, this.localeData());
- return this.add(input - day, 'd');
- } else {
- return day;
- }
- },
-
- month : makeAccessor('Month', true),
-
- startOf : function (units) {
- units = normalizeUnits(units);
- // the following switch intentionally omits break keywords
- // to utilize falling through the cases.
- switch (units) {
- case 'year':
- this.month(0);
- /* falls through */
- case 'quarter':
- case 'month':
- this.date(1);
- /* falls through */
- case 'week':
- case 'isoWeek':
- case 'day':
- this.hours(0);
- /* falls through */
- case 'hour':
- this.minutes(0);
- /* falls through */
- case 'minute':
- this.seconds(0);
- /* falls through */
- case 'second':
- this.milliseconds(0);
- /* falls through */
- }
-
- // weeks are a special case
- if (units === 'week') {
- this.weekday(0);
- } else if (units === 'isoWeek') {
- this.isoWeekday(1);
- }
-
- // quarters are also special
- if (units === 'quarter') {
- this.month(Math.floor(this.month() / 3) * 3);
- }
-
- return this;
- },
-
- endOf: function (units) {
- units = normalizeUnits(units);
- if (units === undefined || units === 'millisecond') {
- return this;
- }
- return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
- },
-
- isAfter: function (input, units) {
- var inputMs;
- units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
- if (units === 'millisecond') {
- input = moment.isMoment(input) ? input : moment(input);
- return +this > +input;
- } else {
- inputMs = moment.isMoment(input) ? +input : +moment(input);
- return inputMs < +this.clone().startOf(units);
- }
- },
-
- isBefore: function (input, units) {
- var inputMs;
- units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
- if (units === 'millisecond') {
- input = moment.isMoment(input) ? input : moment(input);
- return +this < +input;
- } else {
- inputMs = moment.isMoment(input) ? +input : +moment(input);
- return +this.clone().endOf(units) < inputMs;
- }
- },
-
- isBetween: function (from, to, units) {
- return this.isAfter(from, units) && this.isBefore(to, units);
- },
-
- isSame: function (input, units) {
- var inputMs;
- units = normalizeUnits(units || 'millisecond');
- if (units === 'millisecond') {
- input = moment.isMoment(input) ? input : moment(input);
- return +this === +input;
- } else {
- inputMs = +moment(input);
- return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));
- }
- },
-
- min: deprecate(
- 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
- function (other) {
- other = moment.apply(null, arguments);
- return other < this ? this : other;
- }
- ),
-
- max: deprecate(
- 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
- function (other) {
- other = moment.apply(null, arguments);
- return other > this ? this : other;
- }
- ),
-
- zone : deprecate(
- 'moment().zone is deprecated, use moment().utcOffset instead. ' +
- 'https://github.com/moment/moment/issues/1779',
- function (input, keepLocalTime) {
- if (input != null) {
- if (typeof input !== 'string') {
- input = -input;
- }
-
- this.utcOffset(input, keepLocalTime);
-
- return this;
- } else {
- return -this.utcOffset();
- }
- }
- ),
-
- // keepLocalTime = true means only change the timezone, without
- // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
- // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
- // +0200, so we adjust the time as needed, to be valid.
- //
- // Keeping the time actually adds/subtracts (one hour)
- // from the actual represented time. That is why we call updateOffset
- // a second time. In case it wants us to change the offset again
- // _changeInProgress == true case, then we have to adjust, because
- // there is no such time in the given timezone.
- utcOffset : function (input, keepLocalTime) {
- var offset = this._offset || 0,
- localAdjust;
- if (input != null) {
- if (typeof input === 'string') {
- input = utcOffsetFromString(input);
- }
- if (Math.abs(input) < 16) {
- input = input * 60;
- }
- if (!this._isUTC && keepLocalTime) {
- localAdjust = this._dateUtcOffset();
- }
- this._offset = input;
- this._isUTC = true;
- if (localAdjust != null) {
- this.add(localAdjust, 'm');
- }
- if (offset !== input) {
- if (!keepLocalTime || this._changeInProgress) {
- addOrSubtractDurationFromMoment(this,
- moment.duration(input - offset, 'm'), 1, false);
- } else if (!this._changeInProgress) {
- this._changeInProgress = true;
- moment.updateOffset(this, true);
- this._changeInProgress = null;
- }
- }
-
- return this;
- } else {
- return this._isUTC ? offset : this._dateUtcOffset();
- }
- },
-
- isLocal : function () {
- return !this._isUTC;
- },
-
- isUtcOffset : function () {
- return this._isUTC;
- },
-
- isUtc : function () {
- return this._isUTC && this._offset === 0;
- },
-
- zoneAbbr : function () {
- return this._isUTC ? 'UTC' : '';
- },
-
- zoneName : function () {
- return this._isUTC ? 'Coordinated Universal Time' : '';
- },
-
- parseZone : function () {
- if (this._tzm) {
- this.utcOffset(this._tzm);
- } else if (typeof this._i === 'string') {
- this.utcOffset(utcOffsetFromString(this._i));
- }
- return this;
- },
-
- hasAlignedHourOffset : function (input) {
- if (!input) {
- input = 0;
- }
- else {
- input = moment(input).utcOffset();
- }
-
- return (this.utcOffset() - input) % 60 === 0;
- },
-
- daysInMonth : function () {
- return daysInMonth(this.year(), this.month());
- },
-
- dayOfYear : function (input) {
- var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
- return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
- },
-
- quarter : function (input) {
- return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
- },
-
- weekYear : function (input) {
- var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year;
- return input == null ? year : this.add((input - year), 'y');
- },
-
- isoWeekYear : function (input) {
- var year = weekOfYear(this, 1, 4).year;
- return input == null ? year : this.add((input - year), 'y');
- },
-
- week : function (input) {
- var week = this.localeData().week(this);
- return input == null ? week : this.add((input - week) * 7, 'd');
- },
-
- isoWeek : function (input) {
- var week = weekOfYear(this, 1, 4).week;
- return input == null ? week : this.add((input - week) * 7, 'd');
- },
-
- weekday : function (input) {
- var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
- return input == null ? weekday : this.add(input - weekday, 'd');
- },
-
- isoWeekday : function (input) {
- // behaves the same as moment#day except
- // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
- // as a setter, sunday should belong to the previous week.
- return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
- },
-
- isoWeeksInYear : function () {
- return weeksInYear(this.year(), 1, 4);
- },
-
- weeksInYear : function () {
- var weekInfo = this.localeData()._week;
- return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
- },
-
- get : function (units) {
- units = normalizeUnits(units);
- return this[units]();
- },
-
- set : function (units, value) {
- var unit;
- if (typeof units === 'object') {
- for (unit in units) {
- this.set(unit, units[unit]);
- }
- }
- else {
- units = normalizeUnits(units);
- if (typeof this[units] === 'function') {
- this[units](value);
- }
- }
- return this;
- },
-
- // If passed a locale key, it will set the locale for this
- // instance. Otherwise, it will return the locale configuration
- // variables for this instance.
- locale : function (key) {
- var newLocaleData;
-
- if (key === undefined) {
- return this._locale._abbr;
- } else {
- newLocaleData = moment.localeData(key);
- if (newLocaleData != null) {
- this._locale = newLocaleData;
- }
- return this;
- }
- },
-
- lang : deprecate(
- 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
- function (key) {
- if (key === undefined) {
- return this.localeData();
- } else {
- return this.locale(key);
- }
- }
- ),
-
- localeData : function () {
- return this._locale;
- },
-
- _dateUtcOffset : function () {
- // On Firefox.24 Date#getTimezoneOffset returns a floating point.
- // https://github.com/moment/moment/pull/1871
- return -Math.round(this._d.getTimezoneOffset() / 15) * 15;
- }
-
- });
-
- function rawMonthSetter(mom, value) {
- var dayOfMonth;
-
- // TODO: Move this out of here!
- if (typeof value === 'string') {
- value = mom.localeData().monthsParse(value);
- // TODO: Another silent failure?
- if (typeof value !== 'number') {
- return mom;
- }
- }
-
- dayOfMonth = Math.min(mom.date(),
- daysInMonth(mom.year(), value));
- mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
- return mom;
- }
-
- function rawGetter(mom, unit) {
- return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]();
- }
-
- function rawSetter(mom, unit, value) {
- if (unit === 'Month') {
- return rawMonthSetter(mom, value);
- } else {
- return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
- }
- }
-
- function makeAccessor(unit, keepTime) {
- return function (value) {
- if (value != null) {
- rawSetter(this, unit, value);
- moment.updateOffset(this, keepTime);
- return this;
- } else {
- return rawGetter(this, unit);
- }
- };
- }
-
- moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false);
- moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false);
- moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false);
- // Setting the hour should keep the time, because the user explicitly
- // specified which hour he wants. So trying to maintain the same hour (in
- // a new timezone) makes sense. Adding/subtracting hours does not follow
- // this rule.
- moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true);
- // moment.fn.month is defined separately
- moment.fn.date = makeAccessor('Date', true);
- moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true));
- moment.fn.year = makeAccessor('FullYear', true);
- moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true));
-
- // add plural methods
- moment.fn.days = moment.fn.day;
- moment.fn.months = moment.fn.month;
- moment.fn.weeks = moment.fn.week;
- moment.fn.isoWeeks = moment.fn.isoWeek;
- moment.fn.quarters = moment.fn.quarter;
-
- // add aliased format methods
- moment.fn.toJSON = moment.fn.toISOString;
-
- // alias isUtc for dev-friendliness
- moment.fn.isUTC = moment.fn.isUtc;
-
- /************************************
- Duration Prototype
- ************************************/
-
-
- function daysToYears (days) {
- // 400 years have 146097 days (taking into account leap year rules)
- return days * 400 / 146097;
- }
-
- function yearsToDays (years) {
- // years * 365 + absRound(years / 4) -
- // absRound(years / 100) + absRound(years / 400);
- return years * 146097 / 400;
- }
-
- extend(moment.duration.fn = Duration.prototype, {
-
- _bubble : function () {
- var milliseconds = this._milliseconds,
- days = this._days,
- months = this._months,
- data = this._data,
- seconds, minutes, hours, years = 0;
-
- // The following code bubbles up values, see the tests for
- // examples of what that means.
- data.milliseconds = milliseconds % 1000;
-
- seconds = absRound(milliseconds / 1000);
- data.seconds = seconds % 60;
-
- minutes = absRound(seconds / 60);
- data.minutes = minutes % 60;
-
- hours = absRound(minutes / 60);
- data.hours = hours % 24;
-
- days += absRound(hours / 24);
-
- // Accurately convert days to years, assume start from year 0.
- years = absRound(daysToYears(days));
- days -= absRound(yearsToDays(years));
-
- // 30 days to a month
- // TODO (iskren): Use anchor date (like 1st Jan) to compute this.
- months += absRound(days / 30);
- days %= 30;
-
- // 12 months -> 1 year
- years += absRound(months / 12);
- months %= 12;
-
- data.days = days;
- data.months = months;
- data.years = years;
- },
-
- abs : function () {
- this._milliseconds = Math.abs(this._milliseconds);
- this._days = Math.abs(this._days);
- this._months = Math.abs(this._months);
-
- this._data.milliseconds = Math.abs(this._data.milliseconds);
- this._data.seconds = Math.abs(this._data.seconds);
- this._data.minutes = Math.abs(this._data.minutes);
- this._data.hours = Math.abs(this._data.hours);
- this._data.months = Math.abs(this._data.months);
- this._data.years = Math.abs(this._data.years);
-
- return this;
- },
-
- weeks : function () {
- return absRound(this.days() / 7);
- },
-
- valueOf : function () {
- return this._milliseconds +
- this._days * 864e5 +
- (this._months % 12) * 2592e6 +
- toInt(this._months / 12) * 31536e6;
- },
-
- humanize : function (withSuffix) {
- var output = relativeTime(this, !withSuffix, this.localeData());
-
- if (withSuffix) {
- output = this.localeData().pastFuture(+this, output);
- }
-
- return this.localeData().postformat(output);
- },
-
- add : function (input, val) {
- // supports only 2.0-style add(1, 's') or add(moment)
- var dur = moment.duration(input, val);
-
- this._milliseconds += dur._milliseconds;
- this._days += dur._days;
- this._months += dur._months;
-
- this._bubble();
-
- return this;
- },
-
- subtract : function (input, val) {
- var dur = moment.duration(input, val);
-
- this._milliseconds -= dur._milliseconds;
- this._days -= dur._days;
- this._months -= dur._months;
-
- this._bubble();
-
- return this;
- },
-
- get : function (units) {
- units = normalizeUnits(units);
- return this[units.toLowerCase() + 's']();
- },
-
- as : function (units) {
- var days, months;
- units = normalizeUnits(units);
-
- if (units === 'month' || units === 'year') {
- days = this._days + this._milliseconds / 864e5;
- months = this._months + daysToYears(days) * 12;
- return units === 'month' ? months : months / 12;
- } else {
- // handle milliseconds separately because of floating point math errors (issue #1867)
- days = this._days + Math.round(yearsToDays(this._months / 12));
- switch (units) {
- case 'week': return days / 7 + this._milliseconds / 6048e5;
- case 'day': return days + this._milliseconds / 864e5;
- case 'hour': return days * 24 + this._milliseconds / 36e5;
- case 'minute': return days * 24 * 60 + this._milliseconds / 6e4;
- case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000;
- // Math.floor prevents floating point math errors here
- case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds;
- default: throw new Error('Unknown unit ' + units);
- }
- }
- },
-
- lang : moment.fn.lang,
- locale : moment.fn.locale,
-
- toIsoString : deprecate(
- 'toIsoString() is deprecated. Please use toISOString() instead ' +
- '(notice the capitals)',
- function () {
- return this.toISOString();
- }
- ),
-
- toISOString : function () {
- // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
- var years = Math.abs(this.years()),
- months = Math.abs(this.months()),
- days = Math.abs(this.days()),
- hours = Math.abs(this.hours()),
- minutes = Math.abs(this.minutes()),
- seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
-
- if (!this.asSeconds()) {
- // this is the same as C#'s (Noda) and python (isodate)...
- // but not other JS (goog.date)
- return 'P0D';
- }
-
- return (this.asSeconds() < 0 ? '-' : '') +
- 'P' +
- (years ? years + 'Y' : '') +
- (months ? months + 'M' : '') +
- (days ? days + 'D' : '') +
- ((hours || minutes || seconds) ? 'T' : '') +
- (hours ? hours + 'H' : '') +
- (minutes ? minutes + 'M' : '') +
- (seconds ? seconds + 'S' : '');
- },
-
- localeData : function () {
- return this._locale;
- },
-
- toJSON : function () {
- return this.toISOString();
- }
- });
-
- moment.duration.fn.toString = moment.duration.fn.toISOString;
-
- function makeDurationGetter(name) {
- moment.duration.fn[name] = function () {
- return this._data[name];
- };
- }
-
- for (i in unitMillisecondFactors) {
- if (hasOwnProp(unitMillisecondFactors, i)) {
- makeDurationGetter(i.toLowerCase());
- }
- }
-
- moment.duration.fn.asMilliseconds = function () {
- return this.as('ms');
- };
- moment.duration.fn.asSeconds = function () {
- return this.as('s');
- };
- moment.duration.fn.asMinutes = function () {
- return this.as('m');
- };
- moment.duration.fn.asHours = function () {
- return this.as('h');
- };
- moment.duration.fn.asDays = function () {
- return this.as('d');
- };
- moment.duration.fn.asWeeks = function () {
- return this.as('weeks');
- };
- moment.duration.fn.asMonths = function () {
- return this.as('M');
- };
- moment.duration.fn.asYears = function () {
- return this.as('y');
- };
-
- /************************************
- Default Locale
- ************************************/
-
-
- // Set default locale, other locale will inherit from English.
- moment.locale('en', {
- ordinalParse: /\d{1,2}(th|st|nd|rd)/,
- ordinal : function (number) {
- var b = number % 10,
- output = (toInt(number % 100 / 10) === 1) ? 'th' :
- (b === 1) ? 'st' :
- (b === 2) ? 'nd' :
- (b === 3) ? 'rd' : 'th';
- return number + output;
- }
- });
-
- /* EMBED_LOCALES */
-
- /************************************
- Exposing Moment
- ************************************/
-
- function makeGlobal(shouldDeprecate) {
- /*global ender:false */
- if (typeof ender !== 'undefined') {
- return;
- }
- oldGlobalMoment = globalScope.moment;
- if (shouldDeprecate) {
- globalScope.moment = deprecate(
- 'Accessing Moment through the global scope is ' +
- 'deprecated, and will be removed in an upcoming ' +
- 'release.',
- moment);
- } else {
- globalScope.moment = moment;
- }
- }
-
- // CommonJS module is defined
- if (hasModule) {
- module.exports = moment;
- } else if (typeof define === 'function' && define.amd) {
- define(function (require, exports, module) {
- if (module.config && module.config() && module.config().noGlobal === true) {
- // release the global variable
- globalScope.moment = oldGlobalMoment;
- }
-
- return moment;
- });
- makeGlobal(true);
- } else {
- makeGlobal();
- }
-}).call(this);
-
-}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
-},{}],5:[function(require,module,exports){
-/**
- * A mixin for handling (effectively) onClickOutside for React components.
- * Note that we're not intercepting any events in this approach, and we're
- * not using double events for capturing and discarding in layers or wrappers.
- *
- * The idea is that components define function
- *
- * onClickOutside: function() { ... }
- *
- * If no such function is defined, an error will be thrown, as this means
- * either it still needs to be written, or the component should not be using
- * this mixing since it will not exhibit onClickOutside behaviour.
- *
- */
-(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define([], factory);
- } else if (typeof exports === 'object') {
- // Node. Note that this does not work with strict
- // CommonJS, but only CommonJS-like environments
- // that support module.exports
- module.exports = factory();
- } else {
- // Browser globals (root is window)
- root.OnClickOutside = factory();
- }
-}(this, function () {
- "use strict";
-
- // Use a parallel array because we can't use
- // objects as keys, they get toString-coerced
- var registeredComponents = [];
- var handlers = [];
-
- return {
- componentDidMount: function() {
- if(!this.handleClickOutside)
- throw new Error("Component lacks a handleClickOutside(event) function for processing outside click events.");
-
- var fn = (function(localNode, eventHandler) {
- return function(evt) {
- var source = evt.target;
- var found = false;
- // If source=local then this event came from "somewhere"
- // inside and should be ignored. We could handle this with
- // a layered approach, too, but that requires going back to
- // thinking in terms of Dom node nesting, running counter
- // to React's "you shouldn't care about the DOM" philosophy.
- while(source.parentNode) {
- found = (source === localNode);
- if(found) return;
- source = source.parentNode;
- }
- eventHandler(evt);
- }
- }(this.getDOMNode(), this.handleClickOutside));
-
- document.addEventListener("mousedown", fn);
- document.addEventListener("touchstart", fn);
-
- var pos = registeredComponents.length;
- registeredComponents.push(this);
- handlers[pos] = fn;
- },
-
- componentWillUnmount: function() {
- var pos = registeredComponents.indexOf(this);
- if( pos>-1) {
- var fn = handlers[pos];
- if (fn) {
- document.removeEventListener("mousedown", fn);
- document.removeEventListener("touchstart", fn);
- }
- }
- }
- };
-
-}));
-
-},{}],6:[function(require,module,exports){
-module.exports = require('./lib/ReactWithAddons');
-
-},{"./lib/ReactWithAddons":97}],7:[function(require,module,exports){
-/**
- * Copyright 2013-2014, 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 AutoFocusMixin
- * @typechecks static-only
- */
-
-"use strict";
-
-var focusNode = require("./focusNode");
-
-var AutoFocusMixin = {
- componentDidMount: function() {
- if (this.props.autoFocus) {
- focusNode(this.getDOMNode());
- }
- }
-};
-
-module.exports = AutoFocusMixin;
-
-},{"./focusNode":131}],8:[function(require,module,exports){
-/**
- * Copyright 2013 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 BeforeInputEventPlugin
- * @typechecks static-only
- */
-
-"use strict";
-
-var EventConstants = require("./EventConstants");
-var EventPropagators = require("./EventPropagators");
-var ExecutionEnvironment = require("./ExecutionEnvironment");
-var SyntheticInputEvent = require("./SyntheticInputEvent");
-
-var keyOf = require("./keyOf");
-
-var canUseTextInputEvent = (
- ExecutionEnvironment.canUseDOM &&
- 'TextEvent' in window &&
- !('documentMode' in document || isPresto())
-);
-
-/**
- * Opera <= 12 includes TextEvent in window, but does not fire
- * text input events. Rely on keypress instead.
- */
-function isPresto() {
- var opera = window.opera;
- return (
- typeof opera === 'object' &&
- typeof opera.version === 'function' &&
- parseInt(opera.version(), 10) <= 12
- );
-}
-
-var SPACEBAR_CODE = 32;
-var SPACEBAR_CHAR = String.fromCharCode(SPACEBAR_CODE);
-
-var topLevelTypes = EventConstants.topLevelTypes;
-
-// Events and their corresponding property names.
-var eventTypes = {
- beforeInput: {
- phasedRegistrationNames: {
- bubbled: keyOf({onBeforeInput: null}),
- captured: keyOf({onBeforeInputCapture: null})
- },
- dependencies: [
- topLevelTypes.topCompositionEnd,
- topLevelTypes.topKeyPress,
- topLevelTypes.topTextInput,
- topLevelTypes.topPaste
- ]
- }
-};
-
-// Track characters inserted via keypress and composition events.
-var fallbackChars = null;
-
-// Track whether we've ever handled a keypress on the space key.
-var hasSpaceKeypress = false;
-
-/**
- * Return whether a native keypress event is assumed to be a command.
- * This is required because Firefox fires `keypress` events for key commands
- * (cut, copy, select-all, etc.) even though no character is inserted.
- */
-function isKeypressCommand(nativeEvent) {
- return (
- (nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) &&
- // ctrlKey && altKey is equivalent to AltGr, and is not a command.
- !(nativeEvent.ctrlKey && nativeEvent.altKey)
- );
-}
-
-/**
- * Create an `onBeforeInput` event to match
- * http://www.w3.org/TR/2013/WD-DOM-Level-3-Events-20131105/#events-inputevents.
- *
- * This event plugin is based on the native `textInput` event
- * available in Chrome, Safari, Opera, and IE. This event fires after
- * `onKeyPress` and `onCompositionEnd`, but before `onInput`.
- *
- * `beforeInput` is spec'd but not implemented in any browsers, and
- * the `input` event does not provide any useful information about what has
- * actually been added, contrary to the spec. Thus, `textInput` is the best
- * available event to identify the characters that have actually been inserted
- * into the target node.
- */
-var BeforeInputEventPlugin = {
-
- eventTypes: eventTypes,
-
- /**
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {DOMEventTarget} topLevelTarget The listening component root node.
- * @param {string} topLevelTargetID ID of `topLevelTarget`.
- * @param {object} nativeEvent Native browser event.
- * @return {*} An accumulation of synthetic events.
- * @see {EventPluginHub.extractEvents}
- */
- extractEvents: function(
- topLevelType,
- topLevelTarget,
- topLevelTargetID,
- nativeEvent) {
-
- var chars;
-
- if (canUseTextInputEvent) {
- switch (topLevelType) {
- case topLevelTypes.topKeyPress:
- /**
- * If native `textInput` events are available, our goal is to make
- * use of them. However, there is a special case: the spacebar key.
- * In Webkit, preventing default on a spacebar `textInput` event
- * cancels character insertion, but it *also* causes the browser
- * to fall back to its default spacebar behavior of scrolling the
- * page.
- *
- * Tracking at:
- * https://code.google.com/p/chromium/issues/detail?id=355103
- *
- * To avoid this issue, use the keypress event as if no `textInput`
- * event is available.
- */
- var which = nativeEvent.which;
- if (which !== SPACEBAR_CODE) {
- return;
- }
-
- hasSpaceKeypress = true;
- chars = SPACEBAR_CHAR;
- break;
-
- case topLevelTypes.topTextInput:
- // Record the characters to be added to the DOM.
- chars = nativeEvent.data;
-
- // If it's a spacebar character, assume that we have already handled
- // it at the keypress level and bail immediately. Android Chrome
- // doesn't give us keycodes, so we need to blacklist it.
- if (chars === SPACEBAR_CHAR && hasSpaceKeypress) {
- return;
- }
-
- // Otherwise, carry on.
- break;
-
- default:
- // For other native event types, do nothing.
- return;
- }
- } else {
- switch (topLevelType) {
- case topLevelTypes.topPaste:
- // If a paste event occurs after a keypress, throw out the input
- // chars. Paste events should not lead to BeforeInput events.
- fallbackChars = null;
- break;
- case topLevelTypes.topKeyPress:
- /**
- * As of v27, Firefox may fire keypress events even when no character
- * will be inserted. A few possibilities:
- *
- * - `which` is `0`. Arrow keys, Esc key, etc.
- *
- * - `which` is the pressed key code, but no char is available.
- * Ex: 'AltGr + d` in Polish. There is no modified character for
- * this key combination and no character is inserted into the
- * document, but FF fires the keypress for char code `100` anyway.
- * No `input` event will occur.
- *
- * - `which` is the pressed key code, but a command combination is
- * being used. Ex: `Cmd+C`. No character is inserted, and no
- * `input` event will occur.
- */
- if (nativeEvent.which && !isKeypressCommand(nativeEvent)) {
- fallbackChars = String.fromCharCode(nativeEvent.which);
- }
- break;
- case topLevelTypes.topCompositionEnd:
- fallbackChars = nativeEvent.data;
- break;
- }
-
- // If no changes have occurred to the fallback string, no relevant
- // event has fired and we're done.
- if (fallbackChars === null) {
- return;
- }
-
- chars = fallbackChars;
- }
-
- // If no characters are being inserted, no BeforeInput event should
- // be fired.
- if (!chars) {
- return;
- }
-
- var event = SyntheticInputEvent.getPooled(
- eventTypes.beforeInput,
- topLevelTargetID,
- nativeEvent
- );
-
- event.data = chars;
- fallbackChars = null;
- EventPropagators.accumulateTwoPhaseDispatches(event);
- return event;
- }
-};
-
-module.exports = BeforeInputEventPlugin;
-
-},{"./EventConstants":22,"./EventPropagators":27,"./ExecutionEnvironment":28,"./SyntheticInputEvent":107,"./keyOf":153}],9:[function(require,module,exports){
-(function (process){
-/**
- * Copyright 2013-2014, 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 CSSCore
- * @typechecks
- */
-
-var invariant = require("./invariant");
-
-/**
- * The CSSCore module specifies the API (and implements most of the methods)
- * that should be used when dealing with the display of elements (via their
- * CSS classes and visibility on screen. It is an API focused on mutating the
- * display and not reading it as no logical state should be encoded in the
- * display of elements.
- */
-
-var CSSCore = {
-
- /**
- * Adds the class passed in to the element if it doesn't already have it.
- *
- * @param {DOMElement} element the element to set the class on
- * @param {string} className the CSS className
- * @return {DOMElement} the element passed in
- */
- addClass: function(element, className) {
- ("production" !== process.env.NODE_ENV ? invariant(
- !/\s/.test(className),
- 'CSSCore.addClass takes only a single class name. "%s" contains ' +
- 'multiple classes.', className
- ) : invariant(!/\s/.test(className)));
-
- if (className) {
- if (element.classList) {
- element.classList.add(className);
- } else if (!CSSCore.hasClass(element, className)) {
- element.className = element.className + ' ' + className;
- }
- }
- return element;
- },
-
- /**
- * Removes the class passed in from the element
- *
- * @param {DOMElement} element the element to set the class on
- * @param {string} className the CSS className
- * @return {DOMElement} the element passed in
- */
- removeClass: function(element, className) {
- ("production" !== process.env.NODE_ENV ? invariant(
- !/\s/.test(className),
- 'CSSCore.removeClass takes only a single class name. "%s" contains ' +
- 'multiple classes.', className
- ) : invariant(!/\s/.test(className)));
-
- if (className) {
- if (element.classList) {
- element.classList.remove(className);
- } else if (CSSCore.hasClass(element, className)) {
- element.className = element.className
- .replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), '$1')
- .replace(/\s+/g, ' ') // multiple spaces to one
- .replace(/^\s*|\s*$/g, ''); // trim the ends
- }
- }
- return element;
- },
-
- /**
- * Helper to add or remove a class from an element based on a condition.
- *
- * @param {DOMElement} element the element to set the class on
- * @param {string} className the CSS className
- * @param {*} bool condition to whether to add or remove the class
- * @return {DOMElement} the element passed in
- */
- conditionClass: function(element, className, bool) {
- return (bool ? CSSCore.addClass : CSSCore.removeClass)(element, className);
- },
-
- /**
- * Tests whether the element has the class specified.
- *
- * @param {DOMNode|DOMWindow} element the element to set the class on
- * @param {string} className the CSS className
- * @return {boolean} true if the element has the class, false if not
- */
- hasClass: function(element, className) {
- ("production" !== process.env.NODE_ENV ? invariant(
- !/\s/.test(className),
- 'CSS.hasClass takes only a single class name.'
- ) : invariant(!/\s/.test(className)));
- if (element.classList) {
- return !!className && element.classList.contains(className);
- }
- return (' ' + element.className + ' ').indexOf(' ' + className + ' ') > -1;
- }
-
-};
-
-module.exports = CSSCore;
-
-}).call(this,require('_process'))
-},{"./invariant":146,"_process":3}],10:[function(require,module,exports){
-/**
- * Copyright 2013-2014, 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 CSSProperty
- */
-
-"use strict";
-
-/**
- * CSS properties which accept numbers but are not in units of "px".
- */
-var isUnitlessNumber = {
- columnCount: true,
- flex: true,
- flexGrow: true,
- flexShrink: true,
- fontWeight: true,
- lineClamp: true,
- lineHeight: true,
- opacity: true,
- order: true,
- orphans: true,
- widows: true,
- zIndex: true,
- zoom: true,
-
- // SVG-related properties
- fillOpacity: true,
- strokeOpacity: true
-};
-
-/**
- * @param {string} prefix vendor-specific prefix, eg: Webkit
- * @param {string} key style name, eg: transitionDuration
- * @return {string} style name prefixed with `prefix`, properly camelCased, eg:
- * WebkitTransitionDuration
- */
-function prefixKey(prefix, key) {
- return prefix + key.charAt(0).toUpperCase() + key.substring(1);
-}
-
-/**
- * Support style names that may come passed in prefixed by adding permutations
- * of vendor prefixes.
- */
-var prefixes = ['Webkit', 'ms', 'Moz', 'O'];
-
-// Using Object.keys here, or else the vanilla for-in loop makes IE8 go into an
-// infinite loop, because it iterates over the newly added props too.
-Object.keys(isUnitlessNumber).forEach(function(prop) {
- prefixes.forEach(function(prefix) {
- isUnitlessNumber[prefixKey(prefix, prop)] = isUnitlessNumber[prop];
- });
-});
-
-/**
- * Most style properties can be unset by doing .style[prop] = '' but IE8
- * doesn't like doing that with shorthand properties so for the properties that
- * IE8 breaks on, which are listed here, we instead unset each of the
- * individual properties. See http://bugs.jquery.com/ticket/12385.
- * The 4-value 'clock' properties like margin, padding, border-width seem to
- * behave without any problems. Curiously, list-style works too without any
- * special prodding.
- */
-var shorthandPropertyExpansions = {
- background: {
- backgroundImage: true,
- backgroundPosition: true,
- backgroundRepeat: true,
- backgroundColor: true
- },
- border: {
- borderWidth: true,
- borderStyle: true,
- borderColor: true
- },
- borderBottom: {
- borderBottomWidth: true,
- borderBottomStyle: true,
- borderBottomColor: true
- },
- borderLeft: {
- borderLeftWidth: true,
- borderLeftStyle: true,
- borderLeftColor: true
- },
- borderRight: {
- borderRightWidth: true,
- borderRightStyle: true,
- borderRightColor: true
- },
- borderTop: {
- borderTopWidth: true,
- borderTopStyle: true,
- borderTopColor: true
- },
- font: {
- fontStyle: true,
- fontVariant: true,
- fontWeight: true,
- fontSize: true,
- lineHeight: true,
- fontFamily: true
- }
-};
-
-var CSSProperty = {
- isUnitlessNumber: isUnitlessNumber,
- shorthandPropertyExpansions: shorthandPropertyExpansions
-};
-
-module.exports = CSSProperty;
-
-},{}],11:[function(require,module,exports){
-(function (process){
-/**
- * Copyright 2013-2014, 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 CSSPropertyOperations
- * @typechecks static-only
- */
-
-"use strict";
-
-var CSSProperty = require("./CSSProperty");
-var ExecutionEnvironment = require("./ExecutionEnvironment");
-
-var camelizeStyleName = require("./camelizeStyleName");
-var dangerousStyleValue = require("./dangerousStyleValue");
-var hyphenateStyleName = require("./hyphenateStyleName");
-var memoizeStringOnly = require("./memoizeStringOnly");
-var warning = require("./warning");
-
-var processStyleName = memoizeStringOnly(function(styleName) {
- return hyphenateStyleName(styleName);
-});
-
-var styleFloatAccessor = 'cssFloat';
-if (ExecutionEnvironment.canUseDOM) {
- // IE8 only supports accessing cssFloat (standard) as styleFloat
- if (document.documentElement.style.cssFloat === undefined) {
- styleFloatAccessor = 'styleFloat';
- }
-}
-
-if ("production" !== process.env.NODE_ENV) {
- var warnedStyleNames = {};
-
- var warnHyphenatedStyleName = function(name) {
- if (warnedStyleNames.hasOwnProperty(name) && warnedStyleNames[name]) {
- return;
- }
-
- warnedStyleNames[name] = true;
- ("production" !== process.env.NODE_ENV ? warning(
- false,
- 'Unsupported style property ' + name + '. Did you mean ' +
- camelizeStyleName(name) + '?'
- ) : null);
- };
-}
-
-/**
- * Operations for dealing with CSS properties.
- */
-var CSSPropertyOperations = {
-
- /**
- * Serializes a mapping of style properties for use as inline styles:
- *
- * > createMarkupForStyles({width: '200px', height: 0})
- * "width:200px;height:0;"
- *
- * Undefined values are ignored so that declarative programming is easier.
- * The result should be HTML-escaped before insertion into the DOM.
- *
- * @param {object} styles
- * @return {?string}
- */
- createMarkupForStyles: function(styles) {
- var serialized = '';
- for (var styleName in styles) {
- if (!styles.hasOwnProperty(styleName)) {
- continue;
- }
- if ("production" !== process.env.NODE_ENV) {
- if (styleName.indexOf('-') > -1) {
- warnHyphenatedStyleName(styleName);
- }
- }
- var styleValue = styles[styleName];
- if (styleValue != null) {
- serialized += processStyleName(styleName) + ':';
- serialized += dangerousStyleValue(styleName, styleValue) + ';';
- }
- }
- return serialized || null;
- },
-
- /**
- * Sets the value for multiple styles on a node. If a value is specified as
- * '' (empty string), the corresponding style property will be unset.
- *
- * @param {DOMElement} node
- * @param {object} styles
- */
- setValueForStyles: function(node, styles) {
- var style = node.style;
- for (var styleName in styles) {
- if (!styles.hasOwnProperty(styleName)) {
- continue;
- }
- if ("production" !== process.env.NODE_ENV) {
- if (styleName.indexOf('-') > -1) {
- warnHyphenatedStyleName(styleName);
- }
- }
- var styleValue = dangerousStyleValue(styleName, styles[styleName]);
- if (styleName === 'float') {
- styleName = styleFloatAccessor;
- }
- if (styleValue) {
- style[styleName] = styleValue;
- } else {
- var expansion = CSSProperty.shorthandPropertyExpansions[styleName];
- if (expansion) {
- // Shorthand property that IE8 won't like unsetting, so unset each
- // component to placate it
- for (var individualStyleName in expansion) {
- style[individualStyleName] = '';
- }
- } else {
- style[styleName] = '';
- }
- }
- }
- }
-
-};
-
-module.exports = CSSPropertyOperations;
-
-}).call(this,require('_process'))
-},{"./CSSProperty":10,"./ExecutionEnvironment":28,"./camelizeStyleName":118,"./dangerousStyleValue":125,"./hyphenateStyleName":144,"./memoizeStringOnly":155,"./warning":166,"_process":3}],12:[function(require,module,exports){
-(function (process){
-/**
- * Copyright 2013-2014, 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 CallbackQueue
- */
-
-"use strict";
-
-var PooledClass = require("./PooledClass");
-
-var assign = require("./Object.assign");
-var invariant = require("./invariant");
-
-/**
- * A specialized pseudo-event module to help keep track of components waiting to
- * be notified when their DOM representations are available for use.
- *
- * This implements `PooledClass`, so you should never need to instantiate this.
- * Instead, use `CallbackQueue.getPooled()`.
- *
- * @class ReactMountReady
- * @implements PooledClass
- * @internal
- */
-function CallbackQueue() {
- this._callbacks = null;
- this._contexts = null;
-}
-
-assign(CallbackQueue.prototype, {
-
- /**
- * Enqueues a callback to be invoked when `notifyAll` is invoked.
- *
- * @param {function} callback Invoked when `notifyAll` is invoked.
- * @param {?object} context Context to call `callback` with.
- * @internal
- */
- enqueue: function(callback, context) {
- this._callbacks = this._callbacks || [];
- this._contexts = this._contexts || [];
- this._callbacks.push(callback);
- this._contexts.push(context);
- },
-
- /**
- * Invokes all enqueued callbacks and clears the queue. This is invoked after
- * the DOM representation of a component has been created or updated.
- *
- * @internal
- */
- notifyAll: function() {
- var callbacks = this._callbacks;
- var contexts = this._contexts;
- if (callbacks) {
- ("production" !== process.env.NODE_ENV ? invariant(
- callbacks.length === contexts.length,
- "Mismatched list of contexts in callback queue"
- ) : invariant(callbacks.length === contexts.length));
- this._callbacks = null;
- this._contexts = null;
- for (var i = 0, l = callbacks.length; i < l; i++) {
- callbacks[i].call(contexts[i]);
- }
- callbacks.length = 0;
- contexts.length = 0;
- }
- },
-
- /**
- * Resets the internal queue.
- *
- * @internal
- */
- reset: function() {
- this._callbacks = null;
- this._contexts = null;
- },
-
- /**
- * `PooledClass` looks for this.
- */
- destructor: function() {
- this.reset();
- }
-
-});
-
-PooledClass.addPoolingTo(CallbackQueue);
-
-module.exports = CallbackQueue;
-
-}).call(this,require('_process'))
-},{"./Object.assign":34,"./PooledClass":35,"./invariant":146,"_process":3}],13:[function(require,module,exports){
-/**
- * Copyright 2013-2014, 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 ChangeEventPlugin
- */
-
-"use strict";
-
-var EventConstants = require("./EventConstants");
-var EventPluginHub = require("./EventPluginHub");
-var EventPropagators = require("./EventPropagators");
-var ExecutionEnvironment = require("./ExecutionEnvironment");
-var ReactUpdates = require("./ReactUpdates");
-var SyntheticEvent = require("./SyntheticEvent");
-
-var isEventSupported = require("./isEventSupported");
-var isTextInputElement = require("./isTextInputElement");
-var keyOf = require("./keyOf");
-
-var topLevelTypes = EventConstants.topLevelTypes;
-
-var eventTypes = {
- change: {
- phasedRegistrationNames: {
- bubbled: keyOf({onChange: null}),
- captured: keyOf({onChangeCapture: null})
- },
- dependencies: [
- topLevelTypes.topBlur,
- topLevelTypes.topChange,
- topLevelTypes.topClick,
- topLevelTypes.topFocus,
- topLevelTypes.topInput,
- topLevelTypes.topKeyDown,
- topLevelTypes.topKeyUp,
- topLevelTypes.topSelectionChange
- ]
- }
-};
-
-/**
- * For IE shims
- */
-var activeElement = null;
-var activeElementID = null;
-var activeElementValue = null;
-var activeElementValueProp = null;
-
-/**
- * SECTION: handle `change` event
- */
-function shouldUseChangeEvent(elem) {
- return (
- elem.nodeName === 'SELECT' ||
- (elem.nodeName === 'INPUT' && elem.type === 'file')
- );
-}
-
-var doesChangeEventBubble = false;
-if (ExecutionEnvironment.canUseDOM) {
- // See `handleChange` comment below
- doesChangeEventBubble = isEventSupported('change') && (
- !('documentMode' in document) || document.documentMode > 8
- );
-}
-
-function manualDispatchChangeEvent(nativeEvent) {
- var event = SyntheticEvent.getPooled(
- eventTypes.change,
- activeElementID,
- nativeEvent
- );
- EventPropagators.accumulateTwoPhaseDispatches(event);
-
- // If change and propertychange bubbled, we'd just bind to it like all the
- // other events and have it go through ReactBrowserEventEmitter. Since it
- // doesn't, we manually listen for the events and so we have to enqueue and
- // process the abstract event manually.
- //
- // Batching is necessary here in order to ensure that all event handlers run
- // before the next rerender (including event handlers attached to ancestor
- // elements instead of directly on the input). Without this, controlled
- // components don't work properly in conjunction with event bubbling because
- // the component is rerendered and the value reverted before all the event
- // handlers can run. See https://github.com/facebook/react/issues/708.
- ReactUpdates.batchedUpdates(runEventInBatch, event);
-}
-
-function runEventInBatch(event) {
- EventPluginHub.enqueueEvents(event);
- EventPluginHub.processEventQueue();
-}
-
-function startWatchingForChangeEventIE8(target, targetID) {
- activeElement = target;
- activeElementID = targetID;
- activeElement.attachEvent('onchange', manualDispatchChangeEvent);
-}
-
-function stopWatchingForChangeEventIE8() {
- if (!activeElement) {
- return;
- }
- activeElement.detachEvent('onchange', manualDispatchChangeEvent);
- activeElement = null;
- activeElementID = null;
-}
-
-function getTargetIDForChangeEvent(
- topLevelType,
- topLevelTarget,
- topLevelTargetID) {
- if (topLevelType === topLevelTypes.topChange) {
- return topLevelTargetID;
- }
-}
-function handleEventsForChangeEventIE8(
- topLevelType,
- topLevelTarget,
- topLevelTargetID) {
- if (topLevelType === topLevelTypes.topFocus) {
- // stopWatching() should be a noop here but we call it just in case we
- // missed a blur event somehow.
- stopWatchingForChangeEventIE8();
- startWatchingForChangeEventIE8(topLevelTarget, topLevelTargetID);
- } else if (topLevelType === topLevelTypes.topBlur) {
- stopWatchingForChangeEventIE8();
- }
-}
-
-
-/**
- * SECTION: handle `input` event
- */
-var isInputEventSupported = false;
-if (ExecutionEnvironment.canUseDOM) {
- // IE9 claims to support the input event but fails to trigger it when
- // deleting text, so we ignore its input events
- isInputEventSupported = isEventSupported('input') && (
- !('documentMode' in document) || document.documentMode > 9
- );
-}
-
-/**
- * (For old IE.) Replacement getter/setter for the `value` property that gets
- * set on the active element.
- */
-var newValueProp = {
- get: function() {
- return activeElementValueProp.get.call(this);
- },
- set: function(val) {
- // Cast to a string so we can do equality checks.
- activeElementValue = '' + val;
- activeElementValueProp.set.call(this, val);
- }
-};
-
-/**
- * (For old IE.) Starts tracking propertychange events on the passed-in element
- * and override the value property so that we can distinguish user events from
- * value changes in JS.
- */
-function startWatchingForValueChange(target, targetID) {
- activeElement = target;
- activeElementID = targetID;
- activeElementValue = target.value;
- activeElementValueProp = Object.getOwnPropertyDescriptor(
- target.constructor.prototype,
- 'value'
- );
-
- Object.defineProperty(activeElement, 'value', newValueProp);
- activeElement.attachEvent('onpropertychange', handlePropertyChange);
-}
-
-/**
- * (For old IE.) Removes the event listeners from the currently-tracked element,
- * if any exists.
- */
-function stopWatchingForValueChange() {
- if (!activeElement) {
- return;
- }
-
- // delete restores the original property definition
- delete activeElement.value;
- activeElement.detachEvent('onpropertychange', handlePropertyChange);
-
- activeElement = null;
- activeElementID = null;
- activeElementValue = null;
- activeElementValueProp = null;
-}
-
-/**
- * (For old IE.) Handles a propertychange event, sending a `change` event if
- * the value of the active element has changed.
- */
-function handlePropertyChange(nativeEvent) {
- if (nativeEvent.propertyName !== 'value') {
- return;
- }
- var value = nativeEvent.srcElement.value;
- if (value === activeElementValue) {
- return;
- }
- activeElementValue = value;
-
- manualDispatchChangeEvent(nativeEvent);
-}
-
-/**
- * If a `change` event should be fired, returns the target's ID.
- */
-function getTargetIDForInputEvent(
- topLevelType,
- topLevelTarget,
- topLevelTargetID) {
- if (topLevelType === topLevelTypes.topInput) {
- // In modern browsers (i.e., not IE8 or IE9), the input event is exactly
- // what we want so fall through here and trigger an abstract event
- return topLevelTargetID;
- }
-}
-
-// For IE8 and IE9.
-function handleEventsForInputEventIE(
- topLevelType,
- topLevelTarget,
- topLevelTargetID) {
- if (topLevelType === topLevelTypes.topFocus) {
- // In IE8, we can capture almost all .value changes by adding a
- // propertychange handler and looking for events with propertyName
- // equal to 'value'
- // In IE9, propertychange fires for most input events but is buggy and
- // doesn't fire when text is deleted, but conveniently, selectionchange
- // appears to fire in all of the remaining cases so we catch those and
- // forward the event if the value has changed
- // In either case, we don't want to call the event handler if the value
- // is changed from JS so we redefine a setter for `.value` that updates
- // our activeElementValue variable, allowing us to ignore those changes
- //
- // stopWatching() should be a noop here but we call it just in case we
- // missed a blur event somehow.
- stopWatchingForValueChange();
- startWatchingForValueChange(topLevelTarget, topLevelTargetID);
- } else if (topLevelType === topLevelTypes.topBlur) {
- stopWatchingForValueChange();
- }
-}
-
-// For IE8 and IE9.
-function getTargetIDForInputEventIE(
- topLevelType,
- topLevelTarget,
- topLevelTargetID) {
- if (topLevelType === topLevelTypes.topSelectionChange ||
- topLevelType === topLevelTypes.topKeyUp ||
- topLevelType === topLevelTypes.topKeyDown) {
- // On the selectionchange event, the target is just document which isn't
- // helpful for us so just check activeElement instead.
- //
- // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire
- // propertychange on the first input event after setting `value` from a
- // script and fires only keydown, keypress, keyup. Catching keyup usually
- // gets it and catching keydown lets us fire an event for the first
- // keystroke if user does a key repeat (it'll be a little delayed: right
- // before the second keystroke). Other input methods (e.g., paste) seem to
- // fire selectionchange normally.
- if (activeElement && activeElement.value !== activeElementValue) {
- activeElementValue = activeElement.value;
- return activeElementID;
- }
- }
-}
-
-
-/**
- * SECTION: handle `click` event
- */
-function shouldUseClickEvent(elem) {
- // Use the `click` event to detect changes to checkbox and radio inputs.
- // This approach works across all browsers, whereas `change` does not fire
- // until `blur` in IE8.
- return (
- elem.nodeName === 'INPUT' &&
- (elem.type === 'checkbox' || elem.type === 'radio')
- );
-}
-
-function getTargetIDForClickEvent(
- topLevelType,
- topLevelTarget,
- topLevelTargetID) {
- if (topLevelType === topLevelTypes.topClick) {
- return topLevelTargetID;
- }
-}
-
-/**
- * This plugin creates an `onChange` event that normalizes change events
- * across form elements. This event fires at a time when it's possible to
- * change the element's value without seeing a flicker.
- *
- * Supported elements are:
- * - input (see `isTextInputElement`)
- * - textarea
- * - select
- */
-var ChangeEventPlugin = {
-
- eventTypes: eventTypes,
-
- /**
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {DOMEventTarget} topLevelTarget The listening component root node.
- * @param {string} topLevelTargetID ID of `topLevelTarget`.
- * @param {object} nativeEvent Native browser event.
- * @return {*} An accumulation of synthetic events.
- * @see {EventPluginHub.extractEvents}
- */
- extractEvents: function(
- topLevelType,
- topLevelTarget,
- topLevelTargetID,
- nativeEvent) {
-
- var getTargetIDFunc, handleEventFunc;
- if (shouldUseChangeEvent(topLevelTarget)) {
- if (doesChangeEventBubble) {
- getTargetIDFunc = getTargetIDForChangeEvent;
- } else {
- handleEventFunc = handleEventsForChangeEventIE8;
- }
- } else if (isTextInputElement(topLevelTarget)) {
- if (isInputEventSupported) {
- getTargetIDFunc = getTargetIDForInputEvent;
- } else {
- getTargetIDFunc = getTargetIDForInputEventIE;
- handleEventFunc = handleEventsForInputEventIE;
- }
- } else if (shouldUseClickEvent(topLevelTarget)) {
- getTargetIDFunc = getTargetIDForClickEvent;
- }
-
- if (getTargetIDFunc) {
- var targetID = getTargetIDFunc(
- topLevelType,
- topLevelTarget,
- topLevelTargetID
- );
- if (targetID) {
- var event = SyntheticEvent.getPooled(
- eventTypes.change,
- targetID,
- nativeEvent
- );
- EventPropagators.accumulateTwoPhaseDispatches(event);
- return event;
- }
- }
-
- if (handleEventFunc) {
- handleEventFunc(
- topLevelType,
- topLevelTarget,
- topLevelTargetID
- );
- }
- }
-
-};
-
-module.exports = ChangeEventPlugin;
-
-},{"./EventConstants":22,"./EventPluginHub":24,"./EventPropagators":27,"./ExecutionEnvironment":28,"./ReactUpdates":96,"./SyntheticEvent":105,"./isEventSupported":147,"./isTextInputElement":149,"./keyOf":153}],14:[function(require,module,exports){
-/**
- * Copyright 2013-2014, 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 ClientReactRootIndex
- * @typechecks
- */
-
-"use strict";
-
-var nextReactRootIndex = 0;
-
-var ClientReactRootIndex = {
- createReactRootIndex: function() {
- return nextReactRootIndex++;
- }
-};
-
-module.exports = ClientReactRootIndex;
-
-},{}],15:[function(require,module,exports){
-/**
- * Copyright 2013-2014, 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 CompositionEventPlugin
- * @typechecks static-only
- */
-
-"use strict";
-
-var EventConstants = require("./EventConstants");
-var EventPropagators = require("./EventPropagators");
-var ExecutionEnvironment = require("./ExecutionEnvironment");
-var ReactInputSelection = require("./ReactInputSelection");
-var SyntheticCompositionEvent = require("./SyntheticCompositionEvent");
-
-var getTextContentAccessor = require("./getTextContentAccessor");
-var keyOf = require("./keyOf");
-
-var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space
-var START_KEYCODE = 229;
-
-var useCompositionEvent = (
- ExecutionEnvironment.canUseDOM &&
- 'CompositionEvent' in window
-);
-
-// In IE9+, we have access to composition events, but the data supplied
-// by the native compositionend event may be incorrect. In Korean, for example,
-// the compositionend event contains only one character regardless of
-// how many characters have been composed since compositionstart.
-// We therefore use the fallback data while still using the native
-// events as triggers.
-var useFallbackData = (
- !useCompositionEvent ||
- (
- 'documentMode' in document &&
- document.documentMode > 8 &&
- document.documentMode <= 11
- )
-);
-
-var topLevelTypes = EventConstants.topLevelTypes;
-var currentComposition = null;
-
-// Events and their corresponding property names.
-var eventTypes = {
- compositionEnd: {
- phasedRegistrationNames: {
- bubbled: keyOf({onCompositionEnd: null}),
- captured: keyOf({onCompositionEndCapture: null})
- },
- dependencies: [
- topLevelTypes.topBlur,
- topLevelTypes.topCompositionEnd,
- topLevelTypes.topKeyDown,
- topLevelTypes.topKeyPress,
- topLevelTypes.topKeyUp,
- topLevelTypes.topMouseDown
- ]
- },
- compositionStart: {
- phasedRegistrationNames: {
- bubbled: keyOf({onCompositionStart: null}),
- captured: keyOf({onCompositionStartCapture: null})
- },
- dependencies: [
- topLevelTypes.topBlur,
- topLevelTypes.topCompositionStart,
- topLevelTypes.topKeyDown,
- topLevelTypes.topKeyPress,
- topLevelTypes.topKeyUp,
- topLevelTypes.topMouseDown
- ]
- },
- compositionUpdate: {
- phasedRegistrationNames: {
- bubbled: keyOf({onCompositionUpdate: null}),
- captured: keyOf({onCompositionUpdateCapture: null})
- },
- dependencies: [
- topLevelTypes.topBlur,
- topLevelTypes.topCompositionUpdate,
- topLevelTypes.topKeyDown,
- topLevelTypes.topKeyPress,
- topLevelTypes.topKeyUp,
- topLevelTypes.topMouseDown
- ]
- }
-};
-
-/**
- * Translate native top level events into event types.
- *
- * @param {string} topLevelType
- * @return {object}
- */
-function getCompositionEventType(topLevelType) {
- switch (topLevelType) {
- case topLevelTypes.topCompositionStart:
- return eventTypes.compositionStart;
- case topLevelTypes.topCompositionEnd:
- return eventTypes.compositionEnd;
- case topLevelTypes.topCompositionUpdate:
- return eventTypes.compositionUpdate;
- }
-}
-
-/**
- * Does our fallback best-guess model think this event signifies that
- * composition has begun?
- *
- * @param {string} topLevelType
- * @param {object} nativeEvent
- * @return {boolean}
- */
-function isFallbackStart(topLevelType, nativeEvent) {
- return (
- topLevelType === topLevelTypes.topKeyDown &&
- nativeEvent.keyCode === START_KEYCODE
- );
-}
-
-/**
- * Does our fallback mode think that this event is the end of composition?
- *
- * @param {string} topLevelType
- * @param {object} nativeEvent
- * @return {boolean}
- */
-function isFallbackEnd(topLevelType, nativeEvent) {
- switch (topLevelType) {
- case topLevelTypes.topKeyUp:
- // Command keys insert or clear IME input.
- return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1);
- case topLevelTypes.topKeyDown:
- // Expect IME keyCode on each keydown. If we get any other
- // code we must have exited earlier.
- return (nativeEvent.keyCode !== START_KEYCODE);
- case topLevelTypes.topKeyPress:
- case topLevelTypes.topMouseDown:
- case topLevelTypes.topBlur:
- // Events are not possible without cancelling IME.
- return true;
- default:
- return false;
- }
-}
-
-/**
- * Helper class stores information about selection and document state
- * so we can figure out what changed at a later date.
- *
- * @param {DOMEventTarget} root
- */
-function FallbackCompositionState(root) {
- this.root = root;
- this.startSelection = ReactInputSelection.getSelection(root);
- this.startValue = this.getText();
-}
-
-/**
- * Get current text of input.
- *
- * @return {string}
- */
-FallbackCompositionState.prototype.getText = function() {
- return this.root.value || this.root[getTextContentAccessor()];
-};
-
-/**
- * Text that has changed since the start of composition.
- *
- * @return {string}
- */
-FallbackCompositionState.prototype.getData = function() {
- var endValue = this.getText();
- var prefixLength = this.startSelection.start;
- var suffixLength = this.startValue.length - this.startSelection.end;
-
- return endValue.substr(
- prefixLength,
- endValue.length - suffixLength - prefixLength
- );
-};
-
-/**
- * This plugin creates `onCompositionStart`, `onCompositionUpdate` and
- * `onCompositionEnd` events on inputs, textareas and contentEditable
- * nodes.
- */
-var CompositionEventPlugin = {
-
- eventTypes: eventTypes,
-
- /**
- * @param {string} topLevelType Record from `EventConstants`.
- * @param {DOMEventTarget} topLevelTarget The listening component root node.
- * @param {string} topLevelTargetID ID of `topLevelTarget`.
- * @param {object} nativeEvent Native browser event.
- * @return {*} An accumulation of synthetic events.
- * @see {EventPluginHub.extractEvents}
- */
- extractEvents: function(
- topLevelType,
- topLevelTarget,
- topLevelTargetID,
- nativeEvent) {
-
- var eventType;
- var data;
-
- if (useCompositionEvent) {
- eventType = getCompositionEventType(topLevelType);
- } else if (!currentComposition) {
- if (isFallbackStart(topLevelType, nativeEvent)) {
- eventType = eventTypes.compositionStart;
- }
- } else if (isFallbackEnd(topLevelType, nativeEvent)) {
- eventType = eventTypes.compositionEnd;
- }
-
- if (useFallbackData) {
- // The current composition is stored statically and must not be
- // overwritten while composition continues.
- if (!currentComposition && eventType === eventTypes.compositionStart) {
- currentComposition = new FallbackCompositionState(topLevelTarget);
- } else if (eventType === eventTypes.compositionEnd) {
- if (currentComposition) {
- data = currentComposition.getData();
- currentComposition = null;
- }
- }
- }
-
- if (eventType) {
- var event = SyntheticCompositionEvent.getPooled(
- eventType,
- topLevelTargetID,
- nativeEvent
- );
- if (data) {
- // Inject data generated from fallback path into the synthetic event.
- // This matches the property of native CompositionEventInterface.
- event.data = data;
- }
- EventPropagators.accumulateTwoPhaseDispatches(event);
- return event;
- }
- }
-};
-
-module.exports = CompositionEventPlugin;
-
-},{"./EventConstants":22,"./EventPropagators":27,"./ExecutionEnvironment":28,"./ReactInputSelection":70,"./SyntheticCompositionEvent":103,"./getTextContentAccessor":141,"./keyOf":153}],16:[function(require,module,exports){
-(function (process){
-/**
- * Copyright 2013-2014, 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 = require("./Danger");
-var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes");
-
-var getTextContentAccessor = require("./getTextContentAccessor");
-var invariant = require("./invariant");
-
-/**
- * The DOM property to use when setting text content.
- *
- * @type {string}
- * @private
- */
-var textContentAccessor = getTextContentAccessor();
-
-/**
- * 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`.
- parentNode.insertBefore(
- childNode,
- parentNode.childNodes[index] || null
- );
-}
-
-var updateTextContent;
-if (textContentAccessor === 'textContent') {
- /**
- * Sets the text content of `node` to `text`.
- *
- * @param {DOMElement} node Node to change
- * @param {string} text New text content
- */
- updateTextContent = function(node, text) {
- node.textContent = text;
- };
-} else {
- /**
- * Sets the text content of `node` to `text`.
- *
- * @param {DOMElement} node Node to change
- * @param {string} text New text content
- */
- updateTextContent = function(node, text) {
- // In order to preserve newlines correctly, we can't use .innerText to set
- // the contents (see #1080), so we empty the element then append a text node
- while (node.firstChild) {
- node.removeChild(node.firstChild);
- }
- if (text) {
- var doc = node.ownerDocument || document;
- node.appendChild(doc.createTextNode(text));
- }
- };
-}
-
-/**
- * Operations for updating with DOM children.
- */
-var DOMChildrenOperations = {
-
- dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup,
-
- updateTextContent: updateTextContent,
-
- /**
- * Updates a component's children by processing a series of updates. The
- * update configurations are each expected to have a `parentNode` property.
- *
- * @param {array