import { Component, OnInit, Input, Output, EventEmitter, SimpleChanges, ChangeDetectionStrategy, OnChanges, HostListener, ViewChild, ElementRef } from '@angular/core'; @Component({ selector: 'dc-ng-datepicker', template: `
{{pickerTitle}}
  • {{yearArray[i]}}年 {{list}}月
{{d}} {{d}}
{{day.date}}
{{isChooseTimes?'返回':'时间'}} 确定 现在
时间
  • {{hours}}
  • {{minutes}}
  • {{seconds}}
`, styles: [` ul, li { list-style: none; margin: 0; padding: 0; } .date-more { display: inline-block; width: 8px; height: 10px; border: solid 4px transparent; border-top-width: 6px; border-top-color: #fff; position: relative; top: 3px; } .showYearMonthMore .date-more{ top: 0; transform:rotate(180deg); -ms-transform:rotate(180deg); /* Internet Explorer */ -moz-transform:rotate(180deg); /* Firefox */ -webkit-transform:rotate(180deg); /* Safari 和 Chrome */ -o-transform:rotate(180deg); /* Opera */ } .form-control { display: block; width: 100%; height: 34px; padding: 0 0 0 5px; font-size: inherit; line-height: 1.42857143; color: #555; background-color: #fff; background-image: none; border: 1px solid #ccc; border-radius: 4px; -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s; -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; } input.form-control { border: 1px solid #ccc; } input::placeholder { color: #bbb } div.date-picker-box { position: relative; display: inline-block; width: 150px; } div.date-picker-input { position: relative; display: inline-block; width: 100%; background-color: white; color: #333; font-size: 12px; } div.date-picker-input input { height: 30px; border-radius: 3px; } div.date-picker-input i.show { position: absolute; right: 2px; top: 0; font-size: inherit; cursor: pointer; width: 20px; height: 30px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAYklEQVQokdWQUQrAIAxDU9m/O6XHn97A/awQ2w4s+1qgIA3h1UhrDaQB4ESsxSsA5jOsSTNoX3VfTOCN5rzDUCLVyLPEbSlRkjn3Ry6DS3MFfj5VJRvvkPijU1PEDuBK5voNJIwdJa4Jkp0AAAAASUVORK5CYII=) no-repeat center center transparent; } div.date-picker-input i.clear { position: absolute; right: 22px; top: 0; font-size: inherit; cursor: pointer; width: 20px; height: 30px; background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+IEmuOgAAAOVJREFUKJF90DFKA1EQBuAvj2Cu8MBqe8FokedeQb2A6WzU0uN4gxTbxkM8CKKSfqvAXsAi2lj4dlkh5Icp5p9/Zv6ZSdM0Ck7whDucFW6LFV7wDdNSOMUac/9xVeIet9iFMvmQeIw5XjELeOzFdV2LMQ6qGKO6rvv0HA8By55p21ZKSYxRjFFKSdu2403LKS77rOs6OWcpJZBz1nXduOEiHPF9CD8Bb2PPKSU552HT+CZsg78/g6qqBhu9vaqqxg2rSdM0M+TyhWP4xCJgjxu8HxF/4Br7/ugdEp6xwVeJTeEWReMX1Y9FK/4RDOgAAAAASUVORK5CYII=) no-repeat center center transparent; } div.date-picker-input i.clear:hover{ background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+IEmuOgAAAOtJREFUKJF90b1NAzEcBfBfriCVm2vR3S2ABFXYAViADACUjMMGWQCGQIoQWJngrLTXWBSBIhRxooBCnuTCz++9/4dHMUYFJ3jALc4Kt8AMT/iCUTGc4hkXDuMdN1hWJfmYWHl7wbjC/VbcdZ0Qwk4VQtB13fZ6jrsK0y0zDIO2bYUQhBA0TWMYhv1K01GMcVXa2qW2bWu9XkspyTnvG1bVkb4P4bvC29/0vu+llDRN82smLCqbPYO6rvV9L+cs5yylpK7rfcNsFGMc47Vs4RgiJhVWuLb5nP/wgSt7Qy9xiUfM8VnOvHCTovEDCGVJpA/ldQoAAAAASUVORK5CYII=) no-repeat center center transparent; } div.date-picker { position: absolute; width: auto; min-height: 220px; background-color: white; border: 1px #ccc solid; z-index: 1000; right: 0; border-radius: 5px; } div.date-picker.offset-left { right: auto; left: 0; } .years-month-ul { position: absolute; width: 150px; top: 30px; right: 0; margin-right: 40px; background-color: white; box-shadow: 0 0 5px gray; z-index: 1001; } .years-month-ul li { height: 22px; display: flex; line-height: 22px; } .years-month-ul li span { width: 50%; align-items: center; justify-content: center; text-align: center; cursor: pointer; font-size: 12px; border-radius: 3px; color: #212529; } .years-month-ul li span:hover { background-color: #eeeeee; } .years-month-ul li span.selected { background-color: #2bb1ff; color: #fff; } .nav-bar ul { list-style: none; padding-top: 10px; padding-left: 10px; } .nav-bar ul li { font-size: 13px; background: #f5f5f5; border: 1px solid #f5f5f5; border-radius: 4px; color: #1165E5; padding: 3px 12px; margin-bottom: 8px; } .nav-bar ul li.active, .nav-bar ul li:hover { background: #2bb1ff; border: 1px solid #2bb1ff; color: #ffffff; } div.calendar .control-bar,.times-title { width: 100%; display: flex; height: 35px; align-items: center; justify-content: center; background-color: #2bb1ff; border-top-left-radius: 5px; border-top-right-radius: 5px; color:#fff; } div.calendar .control-bar .material-icons { cursor: pointer; font-size: 21px; margin: 2px; display: flex; align-items: center; justify-content: center; width: 30px; height: 30px; font-weight: bold; opacity: 0.7; } div.calendar .control-bar .material-icons:hover{ /*opacity: 1;*/ } div.calendar .control-bar .material-icons.de-year { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+IEmuOgAAAH5JREFUKJGd0jsOwjAQRVHvgm/S0rD/KgWbgIQItsKhYCIlMJGQLbm5z9eyZ6agJHuHDqeMZcIeg8+6ZOxbOOAe4RCHf9hcOGKMsI/nZKxMQoNHhDdsV1iZpAbPCK/YrLAyl7oIXzhHkLGF1Ca3ZmwhVf2punrVfaqeiL9m7w36Lzv4T8TJHwAAAABJRU5ErkJggg==) no-repeat center center transparent; } div.calendar .control-bar .material-icons.de-month { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAANCAYAAACUwi84AAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+IEmuOgAAAGtJREFUGJWN0TEOwjAMBVDfAlqgaxfuPzFwCaCt4Cp9DDhSVSo1kTw9xf5xArFRDW7ot7DF4HfuazxhTBzQLvGMKfGVY6LgBe/EJ47lYsFP4gOH5djItDDjug4d6PY67GaoekXVHqo2+fcXX7YeWEIOj0dbAAAAAElFTkSuQmCC) no-repeat center center transparent; } div.calendar .control-bar .material-icons.in-month { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAANCAYAAACUwi84AAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+IEmuOgAAAHJJREFUGJWF0T0OwjAMBlDfovyvnbj/1IFDAC2Cq/R1wENICkTKEOXF+uwEegzYIuoduHivEbs1sMeUaMrzB4h8OSZ64FCDyAz3RE8caxDY4JbohVOTGmfMiYb6ssP1W4WyfJOhDNh0Uba4Ooe/k/z5Fwscj1hR3883OgAAAABJRU5ErkJggg==) no-repeat center center transparent; } div.calendar .control-bar .material-icons.in-year { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAABS2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4KPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxMzggNzkuMTU5ODI0LCAyMDE2LzA5LzE0LTAxOjA5OjAxICAgICAgICAiPgogPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIi8+CiA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgo8P3hwYWNrZXQgZW5kPSJyIj8+IEmuOgAAAI5JREFUKJGl0jsSwjAMhGHdgjctFfevUnAIHmHgKnwUKBmSKAWDZ1T4964trx04oMEKkVWxvgInn3HDOhcqNjBt0KaozXnFBqbI3W4pumM7wwamyP6vKXpgN8NifMklLil6Yl+xSTI44pWipmJjwwLn0UkTNtda13/FogqhS6pifXrf0XZvUrH/f8TPf+8N2YY8FsbUCEUAAAAASUVORK5CYII=) no-repeat center center transparent; } div.calendar .control-bar .monthTitle { font-size: inherit; font-weight: normal; width: 160px; color: #fff; text-align: center; cursor: pointer; height: 30px; line-height: 30px; } div.calendar .control-bar .monthTitle:hover .date-more { color: #fff; border-top-color: #fff; } div.calendar .days { width: 100%; align-items: center; justify-content: center; display: flex; font-size: inherit; } table { border-spacing: 0; } th, td { text-align: center; position: relative; font-weight: normal; } th { color: #333; } tr > td.disabled { color: #999999; text-decoration: line-through; cursor: not-allowed; } tr > td.range { background-color: #ebf4f8; border-color: transparent; } tr > td.active, tr > td.active:hover { border-radius: 4px; background-color: #2bb1ff !important; color: white; } .date { width: 30px; height: 30px; text-align: center; line-height: 30px; } .cancelArea { position: fixed; width: 100vw; height: 100vh; top: 0; left: 0; z-index: 9; } .pointer { cursor: pointer; } .pull-left { float: left !important; } .times{ width: 90%; margin-left: 5%; border-top:1px #ccc solid; margin-top:8px; padding:8px 0; } .times span{ line-height:28px; padding:0 8px; display:inline-block; background-color:#2bb1ff; border-radius: 4px; color: #fff; cursor: pointer; } .times span.times-now,.times span.times-sure{ float: right; } .times-now{ margin-right:2px; } .choose-times{ position: absolute; width: 230px; min-height: 245px; background-color: #fff; border-left: 1px #ccc solid; border-top: 1px #ccc solid; border-right: 1px #ccc solid; z-index: 1001; border-top-left-radius: 5px; border-top-right-radius: 5px; } .times-cont{ float: left; width:90%; margin-left:5%; } .times-tip{ width:100%; float:left; } .times-tip span{ text-align: center; line-height: 30px; width: 32%; display: inline-block; } .times-list{ width:100%; float: left; border-top:1px #ccc solid; border-left:1px #ccc solid; border-bottom:1px #ccc solid; height:168px; } .times-list li{ width:33%; float: left; text-align: center; height: 100%; border-right: 1px #ccc solid; overflow-y: scroll; position:relative; } .list-cont{ position: absolute; left:0; top:auto; } .times-list li span{ line-height:24px; display: inline-block; font-size: 12px; cursor: pointer; width:100%; } .times-list li span:hover{ background-color: #eef9ff; color: #2bb1ff; } .times-list li span.active{ background-color: #2bb1ff; color: #fff; } `], changeDetection: ChangeDetectionStrategy.OnPush }) export class NgDatepickerComponent implements OnInit, OnChanges { @Input() width: string; @Input() toph: string; @Input() initDate: any; @Input() isHidden: boolean; @Input() defaultShow: boolean; @Input() minDate: Date; @Input() maxDate: Date; @Input() disabledDates: any[]; @Input() availableDates: any[]; @Input() displayDateType: boolean; @Input() quickDateBars: QuickDateBar[]; @Input() selectedQuickDateBar: QuickDateBar; @Input() daysOfWeekDisabled: number[] = []; @Input() language: string; @Input() placeholder: string; @Input() offset: string; @Input() format: string; @Input() now: boolean; @ViewChild('datePickerBox') datePickerBox: ElementRef; @Output() ngModelChange: EventEmitter = new EventEmitter(); changeDateFlag = false; weekTitleEn = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa']; weekTitleZh = ['日', '一', '二', '三', '四', '五', '六']; showYearMonth: boolean = false; monthArray: Array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; yearArray: Array = []; displayDate: string = null; dates: Array = [[]]; hoursArray: Array = []; minutesArray: Array = []; curHours:number=0; curMinutes:number=0; curSeconds:number=0; titleYear: number; titleMonth: number; pickerTitle: string; hours:number=0; minutes:number=0; seconds:number=0; today: Date; monthDays: number[] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; monthFullName: string[] = ['January', 'Febuary', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; monthName: string[] = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; _minDate: Date = new Date('01/01/1900'); _maxDate: Date = new Date('12/31/2117'); _disabledDates: (Date | string)[]; _availableDates: (Date | string)[]; _daysOfWeekDisabled: number[]; minYear: number; minMonth: number; maxYear: number; maxMonth: number; selectedDate: SelectedDate; outputDate: OutputDate; startDate: Date; endDate: Date; hasSelectedBar: boolean; hasInitDate: boolean; isInited: boolean; isFormat: boolean=false; isChooseTimes: boolean=false; constructor() { if (this.isHidden === undefined) { this.isHidden = true; } this.createEmptyDatePicker(); } ngOnInit() { this.minDate = this.minDate || new Date('1900/01/01'); this.maxDate = this.maxDate || new Date('2117/12/31'); if (!this.isInited) { let times = new Date() > this.minDate ? new Date() : this.minDate; this.initDatePicker(times); } if(this.format){ let formatArr = this.format.split(" "); if(formatArr.length==2){ this.isFormat = true; this.displayDate = this.initDate; for(let i=0;i<24;i++){ if(i<10){ this.hoursArray[i]= '0' + i; }else{ this.hoursArray[i]='' + i; } } for(let j=0;j<60;j++){ if(j<10){ this.minutesArray[j] = '0' + j; }else{ this.minutesArray[j] = '' + j; } } } } } @HostListener('document:click', ['$event']) onDocumentClick(ev: any) { if (!this.datePickerBox.nativeElement.contains(ev.target)) { if (!this.isHidden) { this.isChooseTimes = false; this.toggleCalendar(true); } } } ngOnChanges(changes: SimpleChanges) { if (changes['selectedQuickDateBar']) this.hasSelectedBar = true; if (changes['initDate']) this.hasInitDate = true; if (changes['selectedQuickDateBar'] && changes['selectedQuickDateBar'].currentValue) { if (!this.hasInitDate && !this.isInited) { this.initDatePicker(new Date()); } if (this.hasInitDate) { this.setAvailableDates(this.selectedQuickDateBar); } else { this.selectBar(this.selectedQuickDateBar); } } if (changes['maxDate'] && changes['maxDate'].currentValue) { this._maxDate = this.maxDate; } if (changes['minDate'] && changes['minDate'].currentValue) { this._minDate = this.minDate; } if (changes['availableDates'] && changes['availableDates'].currentValue) { this._availableDates = this.availableDates; } if (changes['disabledDates'] && changes['disabledDates'].currentValue) { this._disabledDates = this.disabledDates; } if (changes['daysOfWeekDisabled'] && changes['daysOfWeekDisabled'].currentValue) { this._daysOfWeekDisabled = this.daysOfWeekDisabled; } if (changes['initDate'] && changes['initDate'].currentValue) { this.changeDateFlag = true; let _initDate: Date; let ieInitDate; let ieInitArr; let dateStr = this.initDate.toString(); let newYear = new Date().getFullYear(); let newDay = new Date().getDate(); if (dateStr.indexOf('/') < 0 && dateStr.indexOf('-') < 0 && dateStr.indexOf('月') < 0) { if (dateStr.length == 6 || dateStr.length == 5) { // 201903 20193 ieInitDate = dateStr.substr(0,4) + '/' + dateStr.substring(4); } else if (dateStr.length == 4) { // 0321 ieInitDate = newYear + '/' + dateStr.substr(0,2) + '/' + dateStr.substr(2,2); } else { // 20190321 ieInitDate = dateStr.substr(0,4) + '/' + dateStr.substr(4,2) + '/' + dateStr.substr(6,2); } } else if (dateStr.indexOf('月') > -1) { if (dateStr.indexOf('日') < 0) { // 2019年03月 ieInitDate = dateStr.substr(0,4) + '/' + dateStr.substring(5, dateStr.length - 1); } else if (dateStr.indexOf('年') < 0) { // 03月22日 ieInitDate = newYear + '/' + dateStr.substr(0,2) + '/' + dateStr.substr(3,2); } else { // 2019年03月21日 ieInitDate = dateStr.substr(0,4) + '/' + dateStr.split('年')[1].split('月')[0] + '/' + dateStr.split('月')[1].split('日')[0]; } } else { // 2019-03-21 或者 2019/03/21 或者 2019-03 或者 03/21 if (dateStr.length == 5) { ieInitDate = newYear + '/' + dateStr.substr(0,2) + '/' + dateStr.substr(3,2); } else { ieInitDate = dateStr.replace(/-/g,"/"); } } ieInitArr = ieInitDate.split('/'); let len = ieInitArr.length; let day = len == 2 ? newDay : ieInitArr[2]; _initDate = new Date(ieInitArr[0],(ieInitArr[1]-1),day); if (!_initDate.getMonth()) { _initDate = new Date(); } this.initDatePicker(_initDate); this.selectionEmitter(new Day(_initDate.getDate())); } } decreaseYear() { // 向前推年份 this.yearArray = this.calcYear(this.yearArray[0] - 12); } increaseYear() { // 向后推年份 this.yearArray = this.calcYear(this.yearArray[this.yearArray.length - 1] + 1); } selectMonth(ev: any, month: number) { this.titleMonth = month; this.showYearMonth = false; this.pickerTitle = this.renderTitle(); this.calCalendar(); } selectYear(ev: any, year: number) { this.titleYear = year; this.pickerTitle = this.renderTitle(); } calcYear(minYear: number) { let tempArray: Array = [minYear]; for (let i = 0; i < 11; i++) { tempArray.push(minYear + i + 1); } return tempArray; } clearDate() { this.selectionEmitter(new Day(Date.now()), true); } selectYearMonth() { this.yearArray = this.calcYear(this.titleYear - 5); this.showYearMonth = !this.showYearMonth; // todo 设置年月 // this.titleYear = 2017; // this.titleMonth = 7; // // this.pickerTitle = this.renderTitle(); // this.calCalendar(); } createEmptyDatePicker(): void { for (let i = 0; i < 6; i++) { this.dates.push([]); for (let j = 0; j < 7; j++) { this.dates[i].push(); } } } initDatePicker(date: Date): void { let today: Date = date; this.titleYear = today.getFullYear(); this.titleMonth = today.getMonth() + 1; this.pickerTitle = this.renderTitle(); this.curHours = this.hours = today.getHours(); this.curMinutes = this.minutes = today.getMinutes(); this.curSeconds = this.seconds = today.getSeconds(); this.selectedDate = new SelectedDate(today.getFullYear(), today.getMonth() + 1, today.getDate(),today.getHours(),today.getMinutes(),today.getSeconds()); this.calCalendar(); this.initInput(); if (!this.hasInitDate && !this.hasSelectedBar) { this.selectionEmitter(new Day(today.getDate()), true); } this.isInited = true; } clearDateByOther() { this.changeDateFlag = true; this.selectionEmitter(new Day(Date.now()), true); } //点击现在 timenow(){ this.isHidden = true; this.isChooseTimes = false; let timeDate = new Date(); this.displayDate = timeDate.getFullYear() + '-' + (timeDate.getMonth()+1) + '-' + this.toZero(timeDate.getDate()) + ' ' + this.toZero(timeDate.getHours()) + ':' + this.toZero(timeDate.getMinutes()) + ':' + this.toZero(timeDate.getSeconds()); } toZero(num:number){ if(num<10){ return '0'+num; }else{ return num; } } //点击时间 showTimes(){ this.isChooseTimes = !this.isChooseTimes; } //点击确定 timeSure(){ this.isHidden = true; this.isChooseTimes = false; this.timeChange(); } //改变时间 timeChange(){ let resArr = this.displayDate.split(' '); this.displayDate = resArr[0] + ' ' + this.toZero(this.curHours) + ':' + this.toZero(this.curMinutes) + ':' + this.toZero(this.curSeconds); this.outputEvent(); } //选择小时 chooseHours(i:number){ this.curHours = i; this.timeChange(); } //选择分钟 chooseMinutes(i:number){ this.curMinutes = i; this.timeChange(); } //选择秒 chooseSeconds(i:number){ this.curSeconds = i; this.timeChange(); } selectionEmitter(d: Day, isInit?: boolean): void { if(!this.isFormat){ this.isHidden = true; } this.startDate = new Date(this.titleMonth + '/' + d.date + '/' + this.titleYear); this.endDate = null; this.selectedDate = new SelectedDate(this.titleYear, this.titleMonth, d.date,this.hours,this.minutes,this.seconds); if (isInit) { this.displayDate = ''; } else { /*this.displayDate = (this.displayDateType && this.selectedQuickDateBar ? this.selectedQuickDateBar.value : '') + (this.selectedDate.day < 10 ? ('0' + this.selectedDate.day) : this.selectedDate.day) + '-' + this.monthName[this.selectedDate.month - 1] + '-' + this.selectedDate.year;*/ this.displayDate = (this.displayDateType && this.selectedQuickDateBar ? this.selectedQuickDateBar.value : '') + this.selectedDate.year + '-' + (this.selectedDate.month) + '-' + (this.selectedDate.day < 10 ? ('0' + this.selectedDate.day) : this.selectedDate.day); if(this.isFormat){ this.displayDate += ' ' + (this.selectedDate.hours < 10 ? ('0' + this.selectedDate.hours) : this.selectedDate.hours) + ':' + (this.selectedDate.minutes < 10 ? ('0' + this.selectedDate.minutes) : this.selectedDate.minutes) + ':' + (this.selectedDate.seconds < 10 ? ('0' + this.selectedDate.seconds) : this.selectedDate.seconds); } } this.outputEvent(); } selectDate(d: Day): void { this.showYearMonth = false; if (!d.isDisabled) { if (d.num > 0) this.increaseMonth(); if (d.num < 0) this.decreaseMonth(); this.selectionEmitter(d); } } isDateSelected(d: Day): boolean { // const date: Date = new Date((this.titleMonth + (d.num | 0)) + '/' + d.date + '/' + this.titleYear); const date: Date = new Date((d.month + (d.num || 0)) + '/' + d.date + '/' + d.year); d.isSelected = (this.startDate && this.startDate.getTime() === date.getTime()) || (this.endDate && this.endDate.getTime() === date.getTime()); d.isInRange = (this.startDate && this.startDate.getTime() < date.getTime()) && (this.endDate && this.endDate.getTime() > date.getTime()); d.isDisabled = this.isDateDisbalbed(date); return d.isSelected; } isDateDisbalbed(date: Date): boolean { if (date.getTime() > this.maxDate.getTime() || date.getTime() < this.minDate.getTime()) { return true; } if (this.disabledDates && this.disabledDates.length > 0 && this.disabledDates.filter((disabledDate: any) => date.getTime() === new Date(disabledDate).getTime()).length > 0) { return true; } if (this.availableDates && this.availableDates.length > 0 && this.availableDates.filter((availableDate: any) => date.getTime() === new Date(availableDate).getTime()).length === 0) { return true; } if (this.daysOfWeekDisabled && this.daysOfWeekDisabled.length > 0 && this.daysOfWeekDisabled.indexOf(date.getDay()) > -1) { return true; } return false; } /** * Formate displaying month to full name */ renderTitle(): string { return this.titleYear + '年 ' + this.titleMonth + '月'; } initInput(): void { this.maxYear = this.maxDate && this.maxDate.getFullYear(); this.maxMonth = this.maxDate && this.maxDate.getMonth() + 1; this.minYear = this.minDate && this.minDate.getFullYear(); this.minMonth = this.minDate && this.minDate.getMonth() + 1; } calCalendar(): void { this.clearCalendar(); let startTime: Date = new Date(this.titleMonth + '/01/' + this.titleYear); let startDay: number = startTime.getDay(); let monthDays: number = this.calMonthEndDay(this.titleYear, this.titleMonth, 0); for (let i = 0, k = 1, l = 1; i < 6; i++) { if (i === 0) { for (let j = 0; j < 7; j++) { let temp = null; if (j < startDay) { let lastMonthEndDay: number = this.calMonthEndDay(this.titleYear, this.titleMonth, -1); let lastDay: number = lastMonthEndDay - startDay + j + 1; temp = new Day(lastDay, -1, this.isHoliday(this.titleYear, this.titleMonth, lastDay, -1), false, this.isSelectedDay(this.titleYear, this.titleMonth, lastDay, -1)); if (this.titleMonth == 1) { temp.year = this.titleYear - 1; temp.month = 13; temp.num = -1; } else { temp.year = this.titleYear; temp.month = this.titleMonth; } this.dates[i][j] = temp; } else { temp = new Day(k, 0, this.isHoliday(this.titleYear, this.titleMonth, k, 0), true, this.isSelectedDay(this.titleYear, this.titleMonth, k, 0)); temp.year = this.titleYear; temp.month = this.titleMonth; this.dates[i][j] = temp; k++; } } } else { for (let j = 0; j < 7; j++ , k++) { let temp = null; if (k > monthDays) { temp = new Day(l, 1, this.isHoliday(this.titleYear, this.titleMonth, l, 1), false, this.isSelectedDay(this.titleYear, this.titleMonth, l, 1)); if (this.titleMonth == 12) { temp.year = this.titleYear + 1; temp.month = 1; temp.num = 1; } else { temp.year = this.titleYear; temp.month = this.titleMonth; } this.dates[i][j] = temp; l++; } else { temp = new Day(k, 0, this.isHoliday(this.titleYear, this.titleMonth, k, 0), true, this.isSelectedDay(this.titleYear, this.titleMonth, k, 0)); temp.year = this.titleYear; temp.month = this.titleMonth; this.dates[i][j] = temp; } } } } } increaseMonth(): void { this.titleMonth++; if (this.titleMonth === 13) { this.titleYear++; this.titleMonth = 1; } this.pickerTitle = this.renderTitle(); this.calCalendar(); } decreaseMonth(): void { this.titleMonth--; if (this.titleMonth === 0) { this.titleYear--; this.titleMonth = 12; } this.pickerTitle = this.renderTitle(); this.calCalendar(); } isSelectedDay(y: number, m: number, d: number, num: number): boolean { let year: number = y; let month: number = m + num; if (month === 0) { year--; month = 12; } if (month === 13) { year++; month = 1; } if (year !== this.selectedDate.year) return false; if (month !== this.selectedDate.month) return false; if (d !== this.selectedDate.day) return false; return true; } isHoliday(y: number, m: number, d: number, num: number): boolean { let year: number = y; let month: number = m + num; if (month === 0) { year--; month = 12; } if (month === 13) { year++; month = 1; } let day = new Date(month + '/' + d + '/' + year); if (day.getDay() === 0 || day.getDay() === 6) return true; return false; } calMonthEndDay(y: number, m: number, num: number): number { let year: number = y; let month: number = m + num; if (month === 0) { year--; month = 12; } if (month === 13) { year++; month = 1; } return (year % 4 === 0) && (month === 2) ? this.monthDays[month - 1] + 1 : this.monthDays[month - 1]; } clearCalendar(): void { for (let i = 0; i < 6; i++) { for (let j = 0; j < 7; j++) { this.dates[i][j] = null; } } } resetCalendar(year: number, month: number): void { this.titleMonth = month; this.titleYear = year; // if (this.titleMonth === 12) { // this.titleYear++; // this.titleMonth = 1; // } if (this.titleMonth === 0) { this.titleYear--; this.titleMonth = 12; } this.pickerTitle = this.renderTitle(); this.calCalendar(); } selectBar(bar: QuickDateBar): void { if (bar.startDate && bar.endDate) { this.startDate = bar.startDate; this.endDate = bar.endDate; this.displayDate = (this.displayDateType ? bar.value : '') + this.renderDisplayDate(this.startDate) + ' - ' + this.renderDisplayDate(this.endDate); } else { this.startDate = bar.date || bar.startDate || bar.endDate; this.endDate = null; this.displayDate = (this.displayDateType ? bar.value : '') + this.renderDisplayDate(this.startDate); } this.isHidden = true; this.resetCalendar(this.startDate.getFullYear(), this.startDate.getMonth() + 1); this.selectedQuickDateBar = bar; this.outputEvent(); } setAvailableDates(bar: QuickDateBar): void { this.maxDate = (bar && bar.maxDate) ? bar.maxDate : this._maxDate; this.minDate = (bar && bar.minDate) ? bar.minDate : this._minDate; this.disabledDates = (bar && bar.disabledDates) ? bar.disabledDates : this._disabledDates; this.availableDates = (bar && bar.availableDates) ? bar.availableDates : this._availableDates; this._daysOfWeekDisabled = (bar && bar.daysOfWeekDisabled) ? bar.daysOfWeekDisabled : this._daysOfWeekDisabled; this.initInput(); } isBarSelected(bar: QuickDateBar): boolean { return this.selectedQuickDateBar === bar; } renderDisplayDate(date: Date): string { if (date) return (date.getDate() < 10 ? ('0' + date.getDate()) : date.getDate()) + '-' + this.monthName[date.getMonth()] + '-' + date.getFullYear(); } toggleCalendar(isHidden?: boolean): void { if (this.showYearMonth) { this.showYearMonth = false; } this.isHidden = isHidden ? isHidden : !this.isHidden; if (this.isHidden && this.startDate && this.startDate.toString() !== 'Invalid Date') { this.resetCalendar(this.startDate.getFullYear(), this.startDate.getMonth() + 1); } } outputEvent(): void { this.outputDate = { date: this.startDate, startDate: this.startDate, endDate: this.endDate, dateType: this.selectedQuickDateBar, dateStr: this.startDate?this.startDate.getFullYear() + '-' + this.toZero(this.startDate.getMonth()+1) + '-' + this.toZero(this.startDate.getDate()):'', startDateStr: this.startDate?this.startDate.getFullYear() + '-' + this.toZero(this.startDate.getMonth()+1) + '-' + this.toZero(this.startDate.getDate()):'', endDateStr: this.endDate?this.endDate.getFullYear() + '-' + this.toZero(this.endDate.getMonth()+1) + '-' + this.toZero(this.endDate.getDate()):'' }; if(this.isFormat){ this.outputDate.time = this.toZero(this.curHours) + ':' + this.toZero(this.curMinutes) + ':' + this.toZero(this.curSeconds); } if (!this.changeDateFlag) { this.ngModelChange.emit(this.outputDate); } this.changeDateFlag = false; } } export class Day { constructor(public date: number, public num?: number, public isHoliday?: boolean, public isInMonth?: boolean, public isSelected?: boolean, public isInRange?: boolean, public isDisabled?: boolean, public year?: number, public month?: number) { } } export class SelectedDate { constructor(public year: number, public month: number, public day: number, public hours: number, public minutes: number, public seconds: number) { } } export interface QuickDateBar { date?: Date; startDate?: Date; endDate?: Date; minDate?: Date; maxDate?: Date; disabledDates?: (Date | string)[]; availableDates?: (Date | string)[]; daysOfWeekDisabled?: number[]; label?: string; value?: string; monthly?: true; children?: QuickDateBar; } export interface OutputDate { date?: Date; startDate?: Date; endDate?: Date; dateType?: QuickDateBar; time?: String; dateStr?: String; startDateStr?: String; endDateStr?: String; }