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