1
+ angular . module ( 'ui.bootstrap.datepicker' , [ ] )
2
+
3
+ . constant ( 'datepickerConfig' , {
4
+ dayFormat : 'dd' ,
5
+ monthFormat : 'MMMM' ,
6
+ yearFormat : 'yyyy' ,
7
+ dayHeaderFormat : 'EEE' ,
8
+ dayTitleFormat : 'MMMM yyyy' ,
9
+ monthTitleFormat : 'yyyy' ,
10
+ showWeeks : true ,
11
+ startingDay : 0 ,
12
+ yearRange : 20
13
+ } )
14
+
15
+ . directive ( 'datepicker' , [ '$filter' , '$parse' , 'datepickerConfig' , function ( $filter , $parse , datepickerConfig ) {
16
+ return {
17
+ restrict : 'EA' ,
18
+ replace : true ,
19
+ scope : {
20
+ model : '=ngModel' ,
21
+ dateDisabled : '&'
22
+ } ,
23
+ templateUrl : 'template/datepicker/datepicker.html' ,
24
+ link : function ( scope , element , attrs ) {
25
+ scope . mode = 'day' ; // Initial mode
26
+
27
+ // Configuration parameters
28
+ var selected = new Date ( ) , showWeeks , minDate , maxDate , format = { } ;
29
+ format . day = angular . isDefined ( attrs . dayFormat ) ? scope . $eval ( attrs . dayFormat ) : datepickerConfig . dayFormat ;
30
+ format . month = angular . isDefined ( attrs . monthFormat ) ? scope . $eval ( attrs . monthFormat ) : datepickerConfig . monthFormat ;
31
+ format . year = angular . isDefined ( attrs . yearFormat ) ? scope . $eval ( attrs . yearFormat ) : datepickerConfig . yearFormat ;
32
+ format . dayHeader = angular . isDefined ( attrs . dayHeaderFormat ) ? scope . $eval ( attrs . dayHeaderFormat ) : datepickerConfig . dayHeaderFormat ;
33
+ format . dayTitle = angular . isDefined ( attrs . dayTitleFormat ) ? scope . $eval ( attrs . dayTitleFormat ) : datepickerConfig . dayTitleFormat ;
34
+ format . monthTitle = angular . isDefined ( attrs . monthTitleFormat ) ? scope . $eval ( attrs . monthTitleFormat ) : datepickerConfig . monthTitleFormat ;
35
+ var startingDay = angular . isDefined ( attrs . startingDay ) ? scope . $eval ( attrs . startingDay ) : datepickerConfig . startingDay ;
36
+ var yearRange = angular . isDefined ( attrs . yearRange ) ? scope . $eval ( attrs . yearRange ) : datepickerConfig . yearRange ;
37
+
38
+ if ( attrs . showWeeks ) {
39
+ scope . $parent . $watch ( $parse ( attrs . showWeeks ) , function ( value ) {
40
+ showWeeks = ! ! value ;
41
+ updateShowWeekNumbers ( ) ;
42
+ } ) ;
43
+ } else {
44
+ showWeeks = datepickerConfig . showWeeks ;
45
+ updateShowWeekNumbers ( ) ;
46
+ }
47
+
48
+ if ( attrs . min ) {
49
+ scope . $parent . $watch ( $parse ( attrs . min ) , function ( value ) {
50
+ minDate = new Date ( value ) ;
51
+ refill ( ) ;
52
+ } ) ;
53
+ }
54
+ if ( attrs . max ) {
55
+ scope . $parent . $watch ( $parse ( attrs . max ) , function ( value ) {
56
+ maxDate = new Date ( value ) ;
57
+ refill ( ) ;
58
+ } ) ;
59
+ }
60
+
61
+ function updateCalendar ( rows , labels , title ) {
62
+ scope . rows = rows ;
63
+ scope . labels = labels ;
64
+ scope . title = title ;
65
+ }
66
+
67
+ // Define whether the week number are visible
68
+ function updateShowWeekNumbers ( ) {
69
+ scope . showWeekNumbers = ( scope . mode === 'day' && showWeeks ) ;
70
+ }
71
+
72
+ function compare ( date1 , date2 ) {
73
+ if ( scope . mode === 'year' ) {
74
+ return date2 . getFullYear ( ) - date1 . getFullYear ( ) ;
75
+ } else if ( scope . mode === 'month' ) {
76
+ return new Date ( date2 . getFullYear ( ) , date2 . getMonth ( ) ) - new Date ( date1 . getFullYear ( ) , date1 . getMonth ( ) ) ;
77
+ } else if ( scope . mode === 'day' ) {
78
+ return ( new Date ( date2 . getFullYear ( ) , date2 . getMonth ( ) , date2 . getDate ( ) ) - new Date ( date1 . getFullYear ( ) , date1 . getMonth ( ) , date1 . getDate ( ) ) ) ;
79
+ }
80
+ }
81
+
82
+ function isDisabled ( date ) {
83
+ return ( ( minDate && compare ( date , minDate ) > 0 ) || ( maxDate && compare ( date , maxDate ) < 0 ) || ( scope . dateDisabled && scope . dateDisabled ( { date : date , mode : scope . mode } ) ) ) ;
84
+ }
85
+
86
+ // Split array into smaller arrays
87
+ var split = function ( a , size ) {
88
+ var arrays = [ ] ;
89
+ while ( a . length > 0 ) {
90
+ arrays . push ( a . splice ( 0 , size ) ) ;
91
+ }
92
+ return arrays ;
93
+ } ;
94
+ var getDaysInMonth = function ( year , month ) {
95
+ return new Date ( year , month + 1 , 0 ) . getDate ( ) ;
96
+ } ;
97
+
98
+ var fill = {
99
+ day : function ( ) {
100
+ var days = [ ] , labels = [ ] , lastDate = null ;
101
+
102
+ function addDays ( dt , n , isCurrentMonth ) {
103
+ for ( var i = 0 ; i < n ; i ++ ) {
104
+ days . push ( { date : new Date ( dt ) , isCurrent : isCurrentMonth , isSelected : isSelected ( dt ) , label : $filter ( 'date' ) ( dt , format . day ) , disabled : isDisabled ( dt ) } ) ;
105
+ dt . setDate ( dt . getDate ( ) + 1 ) ;
106
+ }
107
+ lastDate = dt ;
108
+ }
109
+
110
+ var d = new Date ( selected ) ;
111
+ d . setDate ( 1 ) ;
112
+
113
+ var difference = startingDay - d . getDay ( ) ;
114
+ var numDisplayedFromPreviousMonth = ( difference > 0 ) ? 7 - difference : - difference ;
115
+
116
+ if ( numDisplayedFromPreviousMonth > 0 ) {
117
+ d . setDate ( - numDisplayedFromPreviousMonth + 1 ) ;
118
+ addDays ( d , numDisplayedFromPreviousMonth , false ) ;
119
+ }
120
+ addDays ( lastDate || d , getDaysInMonth ( selected . getFullYear ( ) , selected . getMonth ( ) ) , true ) ;
121
+ addDays ( lastDate , ( 7 - days . length % 7 ) % 7 , false ) ;
122
+
123
+ // Day labels
124
+ for ( i = 0 ; i < 7 ; i ++ ) {
125
+ labels . push ( $filter ( 'date' ) ( days [ i ] . date , format . dayHeader ) ) ;
126
+ }
127
+ updateCalendar ( split ( days , 7 ) , labels , $filter ( 'date' ) ( selected , format . dayTitle ) ) ;
128
+ } ,
129
+ month : function ( ) {
130
+ var months = [ ] , i = 0 , year = selected . getFullYear ( ) ;
131
+ while ( i < 12 ) {
132
+ var dt = new Date ( year , i ++ , 1 ) ;
133
+ months . push ( { date : dt , isCurrent : true , isSelected : isSelected ( dt ) , label : $filter ( 'date' ) ( dt , format . month ) , disabled : isDisabled ( dt ) } ) ;
134
+ }
135
+ updateCalendar ( split ( months , 3 ) , [ ] , $filter ( 'date' ) ( selected , format . monthTitle ) ) ;
136
+ } ,
137
+ year : function ( ) {
138
+ var years = [ ] , year = parseInt ( ( selected . getFullYear ( ) - 1 ) / yearRange , 10 ) * yearRange + 1 ;
139
+ for ( var i = 0 ; i < yearRange ; i ++ ) {
140
+ var dt = new Date ( year + i , 0 , 1 ) ;
141
+ years . push ( { date : dt , isCurrent : true , isSelected : isSelected ( dt ) , label : $filter ( 'date' ) ( dt , format . year ) , disabled : isDisabled ( dt ) } ) ;
142
+ }
143
+ var title = years [ 0 ] . label + ' - ' + years [ years . length - 1 ] . label ;
144
+ updateCalendar ( split ( years , 5 ) , [ ] , title ) ;
145
+ }
146
+ } ;
147
+ var refill = function ( ) {
148
+ fill [ scope . mode ] ( ) ;
149
+ } ;
150
+ var isSelected = function ( dt ) {
151
+ if ( scope . model && scope . model . getFullYear ( ) === dt . getFullYear ( ) ) {
152
+ if ( scope . mode === 'year' ) {
153
+ return true ;
154
+ }
155
+ if ( scope . model . getMonth ( ) === dt . getMonth ( ) ) {
156
+ return ( scope . mode === 'month' || ( scope . mode === 'day' && scope . model . getDate ( ) === dt . getDate ( ) ) ) ;
157
+ }
158
+ }
159
+ return false ;
160
+ } ;
161
+
162
+ scope . $watch ( 'model' , function ( dt , olddt ) {
163
+ if ( angular . isDate ( dt ) ) {
164
+ selected = angular . copy ( dt ) ;
165
+ }
166
+
167
+ if ( ! angular . equals ( dt , olddt ) ) {
168
+ refill ( ) ;
169
+ }
170
+ } ) ;
171
+ scope . $watch ( 'mode' , function ( ) {
172
+ updateShowWeekNumbers ( ) ;
173
+ refill ( ) ;
174
+ } ) ;
175
+
176
+ scope . select = function ( dt ) {
177
+ selected = new Date ( dt ) ;
178
+
179
+ if ( scope . mode === 'year' ) {
180
+ scope . mode = 'month' ;
181
+ selected . setFullYear ( dt . getFullYear ( ) ) ;
182
+ } else if ( scope . mode === 'month' ) {
183
+ scope . mode = 'day' ;
184
+ selected . setMonth ( dt . getMonth ( ) ) ;
185
+ } else if ( scope . mode === 'day' ) {
186
+ scope . model = new Date ( selected ) ;
187
+ }
188
+ } ;
189
+ scope . move = function ( step ) {
190
+ if ( scope . mode === 'day' ) {
191
+ selected . setMonth ( selected . getMonth ( ) + step ) ;
192
+ } else if ( scope . mode === 'month' ) {
193
+ selected . setFullYear ( selected . getFullYear ( ) + step ) ;
194
+ } else if ( scope . mode === 'year' ) {
195
+ selected . setFullYear ( selected . getFullYear ( ) + step * yearRange ) ;
196
+ }
197
+ refill ( ) ;
198
+ } ;
199
+ scope . toggleMode = function ( ) {
200
+ scope . mode = ( scope . mode === 'day' ) ? 'month' : ( scope . mode === 'month' ) ? 'year' : 'day' ;
201
+ } ;
202
+ scope . getWeekNumber = function ( row ) {
203
+ if ( scope . mode !== 'day' || ! scope . showWeekNumbers || row . length !== 7 ) {
204
+ return ;
205
+ }
206
+
207
+ var index = ( startingDay > 4 ) ? 11 - startingDay : 4 - startingDay ; // Thursday
208
+ var d = new Date ( row [ index ] . date ) ;
209
+ d . setHours ( 0 , 0 , 0 ) ;
210
+ return Math . ceil ( ( ( ( d - new Date ( d . getFullYear ( ) , 0 , 1 ) ) / 86400000 ) + 1 ) / 7 ) ; // 86400000 = 1000*60*60*24;
211
+ } ;
212
+ }
213
+ } ;
214
+ } ] ) ;
0 commit comments