From c7f506b6e2c36b435859c70f111d5f5645c031ca Mon Sep 17 00:00:00 2001
From: Kevin <kevin.petit@viacesi.fr>
Date: Fri, 15 Feb 2013 13:40:42 +0100
Subject: [PATCH] Update bootstrap datepicker library and add minViewMode to
 options

---
 .../bootstrap-datepicker/css/datepicker.css   | 10 +++
 .../js/bootstrap-datepicker.js                | 79 ++++++++++++++++---
 src/inputs/date/date.js                       |  2 +
 src/inputs/date/datefield.js                  |  1 +
 4 files changed, 79 insertions(+), 13 deletions(-)

diff --git a/src/inputs/date/bootstrap-datepicker/css/datepicker.css b/src/inputs/date/bootstrap-datepicker/css/datepicker.css
index f87f973..dfe9df8 100644
--- a/src/inputs/date/bootstrap-datepicker/css/datepicker.css
+++ b/src/inputs/date/bootstrap-datepicker/css/datepicker.css
@@ -282,6 +282,16 @@
 .datepicker tfoot tr:first-child th:hover {
   background: #eeeeee;
 }
+.datepicker .cw {
+  font-size: 10px;
+  width: 12px;
+  padding: 0 2px 0 5px;
+  vertical-align: middle;
+}
+.datepicker thead tr:first-child th.cw {
+  cursor: default;
+  background-color: transparent;
+}
 .input-append.date .add-on i,
 .input-prepend.date .add-on i {
   display: block;
diff --git a/src/inputs/date/bootstrap-datepicker/js/bootstrap-datepicker.js b/src/inputs/date/bootstrap-datepicker/js/bootstrap-datepicker.js
index 4766bba..3d80a50 100644
--- a/src/inputs/date/bootstrap-datepicker/js/bootstrap-datepicker.js
+++ b/src/inputs/date/bootstrap-datepicker/js/bootstrap-datepicker.js
@@ -35,9 +35,10 @@
 
 		this.element = $(element);
 		this.language = options.language||this.element.data('date-language')||"en";
+		this.language = this.language in dates ? this.language : this.language.split('-')[0]; //Check if "de-DE" style date is available, if not language should fallback to 2 letter code eg "de"
 		this.language = this.language in dates ? this.language : "en";
 		this.isRTL = dates[this.language].rtl||false;
-		this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||'mm/dd/yyyy');
+		this.format = DPGlobal.parseFormat(options.format||this.element.data('date-format')||dates[this.language].format||'mm/dd/yyyy');
 		this.isInline = false;
 		this.isInput = this.element.is('input');
 		this.component = this.element.is('.date') ? this.element.find('.add-on') : false;
@@ -53,7 +54,7 @@
 		} else if ('dateForceParse' in this.element.data()) {
 			this.forceParse = this.element.data('date-force-parse');
 		}
-		 
+
 
 		this.picker = $(DPGlobal.template)
 							.appendTo(this.isInline ? this.element : 'body')
@@ -74,7 +75,7 @@
 		}
 		$(document).on('mousedown', function (e) {
 			// Clicked outside the datepicker, hide it
-			if ($(e.target).closest('.datepicker').length === 0) {
+			if ($(e.target).closest('.datepicker.datepicker-inline, .datepicker.datepicker-dropdown').length === 0) {
 				that.hide();
 			}
 		});
@@ -105,9 +106,38 @@
 				break;
 		}
 
+		this.minViewMode = options.minViewMode||this.element.data('date-min-view-mode')||0;
+		if (typeof this.minViewMode === 'string') {
+			switch (this.minViewMode) {
+				case 'months':
+					this.minViewMode = 1;
+					break;
+				case 'years':
+					this.minViewMode = 2;
+					break;
+				default:
+					this.minViewMode = 0;
+					break;
+			}
+		}
+
+		this.viewMode = this.startViewMode = Math.max(this.startViewMode, this.minViewMode);
+
 		this.todayBtn = (options.todayBtn||this.element.data('date-today-btn')||false);
 		this.todayHighlight = (options.todayHighlight||this.element.data('date-today-highlight')||false);
 
+		this.calendarWeeks = false;
+		if ('calendarWeeks' in options) {
+			this.calendarWeeks = options.calendarWeeks;
+		} else if ('dateCalendarWeeks' in this.element.data()) {
+			this.calendarWeeks = this.element.data('date-calendar-weeks');
+		}
+		if (this.calendarWeeks)
+			this.picker.find('tfoot th.today')
+						.attr('colspan', function(i, val){
+							return parseInt(val) + 1;
+						});
+
 		this.weekStart = ((options.weekStart||this.element.data('date-weekstart')||dates[this.language].weekStart||0) % 7);
 		this.weekEnd = ((this.weekStart + 6) % 7);
 		this.startDate = -Infinity;
@@ -197,6 +227,7 @@
 
 		hide: function(e){
 			if(this.isInline) return;
+			if (!this.picker.is(':visible')) return;
 			this.picker.hide();
 			$(window).off('resize', this.place);
 			this.viewMode = this.startViewMode;
@@ -318,7 +349,6 @@
 
 			if(fromArgs) this.setValue();
 
-			var oldViewDate = this.viewDate;
 			if (this.date < this.startDate) {
 				this.viewDate = new Date(this.startDate);
 			} else if (this.date > this.endDate) {
@@ -326,19 +356,17 @@
 			} else {
 				this.viewDate = new Date(this.date);
 			}
-
-			if (oldViewDate && oldViewDate.getTime() != this.viewDate.getTime()){
-				this.element.trigger({
-					type: 'changeDate',
-					date: this.viewDate
-				});
-			}
 			this.fill();
 		},
 
 		fillDow: function(){
 			var dowCnt = this.weekStart,
 			html = '<tr>';
+			if(this.calendarWeeks){
+				var cell = '<th class="cw">&nbsp;</th>';
+				html += cell;
+				this.picker.find('.datepicker-days thead tr:first-child').prepend(cell);
+			}
 			while (dowCnt < this.weekStart + 7) {
 				html += '<th class="dow">'+dates[this.language].daysMin[(dowCnt++)%7]+'</th>';
 			}
@@ -365,7 +393,7 @@
 				endMonth = this.endDate !== Infinity ? this.endDate.getUTCMonth() : Infinity,
 				currentDate = this.date && this.date.valueOf(),
 				today = new Date();
-			this.picker.find('.datepicker-days thead th:eq(1)')
+			this.picker.find('.datepicker-days thead th.switch')
 						.text(dates[this.language].months[month]+' '+year);
 			this.picker.find('tfoot th.today')
 						.text(dates[this.language].today)
@@ -384,6 +412,21 @@
 			while(prevMonth.valueOf() < nextMonth) {
 				if (prevMonth.getUTCDay() == this.weekStart) {
 					html.push('<tr>');
+					if(this.calendarWeeks){
+						// ISO 8601: First week contains first thursday.
+						// ISO also states week starts on Monday, but we can be more abstract here.
+						var
+							// Start of current week: based on weekstart/current date
+							ws = new Date(+prevMonth + (this.weekStart - prevMonth.getUTCDay() - 7) % 7 * 864e5),
+							// Thursday of this week
+							th = new Date(+ws + (7 + 4 - ws.getUTCDay()) % 7 * 864e5),
+							// First Thursday of year, year from thursday
+							yth = new Date(+(yth = UTCDate(th.getUTCFullYear(), 0, 1)) + (7 + 4 - yth.getUTCDay())%7*864e5),
+							// Calendar week: ms between thursdays, div ms per day, div 7 days
+							calWeek =  (th - yth) / 864e5 / 7 + 1;
+						html.push('<td class="cw">'+ calWeek +'</td>');
+
+					}
 				}
 				clsName = '';
 				if (prevMonth.getUTCFullYear() < year || (prevMonth.getUTCFullYear() == year && prevMonth.getUTCMonth() < month)) {
@@ -519,19 +562,29 @@
 						if (!target.is('.disabled')) {
 							this.viewDate.setUTCDate(1);
 							if (target.is('.month')) {
+								var day = 1;
 								var month = target.parent().find('span').index(target);
+								var year = this.viewDate.getUTCFullYear();
 								this.viewDate.setUTCMonth(month);
 								this.element.trigger({
 									type: 'changeMonth',
 									date: this.viewDate
 								});
+								if ( this.minViewMode == 1 ) {
+									this._setDate(UTCDate(year, month, day,0,0,0,0));
+								}
 							} else {
 								var year = parseInt(target.text(), 10)||0;
+								var day = 1;
+								var month = 0;
 								this.viewDate.setUTCFullYear(year);
 								this.element.trigger({
 									type: 'changeYear',
 									date: this.viewDate
 								});
+								if ( this.minViewMode == 2 ) {
+									this._setDate(UTCDate(year, month, day,0,0,0,0));
+								}
 							}
 							this.showMode(-1);
 							this.fill();
@@ -728,7 +781,7 @@
 
 		showMode: function(dir) {
 			if (dir) {
-				this.viewMode = Math.max(0, Math.min(2, this.viewMode + dir));
+				this.viewMode = Math.max(this.minViewMode, Math.min(2, this.viewMode + dir));
 			}
 			/*
 				vitalets: fixing bug of very special conditions:
diff --git a/src/inputs/date/date.js b/src/inputs/date/date.js
index 1d233ef..c9e2702 100644
--- a/src/inputs/date/date.js
+++ b/src/inputs/date/date.js
@@ -159,12 +159,14 @@ $(function(){
         @default {
             weekStart: 0,
             startView: 0,
+            minViewMode: 0,
             autoclose: false
         }
         **/
         datepicker:{
             weekStart: 0,
             startView: 0,
+            minViewMode: 0,
             autoclose: false
         },
         /**
diff --git a/src/inputs/date/datefield.js b/src/inputs/date/datefield.js
index 0919de4..de9e5f0 100644
--- a/src/inputs/date/datefield.js
+++ b/src/inputs/date/datefield.js
@@ -69,6 +69,7 @@ Automatically shown in inline mode.
         datepicker: {
             weekStart: 0,
             startView: 0,
+            minViewMode: 0,
             autoclose: true
         }
     });