@@ -49,6 +49,7 @@ const SELECTOR_CALENDAR_CELL_INNER = '.calendar-cell-inner'
49
49
50
50
const Default = {
51
51
calendarDate : new Date ( ) ,
52
+ calendars : 1 ,
52
53
disabledDates : null ,
53
54
endDate : null ,
54
55
firstDayOfWeek : 1 ,
@@ -63,6 +64,7 @@ const Default = {
63
64
64
65
const DefaultType = {
65
66
calendarDate : '(date|string|null)' ,
67
+ calendars : 'number' ,
66
68
disabledDates : '(array|null)' ,
67
69
endDate : '(date|string|null)' ,
68
70
firstDayOfWeek : 'number' ,
@@ -89,8 +91,10 @@ class Calendar extends BaseComponent {
89
91
this . _calendarDate = this . _config . calendarDate
90
92
this . _startDate = this . _config . startDate
91
93
this . _endDate = this . _config . endDate
94
+ this . _hoverDate = null
92
95
this . _selectEndDate = this . _config . selectEndDate
93
96
this . _view = 'days'
97
+
94
98
this . _createCalendar ( )
95
99
this . _addEventListeners ( )
96
100
}
@@ -135,13 +139,18 @@ class Calendar extends BaseComponent {
135
139
return
136
140
}
137
141
142
+ this . _hoverDate = new Date ( Manipulator . getDataAttribute ( event . target , 'date' ) )
143
+
138
144
EventHandler . trigger ( this . _element , EVENT_CELL_HOVER , {
139
145
date : new Date ( Manipulator . getDataAttribute ( event . target , 'date' ) )
140
146
} )
141
147
} )
142
148
143
149
EventHandler . on ( this . _element , EVENT_MOUSELEAVE , SELECTOR_CALENDAR_CELL_INNER , event => {
144
150
event . preventDefault ( )
151
+
152
+ this . _hoverDate = null
153
+
145
154
EventHandler . trigger ( this . _element , EVENT_CELL_HOVER , {
146
155
date : null
147
156
} )
@@ -172,14 +181,14 @@ class Calendar extends BaseComponent {
172
181
event . preventDefault ( )
173
182
this . _view = 'months'
174
183
this . _element . innerHTML = ''
175
- this . _createCalendar ( )
184
+ this . _createCalendarPanel ( )
176
185
} )
177
186
178
187
EventHandler . on ( this . _element , 'click' , '.btn-year' , event => {
179
188
event . preventDefault ( )
180
189
this . _view = 'years'
181
190
this . _element . innerHTML = ''
182
- this . _createCalendar ( )
191
+ this . _createCalendarPanel ( )
183
192
} )
184
193
}
185
194
@@ -252,10 +261,18 @@ class Calendar extends BaseComponent {
252
261
}
253
262
}
254
263
255
- _createCalendar ( ) {
256
- const { firstDayOfWeek, locale, weekdayFormat } = this . _config
257
- const year = this . _calendarDate . getFullYear ( )
258
- const month = this . _calendarDate . getMonth ( )
264
+ _createCalendarPanel ( addMonths ) {
265
+ let date = this . _calendarDate
266
+
267
+ if ( addMonths !== 0 ) {
268
+ date = new Date ( this . _calendarDate . getFullYear ( ) , this . _calendarDate . getMonth ( ) + addMonths , 1 )
269
+ }
270
+
271
+ const year = date . getFullYear ( )
272
+ const month = date . getMonth ( )
273
+
274
+ const calendarPanelEl = document . createElement ( 'div' )
275
+ calendarPanelEl . classList . add ( 'calendar-panel' )
259
276
260
277
// Create navigation
261
278
const navigationElement = document . createElement ( 'div' )
@@ -271,10 +288,10 @@ class Calendar extends BaseComponent {
271
288
</div>
272
289
<div class="calendar-nav-date">
273
290
<button class="btn btn-transparent btn-sm btn-month">
274
- ${ this . _calendarDate . toLocaleDateString ( locale , { month : 'long' } ) }
291
+ ${ date . toLocaleDateString ( this . _config . locale , { month : 'long' } ) }
275
292
</button>
276
293
<button class="btn btn-transparent btn-sm btn-year">
277
- ${ this . _calendarDate . toLocaleDateString ( locale , { year : 'numeric' } ) }
294
+ ${ date . toLocaleDateString ( this . _config . locale , { year : 'numeric' } ) }
278
295
</button>
279
296
</div>
280
297
<div class="calendar-nav-next">
@@ -287,9 +304,9 @@ class Calendar extends BaseComponent {
287
304
</div>
288
305
`
289
306
290
- const monthDetails = getMonthDetails ( year , month , firstDayOfWeek )
291
- const listOfMonths = createGroupsInArray ( getMonthsNames ( locale ) , 4 )
292
- const listOfYears = createGroupsInArray ( getYears ( this . _calendarDate . getFullYear ( ) ) , 4 )
307
+ const monthDetails = getMonthDetails ( year , month , this . _config . firstDayOfWeek )
308
+ const listOfMonths = createGroupsInArray ( getMonthsNames ( this . _config . locale ) , 4 )
309
+ const listOfYears = createGroupsInArray ( getYears ( date . getFullYear ( ) ) , 4 )
293
310
const weekDays = monthDetails [ 0 ]
294
311
295
312
const calendarTable = document . createElement ( 'table' )
@@ -300,11 +317,11 @@ class Calendar extends BaseComponent {
300
317
${ weekDays . map ( ( { date } ) => (
301
318
`<th class="calendar-cell">
302
319
<div class="calendar-header-cell-inner">
303
- ${ typeof weekdayFormat === 'string' ?
304
- date . toLocaleDateString ( locale , { weekday : weekdayFormat } ) :
320
+ ${ typeof this . _config . weekdayFormat === 'string' ?
321
+ date . toLocaleDateString ( this . _config . locale , { weekday : this . _config . weekdayFormat } ) :
305
322
date
306
- . toLocaleDateString ( locale , { weekday : 'long' } )
307
- . slice ( 0 , weekdayFormat ) }
323
+ . toLocaleDateString ( this . _config . locale , { weekday : 'long' } )
324
+ . slice ( 0 , this . _config . weekdayFormat ) }
308
325
</div>
309
326
</th>`
310
327
) ) . join ( '' ) }
@@ -315,7 +332,7 @@ class Calendar extends BaseComponent {
315
332
`<tr>${ week . map ( ( { date, month } ) => (
316
333
`<td class="calendar-cell ${ this . _dayClassNames ( date , month ) } ">
317
334
<div class="calendar-cell-inner day" data-coreui-date="${ date } ">
318
- ${ date . toLocaleDateString ( locale , { day : 'numeric' } ) }
335
+ ${ date . toLocaleDateString ( this . _config . locale , { day : 'numeric' } ) }
319
336
</div>
320
337
</td>`
321
338
) ) . join ( '' ) } </tr>`
@@ -340,28 +357,50 @@ class Calendar extends BaseComponent {
340
357
) ) . join ( '' ) : '' }
341
358
</tbody>
342
359
`
360
+ calendarPanelEl . append ( navigationElement , calendarTable )
361
+
362
+ return calendarPanelEl
363
+ }
364
+
365
+ _createCalendar ( ) {
366
+ const calendarsEl = document . createElement ( 'div' )
367
+ calendarsEl . classList . add ( 'calendars' )
368
+ Array . from ( { length : this . _config . calendars } ) . forEach ( ( _ , index ) => (
369
+ calendarsEl . append ( this . _createCalendarPanel ( index ) )
370
+ ) )
343
371
344
372
this . _element . classList . add ( CLASS_NAME_CALENDAR )
345
- this . _element . append ( navigationElement , calendarTable )
373
+ this . _element . append ( calendarsEl )
346
374
}
347
375
348
376
_updateCalendar ( ) {
349
377
this . _element . innerHTML = ''
350
- this . _createCalendar ( )
378
+ this . _createCalendarPanel ( )
351
379
}
352
380
353
381
_dayClassNames ( date , month ) {
354
- const classNames = [
355
- isToday ( date ) && 'today' ,
356
- isDateDisabled ( date , this . _config . minDate , this . _config . maxDate , this . _config . disabledDates ) && 'disabled' ,
357
- `${ month } ` ,
358
- isLastDayOfMonth ( date ) && 'last' ,
359
- month === 'current' && isDateInRange ( date , this . _startDate , this . _endDate ) && 'range' ,
360
- isDateSelected ( date , this . _startDate , this . _endDate ) && 'selected' ,
361
- isStartDate ( date , this . _startDate , this . _endDate ) && 'start' ,
362
- isEndDate ( date , this . _startDate , this . _endDate ) && 'end'
363
- ]
364
- return classNames . filter ( Boolean ) . join ( ' ' )
382
+ const classNames = {
383
+ today : isToday ( date ) ,
384
+ disabled : isDateDisabled ( date , this . _config . minDate , this . _config . maxDate , this . _config . disabledDates ) ,
385
+ [ month ] : true ,
386
+ last : isLastDayOfMonth ( date ) ,
387
+ range : month === 'current' && isDateInRange ( date , this . _startDate , this . _endDate ) ,
388
+ 'range-hover' : month === 'current' && ( this . _hoverDate && this . _selectEndDate ?
389
+ isDateInRange ( date , this . _startDate , this . _hoverDate ) :
390
+ isDateInRange ( date , this . _hoverDate , this . _endDate ) ) ,
391
+ selected : isDateSelected ( date , this . _startDate , this . _endDate ) ,
392
+ start : isStartDate ( date , this . _startDate , this . _endDate ) ,
393
+ end : isEndDate ( date , this . _startDate , this . _endDate )
394
+ }
395
+
396
+ // eslint-disable-next-line unicorn/no-array-reduce, unicorn/prefer-object-from-entries
397
+ const result = Object . keys ( classNames ) . reduce ( ( o , key ) => {
398
+ // eslint-disable-next-line no-unused-expressions
399
+ classNames [ key ] === true && ( o [ key ] = classNames [ key ] )
400
+ return o
401
+ } , { } )
402
+
403
+ return Object . keys ( result ) . join ( ' ' )
365
404
}
366
405
367
406
_getConfig ( config ) {
0 commit comments