From d40f6d89bf9084e5d03df1aeea8bffd67662f0c0 Mon Sep 17 00:00:00 2001
From: Daan De Deckere <info@daandd.be>
Date: Mon, 12 Feb 2018 20:04:46 +0100
Subject: [PATCH] Add onSubtractTime and onAddTime hooks (#508)

---
 DateTime.d.ts       |   10 +++++
 react-datetime.d.ts |   14 ++++++-
 test/tests.spec.js  |   58 +++++++++++++++++++++++++++++
 DateTime.js         |   33 ++++++++++------
 README.md           |    2 +
 5 files changed, 102 insertions(+), 15 deletions(-)

diff --git a/DateTime.d.ts b/DateTime.d.ts
index ae2a8b9..444b6f0 100644
--- a/DateTime.d.ts
+++ b/DateTime.d.ts
@@ -99,6 +99,16 @@
          */
         onViewModeChange?: (viewMode: string) => void;
         /*
+         Callback trigger when the user navigates to the previous month, year or decade.
+         The callback receives the amount and type ('month', 'year') as parameters.
+         */
+        onNavigateBack?: (amount: number, type: string) => void;
+        /*
+         Callback trigger when the user navigates to the next month, year or decade.
+         The callback receives the amount and type ('month', 'year') as parameters.
+         */
+        onNavigateForward?: (amount: number, type: string) => void;
+        /*
          The default view to display when the picker is shown. ('years', 'months', 'days', 'time')
          */
         viewMode?: ViewMode | number;
diff --git a/DateTime.js b/DateTime.js
index 81b9544..6f8e908 100644
--- a/DateTime.js
+++ b/DateTime.js
@@ -26,6 +26,8 @@
 		onBlur: TYPES.func,
 		onChange: TYPES.func,
 		onViewModeChange: TYPES.func,
+		onNavigateBack: TYPES.func,
+		onNavigateForward: TYPES.func,
 		locale: TYPES.string,
 		utc: TYPES.bool,
 		input: TYPES.bool,
@@ -254,26 +256,29 @@
 		};
 	},
 
-	addTime: function( amount, type, toSelected ) {
-		return this.updateTime( 'add', amount, type, toSelected );
+	subtractTime: function( amount, type, toSelected ) {
+		var me = this;
+		return function() {
+			me.props.onNavigateBack( amount, type );
+			me.updateTime( 'subtract', amount, type, toSelected );
+		};
 	},
 
-	subtractTime: function( amount, type, toSelected ) {
-		return this.updateTime( 'subtract', amount, type, toSelected );
+	addTime: function( amount, type, toSelected ) {
+		var me = this;
+		return function() {
+			me.props.onNavigateForward( amount, type );
+			me.updateTime( 'add', amount, type, toSelected );
+		};
 	},
 
 	updateTime: function( op, amount, type, toSelected ) {
-		var me = this;
+		var update = {},
+			date = toSelected ? 'selectedDate' : 'viewDate';
 
-		return function() {
-			var update = {},
-				date = toSelected ? 'selectedDate' : 'viewDate'
-			;
+		update[ date ] = this.state[ date ].clone()[ op ]( amount, type );
 
-			update[ date ] = me.state[ date ].clone()[ op ]( amount, type );
-
-			me.setState( update );
-		};
+		this.setState( update );
 	},
 
 	allowedSetTime: ['hours', 'minutes', 'seconds', 'milliseconds'],
@@ -459,6 +464,8 @@
 	onBlur: function() {},
 	onChange: function() {},
 	onViewModeChange: function() {},
+	onNavigateBack: function() {},
+	onNavigateForward: function() {},
 	timeFormat: true,
 	timeConstraints: {},
 	dateFormat: true,
diff --git a/README.md b/README.md
index 16b7835..fb97b2e 100644
--- a/README.md
+++ b/README.md
@@ -54,6 +54,8 @@
 | **onFocus** | `function` | empty function | Callback trigger for when the user opens the datepicker. The callback receives an event of type SyntheticEvent. |
 | **onBlur** | `function` | empty function | Callback trigger for when the user clicks outside of the input, simulating a regular onBlur. The callback receives the selected `moment` object as only parameter, if the date in the input is valid. If the date in the input is not valid, the callback returned. |
 | **onViewModeChange** | `function` | empty function | Callback trigger when the view mode changes. The callback receives the selected view mode string (`years`, `months`, `days` or `time`) as only parameter.|
+| **onNavigateBack** | `function` | empty function | Callback trigger when the user navigates to the previous month, year or decade. The callback receives the amount and type ('month', 'year') as parameters. |
+| **onNavigateForward** | `function` | empty function | Callback trigger when the user navigates to the next month, year or decade. The callback receives the amount and type ('month', 'year') as parameters. |
 | **viewMode** | `string` or `number` | `'days'` | The default view to display when the picker is shown (`'years'`, `'months'`, `'days'`, `'time'`). |
 | **className** | `string` or `string array` | `''` | Extra class name for the outermost markup element. |
 | **inputProps** | `object` | `undefined` | Defines additional attributes for the input element of the component. For example: `onClick`, `placeholder`, `disabled`, `required`, `name` and `className` (`className` *sets* the class attribute for the input element). See [Customize the Input Appearance](#customize-the-input-appearance). |
diff --git a/react-datetime.d.ts b/react-datetime.d.ts
index d994914..0d06291 100644
--- a/react-datetime.d.ts
+++ b/react-datetime.d.ts
@@ -80,6 +80,16 @@
     */
     onViewModeChange?: (viewMode: string) => void;
     /*
+      Callback trigger when the user navigates to the previous month, year or decade.
+      The callback receives the amount and type ('month', 'year') as parameters.
+     */
+    onNavigateBack?: (amount: number, type: string) => void;
+    /*
+      Callback trigger when the user navigates to the next month, year or decade.
+      The callback receives the amount and type ('month', 'year') as parameters.
+     */
+    onNavigateForward?: (amount: number, type: string) => void;
+    /*
      The default view to display when the picker is shown. ('years', 'months', 'days', 'time')
      */
     viewMode?: string|number;
@@ -92,8 +102,8 @@
      */
     inputProps?: Object;
     /*
-     Replace the rendering of the input element. The accepted function has openCalendar 
-     (a function which opens the calendar) and the default calculated props for the input. 
+     Replace the rendering of the input element. The accepted function has openCalendar
+     (a function which opens the calendar) and the default calculated props for the input.
      Must return a React component or null.
      */
     renderInput?: (props: Object, openCalendar: Function) => React.Component<any, any>;
diff --git a/test/tests.spec.js b/test/tests.spec.js
index a546cbe..8cf9fbe 100644
--- a/test/tests.spec.js
+++ b/test/tests.spec.js
@@ -1087,6 +1087,64 @@
 
 	});
 
+	describe('onNavigateForward', () => {
+		it('when moving to next month', () => {
+			const component = utils.createDatetime({ onNavigateForward: (amount, type) => {
+				expect(amount).toEqual(1);
+				expect(type).toEqual('months');
+			}});
+
+			utils.clickOnElement(component.find('.rdtNext'));
+		});
+
+		it('when moving to next year', () => {
+			const component = utils.createDatetime({ viewMode: 'months', onNavigateForward: (amount, type) => {
+				expect(amount).toEqual(1);
+				expect(type).toEqual('years');
+			}});
+
+			utils.clickOnElement(component.find('.rdtNext'));
+		});
+
+		it('when moving decade forward', () => {
+			const component = utils.createDatetime({ viewMode: 'years', onNavigateForward: (amount, type) => {
+				expect(amount).toEqual(10);
+				expect(type).toEqual('years');
+			}});
+
+			utils.clickOnElement(component.find('.rdtNext'));
+		});
+	});
+
+	describe('onNavigateBack', () => {
+		it('when moving to previous month', () => {
+			const component = utils.createDatetime({ onNavigateBack: (amount, type) => {
+				expect(amount).toEqual(1);
+				expect(type).toEqual('months');
+			}});
+
+			utils.clickOnElement(component.find('.rdtPrev'));
+		});
+
+		it('when moving to previous year', () => {
+			const component = utils.createDatetime({ viewMode: 'months', onNavigateBack: (amount, type) => {
+				expect(amount).toEqual(1);
+				expect(type).toEqual('years');
+			}});
+
+			utils.clickOnElement(component.find('.rdtPrev'));
+		});
+
+		it('when moving decade back', () => {
+			const component = utils.createDatetime({ viewMode: 'years', onNavigateBack: (amount, type) => {
+				expect(amount).toEqual(10);
+				expect(type).toEqual('years');
+			}});
+
+			utils.clickOnElement(component.find('.rdtPrev'));
+		});
+	});
+
 	describe('with set value', () => {
 		it('date value', () => {
 			const date = new Date(2000, 0, 15, 2, 2, 2, 2),

--
Gitblit v1.9.3