WIP: componente non funzionante

This commit is contained in:
Alessandro Seravalli 2025-05-08 12:56:49 +02:00
parent 3082f2129e
commit 7a575c5375
69 changed files with 3548 additions and 7678 deletions

View File

@ -1,33 +1,20 @@
import { ModuleWithProviders, NgModule, NO_ERRORS_SCHEMA } from "@angular/core"; import { CommonModule } from "@angular/common";
import { ModuleWithProviders, NgModule, } from "@angular/core";
import { FormsModule } from "@angular/forms"; import { FormsModule } from "@angular/forms";
import { XdceArchModule } from "@isp/xdce-arch-core"; import { XdceArchModule } from "@isp/xdce-arch-core";
import { NbpModule, NgbDatepickerService, NgbDatepickerServiceNOA11Y } from "@isp/xdce-widget"; import { NbpModule } from "@isp/xdce-widget";
import { NgbModule } from "@ng-bootstrap/ng-bootstrap"; import { NgbModule } from "@ng-bootstrap/ng-bootstrap";
import { TranslateModule } from '@ngx-translate/core';
import { import {
AgGridModule, AgGridModule,
AngularFrameworkComponentWrapper, AngularFrameworkComponentWrapper,
AngularFrameworkOverrides, AngularFrameworkOverrides,
} from "ag-grid-angular"; } from "ag-grid-angular";
import { NgbFidDatepickerNavigation } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-navigation";
import { NbpBreadCrumbsComponent } from "./widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component"; import { NbpBreadCrumbsComponent } from "./widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component";
import { NbpFidBarChartComponent } from "./widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component"; import { NbpFidBarChartComponent } from "./widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component";
import { NbpFidButtonBarComponent } from "./widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component"; import { NbpFidButtonBarComponent } from "./widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component";
import { FidRplCalendarNOA11Y } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker"; import { RplDeclarations, RplEntryComponents, RplExports, RplRootProviders } from './widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply.module';
import { NgbFidDatepickerDayViewNOA11Y } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-day-view"; import { NbpFidCalendarGenericComponent } from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component";
import { NgbFidInputDatepickerNOA11Y } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-input";
import { NgbFidDatepickerNavigationNOA11Y } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-navigation";
import { NgbFidDatepickerReplyMonthViewNOA11Y } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply-month-view";
import { NgbFidDatepickerReplyYearsViewNOA11Y } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply-years-view";
import { NgbFidDatepickerRoutingViewNOA11Y } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-routing-view";
import { FidRplCalendar } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker";
import { NgbFidDatepickerDayView } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-day-view";
import { NgbFidInputDatepicker } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-input";
import { NgbFidDatepickerReplyMonthView } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-reply-month-view";
import { NgbFidDatepickerReplyYearsView } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-reply-years-view";
import { NgbFidDatepickerRoutingView } from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-routing-view";
import { NbpCalendarGenericComponentA11Y } from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-calendar-generic.component.a11y";
import { NbpCalendarGenericComponentNOA11Y } from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-calendar-generic.component.noa11y";
import { NbpFidCalendarGeneric } from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component";
import { NbpFidComboComponent } from "./widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component"; import { NbpFidComboComponent } from "./widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component";
import { NbpFidDonutChartComponent } from "./widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component"; import { NbpFidDonutChartComponent } from "./widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component";
import { NbpFidPyramidChartComponent } from "./widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component"; import { NbpFidPyramidChartComponent } from "./widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component";
@ -43,7 +30,6 @@ import { ShowcaseComponent } from "./widgetfideuram/components/showcase/showcase
import { Showcase1Component } from "./widgetfideuram/components/showcase/showcase1.component"; import { Showcase1Component } from "./widgetfideuram/components/showcase/showcase1.component";
import { WidgetFideuramShowcaseComponent } from "./widgetfideuram/components/widget-fideuram-showcase/widget-fideuram-showcase.component"; import { WidgetFideuramShowcaseComponent } from "./widgetfideuram/components/widget-fideuram-showcase/widget-fideuram-showcase.component";
export { AgGridModule } from "ag-grid-angular"; export { AgGridModule } from "ag-grid-angular";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-navigation";
export * from "./widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component"; export * from "./widgetfideuram/components/nbp-bread-crumbs/nbp-bread-crumbs.component";
export * from "./widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component"; export * from "./widgetfideuram/components/nbp-fid-bar-chart/nbp-fid-bar-chart.component";
export * from "./widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component"; export * from "./widgetfideuram/components/nbp-fid-button-bar/nbp-fid-button-bar.component";
@ -53,14 +39,9 @@ export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstra
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-navigation"; export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-navigation";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply-month-view"; export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply-month-view";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply-years-view"; export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply-years-view";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker"; export * from './widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap-noa11y/datepicker/datepicker-reply.module';
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-day-view";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-input";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-reply-month-view";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/@ng-bootstrap/datepicker/datepicker-reply-years-view";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-calendar-generic.component.a11y";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-calendar-generic.component.noa11y";
export * from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component"; export * from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component";
export { NbpFidCalendarGenericComponent } from "./widgetfideuram/components/nbp-fid-calendar-generic/nbp-fid-calendar-generic.component";
export * from "./widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component"; export * from "./widgetfideuram/components/nbp-fid-combo/nbp-fid-combo.component";
export * from "./widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component"; export * from "./widgetfideuram/components/nbp-fid-donut-chart/nbp-fid-donut-chart.component";
export * from "./widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component"; export * from "./widgetfideuram/components/nbp-fid-pyramid-chart/nbp-fid-pyramid-chart.component";
@ -78,8 +59,9 @@ export * from "./widgetfideuram/components/widget-fideuram-showcase/widget-fideu
export * from "./widgetfideuram/Utils"; export * from "./widgetfideuram/Utils";
@NgModule({ @NgModule({
imports: [XdceArchModule, NbpModule, AgGridModule, FormsModule, NgbModule], imports: [XdceArchModule, NbpModule, AgGridModule, FormsModule, NgbModule, TranslateModule, CommonModule],
declarations: [ declarations: [
NbpBreadCrumbsComponent, NbpBreadCrumbsComponent,
NbpFidBarChartComponent, NbpFidBarChartComponent,
@ -98,23 +80,8 @@ export * from "./widgetfideuram/Utils";
ShowcaseComponent, ShowcaseComponent,
Showcase1Component, Showcase1Component,
WidgetFideuramShowcaseComponent, WidgetFideuramShowcaseComponent,
NbpFidCalendarGeneric, NbpFidCalendarGenericComponent,
NgbFidInputDatepicker, ...RplDeclarations
FidRplCalendarNOA11Y,
NbpCalendarGenericComponentNOA11Y,
NbpCalendarGenericComponentA11Y,
FidRplCalendar,
NgbFidInputDatepickerNOA11Y,
NgbFidDatepickerRoutingView,
NgbFidDatepickerRoutingViewNOA11Y,
NgbFidDatepickerNavigation,
NgbFidDatepickerDayView,
NgbFidDatepickerReplyMonthView,
NgbFidDatepickerReplyYearsView,
NgbFidDatepickerNavigationNOA11Y,
NgbFidDatepickerDayViewNOA11Y,
NgbFidDatepickerReplyMonthViewNOA11Y,
NgbFidDatepickerReplyYearsViewNOA11Y
], ],
exports: [ exports: [
NbpBreadCrumbsComponent, NbpBreadCrumbsComponent,
@ -135,27 +102,12 @@ export * from "./widgetfideuram/Utils";
Showcase1Component, Showcase1Component,
WidgetFideuramShowcaseComponent, WidgetFideuramShowcaseComponent,
AgGridModule, AgGridModule,
NbpFidCalendarGeneric, NbpFidCalendarGenericComponent,
FidRplCalendarNOA11Y, ...RplExports
FidRplCalendar,
NgbFidDatepickerRoutingView,
NgbFidDatepickerRoutingViewNOA11Y,
NgbFidInputDatepickerNOA11Y,
NgbFidInputDatepicker,
NgbFidDatepickerNavigation,
NgbFidDatepickerDayView,
NgbFidDatepickerReplyMonthView,
NgbFidDatepickerReplyYearsView,
NgbFidDatepickerNavigationNOA11Y,
NgbFidDatepickerDayViewNOA11Y,
NgbFidDatepickerReplyMonthViewNOA11Y,
NgbFidDatepickerReplyYearsViewNOA11Y
], ],
providers: [ providers: [
AngularFrameworkOverrides, AngularFrameworkOverrides,
AngularFrameworkComponentWrapper, AngularFrameworkComponentWrapper,
{ provide: 'NgbDatepickerServiceNOA11Y', useClass: NgbDatepickerServiceNOA11Y },
{ provide: 'NgbDatepickerService', useClass: NgbDatepickerService }
], ],
entryComponents: [ entryComponents: [
NbpFidToggleTabComponentA11Y, NbpFidToggleTabComponentA11Y,
@ -164,28 +116,14 @@ export * from "./widgetfideuram/Utils";
NbpFidToggleTabsetComponentNOA11Y, NbpFidToggleTabsetComponentNOA11Y,
NbpFidToggleTabComponent, NbpFidToggleTabComponent,
NbpFidToggleTabsetComponent, NbpFidToggleTabsetComponent,
NbpCalendarGenericComponentA11Y, ...RplEntryComponents
NbpCalendarGenericComponentNOA11Y,
FidRplCalendarNOA11Y,
FidRplCalendar,
NgbFidDatepickerRoutingView,
NgbFidDatepickerRoutingViewNOA11Y,
NgbFidDatepickerNavigation,
NgbFidDatepickerDayView,
NgbFidDatepickerReplyMonthView,
NgbFidDatepickerReplyYearsView,
NgbFidDatepickerNavigationNOA11Y,
NgbFidDatepickerDayViewNOA11Y,
NgbFidDatepickerReplyMonthViewNOA11Y,
NgbFidDatepickerReplyYearsViewNOA11Y
], ],
schemas: [NO_ERRORS_SCHEMA]
}) })
export class XdceWidgetFideuramModule { export class XdceWidgetFideuramModule {
static forRoot(): ModuleWithProviders { static forRoot(): ModuleWithProviders {
return { return {
ngModule: XdceWidgetFideuramModule, ngModule: XdceWidgetFideuramModule,
providers: [], providers: [...RplRootProviders],
}; };
} }
} }

View File

@ -0,0 +1,26 @@
import {Injectable, TemplateRef} from '@angular/core';
import {DayTemplateContextNOA11Y} from './datepicker-day-template-context';
import {NgbDateStruct} from './ngb-date-struct';
/**
* Configuration service for the NgbDatepicker component.
* You can inject this service, typically in your root component, and customize the values of its properties in
* order to provide default values for all the datepickers used in the application.
*/
@Injectable()
export class NgbDatepickerConfigNOA11Y {
dayTemplate: TemplateRef<DayTemplateContextNOA11Y>;
displayMonths = 1;
firstDayOfWeek = 1;
markDisabled: (date: NgbDateStruct, current: {year: number, month: number}) => boolean;
minDate: NgbDateStruct;
maxDate: NgbDateStruct;
navigation: 'select' | 'arrows' | 'none' = 'select';
outsideDays: 'visible' | 'collapsed' | 'hidden' = 'visible';
showWeekdays = true;
showWeekNumbers = false;
startDate: {year: number, month: number};
disabledWeekend: boolean;
holidays: Array<NgbDateStruct>;
taxDeadlines: Array<NgbDateStruct>;
}

View File

@ -0,0 +1,56 @@
import {NgbDateStruct} from './ngb-date-struct';
/**
* Context for the datepicker 'day' template in case you want to override the default one
*/
export interface DayTemplateContextNOA11Y {
/**
* Month currently displayed by the datepicker
*/
currentMonth: number;
/**
* Date that corresponds to the template
*/
date: NgbDateStruct;
/**
* True if current date is disabled
*/
disabled: boolean;
/**
* True if current date is focused
*/
focused: boolean;
/**
* True if current date is selected
*/
selected: boolean;
/**
* True if current date is today
*/
isToday: boolean;
/**
* True if current date is a weekend day
*/
isWeekend: boolean;
/**
* True if current date is a weekend day
*/
isDayPast: boolean;
/**
* True if current date is a tax deadlines
*/
isFiscalDay: boolean;
/**
* True if current date is an holiday
*/
isHoliday?: boolean;
}

View File

@ -0,0 +1,4 @@
<div [ngClass]=" abilitaGiorni(date) ? 'ngbdatepickerdayview' : 'ngbdatepickerdayviewdisabled'">
<span [attr.role]="'button'" [attr.aria-label]="' '" [attr.aria.labelledby]="' '" [attr.aria-describedby]="labelDay(date)">{{ date.day }}</span>
<div *ngIf="isFiscalDay" class="is-fiscal"></div>
</div>

View File

@ -0,0 +1,32 @@
.ngbdatepickerdayview {
border-radius: 0!important;
box-sizing: border-box;
text-align: center;
width: inherit!important;
height: inherit!important;
line-height: 2.6875rem!important;
vertical-align: middle;
}
.ngbdatepickerdayviewdisabled {
box-sizing: border-box;
text-align: center;
width: inherit!important;
height: inherit!important;
line-height: 2.6875rem!important;
vertical-align: middle;
cursor: default;
}
.is-fiscal {
// Triangolo bianco
border-bottom-width: 0.5rem;
border-bottom-style: solid;
border-left: 0.5rem solid transparent;
border-right: 0.5rem solid transparent;
transform: rotate(45deg);
transform-origin: top;
position: absolute;
top: 0;
right: -0.5rem;
}

View File

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'; import {ChangeDetectionStrategy, Component, Input} from '@angular/core';
import { NgbDatepickerDayViewNOA11Y } from '@isp/xdce-widget'; import {NgbDateStruct} from './ngb-date-struct';
@Component({ @Component({
selector: '[ngbFidDatepickerDayView]', selector: '[ngbFidDatepickerDayView]',
@ -9,17 +9,63 @@ import { NgbDatepickerDayViewNOA11Y } from '@isp/xdce-widget';
'[class.bg-primary]': 'selected', '[class.bg-primary]': 'selected',
'[class.text-white]': 'selected', '[class.text-white]': 'selected',
'[class.text-muted]': 'isMuted()', '[class.text-muted]': 'isMuted()',
'[class.outside]': 'isOutside()', '[class.outside]': 'isMuted()',
'[class.notOutside]': '!isOutside()',
'[class.active]': 'focused', '[class.active]': 'focused',
'[class.is-today]': 'isToday', '[class.is-today]': 'isToday',
'[class.is-holiday]': 'isHoliday', '[class.is-holiday]' : 'isHoliday',
'[class.is-weekend]': 'isWeekend && !selected', '[class.is-weekend]': 'isWeekend',
'[class.is-daypast]': 'isDayPast', '[class.is-daypast]': 'isDayPast',
'[class.is-fiscal]': 'isFiscalDay' '[class.is-fiscal]' : 'isFiscalDay'
}, },
template: '<ng-container></ng-container>',
templateUrl: './datepicker-day-view.html',
styleUrls: ['./datepicker-day-view.scss'],
}) })
export class NgbFidDatepickerDayViewNOA11Y extends NgbDatepickerDayViewNOA11Y { export class NgbDatepickerDayViewNOA11Y {
@Input() currentMonth: number;
@Input() date: NgbDateStruct;
@Input() disabled: boolean;
@Input() focused: boolean;
@Input() selected: boolean;
@Input() startDateEnabled: any;
@Input() endDateEnabled: any;
@Input() isToday: boolean;
@Input() isWeekend: boolean;
@Input() isDayPast: boolean;
@Input() taxDeadlines: any;
@Input() isFiscalDay: boolean;
@Input() isHoliday : boolean;
isMuted() { return !this.selected && (this.date.month !== this.currentMonth || this.disabled); }
abilitaGiorni(data) {
let startDate, endDate;
let buffer = new Date(data.year, data.month - 1, data.day);
if (this.startDateEnabled instanceof Date) {
startDate = new Date(this.startDateEnabled.getFullYear(), this.startDateEnabled.getMonth(), this.startDateEnabled.getDate());
endDate = new Date(this.endDateEnabled.getFullYear(), this.endDateEnabled.getMonth(), this.endDateEnabled.getDate());
} else {
startDate = new Date(this.startDateEnabled.year, this.startDateEnabled.month - 1, this.startDateEnabled.day);
endDate = new Date(this.endDateEnabled.year, this.endDateEnabled.month - 1, this.endDateEnabled.day);
}
if (startDate && endDate) {
return (startDate <= buffer && buffer <= endDate);
} else {
return true;
}
}
labelDay(data){
let result;
let weekdays = ['Domenica', 'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato'];
result = weekdays[new Date(data.year, data.month - 1, data.day).getDay()] + ' ' + data.day;
return result;
}
} }

View File

@ -0,0 +1,47 @@
import {Injectable} from '@angular/core';
import { NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
const WEEKDAYS_SHORT = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'];
const MONTHS_SHORT = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
const MONTHS_FULL = [
'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November',
'December'
];
/**
* Type of the service supplying month and weekday names to to NgbDatepicker component.
* See the i18n demo for how to extend this class and define a custom provider for i18n.
*/
@Injectable()
export abstract class NgbDatepickerI18nNOA11Y {
/**
* Returns the short weekday name to display in the heading of the month view.
* With default calendar we use ISO 8601: 'weekday' is 1=Mon ... 7=Sun
*/
abstract getWeekdayShortName(weekday: number): string;
/**
* Returns the short month name to display in the date picker navigation.
* With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec
*/
abstract getMonthShortName(month: number): string;
/**
* Returns the full month name to display in the date picker navigation.
* With default calendar we use ISO 8601: 'month' is 1=January ... 12=December
*/
abstract getMonthFullName(month: number): string;
abstract getDayAriaLabel(date: NgbDateStruct): string;
}
@Injectable()
export class NgbDatepickerI18nDefaultNOA11Y extends NgbDatepickerI18nNOA11Y {
getWeekdayShortName(weekday: number): string { return WEEKDAYS_SHORT[weekday - 1]; }
getMonthShortName(month: number): string { return MONTHS_SHORT[month - 1]; }
getMonthFullName(month: number): string { return MONTHS_FULL[month - 1]; }
getDayAriaLabel(date: NgbDateStruct): string { return `${date.day} ${MONTHS_FULL[date.month-1]} ${date.year}`}
}

View File

@ -1,55 +1,45 @@
import { import {
ComponentFactoryResolver,
ComponentRef,
Directive, Directive,
ElementRef,
EventEmitter,
Input, Input,
ComponentRef,
ElementRef,
ViewContainerRef,
Renderer2,
ComponentFactoryResolver,
NgZone, NgZone,
TemplateRef,
forwardRef,
EventEmitter,
Output,
OnChanges, OnChanges,
OnDestroy, OnDestroy,
Output, SimpleChanges, QueryList
Renderer2, } from '@angular/core';
SimpleChanges, import { AbstractControl, ControlValueAccessor, Validator, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
TemplateRef,
ViewContainerRef, import { NgbDate } from './ngb-date';
forwardRef, import { RplCalendarNOA11Y, NgbDatepickerNavigateEventNOA11Y } from './datepicker';
} from "@angular/core"; import { DayTemplateContextNOA11Y } from './datepicker-day-template-context';
import { import { NgbDateParserFormatterNOA11Y } from './ngb-date-parser-formatter';
AbstractControl,
ControlValueAccessor, import { Positioning } from '../util/positioning';
NG_VALIDATORS, import { NgbDateStruct } from './ngb-date-struct';
NG_VALUE_ACCESSOR, import { NgbCalendarNOA11Y } from './ngb-calendar';
Validator, import { NgbDatepickerServiceNOA11Y } from './datepicker-service';
} from "@angular/forms"; import {NbpCalendarPattern, NbpCalendarPosition, NbpDateSeparator} from '../../nbp-calendar-generic.enum';
import { EventManager } from "@isp/xdce-arch-core-base"; import {EventManager, NATIVE_CONNECTOR} from '@isp/xdce-arch-core-base';
import { import {take} from 'rxjs/operators';
DayTemplateContextNOA11Y,
NbpCalendarPattern,
NbpCalendarPosition,
NbpDateSeparator,
NgbCalendarNOA11Y,
NgbDate,
NgbDateParserFormatterNOA11Y,
NgbDateStruct,
NgbDatepickerNavigateEventNOA11Y,
NgbDatepickerServiceNOA11Y,
} from "@isp/xdce-widget";
import { Positioning } from "../util/positioning";
import {
FidRplCalendarNOA11Y,
} from "./datepicker";
const NGB_DATEPICKER_VALUE_ACCESSOR = { const NGB_DATEPICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgbFidInputDatepickerNOA11Y), useExisting: forwardRef(() => NgbInputDatepickerNOA11Y),
multi: true, multi: true
}; };
const NGB_DATEPICKER_VALIDATOR = { const NGB_DATEPICKER_VALIDATOR = {
provide: NG_VALIDATORS, provide: NG_VALIDATORS,
useExisting: forwardRef(() => NgbFidInputDatepickerNOA11Y), useExisting: forwardRef(() => NgbInputDatepickerNOA11Y),
multi: true, multi: true
}; };
/** /**
@ -57,25 +47,21 @@ const NGB_DATEPICKER_VALIDATOR = {
* Manages integration with the input field itself (data entry) and ngModel (validation etc.). * Manages integration with the input field itself (data entry) and ngModel (validation etc.).
*/ */
@Directive({ @Directive({
selector: "input[fidRplCalendarNOA11Y]", selector: 'input[rplFidCalendarNOA11Y]',
exportAs: "fidRplCalendarNOA11Y", exportAs: 'rplFidCalendarNOA11Y',
host: { host: {
"(input)": "waitForFormat($event.target.value)", '(input)': 'waitForFormat($event.target.value)',
"(change)": "manualDateChange($event.target.value, true)", '(change)': 'manualDateChange($event.target.value, true)',
"(keyup.esc)": "close()", '(keyup.esc)': 'close()',
"(blur)": "onBlur()", '(blur)': 'onBlur()',
"(document:click)": "onFocusOut($event)", '(document:click)':'onFocusOut($event)'
}, },
providers: [ providers: [NGB_DATEPICKER_VALUE_ACCESSOR, NGB_DATEPICKER_VALIDATOR, NgbDatepickerServiceNOA11Y]
NGB_DATEPICKER_VALUE_ACCESSOR,
NGB_DATEPICKER_VALIDATOR,
NgbDatepickerServiceNOA11Y,
],
}) })
export class NgbFidInputDatepickerNOA11Y
implements OnChanges, OnDestroy, ControlValueAccessor, Validator export class NgbInputDatepickerNOA11Y implements OnChanges,
{ OnDestroy, ControlValueAccessor, Validator {
private _cRef: ComponentRef<FidRplCalendarNOA11Y> = null; private _cRef: ComponentRef<RplCalendarNOA11Y> = null;
private _model: NgbDate; private _model: NgbDate;
private _zoneSubscription: any; private _zoneSubscription: any;
@ -101,10 +87,7 @@ export class NgbFidInputDatepickerNOA11Y
* Callback to mark a given date as disabled. * Callback to mark a given date as disabled.
* 'Current' contains the month that will be displayed in the view * 'Current' contains the month that will be displayed in the view
*/ */
@Input() markDisabled: ( @Input() markDisabled: (date: NgbDateStruct, current: { year: number, month: number }) => boolean;
date: NgbDateStruct,
current: { year: number; month: number }
) => boolean;
/** /**
* Min date for the navigation. If not provided will be 10 years before today or `startDate` * Min date for the navigation. If not provided will be 10 years before today or `startDate`
@ -134,19 +117,20 @@ export class NgbFidInputDatepickerNOA11Y
* Navigation type: `select` (default with select boxes for month and year), `arrows` * Navigation type: `select` (default with select boxes for month and year), `arrows`
* (without select boxes, only navigation arrows) or `none` (no navigation at all) * (without select boxes, only navigation arrows) or `none` (no navigation at all)
*/ */
@Input() navigation: "select" | "arrows" | "none"; @Input() navigation: 'select' | 'arrows' | 'none';
/** /**
* The way to display days that don't belong to current month: `visible` (default), * The way to display days that don't belong to current month: `visible` (default),
* `hidden` (not displayed) or `collapsed` (not displayed with empty space collapsed) * `hidden` (not displayed) or `collapsed` (not displayed with empty space collapsed)
*/ */
@Input() outsideDays: "visible" | "collapsed" | "hidden"; @Input() outsideDays: 'visible' | 'collapsed' | 'hidden';
/** /**
* Placement of a datepicker popup. Accepts: "top", "bottom", "left", "right", "bottom-left", * Placement of a datepicker popup. Accepts: "top", "bottom", "left", "right", "bottom-left",
* "bottom-right" etc. * "bottom-right" etc.
*/ */
@Input() placement = "bottom-left"; @Input() placement = 'bottom-left';
/** /**
* Whether to display days of the week * Whether to display days of the week
@ -164,7 +148,7 @@ export class NgbFidInputDatepickerNOA11Y
* If nothing or invalid date provided, calendar will open with current month. * If nothing or invalid date provided, calendar will open with current month.
* Use 'navigateTo(date)' as an alternative * Use 'navigateTo(date)' as an alternative
*/ */
@Input() startDate: { year: number; month: number }; @Input() startDate: { year: number, month: number };
@Input() disabledWeekend: boolean; @Input() disabledWeekend: boolean;
@ -189,15 +173,15 @@ export class NgbFidInputDatepickerNOA11Y
*/ */
@Output() navigate = new EventEmitter<NgbDatepickerNavigateEventNOA11Y>(); @Output() navigate = new EventEmitter<NgbDatepickerNavigateEventNOA11Y>();
private _onChange = (_: any) => {}; private _onChange = (_: any) => { };
private _onTouched = () => {}; private _onTouched = () => { };
private _validatorChange = () => {}; private _validatorChange = () => { };
private _placement: any = NbpCalendarPosition; private _placement: any = NbpCalendarPosition;
private positionService: Positioning; private positionService: Positioning;
private get isInModal(): boolean { private get isInModal(): boolean {
let el: HTMLElement = <HTMLElement>this._elRef.nativeElement; let el: HTMLElement = (<HTMLElement> this._elRef.nativeElement);
if (!el || !el.parentElement || !el.parentElement.tagName) { if (!el || !el.parentElement || !el.parentElement.tagName) {
return false; return false;
@ -206,39 +190,28 @@ export class NgbFidInputDatepickerNOA11Y
while (!tagName.match(/modal/i) && !tagName.match(/body/i)) { while (!tagName.match(/modal/i) && !tagName.match(/body/i)) {
el = el.parentElement; el = el.parentElement;
tagName = tagName = el.parentElement && el.parentElement.tagName ? el.parentElement.tagName : '';
el.parentElement && el.parentElement.tagName
? el.parentElement.tagName
: "";
} }
return tagName && !!tagName.match(/modal/i); return tagName && !!tagName.match(/modal/i);
} }
private get isCorporate(): boolean { private get isCorporate(): boolean {
return this._cRef.location.nativeElement.classList.contains( return this._cRef.location.nativeElement.classList.contains('isp-corporate-mode-wrapper');
"isp-corporate-mode-wrapper"
);
} }
get _isNative(): boolean { get _isNative(): boolean {
return /(ip(a|o)d|iphone|android)/gi.test(window.navigator.userAgent); return /(ip(a|o)d|iphone|android)/ig.test(window.navigator.userAgent)
} }
constructor( constructor(
private _parserFormatter: NgbDateParserFormatterNOA11Y, private _parserFormatter: NgbDateParserFormatterNOA11Y, private _elRef: ElementRef, private _vcRef: ViewContainerRef,
private _elRef: ElementRef, private _renderer: Renderer2, private _cfr: ComponentFactoryResolver, ngZone: NgZone,
private _vcRef: ViewContainerRef, private _service: NgbDatepickerServiceNOA11Y, private _calendar: NgbCalendarNOA11Y,
private _renderer: Renderer2,
private _cfr: ComponentFactoryResolver,
ngZone: NgZone,
private _service: NgbDatepickerServiceNOA11Y,
private _calendar: NgbCalendarNOA11Y,
private eventManager: EventManager private eventManager: EventManager
) { ) {
this.positionService = new Positioning(); this.positionService = new Positioning();
this._zoneSubscription = ngZone.onStable.subscribe(() => this._zoneSubscription = ngZone.onStable.subscribe(() => this.setDatepickerPosition());
this.setDatepickerPosition()
);
} }
setDatepickerPosition() { setDatepickerPosition() {
@ -247,66 +220,40 @@ export class NgbFidInputDatepickerNOA11Y
} }
const calendar: HTMLElement = this._cRef.location.nativeElement; const calendar: HTMLElement = this._cRef.location.nativeElement;
const datepickerInput: HTMLElement = this._elRef.nativeElement; const datepickerInput: HTMLElement = this._elRef.nativeElement;
const calendarClone: HTMLElement = <HTMLElement>calendar.cloneNode(true); const calendarClone: HTMLElement = (<HTMLElement>calendar.cloneNode(true));
this._renderer.removeClass( this._renderer.removeClass(calendarClone.querySelector('.isp-main-datepicker'), 'd-none');
calendarClone.querySelector(".isp-main-datepicker"), this._renderer.addClass(calendarClone, 'invisible');
"d-none"
);
this._renderer.addClass(calendarClone, "invisible");
window.document.body.appendChild(calendarClone); window.document.body.appendChild(calendarClone);
const navigation: number = calendarClone.querySelector( const navigation: number = calendarClone.querySelector(".isp-datepicker-navigation")['offsetHeight'];
".isp-datepicker-navigation" const routingView: number = calendarClone.querySelector(".isp-datepicker-routing-view")['offsetHeight'];
)["offsetHeight"]; const position: ClientRect = this.positionService.positionElements(datepickerInput, calendarClone, this.placement);
const routingView: number = calendarClone.querySelector(
".isp-datepicker-routing-view"
)["offsetHeight"];
const position: ClientRect = this.positionService.positionElements(
datepickerInput,
calendarClone,
this.placement
);
this._renderer.removeChild(calendarClone.parentElement, calendarClone); this._renderer.removeChild(calendarClone.parentElement, calendarClone);
switch (this.placement) { switch (this.placement) {
case this._placement.TOP: case this._placement.TOP:
case this._placement.TOP_RIGHT: case this._placement.TOP_RIGHT:
case this._placement.TOP_LEFT: case this._placement.TOP_LEFT:
position.top = this.isCorporate position.top = this.isCorporate ? (-navigation - routingView) : (-navigation - routingView - 3);
? -navigation - routingView
: -navigation - routingView - 3;
break; break;
case this._placement.RIGHT: case this._placement.RIGHT:
case this._placement.LEFT: case this._placement.LEFT:
position.top = -navigation - routingView / 2; position.top = (-navigation - (routingView / 2));
break; break;
} }
calendar.style.top = `${position.top}px`; calendar.style.top = `${position.top}px`;
calendar.style.left = `${position.left}px`; calendar.style.left = `${position.left}px`;
this._renderer.removeClass( this._renderer.removeClass(calendar.querySelector('.isp-main-datepicker'), 'd-none');
calendar.querySelector(".isp-main-datepicker"),
"d-none"
);
} }
registerOnChange(fn: (value: any) => any): void { registerOnChange(fn: (value: any) => any): void { this._onChange = fn; }
this._onChange = fn;
}
registerOnTouched(fn: () => any): void { registerOnTouched(fn: () => any): void { this._onTouched = fn; }
this._onTouched = fn;
}
registerOnValidatorChange(fn: () => void): void { registerOnValidatorChange(fn: () => void): void { this._validatorChange = fn; };
this._validatorChange = fn;
}
setDisabledState(isDisabled: boolean): void { setDisabledState(isDisabled: boolean): void {
this._renderer.setProperty( this._renderer.setProperty(this._elRef.nativeElement, 'disabled', isDisabled);
this._elRef.nativeElement,
"disabled",
isDisabled
);
if (this.isOpen()) { if (this.isOpen()) {
this._cRef.instance.setDisabledState(isDisabled); this._cRef.instance.setDisabledState(isDisabled);
} }
@ -319,55 +266,40 @@ export class NgbFidInputDatepickerNOA11Y
return null; return null;
} }
if (typeof value === "string") { if (typeof value === 'string') {
let newValue: NgbDate; let newValue: NgbDate;
newValue = new NgbDate( newValue = new NgbDate(parseInt(value.substring(0, 4), 10),
parseInt(value.substring(0, 4), 10),
parseInt(value.substring(5, 7), 10), parseInt(value.substring(5, 7), 10),
parseInt(value.substring(8, 10), 10) parseInt(value.substring(8, 10), 10));
);
if (!this._calendar.isValid(newValue)) { if (!this._calendar.isValid(newValue)) {
return { ngbDate: { invalid: c.value } }; return { 'ngbDate': { invalid: c.value } };
} }
if ( if (this.minDate && NgbDate.from(newValue).before(NgbDate.from(this.minDate))) {
this.minDate && return { 'ngbDate': { requiredBefore: this.minDate } };
NgbDate.from(newValue).before(NgbDate.from(this.minDate))
) {
return { ngbDate: { requiredBefore: this.minDate } };
} }
if ( if (this.maxDate && NgbDate.from(newValue).after(NgbDate.from(this.maxDate))) {
this.maxDate && return { 'ngbDate': { requiredAfter: this.maxDate } };
NgbDate.from(newValue).after(NgbDate.from(this.maxDate))
) {
return { ngbDate: { requiredAfter: this.maxDate } };
} }
} else { } else {
if (!this._calendar.isValid(value)) { if (!this._calendar.isValid(value)) {
return { ngbDate: { invalid: c.value } }; return { 'ngbDate': { invalid: c.value } };
} }
if ( if (this.minDate && NgbDate.from(value).before(NgbDate.from(this.minDate))) {
this.minDate && return { 'ngbDate': { requiredBefore: this.minDate } };
NgbDate.from(value).before(NgbDate.from(this.minDate))
) {
return { ngbDate: { requiredBefore: this.minDate } };
} }
if ( if (this.maxDate && NgbDate.from(value).after(NgbDate.from(this.maxDate))) {
this.maxDate && return { 'ngbDate': { requiredAfter: this.maxDate } };
NgbDate.from(value).after(NgbDate.from(this.maxDate))
) {
return { ngbDate: { requiredAfter: this.maxDate } };
} }
} }
} }
writeValue(value: any) { writeValue(value: any) {
const ngbDate = value const ngbDate = value ? new NgbDate(value.year, value.month, value.day) : null;
? new NgbDate(value.year, value.month, value.day)
: null;
this._model = this._calendar.isValid(value) ? ngbDate : null; this._model = this._calendar.isValid(value) ? ngbDate : null;
this._writeModelValue(this._model); this._writeModelValue(this._model);
} }
@ -384,52 +316,38 @@ export class NgbFidInputDatepickerNOA11Y
manualDateChange(value: string, updateView = false) { manualDateChange(value: string, updateView = false) {
let datesplitted = value.split(/[./-]/g); let datesplitted = value.split(/[./-]/g);
if ( if(this.nbpLabelPattern == this._pattern.MMAAAA && datesplitted.length < 3 && datesplitted.length > 1)
this.nbpLabelPattern == this._pattern.MMAAAA && {
datesplitted.length < 3 && value = '01.' + value;
datesplitted.length > 1
) {
value = "01." + value;
} }
let [year, month, day] = value.split("-"); let [year, month, day] = value.split('-');
if (this.isUnifiedVg && this._isNative) { if (this.isUnifiedVg && this._isNative) {
if (year && month && day) { if (year && month && day) {
// value = day + '.' + month + '.' + year; // value = day + '.' + month + '.' + year;
} }
} }
this._model = this._service.toValidDate( this._model = this._service.toValidDate(this._parserFormatter.parse(value, this.nbpLabelPattern), null);
this._parserFormatter.parse(value, this.nbpLabelPattern), this._onChange(this._model ? this._model.toStruct() : (value === '' ? null : value));
null
);
this._onChange(
this._model ? this._model.toStruct() : value === "" ? null : value
);
if (updateView && this._model) { if (updateView && this._model) {
this._writeModelValue(this._model); this._writeModelValue(this._model);
} }
} }
isOpen() { isOpen() { return !!this._cRef; }
return !!this._cRef;
}
/** /**
* Opens the datepicker with the selected date indicated by the ngModel value. * Opens the datepicker with the selected date indicated by the ngModel value.
*/ */
open(mode: boolean) { open(mode: boolean) {
if (!this.isOpen()) { if (!this.isOpen()) {
if (this._model && (this.minDate || this.maxDate)) { if (this._model && (this.minDate || this.maxDate)) {
if ( if ((this.minDate && NgbDate.from(this._model).before(NgbDate.from(this.minDate))) || (this.maxDate && NgbDate.from(this._model).after(NgbDate.from(this.maxDate)))) {
(this.minDate &&
NgbDate.from(this._model).before(NgbDate.from(this.minDate))) ||
(this.maxDate &&
NgbDate.from(this._model).after(NgbDate.from(this.maxDate)))
) {
this._model = null; this._model = null;
} }
} }
const cf = this._cfr.resolveComponentFactory(FidRplCalendarNOA11Y); const cf = this._cfr.resolveComponentFactory(RplCalendarNOA11Y);
this._cRef = this._vcRef.createComponent(cf); this._cRef = this._vcRef.createComponent(cf);
this._applyPopupStyling(this._cRef.location.nativeElement); this._applyPopupStyling(this._cRef.location.nativeElement);
@ -441,11 +359,8 @@ export class NgbFidInputDatepickerNOA11Y
this._cRef.instance.holidays = this.holidays; this._cRef.instance.holidays = this.holidays;
this._cRef.instance.taxDeadlines = this.taxDeadlines; this._cRef.instance.taxDeadlines = this.taxDeadlines;
if (mode) { if (mode){
this._renderer.addClass( this._renderer.addClass(this._cRef.location.nativeElement, 'isp-corporate-mode-wrapper');
this._cRef.location.nativeElement,
"isp-corporate-mode-wrapper"
);
} }
this._cRef.instance.ngOnInit(); this._cRef.instance.ngOnInit();
@ -470,7 +385,7 @@ export class NgbFidInputDatepickerNOA11Y
if (this.isOpen()) { if (this.isOpen()) {
this._vcRef.remove(this._vcRef.indexOf(this._cRef.hostView)); this._vcRef.remove(this._vcRef.indexOf(this._cRef.hostView));
this._cRef = null; this._cRef = null;
this.eventManager.emit("DATEPICKER_CLOSE", true); this.eventManager.emit('DATEPICKER_CLOSE', true);
} }
} }
@ -487,31 +402,20 @@ export class NgbFidInputDatepickerNOA11Y
addMargin(value: string) { addMargin(value: string) {
if (this._cRef) { if (this._cRef) {
this._renderer.setStyle( this._renderer.setStyle(this._cRef.location.nativeElement, "margin-top", value);
this._cRef.location.nativeElement,
"margin-top",
value
);
} }
} }
onFocusOut($event) { onFocusOut($event) {
const parent: HTMLElement = this._elRef.nativeElement.parentElement; const parent: HTMLElement = this._elRef.nativeElement.parentElement;
const icon: HTMLElement = parent.querySelector("i"); const icon: HTMLElement = parent.querySelector('i');
if ( if(this.isOpen() && !(event.target === icon || this._elRef.nativeElement.contains($event.target) || this._cRef.location.nativeElement.contains($event.target))) {
this.isOpen() &&
!(
event.target === icon ||
this._elRef.nativeElement.contains($event.target) ||
this._cRef.location.nativeElement.contains($event.target)
)
) {
this._cRef.instance.focusOutComponent($event); this._cRef.instance.focusOutComponent($event);
console.info("onfocusout close"); console.info('onfocusout close');
this.close(); this.close();
if (this.eventManager) { if (this.eventManager) {
this.eventManager.emit("HANDLER_CALENDAR", {}); this.eventManager.emit('HANDLER_CALENDAR', {});
} }
} }
} }
@ -522,18 +426,16 @@ export class NgbFidInputDatepickerNOA11Y
* If nothing or invalid date provided calendar will open current month. * If nothing or invalid date provided calendar will open current month.
* Use 'startDate' input as an alternative * Use 'startDate' input as an alternative
*/ */
navigateTo(date?: { year: number; month: number }) { navigateTo(date?: { year: number, month: number }) {
if (this.isOpen()) { if (this.isOpen()) {
this._cRef.instance.navigateTo(date); this._cRef.instance.navigateTo(date);
} }
} }
onBlur() { onBlur() { this._onTouched(); }
this._onTouched();
}
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (changes["minDate"] || changes["maxDate"]) { if (changes['minDate'] || changes['maxDate']) {
this._validatorChange(); this._validatorChange();
} }
} }
@ -564,20 +466,10 @@ export class NgbFidInputDatepickerNOA11Y
return 0; return 0;
} }
private _applyDatepickerInputs(datepickerInstance: FidRplCalendarNOA11Y): void { private _applyDatepickerInputs(datepickerInstance: RplCalendarNOA11Y): void {
[ ['dayTemplate', 'displayMonths', 'firstDayOfWeek', 'markDisabled', 'minDate', 'maxDate', 'navigation',
"dayTemplate", 'outsideDays', 'showNavigation', 'showWeekdays', 'showWeekNumbers']
"displayMonths", .forEach((optionName: string) => {
"firstDayOfWeek",
"markDisabled",
"minDate",
"maxDate",
"navigation",
"outsideDays",
"showNavigation",
"showWeekdays",
"showWeekNumbers",
].forEach((optionName: string) => {
if ((this as any)[optionName] !== undefined) { if ((this as any)[optionName] !== undefined) {
(datepickerInstance as any)[optionName] = (this as any)[optionName]; (datepickerInstance as any)[optionName] = (this as any)[optionName];
} }
@ -586,53 +478,27 @@ export class NgbFidInputDatepickerNOA11Y
} }
private _applyPopupStyling(nativeElement: any) { private _applyPopupStyling(nativeElement: any) {
this._renderer.addClass(nativeElement, "dropdown-menu"); this._renderer.addClass(nativeElement, 'dropdown-menu');
this._renderer.setStyle(nativeElement, "padding", "0"); this._renderer.setStyle(nativeElement, 'padding', '0');
} }
private _subscribeForDatepickerOutputs( private _subscribeForDatepickerOutputs(datepickerInstance: RplCalendarNOA11Y) {
datepickerInstance: FidRplCalendarNOA11Y datepickerInstance.navigate.subscribe((date: any) => this.navigate.emit(date));
) {
datepickerInstance.navigate.subscribe((date: any) =>
this.navigate.emit(date)
);
} }
private _writeModelValue(model: NgbDate) { private _writeModelValue(model: NgbDate) {
if (model) { if (model) {
const { day, month, year } = model; const { day, month, year } = model;
if (this.nbpLabelPattern == this._pattern.MMAAAA) { if(this.nbpLabelPattern == this._pattern.MMAAAA) {
this._renderer.setProperty( this._renderer.setProperty(this._elRef.nativeElement, 'value', this._parserFormatter.format({year, month, day: 0}, this.nbpLabelPattern, this.nbpDateSeparator));
this._elRef.nativeElement,
"value",
this._parserFormatter.format(
{ year, month, day: 0 },
this.nbpLabelPattern,
this.nbpDateSeparator
)
);
} else {
this._renderer.setProperty(
this._elRef.nativeElement,
"value",
this._parserFormatter.format(
{ year, month, day },
this.nbpLabelPattern,
this.nbpDateSeparator
)
);
} }
else {
this._renderer.setProperty(this._elRef.nativeElement, 'value', this._parserFormatter.format({year, month, day}, this.nbpLabelPattern, this.nbpDateSeparator));
}
} else { } else {
this._renderer.setProperty( this._renderer.setProperty(this._elRef.nativeElement, 'value', this._parserFormatter.format(model, this.nbpLabelPattern, this.nbpDateSeparator));
this._elRef.nativeElement,
"value",
this._parserFormatter.format(
model,
this.nbpLabelPattern,
this.nbpDateSeparator
)
);
} }
if (this.isOpen()) { if (this.isOpen()) {

View File

@ -0,0 +1,75 @@
import {Injectable} from '@angular/core';
import {NgbDatepickerServiceNOA11Y} from './datepicker-service';
import {NgbCalendarNOA11Y} from './ngb-calendar';
import {toString} from '../util/util';
import {NgbDate} from './ngb-date';
enum Key {
Enter = 13,
Space = 32,
PageUp = 33,
PageDown = 34,
End = 35,
Home = 36,
ArrowLeft = 37,
ArrowUp = 38,
ArrowRight = 39,
ArrowDown = 40
}
@Injectable()
export class NgbDatepickerKeyMapServiceNOA11Y {
private _minDate: NgbDate;
private _maxDate: NgbDate;
private _firstViewDate: NgbDate;
private _lastViewDate: NgbDate;
constructor(private _service: NgbDatepickerServiceNOA11Y, private _calendar: NgbCalendarNOA11Y) {
_service.model$.subscribe(model => {
this._minDate = model.minDate;
this._maxDate = model.maxDate;
this._firstViewDate = model.firstDate;
this._lastViewDate = model.lastDate;
});
}
processKey(event: KeyboardEvent) {
if (Key[toString(event.which)]) {
switch (event.which) {
case Key.PageUp:
this._service.focusMove(event.shiftKey ? 'y' : 'm', -1);
break;
case Key.PageDown:
this._service.focusMove(event.shiftKey ? 'y' : 'm', 1);
break;
case Key.End:
this._service.focus(event.shiftKey ? this._maxDate : this._lastViewDate);
break;
case Key.Home:
this._service.focus(event.shiftKey ? this._minDate : this._firstViewDate);
break;
case Key.ArrowLeft:
this._service.focusMove('d', -1);
break;
case Key.ArrowUp:
this._service.focusMove('d', -this._calendar.getDaysPerWeek());
break;
case Key.ArrowRight:
this._service.focusMove('d', 1);
break;
case Key.ArrowDown:
this._service.focusMove('d', this._calendar.getDaysPerWeek());
break;
case Key.Enter:
case Key.Space:
this._service.focusSelect();
break;
default:
return;
}
event.preventDefault();
event.stopPropagation();
}
}
}

View File

@ -0,0 +1,8 @@
<select [disabled]="disabled" class="custom-select d-inline-block" [value]="date?.month" (change)="changeMonth($event.target.value)"
tabindex="-1">
<option *ngFor="let m of months" [value]="m">{{ i18n.getMonthShortName(m) }}</option>
</select>
<select [disabled]="disabled" class="custom-select d-inline-block" [value]="date?.year" (change)="changeYear($event.target.value)"
tabindex="-1">
<option *ngFor="let y of years" [value]="y">{{ y }}</option>
</select>

View File

@ -0,0 +1,41 @@
select {
font-family: sans-serif;
margin: 0;
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
line-height: 1.25;
height: inherit;
width: 50%;
-ms-touch-action: manipulation;
touch-action: manipulation;
text-transform: none;
.custom-select {
display: inline-block;
max-width: 100%;
height: calc(2.25rem + 0.125rem);
padding: .375rem 1.75rem .375rem .75rem;
line-height: 1.25;
vertical-align: middle;
border-width: 0.0625rem;
border-style: solid;
border-radius: .25rem;
-moz-appearance: none;
-webkit-appearance: none;
}
.d-inline-block {
display: inline-block !important;
}
}
optgroup {
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
}
/* mounth and Year*/
ngb-datepicker-navigation-select.d-block {
width: 9rem !important;
}

View File

@ -0,0 +1,55 @@
import { Component, Input, Output, EventEmitter, OnChanges, SimpleChanges, ChangeDetectionStrategy } from '@angular/core';
import { NgbDate } from './ngb-date';
import { toInteger } from '../util/util';
import { NgbDatepickerI18nNOA11Y } from './datepicker-i18n';
import { NgbCalendarNOA11Y } from './ngb-calendar';
@Component({
selector: 'ngb-fid-datepicker-navigation-select',
changeDetection: ChangeDetectionStrategy.OnPush,
templateUrl: './datepicker-navigation-select.html',
styleUrls: ['./datepicker-navigation-select.scss'],
})
export class NgbDatepickerNavigationSelectNOA11Y implements OnChanges {
months: number[];
years: number[] = [];
@Input() date: NgbDate;
@Input() disabled: boolean;
@Input() maxDate: NgbDate;
@Input() minDate: NgbDate;
@Output() select = new EventEmitter<NgbDate>();
constructor(public i18n: NgbDatepickerI18nNOA11Y, private calendar: NgbCalendarNOA11Y) { this.months = calendar.getMonths(); }
ngOnChanges(changes: SimpleChanges) {
if (changes['maxDate'] || changes['minDate'] || changes['date']) {
this._generateYears();
this._generateMonths();
}
}
changeMonth(month: string) { this.select.emit(new NgbDate(this.date.year, toInteger(month), 1)); }
changeYear(year: string) { this.select.emit(new NgbDate(toInteger(year), this.date.month, 1)); }
private _generateMonths() {
this.months = this.calendar.getMonths();
if (this.date && this.date.year === this.minDate.year) {
const index = this.months.findIndex(month => month === this.minDate.month);
this.months = this.months.slice(index);
}
if (this.date && this.date.year === this.maxDate.year) {
const index = this.months.findIndex(month => month === this.maxDate.month);
this.months = this.months.slice(0, index + 1);
}
}
private _generateYears() {
this.years = Array.from({ length: this.maxDate.year - this.minDate.year + 1 }, (e, i) => this.minDate.year + i);
}
}

View File

@ -0,0 +1,58 @@
<ng-template #retail>
<div class="isp-datepicker-navigation">
<span>
<!-- Bottone mensile ad una freccia -->
<button type='button' class='btn btn-sm btn-link camillo' (click)='!!doNavigate(navigation.PREV)'
[disabled]='prevDisabled()' tabindex='-1'
[attr.role]="'button'" [attr.aria-label]="' '">
<span class='ngb-dp-navigation-chevron camillo'></span>
</button>
</span>
<div class="header-navigation-date" (click)="setTemplate()">
<ngb-fid-datepicker-navigation-select *ngIf='showSelect' class='d-block' [style.width.rem]='months * 9' [date]='date'
[minDate]='minDate'
[maxDate]='maxDate' [disabled]='disabled'
(select)='selectDate($event)'></ngb-fid-datepicker-navigation-select>
</div>
<span>
<!-- Bottone mensile ad una freccia -->
<button type='button' class='btn btn-sm btn-link camillo' (click)='!!doNavigate(navigation.NEXT)'
[disabled]='nextDisabled()' tabindex='-1'
[attr.role]="'button'" [attr.aria-label]="' '">
<span class='ngb-dp-navigation-chevron right camillo'></span>
</button>
</span>
</div>
</ng-template>
<ng-template #corporate>
<div class="isp-datepicker-navigation">
<span>
<!-- Bottone mensile ad una freccia -->
<button type='button' class='btn btn-sm btn-link camillo' (click)='!!doNavigate(navigation.PREV)'
[disabled]='prevDisabled()' tabindex='-1'
[attr.role]="'button'" [attr.aria-label]="' '">
<span class='icomoon-Simboli_Risorsa-12 camillo'></span>
</button>
</span>
<div class="header-navigation-date" (click)="setTemplate()">
<ngb-fid-datepicker-navigation-select *ngIf='showSelect' class='d-block' [style.width.rem]='months * 9' [date]='date'
[minDate]='minDate'
[maxDate]='maxDate' [disabled]='disabled'
(select)='selectDate($event)'></ngb-fid-datepicker-navigation-select>
</div>
<span>
<!-- Bottone mensile ad una freccia -->
<button type='button' class='btn btn-sm btn-link camillo' (click)='!!doNavigate(navigation.NEXT)'
[disabled]='nextDisabled()' tabindex='-1'
[attr.role]="'button'" [attr.aria-label]="' '">
<span class='icomoon-Simboli_Risorsa-13 right camillo'></span>
</button>
</span>
</div>
</ng-template>
<ng-container [ngTemplateOutlet]="widgetTemplate"></ng-container>

View File

@ -0,0 +1,108 @@
:host(.isp-corporate-mode-wrapper) {
.isp-datepicker-navigation {
span button {
&.btn-link {
span.icomoon-Simboli_Risorsa-13, span.icomoon-Simboli_Risorsa-12 {
&::before {
border: none;
transform: none;
margin: 0;
font-weight: bold!important;
display: inline-block;
height: 0.75rem;
width: 0.75rem;
}
&.right {
&::before {
transform: none;
display: inline-block;
height: 0.75rem;
width: 0.75rem;
}
}
}
}
}
}
}
.isp-datepicker-navigation {
width: 100%;
height: 3.125rem;
line-height: 1.85rem;
-webkit-box-pack: justify !important;
-ms-flex-pack: justify !important;
justify-content: space-between !important;
display: -webkit-box !important;
display: -ms-flexbox !important;
display: flex !important;
border-top-width: 0.0625rem;
border-top-style: solid;
span button {
text-decoration: none;
font-family: sans-serif;
font-size: 100%;
line-height: 1.15;
margin: 0;
text-transform: none;
overflow: visible;
-webkit-appearance: button;
-ms-touch-action: manipulation;
touch-action: manipulation;
&.btn-link {
width: 3.3125rem;
min-height: 100% !important;
cursor: pointer;
border-style: solid;
border-width: 0.0625rem !important;
font-weight: 400;
border-radius: 0;
span.ngb-dp-navigation-chevron {
&::before {
border-style: solid;
border-width: 0.125rem 0.125rem 0rem 0rem;
content: '';
display: inline-block;
height: 0.75rem;
transform: rotate(-135deg);
-webkit-transform: rotate(-135deg);
-ms-transform: rotate(-135deg);
width: 0.75rem;
margin: 0 0 0 0.5rem;
}
&.right {
&::before {
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
margin: 0 0.5rem 0 0;
}
}
}
}
&.camillo {
display: inline-block;
margin: 0;
padding: 0;
border-top: none;
border-bottom: none;
border-left-width: 0.0625rem;
border-left-style: solid;
border-right-width: 0.0625rem;
border-right-style: solid;
}
}
.header-navigation-date {
min-width: 8.3125rem;
min-height: 100%;
cursor: pointer;
}
}
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 100%;
vertical-align: baseline;
}

View File

@ -1,13 +1,87 @@
import { ChangeDetectionStrategy, Component } from "@angular/core"; import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, Injector } from '@angular/core';
import { NgbDatepickerNavigationNOA11Y } from "@isp/xdce-widget"; import { NavigationEvent } from './datepicker-view-model';
import { NgbDate } from './ngb-date';
import { NgbDatepickerI18nNOA11Y } from './datepicker-i18n';
import { NgbCalendarNOA11Y } from './ngb-calendar';
import { NgbDateStruct } from './ngb-date-struct';
import { NbpBaseComponent } from '@isp/xdce-widget/base';
import { CalendarItemNOA11Y } from './datepicker';
@Component({ @Component({
selector: 'ngb-fid-datepicker-navigation', selector: 'ngb-fid-datepicker-navigation',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { 'class': 'd-flex justify-content-between', '[class.collapsed]': '!showSelect' }, host: { 'class': 'd-flex justify-content-between', '[class.collapsed]': '!showSelect' },
template: '<ng-container></ng-container>', templateUrl: './datepicker-navigation.html',
styleUrls: ['./datepicker-navigation.scss'],
}) })
export class NgbFidDatepickerNavigationNOA11Y extends NgbDatepickerNavigationNOA11Y { export class NgbDatepickerNavigationNOA11Y extends NbpBaseComponent{
navigation = NavigationEvent;
@Input() date: NgbDate;
@Input() disabled: boolean;
@Input() months: number;
@Input() years: CalendarItemNOA11Y [][];
@Input() showSelect: boolean;
@Input() showWeekNumbers: boolean;
@Input() template: number = 0;
@Input() disabledWeekend: boolean;
@Input() holidays: Array<NgbDateStruct>
@Input() taxDeadlines: Array<NgbDateStruct>
@Output() navigate = new EventEmitter<NavigationEvent>();
@Output() select = new EventEmitter<NgbDate>();
@Output() newTemplate = new EventEmitter<number>();
_minDate: NgbDate;
@Input()
get minDate() {
return this._minDate;
}
set minDate(minDate: NgbDate) {
this._minDate = minDate;
}
_maxDate: NgbDate;
@Input()
get maxDate() {
return this._maxDate;
}
set maxDate(maxDate: NgbDate) {
this._maxDate = maxDate;
}
constructor(public i18n: NgbDatepickerI18nNOA11Y, private _calendar: NgbCalendarNOA11Y, private injector : Injector) {
super(injector);
}
doNavigate(event: NavigationEvent) {
this.navigate.emit(event);
}
nextDisabled() {
let yearsSize = 0;
this.years.forEach(row => yearsSize += row.length);
return this.disabled || (this.maxDate && ((this.template == 0 && this._calendar.getNext(this.date, 'm').after(this.maxDate))
|| (this.template == 1 && this.date.year + 1 > this.maxDate.year)
|| (this.template == 2 && this.years[0][0].number + yearsSize > this.maxDate.year)));
}
prevDisabled() {
let prevMonthDate = new Date(this.date.year, this.date.month + 1, 0);
let prevMonth = new NgbDate(prevMonthDate.getFullYear(), prevMonthDate.getMonth() - 1, prevMonthDate.getDate());
return this.disabled || (this.minDate && ((this.template == 0 && prevMonth.before(this.minDate))
|| (this.template == 1 && this.date.year - 1 < this.minDate.year)
|| (this.template == 2 && this.years[0][0].number - 1 < this.minDate.year)));
}
selectDate(date: NgbDate) {
this.select.emit(date);
}
setTemplate() {
this.template = (this.template + 1) % 3;
this.newTemplate.emit(this.template);
}
} }

View File

@ -0,0 +1,3 @@
<div [ngClass]=" abilitaMesi(mese) ? 'ngbdatepickerreplymonthview' : 'ngbdatepickerreplymonthviewdisabled disabledView'">
<span [attr.role]="'button'" [attr.aria-label]="' '" [attr.aria.labelledby]="' '" [attr.aria-describedby]="' '">{{ mese.name | translate | slice: 0:3 | uppercase }}</span>
</div>

View File

@ -0,0 +1,20 @@
div[ngbFidDatepickerReplyMonthView] {
border-radius: 0 !important;
box-sizing: border-box;
text-align: center;
min-width: 4.95rem !important;
height: 2.8125rem !important;
line-height: 2.8125rem !important;
vertical-align: middle !important;
border-right-width: 0.0625rem;
border-right-style: solid;
border-top-width: 0.0625rem;
border-top-style: solid;
border-collapse: collapse;
border-spacing: 0;
.ngbdatepickerreplymonthviewdisabled {
cursor: default;
opacity: 0.5;
}
}

View File

@ -1,5 +1,9 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ChangeDetectionStrategy, Component, Input, OnInit, OnChanges, SimpleChanges, OnDestroy } from '@angular/core';
import { NgbDatepickerReplyMonthViewNOA11Y } from '@isp/xdce-widget'; import { NgbMeseStruct } from './ngb-mese-struct';
import { NgbYearStruct } from './ngb-year-struct';
import { NgbDatepickerServiceNOA11Y } from './datepicker-service';
import { Subscription } from 'rxjs';
import { DatepickerViewModel } from './datepicker-view-model';
@Component({ @Component({
@ -11,12 +15,72 @@ import { NgbDatepickerReplyMonthViewNOA11Y } from '@isp/xdce-widget';
'[class.text-white]': 'selected', '[class.text-white]': 'selected',
'[class.text-muted]': 'isMuted()', '[class.text-muted]': 'isMuted()',
'[class.outside]': 'isMuted()', '[class.outside]': 'isMuted()',
'[class.focused]': 'mounthFocusVisible',
'[class.active]': 'focused', '[class.active]': 'focused',
'[class.is-current]': 'isCurrent', '[class.is-current]': 'isCurrent'
'[attr.tabindex]':"focused && mounthFocusVisible ? 0 : -1"
}, },
template: '<ng-container></ng-container>'
templateUrl: './datepicker-reply-month-view.html',
styleUrls: ['./datepicker-reply-month-view.scss'],
}) })
export class NgbFidDatepickerReplyMonthViewNOA11Y extends NgbDatepickerReplyMonthViewNOA11Y { export class NgbDatepickerReplyMonthViewNOA11Y implements OnInit, OnDestroy {
@Input() currentMonth: number;
@Input() mese: NgbMeseStruct;
@Input() year: number;
@Input() disabled: boolean;
@Input() focused: boolean;
@Input() selected: boolean;
@Input() startDateEnabled: any;
@Input() endDateEnabled: any;
isCurrent : boolean = false;
private _sub : Subscription;
ngOnDestroy(): void {
// if(this._sub) {
// this._sub.unsubscribe();
// }
}
ngOnInit() {
const now = new Date();
// console.info('onInit month', this.mese.number, (now.getMonth()+1), this.year, now.getFullYear(), this.mese.number === (now.getMonth()+1), this.year === now.getFullYear());
// console.info('onInit month', typeof (this.mese.number), typeof ((now.getMonth()+1)), typeof (this.year), typeof (now.getFullYear()), this.mese.number === (now.getMonth()+1), this.year === now.getFullYear());
// console.info('onInit month selected', this.selected);
this.isCurrent = this.mese.number === (now.getMonth()+1) && this.year === now.getFullYear();
this.setSelected(this.service._model$.getValue());
}
isMuted() { return false };
abilitaMesi(data) {
return (((this.startDateEnabled.year == this.year && this.startDateEnabled.month <= data.number) ||
(data.number < this.startDateEnabled.month && this.startDateEnabled.year < this.year) ||
(this.startDateEnabled.month <= data.number && this.startDateEnabled.year <= this.year))
&& ((data.number <= this.endDateEnabled.month && this.year <= this.endDateEnabled.year) || (data.number > this.endDateEnabled.month && this.year < this.endDateEnabled.year)))
}
setSelected(model : DatepickerViewModel) {
// console.info('selected:month', model, this.mese, this.year);
if(model && model.selectedDate) {
this.selected = (this.mese && this.mese.number === model.selectedDate.month) && this.year === model.selectedDate.year;
return;
}
// console.info('selected:month no current, checking first');
if(model && model.firstDate) {
this.selected = (this.mese && this.mese.number === model.firstDate.month) && this.year === model.firstDate.year;
return;
}
}
constructor(private service : NgbDatepickerServiceNOA11Y) {
// this._sub = this.service.model$.subscribe(this.setSelected);
}
// isMuted() { return !this.selected && (this.mese.number !== this.currentMonth || this.disabled); }
} }

View File

@ -0,0 +1,3 @@
<div [ngClass]=" abilitaAnni(year) ? 'ngbDatepickerReplyYearsView' : 'ngbDatepickerReplyYearsViewdisabled disabledView'">
<span [attr.role]="'button'" [attr.aria-label]="' '" [attr.aria.labelledby]="' '" [attr.aria-describedby]="' '">{{ year.name }}</span>
</div>

View File

@ -0,0 +1,19 @@
div[ngbFidDatepickerReplyYearsView] {
border-radius: 0 !important;
box-sizing: border-box;
text-align: center;
min-width: 4.95rem !important;
height: 2.8125rem !important;
line-height: 2.8125rem !important;
vertical-align: middle !important;
border-right-width: 0.0625rem;
border-right-style: solid;
border-top-width: 0.0625rem;
border-top-style: solid;
border-collapse: collapse;
border-spacing:0.0625rem;
.ngbDatepickerReplyYearsViewdisabled {
cursor: default;
opacity: 0.5;
}
}

View File

@ -1,5 +1,8 @@
import { ChangeDetectionStrategy, Component } from '@angular/core'; import { ChangeDetectionStrategy, Component, Input, OnInit, OnDestroy } from '@angular/core';
import { NgbDatepickerReplyYearsViewNOA11Y } from '@isp/xdce-widget'; import { NgbYearStruct } from './ngb-year-struct';
import { NgbDatepickerServiceNOA11Y } from './datepicker-service';
import { Subscription } from 'rxjs';
import { DatepickerViewModel } from './datepicker-view-model';
@Component({ @Component({
selector: '[ngbFidDatepickerReplyYearsView]', selector: '[ngbFidDatepickerReplyYearsView]',
@ -11,12 +14,66 @@ import { NgbDatepickerReplyYearsViewNOA11Y } from '@isp/xdce-widget';
'[class.text-muted]': 'isMuted()', '[class.text-muted]': 'isMuted()',
'[class.outside]': 'isMuted()', '[class.outside]': 'isMuted()',
'[class.active]': 'focused', '[class.active]': 'focused',
'[class.focused]': 'yearFocusVisible', '[class.is-current]':'isCurrent'
'[class.is-current]':'isCurrent',
'[attr.tabindex]':"focused && yearFocusVisible ? 0 : -1"
}, },
template: '<ng-container></ng-container>',
templateUrl: './datepicker-reply-years-view.html',
styleUrls: ['./datepicker-reply-years-view.scss'],
}) })
export class NgbFidDatepickerReplyYearsViewNOA11Y extends NgbDatepickerReplyYearsViewNOA11Y { export class NgbDatepickerReplyYearsViewNOA11Y implements OnInit, OnDestroy {
@Input() currentMonth: number;
@Input() year: NgbYearStruct;
@Input() disabled: boolean;
@Input() focused: boolean;
@Input() selected: boolean;
@Input() startDateEnabled: any;
@Input() endDateEnabled: any;
isCurrent : boolean = false;
private _sub : Subscription;
isMuted() { return false };
ngOnInit(): void {
const now = new Date();
this.isCurrent = this.year.number === now.getFullYear();
this.setSelected(this.service._model$.getValue());
}
setSelected(model : DatepickerViewModel) {
// console.info('selected:year', model, this.year);
if(model && model.selectedDate) {
this.selected = this.year && model.selectedDate.year === this.year.number;
return;
}
// console.info('selected:year no current, checking first');
if(model && model.firstDate) {
this.selected = this.year && model.firstDate.year === this.year.number;
}
}
ngOnDestroy(): void {
// if(this._sub) {
// this._sub.unsubscribe();
// }
}
abilitaAnni(data) {
if(this.startDateEnabled.year <= data.number && data.number <= this.endDateEnabled.year){
return true
}
return false
}
constructor(private service : NgbDatepickerServiceNOA11Y) {
// this._sub = this.service.model$.subscribe(this.setSelected);
}
// isMuted() { return !this.selected && (this.mese.number !== this.currentMonth || this.disabled); }
} }

View File

@ -0,0 +1,49 @@
import { RplCalendarNOA11Y } from './datepicker';
import { NgbDatepickerConfigNOA11Y } from './datepicker-config';
import { NgbDatepickerDayViewNOA11Y } from './datepicker-day-view';
import { NgbDatepickerI18nDefaultNOA11Y, NgbDatepickerI18nNOA11Y } from './datepicker-i18n';
import { NgbInputDatepickerNOA11Y } from './datepicker-input';
import { NgbDatepickerNavigationNOA11Y } from './datepicker-navigation';
import { NgbDatepickerNavigationSelectNOA11Y } from './datepicker-navigation-select';
import { NgbDatepickerReplyMonthViewNOA11Y } from './datepicker-reply-month-view';
import { NgbDatepickerReplyYearsViewNOA11Y } from './datepicker-reply-years-view';
import { NgbDatepickerRoutingViewNOA11Y } from './datepicker-routing-view';
import { NgbCalendarGregorianNOA11Y, NgbCalendarNOA11Y } from './ngb-calendar';
import { NgbDateISOParserFormatterNOA11Y, NgbDateParserFormatterNOA11Y } from './ngb-date-parser-formatter';
export * from './datepicker';
export * from './datepicker-config';
export * from './datepicker-day-template-context';
export * from './datepicker-day-view';
export * from './datepicker-i18n';
export * from './datepicker-input';
export * from './datepicker-keymap-service';
export * from './datepicker-navigation';
export * from './datepicker-navigation-select';
export * from './datepicker-reply-month-view';
export * from './datepicker-reply-years-view';
export * from './datepicker-routing-view';
export * from './datepicker-service';
export * from './hijri/ngb-calendar-hijri';
export * from './hijri/ngb-calendar-islamic-civil';
export * from './ngb-calendar';
export * from './ngb-date-parser-formatter';
export const RplDeclarations = [
RplCalendarNOA11Y,
NgbDatepickerRoutingViewNOA11Y,
NgbDatepickerNavigationNOA11Y,
NgbDatepickerNavigationSelectNOA11Y,
NgbDatepickerDayViewNOA11Y,
NgbDatepickerReplyMonthViewNOA11Y,
NgbDatepickerReplyYearsViewNOA11Y,
NgbInputDatepickerNOA11Y
];
export const RplExports = [RplCalendarNOA11Y, NgbInputDatepickerNOA11Y];
export const RplEntryComponents = [RplCalendarNOA11Y];
export const RplRootProviders = [
{ provide: NgbCalendarNOA11Y, useClass: NgbCalendarGregorianNOA11Y },
{ provide: NgbDatepickerI18nNOA11Y, useClass: NgbDatepickerI18nDefaultNOA11Y },
{ provide: NgbDateParserFormatterNOA11Y, useClass: NgbDateISOParserFormatterNOA11Y }, NgbDatepickerConfigNOA11Y
];

View File

@ -1,58 +1,42 @@
import { import {
ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output,
ChangeDetectorRef, TemplateRef, ChangeDetectionStrategy, ChangeDetectorRef, SimpleChanges, OnChanges, OnDestroy, ViewChild, ElementRef
Component, } from '@angular/core';
ElementRef, import {DayViewModel, MonthViewModel, WeekViewModel} from './datepicker-view-model';
EventEmitter, import {NgbDate} from './ngb-date';
Input, import {NgbDatepickerI18nNOA11Y} from './datepicker-i18n';
OnChanges, import {DayTemplateContextNOA11Y} from './datepicker-day-template-context';
OnDestroy, import {NgbDataTemplateStruct} from './ngb-dataTemplate-struct';
OnInit, import { NgbDatepickerServiceNOA11Y } from './datepicker-service';
Output, import { CalendarItemNOA11Y } from './datepicker';
SimpleChanges, import { Subscription } from 'rxjs';
TemplateRef,
ViewChild,
} from "@angular/core";
import {
CalendarItemNOA11Y,
DayTemplateContextNOA11Y,
DayViewModel,
MonthViewModel,
NgbDataTemplateStruct,
NgbDate,
NgbDatepickerI18nNOA11Y,
NgbDatepickerServiceNOA11Y,
WeekViewModel
} from "@isp/xdce-widget";
import { Subscription } from "rxjs";
@Component({ @Component({
selector: "ngb-datepicker-routing-view", selector: 'ngb-fid-datepicker-routing-view',
host: { class: "d-block" }, host: { 'class': 'd-block' },
templateUrl: './datepicker-routing-view.html', templateUrl: './datepicker-routing-view.html',
styleUrls: ["./datepicker-routing-view.scss"], styleUrls: ['./datepicker-routing-view.scss'],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush
}) })
export class NgbFidDatepickerRoutingViewNOA11Y export class NgbDatepickerRoutingViewNOA11Y implements OnInit, OnChanges, OnDestroy {
implements OnInit, OnChanges, OnDestroy
{
@Input() dayTemplate: TemplateRef<DayTemplateContextNOA11Y>; @Input() dayTemplate: TemplateRef<DayTemplateContextNOA11Y>;
@Input() monthTemplate: TemplateRef<DayTemplateContextNOA11Y>; @Input() monthTemplate: TemplateRef<DayTemplateContextNOA11Y>;
@Input() yearsTemplate: TemplateRef<DayTemplateContextNOA11Y>; @Input() yearsTemplate: TemplateRef<DayTemplateContextNOA11Y>;
@Input() currentTemplate: number; @Input() currentTemplate: number;
@Input() mesi: any; @Input() mesi: any;
@Input() years: any; @Input() years: any;
@Input() disabledWeekend: boolean; @Input() disabledWeekend : boolean;
@Input() date: any; @Input() date: any;
@Input() dataTemplate: NgbDataTemplateStruct; @Input() dataTemplate: NgbDataTemplateStruct;
@Input() month: MonthViewModel; @Input() month: MonthViewModel;
@Input() outsideDays: "visible" | "hidden" | "collapsed"; @Input() outsideDays: 'visible' | 'hidden' | 'collapsed';
@Input() showWeekdays; @Input() showWeekdays;
@Input() showWeekNumbers; @Input() showWeekNumbers;
@Input() startDateEnabled: any; @Input() startDateEnabled: any;
@Input() endDateEnabled: any; @Input() endDateEnabled: any;
@ -60,21 +44,20 @@ export class NgbFidDatepickerRoutingViewNOA11Y
@Input() isWeekend: boolean; @Input() isWeekend: boolean;
@Input() taxDeadlines: any; @Input() taxDeadlines: any;
@Output() select = new EventEmitter<NgbDate>(); @Output() select = new EventEmitter<NgbDate>();
@Output() changeTemplate = new EventEmitter<NgbDataTemplateStruct>(); @Output() changeTemplate = new EventEmitter<NgbDataTemplateStruct>();
@ViewChild("ispDatepickerRoutingView") routingView: ElementRef; @ViewChild("ispDatepickerRoutingView") routingView: ElementRef;
currentYear: number; currentYear : number;
currentMonth: number; currentMonth : number;
currentDay: number; currentDay : number;
sub: Subscription; sub: Subscription;
constructor( constructor(public i18n: NgbDatepickerI18nNOA11Y, private cdr: ChangeDetectorRef, private service : NgbDatepickerServiceNOA11Y) {
public i18n: NgbDatepickerI18nNOA11Y,
private cdr: ChangeDetectorRef, }
private service: NgbDatepickerServiceNOA11Y
) {}
ngOnInit() { ngOnInit() {
// alert("in select in routing : " + this.startDateEnabled) // alert("in select in routing : " + this.startDateEnabled)
// alert("in select in routing : " + this.endDateEnabled) // alert("in select in routing : " + this.endDateEnabled)
@ -85,7 +68,7 @@ export class NgbFidDatepickerRoutingViewNOA11Y
this.dataTemplate.month = this.date && this.date.month; this.dataTemplate.month = this.date && this.date.month;
this.dataTemplate.year = this.date && this.date.year; this.dataTemplate.year = this.date && this.date.year;
const model = this.service._model$.getValue(); const model = this.service._model$.getValue();
if (model && model.selectedDate) { if(model && model.selectedDate) {
this.currentDay = model.selectedDate.day; this.currentDay = model.selectedDate.day;
this.currentMonth = model.selectedDate.month; this.currentMonth = model.selectedDate.month;
this.currentYear = model.selectedDate.year; this.currentYear = model.selectedDate.year;
@ -98,6 +81,7 @@ export class NgbFidDatepickerRoutingViewNOA11Y
// } // }
// }) // })
// console.info('routing init', this.date, this.dataTemplate); // console.info('routing init', this.date, this.dataTemplate);
} }
ngOnDestroy(): void { ngOnDestroy(): void {
@ -106,15 +90,15 @@ export class NgbFidDatepickerRoutingViewNOA11Y
// } // }
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes : SimpleChanges) {
if (changes.years) { if(changes.years) {
this.years = [...changes.years.currentValue]; this.years = [...changes.years.currentValue];
} }
if (changes.currentTemplate || changes.dataTemplate) { if(changes.currentTemplate || changes.dataTemplate) {
this.resetMesi(); this.resetMesi();
this.resetAnni(); this.resetAnni();
const model = this.service._model$.getValue(); const model = this.service._model$.getValue();
if (model && model.selectedDate) { if(model && model.selectedDate) {
this.currentDay = model.selectedDate.day; this.currentDay = model.selectedDate.day;
this.currentMonth = model.selectedDate.month; this.currentMonth = model.selectedDate.month;
this.currentYear = model.selectedDate.year; this.currentYear = model.selectedDate.year;
@ -123,7 +107,8 @@ export class NgbFidDatepickerRoutingViewNOA11Y
this.cdr.detectChanges(); this.cdr.detectChanges();
} }
doSelect(day: DayViewModel, $event: any) { doSelect(day: DayViewModel, $event : any) {
if (!this.abilitaGiorni(day.date)) { if (!this.abilitaGiorni(day.date)) {
return; return;
} }
@ -149,46 +134,34 @@ export class NgbFidDatepickerRoutingViewNOA11Y
} }
abilitaGiorni(data) { abilitaGiorni(data) {
let buffer = new Date(data.year, data.month - 1, data.day); let buffer = new Date(data.year, data.month - 1, data.day);
let startDate = new Date( let startDate = new Date(this.startDateEnabled.year, this.startDateEnabled.month - 1, this.startDateEnabled.day);
this.startDateEnabled.year,
this.startDateEnabled.month - 1,
this.startDateEnabled.day
);
let endDate = new Date( let endDate = new Date(this.endDateEnabled.year, this.endDateEnabled.month - 1, this.endDateEnabled.day);
this.endDateEnabled.year,
this.endDateEnabled.month - 1, return (startDate <= buffer && buffer <= endDate);
this.endDateEnabled.day
);
return startDate <= buffer && buffer <= endDate;
} }
abilitaMesi(data) { abilitaMesi(data) {
return (
((this.startDateEnabled.year == this.dataTemplate.year && return (((this.startDateEnabled.year == this.dataTemplate.year && this.startDateEnabled.month <= data.number) ||
this.startDateEnabled.month <= data.number) || (data.number < this.startDateEnabled.month && this.startDateEnabled.year < this.dataTemplate.year) ||
(data.number < this.startDateEnabled.month && (this.startDateEnabled.month <= data.number && this.startDateEnabled.year <= this.dataTemplate.year))
this.startDateEnabled.year < this.dataTemplate.year) || && ((data.number <= this.endDateEnabled.month && this.dataTemplate.year <= this.endDateEnabled.year) || (data.number > this.endDateEnabled.month && this.dataTemplate.year < this.endDateEnabled.year)))
(this.startDateEnabled.month <= data.number &&
this.startDateEnabled.year <= this.dataTemplate.year)) &&
((data.number <= this.endDateEnabled.month &&
this.dataTemplate.year <= this.endDateEnabled.year) ||
(data.number > this.endDateEnabled.month &&
this.dataTemplate.year < this.endDateEnabled.year))
);
} }
abilitaAnni(data) { abilitaAnni(data) {
return (
this.startDateEnabled.year <= data.number && return (this.startDateEnabled.year <= data.number && data.number <= this.endDateEnabled.year);
data.number <= this.endDateEnabled.year
);
} }
doSelectMonth(mese: any, $event: any) { doSelectMonth(mese: any, $event: any) {
if (!this.abilitaMesi(mese)) { if (!this.abilitaMesi(mese)) {
return; return;
} }
@ -199,11 +172,8 @@ export class NgbFidDatepickerRoutingViewNOA11Y
// reset giorni // reset giorni
this.month.weeks.forEach((week) => { this.month.weeks.forEach((week) => {
week.days.forEach((day) => { week.days.forEach((day) => {
day.context.selected = day.context.selected = day.date.day === this.currentDay && day.date.month === this.currentMonth && day.date.year === this.currentYear;
day.date.day === this.currentDay && })
day.date.month === this.currentMonth &&
day.date.year === this.currentYear;
});
}); });
this.resetMesi(); this.resetMesi();
@ -214,6 +184,7 @@ export class NgbFidDatepickerRoutingViewNOA11Y
} }
doSelectYear(year: any, $event: any) { doSelectYear(year: any, $event: any) {
if (!this.abilitaAnni(year)) { if (!this.abilitaAnni(year)) {
return; return;
} }
@ -231,28 +202,22 @@ export class NgbFidDatepickerRoutingViewNOA11Y
} }
isCollapsed(week: WeekViewModel) { isCollapsed(week: WeekViewModel) {
return ( return this.outsideDays === 'collapsed' && week.days[0].date.month !== this.month.number &&
this.outsideDays === "collapsed" && week.days[week.days.length - 1].date.month !== this.month.number;
week.days[0].date.month !== this.month.number &&
week.days[week.days.length - 1].date.month !== this.month.number
);
} }
isHiddenWeek(week: WeekViewModel) { isHiddenWeek(week: WeekViewModel) {
let counter = 0; let counter = 0;
for (let i = 0; i < week.days.length; i++) { for(let i=0; i<week.days.length; i++) {
if (this.isHidden(week.days[i])) { if (this.isHidden(week.days[i])) {
counter++; counter ++;
} }
} }
return counter === 7; return counter === 7;
} }
isHidden(day: DayViewModel) { isHidden(day: DayViewModel) {
return ( return (this.outsideDays === 'hidden' || this.outsideDays === 'collapsed') && this.month.number !== day.date.month;
(this.outsideDays === "hidden" || this.outsideDays === "collapsed") &&
this.month.number !== day.date.month
);
} }
getRoutingViewHeight() { getRoutingViewHeight() {
@ -263,25 +228,23 @@ export class NgbFidDatepickerRoutingViewNOA11Y
return this.routingView.nativeElement.offsetWidth; return this.routingView.nativeElement.offsetWidth;
} }
private resetMesi() { private resetMesi(){
let months: CalendarItemNOA11Y[][] = []; let months : CalendarItemNOA11Y[][] = [];
months = this.mesi.map((row) => { months = this.mesi.map((row) => {
return row.map((m) => { return row.map((m) => {
const res = { ...m }; const res = {...m};
res.selected = res.selected = res.number === this.currentMonth && this.dataTemplate.year === this.currentYear;
res.number === this.currentMonth &&
this.dataTemplate.year === this.currentYear;
return res; return res;
}); })
}); });
this.mesi = months; this.mesi = months;
} }
private resetAnni() { private resetAnni() {
let yrs: CalendarItemNOA11Y[][] = []; let yrs : CalendarItemNOA11Y[][] = [];
yrs = this.years.map((row) => { yrs = this.years.map((row) => {
return row.map((y) => { return row.map((y) => {
const res = { ...y }; const res = {...y};
res.selected = res.number === this.currentYear; res.selected = res.number === this.currentYear;
return res; return res;
}); });

View File

@ -0,0 +1,273 @@
import {NgbCalendarNOA11Y, NgbPeriodNOA11Y} from './ngb-calendar';
import {NgbDate} from './ngb-date';
import {DatepickerViewModel, NgbMarkDisabled} from './datepicker-view-model';
import {Injectable} from '@angular/core';
import {isInteger} from '../util/util';
import {Subject, Observable, BehaviorSubject} from 'rxjs';
import {buildMonths, checkDateInRange, checkMinBeforeMax, isChangedDate, isDateSelectable} from './datepicker-tools';
import {filter} from 'rxjs/operators';
import { NgbDateStruct } from './ngb-date-struct';
@Injectable()
export class NgbDatepickerServiceNOA11Y {
private _state: DatepickerViewModel =
{disabled: false,
displayMonths: 1,
firstDayOfWeek: 1,
focusVisible: false,
months: [],
selectedDate: null
};
public _model$ = new BehaviorSubject<DatepickerViewModel>(this._state);
get model$() : Observable<DatepickerViewModel> { return this._model$.asObservable().pipe(filter(model => model.months.length > 0)); }
set disabled(disabled: boolean) {
if (this._state.disabled !== disabled) {
this._nextState({disabled: disabled});
}
}
set displayMonths(months: number) {
if (isInteger(months) && months > 0 && this._state.displayMonths !== months) {
this._nextState({displayMonths: months});
}
}
set firstDayOfWeek(firstDayOfWeek: number) {
if (isInteger(firstDayOfWeek) && firstDayOfWeek >= 0 && this._state.firstDayOfWeek !== firstDayOfWeek) {
this._nextState({firstDayOfWeek: firstDayOfWeek});
}
}
set focusVisible(focusVisible: boolean) {
if (this._state.focusVisible !== focusVisible && !this._state.disabled) {
this._nextState({focusVisible: focusVisible});
}
}
set maxDate(date: NgbDate) {
if (date === undefined || this._calendar.isValid(date) && isChangedDate(this._state.maxDate, date)) {
this._nextState({maxDate: date});
}
}
set markDisabled(markDisabled: NgbMarkDisabled) {
if (this._state.markDisabled !== markDisabled) {
this._nextState({markDisabled: markDisabled});
}
}
set minDate(date: NgbDate) {
if (date === undefined || this._calendar.isValid(date) && isChangedDate(this._state.minDate, date)) {
this._nextState({minDate: date});
}
}
set disabledWeekend(disabledWeekend: boolean) {
if (this._state.disabledWeekend !== disabledWeekend) {
this._nextState({disabledWeekend: disabledWeekend});
}
}
set holidays(holidays: Array<NgbDateStruct>) {
if (this._state.holidays !== holidays) {
this._nextState({holidays: holidays});
}
}
set taxDeadlines(taxDeadlines: Array<NgbDateStruct>) {
if (this._state.taxDeadlines !== taxDeadlines) {
this._nextState({taxDeadlines: taxDeadlines});
}
}
constructor(private _calendar: NgbCalendarNOA11Y) {}
focus(date: NgbDate) {
if (!this._state.disabled && this._calendar.isValid(date) && isChangedDate(this._state.focusDate, date)) {
this._nextState({focusDate: date});
}
}
focusMove(period?: NgbPeriodNOA11Y, number?: number) {
this.focus(this._calendar.getNext(this._state.focusDate, period, number));
}
focusSelect() {
if (isDateSelectable(this._state.months, this._state.focusDate)) {
this.select(this._state.focusDate);
}
}
open(date: NgbDate) {
if (!this._state.disabled && this._calendar.isValid(date)) {
this._nextState({firstDate: date});
}
}
select(date: NgbDate) {
const validDate = this.toValidDate(date, null);
if (!this._state.disabled && isChangedDate(this._state.selectedDate, validDate)) {
this._nextState({selectedDate: validDate});
}
}
toValidDate(date: {year: number, month: number, day?: number}, defaultValue?: NgbDate): NgbDate {
const ngbDate = NgbDate.from(date);
if (defaultValue === undefined) {
defaultValue = this._calendar.getToday();
}
return this._calendar.isValid(ngbDate) ? ngbDate : defaultValue;
}
private _nextState(patch: Partial<DatepickerViewModel>) {
const newState = this._updateState(patch);
this._patchContexts(newState);
this._state = newState;
this._model$.next(this._state);
}
private _patchContexts(state: DatepickerViewModel) {
state.months.forEach(month => {
month.weeks.forEach(week => {
week.days.forEach(day => {
// patch focus flag
if (state.focusDate) {
day.context.focused = state.focusDate.equals(day.date) && state.focusVisible;
}
// override context disabled
if (state.disabled === true) {
day.context.disabled = true;
}
// patch selection flag
if (state.selectedDate !== undefined) {
day.context.selected = state.selectedDate !== null && state.selectedDate.equals(day.date);
}
// check if day is today
if (day.date.year === new Date().getFullYear()
&& day.date.month === new Date().getMonth() + 1
&& day.date.day === new Date().getDate()) {
day.context.isToday = true;
} else {
/* Se è un giorno del mese corrente ma passato rispetto ad oggi metto la classe default */
if (day.date.year === new Date().getFullYear()
&& day.date.month === new Date().getMonth() + 1
&& day.date.day < new Date().getDate()) {
day.context.isDayPast = true;
}
}
// check if day is a weekend day
const otherday = new Date(day.date.year, day.date.month - 1, day.date.day);
if (otherday.getDay() === 0 || otherday.getDay() === 6) {
day.context.isWeekend = true;
// disable weekend days if flag disableWeekend is set
if(state.disabledWeekend) {
day.context.disabled = true;
}
/* disabilito i giorni di weekend che non sono del mese visualizzato */
if (day.date.month !== new Date().getMonth() + 1
&& (this._state.focusVisible && day.date.month !== this._state.firstDate.month)) {
day.context.disabled = true;
}
}
// Disabilitazione del giorno nel caso in cui è un giorno di festa
if(state.holidays){
state.holidays.forEach((value, index) => {
if (value.year === day.date.year &&
value.month === day.date.month &&
value.day === day.date.day) {
day.context.disabled = true;
day.context.isHoliday = true;
}
});
}
// Controllo se al componente è stato passato un array contenente i giorni di scadenza fiscale
if(state.taxDeadlines){
state.taxDeadlines.forEach((value, index) => {
if (value.year === day.date.year &&
value.month === day.date.month &&
value.day === day.date.day) {
day.context.isFiscalDay = true;
}
});
}
});
});
});
}
private _updateState(patch: Partial<DatepickerViewModel>): DatepickerViewModel {
// patching fields
const state = Object.assign({}, this._state, patch);
let startDate = state.firstDate;
// min/max dates changed
if ('minDate' in patch || 'maxDate' in patch) {
checkMinBeforeMax(state.minDate, state.maxDate);
state.focusDate = checkDateInRange(state.focusDate, state.minDate, state.maxDate);
state.firstDate = checkDateInRange(state.firstDate, state.minDate, state.maxDate);
startDate = state.focusDate;
}
// disabled
if ('disabled' in patch) {
state.focusVisible = false;
}
// focus date changed
if ('focusDate' in patch) {
state.focusDate = checkDateInRange(state.focusDate, state.minDate, state.maxDate);
startDate = state.focusDate;
// nothing to rebuild if only focus changed and it is still visible
if (state.months.length !== 0 && !state.focusDate.before(state.firstDate) &&
!state.focusDate.after(state.lastDate)) {
return state;
}
}
// first date changed
if ('firstDate' in patch) {
state.firstDate = checkDateInRange(state.firstDate, state.minDate, state.maxDate);
startDate = state.firstDate;
}
// rebuilding months
if (startDate) {
const forceRebuild = 'firstDayOfWeek' in patch || 'markDisabled' in patch || 'minDate' in patch ||
'maxDate' in patch || 'disabled' in patch;
const months = buildMonths(
this._calendar, state.months, startDate, state.minDate, state.maxDate, state.displayMonths,
state.firstDayOfWeek, state.markDisabled, forceRebuild);
// updating months and boundary dates
state.months = months;
state.firstDate = months.length > 0 ? months[0].firstDate : undefined;
state.lastDate = months.length > 0 ? months[months.length - 1].lastDate : undefined;
// adjusting focus after months were built
if ('firstDate' in patch) {
if (state.focusDate === undefined || state.focusDate.before(state.firstDate) ||
state.focusDate.after(state.lastDate)) {
state.focusDate = startDate;
}
}
}
return state;
}
}

View File

@ -0,0 +1,144 @@
import {NgbDate} from './ngb-date';
import {DayViewModel, MonthViewModel, NgbMarkDisabled} from './datepicker-view-model';
import {NgbCalendarNOA11Y} from './ngb-calendar';
export function isChangedDate(prev: NgbDate, next: NgbDate) {
return !dateComparator(prev, next);
}
export function dateComparator(prev: NgbDate, next: NgbDate) {
return (!prev && !next) || (!!prev && !!next && prev.equals(next));
}
export function checkMinBeforeMax(minDate: NgbDate, maxDate: NgbDate) {
if (maxDate && minDate && maxDate.before(minDate)) {
throw new Error(`'maxDate' ${maxDate} should be greater than 'minDate' ${minDate}`);
}
}
export function checkDateInRange(date: NgbDate, minDate: NgbDate, maxDate: NgbDate): NgbDate {
if (date && minDate && date.before(minDate)) {
return NgbDate.from(minDate);
}
if (date && maxDate && date.after(maxDate)) {
return NgbDate.from(maxDate);
}
return date;
}
export function isDateSelectable(months: MonthViewModel[], date: NgbDate) {
let selectable = false;
const month = months.find(curMonth => curMonth.year === date.year && curMonth.number === date.month);
if (month) {
month.weeks.find(week => {
const day = week.days.find(day => date.equals(day.date));
if (day && !day.context.disabled) {
selectable = true;
}
return !!day;
});
}
return selectable;
}
export function buildMonths(
calendar: NgbCalendarNOA11Y, months: MonthViewModel[], date: NgbDate, minDate: NgbDate, maxDate: NgbDate,
displayMonths: number, firstDayOfWeek: number, markDisabled: NgbMarkDisabled, force: boolean): MonthViewModel[] {
const newMonths = [];
for (let i = 0; i < displayMonths; i++) {
const newDate = calendar.getNext(date, 'm', i);
const index = months.findIndex(month => month.firstDate.equals(newDate));
if (force || index === -1) {
newMonths.push(buildMonth(calendar, newDate, minDate, maxDate, firstDayOfWeek, markDisabled));
} else {
newMonths.push(months[index]);
}
}
return newMonths;
}
export function buildMonth(
calendar: NgbCalendarNOA11Y, date: NgbDate, minDate: NgbDate, maxDate: NgbDate, firstDayOfWeek: number,
markDisabled: NgbMarkDisabled): MonthViewModel {
const month:
MonthViewModel = {firstDate: null, lastDate: null, number: date.month, year: date.year, weeks: [], weekdays: []};
date = getFirstViewDate(calendar, date, firstDayOfWeek);
// month has weeks
for (let week = 0; week < calendar.getWeeksPerMonth(); week++) {
const days: DayViewModel[] = [];
// week has days
for (let day = 0; day < calendar.getDaysPerWeek(); day++) {
if (week === 0) {
month.weekdays.push(calendar.getWeekday(date));
}
const newDate = new NgbDate(date.year, date.month, date.day);
const nextDate = calendar.getNext(newDate);
// marking date as disabled
let disabled = !!((minDate && newDate.before(minDate)) || (maxDate && newDate.after(maxDate)));
if (!disabled && markDisabled) {
disabled = markDisabled(newDate, {month: month.number, year: month.year});
}
// saving first date of the month
if (month.firstDate === null && newDate.month === month.number) {
month.firstDate = newDate;
}
// saving last date of the month
if (newDate.month === month.number && nextDate.month !== month.number) {
month.lastDate = newDate;
}
days.push({
date: newDate,
context: {
date: {year: newDate.year, month: newDate.month, day: newDate.day},
currentMonth: month.number,
disabled: disabled,
focused: false,
selected: false,
isToday: false,
isWeekend: false,
isDayPast: false,
isFiscalDay: false
}
});
date = nextDate;
}
month.weeks.push(
{number: calendar.getWeekNumber(days.map(day => NgbDate.from(day.date)), firstDayOfWeek), days: days});
}
return month;
}
export function getFirstViewDate(calendar: NgbCalendarNOA11Y, date: NgbDate, firstDayOfWeek: number): NgbDate {
const currentMonth = date.month;
let today = new NgbDate(date.year, date.month, date.day);
let yesterday = calendar.getPrev(today);
const firstDayOfCurrentMonthIsAlsoFirstDayOfWeek =
() => { return today.month !== yesterday.month && firstDayOfWeek === calendar.getWeekday(today); };
const reachedTheFirstDayOfTheLastWeekOfPreviousMonth =
() => { return today.month !== currentMonth && firstDayOfWeek === calendar.getWeekday(today); };
// going back in time
while (!reachedTheFirstDayOfTheLastWeekOfPreviousMonth() && !firstDayOfCurrentMonthIsAlsoFirstDayOfWeek()) {
today = new NgbDate(yesterday.year, yesterday.month, yesterday.day);
yesterday = calendar.getPrev(yesterday);
}
return today;
}

View File

@ -0,0 +1,51 @@
import {NgbDate} from './ngb-date';
import {NgbDateStruct} from './ngb-date-struct';
import {DayTemplateContextNOA11Y} from './datepicker-day-template-context';
export type NgbMarkDisabled = (date: NgbDateStruct, current: {year: number, month: number}) => boolean;
export type DayViewModel = {
date: NgbDate,
context: DayTemplateContextNOA11Y
}
export type WeekViewModel = {
number: number,
days: DayViewModel[]
}
export type MonthViewModel = {
firstDate: NgbDate,
lastDate: NgbDate,
number: number,
year: number,
weeks: WeekViewModel[],
weekdays: number[]
};
// clang-format off
export type DatepickerViewModel = {
disabled: boolean,
displayMonths: number,
firstDate?: NgbDate,
firstDayOfWeek: number,
focusDate?: NgbDate,
focusVisible: boolean,
lastDate?: NgbDate,
markDisabled?: NgbMarkDisabled,
maxDate?: NgbDate,
minDate?: NgbDate,
months: MonthViewModel[],
selectedDate: NgbDate,
disabledWeekend?: boolean,
holidays?: NgbDateStruct[],
taxDeadlines?: NgbDateStruct[]
}
// clang-format on
export enum NavigationEvent {
PREV,
NEXT,
PREVYEAR,
NEXTYEAR,
}

View File

@ -50,7 +50,7 @@
</div> </div>
<!-- componente routing che usa il template selezionato--> <!-- componente routing che usa il template selezionato-->
<ngb-datepicker-routing-view <ngb-fid-datepicker-routing-view
[mesi]="mesi" [mesi]="mesi"
[years]="years" [years]="years"
[disabledWeekend]="disabledWeekend" [disabledWeekend]="disabledWeekend"
@ -70,7 +70,7 @@
[attr.label]="' '" [attr.label]="' '"
[attr.labelledby]="' '" [attr.labelledby]="' '"
[attr.describedby]="' '"> [attr.describedby]="' '">
</ngb-datepicker-routing-view> </ngb-fid-datepicker-routing-view>
</div> </div>
</ng-template> </ng-template>

View File

@ -1,81 +1,90 @@
import { Subscription } from 'rxjs';
import { import {
ChangeDetectionStrategy, ChangeDetectionStrategy,
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
ElementRef,
EventEmitter,
forwardRef,
Input, Input,
OnChanges, OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
TemplateRef, TemplateRef,
ViewChild forwardRef,
} from "@angular/core"; OnInit,
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms"; SimpleChanges,
import { EventEmitter,
DatepickerViewModel, Output,
DayTemplateContextNOA11Y, OnDestroy,
EnabledRangeService, ElementRef, ViewChild, ViewChildren
isChangedDate, } from '@angular/core';
NavigationEvent, import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
NgbCalendarNOA11Y, import { NgbCalendarNOA11Y } from './ngb-calendar';
NgbDataTemplateStruct, import { NgbDate } from './ngb-date';
NgbDate, import { NgbDatepickerServiceNOA11Y } from './datepicker-service';
NgbDatepickerConfigNOA11Y, import { NgbDatepickerKeyMapServiceNOA11Y } from './datepicker-keymap-service';
NgbDatepickerI18nNOA11Y, import { DatepickerViewModel, NavigationEvent } from './datepicker-view-model';
NgbDatepickerKeyMapServiceNOA11Y, import { toInteger } from '../util/util';
RplCalendarNavigateEventNOA11Y, import { DayTemplateContextNOA11Y } from './datepicker-day-template-context';
NgbDatepickerServiceNOA11Y, import { NgbDatepickerConfigNOA11Y } from './datepicker-config';
NgbDateStruct, import { NgbDateStruct } from './ngb-date-struct';
NgbDatepickerNavigateEventNOA11Y, import { NgbDatepickerI18nNOA11Y } from './datepicker-i18n';
CalendarItemNOA11Y import { isChangedDate } from './datepicker-tools';
} from "@isp/xdce-widget"; import { NgbDataTemplateStruct } from './ngb-dataTemplate-struct';
import { toInteger } from "../util/util"; import { EnabledRangeService } from '../../nbp-enabled-range.service';
import { Subscription } from "rxjs"; import {NgbDatepickerRoutingViewNOA11Y} from "./datepicker-routing-view";
import { NgbFidDatepickerRoutingViewNOA11Y } from "./datepicker-routing-view";
const NGB_CALENDAR_VALUE_ACCESSOR = { const NGB_CALENDAR_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR, provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FidRplCalendarNOA11Y), useExisting: forwardRef(() => RplCalendarNOA11Y),
multi: true, multi: true
}; };
/**
* The payload of the datepicker navigation event
*/
export interface RplCalendarNavigateEventNOA11Y {
/**
* Currently displayed month
*/
current: { year: number, month: number };
/**
* Month we're navigating to
*/
next: { year: number, month: number };
}
export class CalendarItemNOA11Y {
name: string;
number: number;
focused: boolean;
disabled: boolean;
selected: boolean;
}
/** /**
* A lightweight and highly configurable datepicker directive * A lightweight and highly configurable datepicker directive
*/ */
@Component({ @Component({
exportAs: "fidRplCalendarNOA11Y", exportAs: 'rplCalendarNOA11Y',
selector: "fid-rpl-calendar-noa11y", selector: 'rpl-calendar-noa11y',
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
host: { host: {
class: "d-inline-block rounded", 'class': 'd-inline-block rounded',
tabindex: "0", 'tabindex': '0',
"[attr.tabindex]": 'model.disabled ? undefined : "0"', '[attr.tabindex]': 'model.disabled ? undefined : "0"',
"(blur)": "showFocus(false)", '(blur)': 'showFocus(false)',
"(focus)": "showFocus(true)", '(focus)': 'showFocus(true)',
"(keydown)": "onKeyDown($event)", '(keydown)': 'onKeyDown($event)'
}, },
templateUrl: './datepicker.html', templateUrl: './datepicker.html',
styleUrls: ["./datepicker.scss"], styleUrls: ['./datepicker.scss'],
providers: [ providers: [NGB_CALENDAR_VALUE_ACCESSOR, NgbDatepickerServiceNOA11Y, NgbDatepickerKeyMapServiceNOA11Y]
NGB_CALENDAR_VALUE_ACCESSOR,
NgbDatepickerServiceNOA11Y,
NgbDatepickerKeyMapServiceNOA11Y,
],
}) })
export class FidRplCalendarNOA11Y export class RplCalendarNOA11Y implements OnDestroy,
implements OnDestroy, OnChanges, OnInit, ControlValueAccessor OnChanges, OnInit, ControlValueAccessor {
{
model: DatepickerViewModel; model: DatepickerViewModel;
@ViewChild(forwardRef(() => NgbFidDatepickerRoutingViewNOA11Y)) @ViewChild(forwardRef(() => NgbDatepickerRoutingViewNOA11Y)) datepickerRoutingView: NgbDatepickerRoutingViewNOA11Y;
datepickerRoutingView: NgbFidDatepickerRoutingViewNOA11Y; @ViewChild(forwardRef(() => NgbDatepickerRoutingViewNOA11Y)) datepickerHeader: NgbDatepickerRoutingViewNOA11Y;
@ViewChild(forwardRef(() => NgbFidDatepickerRoutingViewNOA11Y))
datepickerHeader: NgbFidDatepickerRoutingViewNOA11Y;
private _subscription: Subscription; private _subscription: Subscription;
/** /**
@ -97,10 +106,7 @@ export class FidRplCalendarNOA11Y
* Callback to mark a given date as disabled. * Callback to mark a given date as disabled.
* 'Current' contains the month that will be displayed in the view * 'Current' contains the month that will be displayed in the view
*/ */
@Input() markDisabled: ( @Input() markDisabled: (date: NgbDateStruct, current: { year: number, month: number }) => boolean;
date: NgbDateStruct,
current: { year: number; month: number }
) => boolean;
/** /**
* Min date for the navigation. If not provided will be 10 years before today or `startDate` * Min date for the navigation. If not provided will be 10 years before today or `startDate`
@ -112,7 +118,7 @@ export class FidRplCalendarNOA11Y
} }
set minDate(minDate: NgbDateStruct) { set minDate(minDate: NgbDateStruct) {
this._minDate = minDate; this._minDate = minDate;
this.startDateEnabled = minDate; this.startDateEnabled = minDate
} }
/** /**
@ -132,13 +138,13 @@ export class FidRplCalendarNOA11Y
* Navigation type: `select` (default with select boxes for month and year), `arrows` * Navigation type: `select` (default with select boxes for month and year), `arrows`
* (without select boxes, only navigation arrows) or `none` (no navigation at all) * (without select boxes, only navigation arrows) or `none` (no navigation at all)
*/ */
@Input() navigation: "select" | "arrows" | "none"; @Input() navigation: 'select' | 'arrows' | 'none';
/** /**
* The way to display days that don't belong to current month: `visible` (default), * The way to display days that don't belong to current month: `visible` (default),
* `hidden` (not displayed) or `collapsed` (not displayed with empty space collapsed) * `hidden` (not displayed) or `collapsed` (not displayed with empty space collapsed)
*/ */
@Input() outsideDays: "visible" | "collapsed" | "hidden"; @Input() outsideDays: 'visible' | 'collapsed' | 'hidden';
/** /**
* Whether to display days of the week * Whether to display days of the week
@ -156,7 +162,7 @@ export class FidRplCalendarNOA11Y
* If nothing or invalid date provided, calendar will open with current month. * If nothing or invalid date provided, calendar will open with current month.
* Use 'navigateTo(date)' as an alternative * Use 'navigateTo(date)' as an alternative
*/ */
@Input() startDate: { year: number; month: number; day?: number }; @Input() startDate: { year: number, month: number, day?: number };
@Input() startDateEnabled: any; @Input() startDateEnabled: any;
@Input() endDateEnabled: any; @Input() endDateEnabled: any;
@ -175,16 +181,12 @@ export class FidRplCalendarNOA11Y
// */ // */
// @Input() endDateEnabled: { year: number, month: number, day: number }; // @Input() endDateEnabled: { year: number, month: number, day: number };
/** /**
* In questa variabile sono memorizzati i dati iniziali che scenderanno l'albero dei template * In questa variabile sono memorizzati i dati iniziali che scenderanno l'albero dei template
*/ */
dataTemplate: NgbDataTemplateStruct = { dataTemplate: NgbDataTemplateStruct = { template: 0, day: 0, month: 0, year: 0, valid: false };
template: 0,
day: 0,
month: 0,
year: 0,
valid: false,
};
/** /**
* An event fired when navigation happens and currently displayed month changes. * An event fired when navigation happens and currently displayed month changes.
@ -192,199 +194,59 @@ export class FidRplCalendarNOA11Y
*/ */
@Output() navigate = new EventEmitter<NgbDatepickerNavigateEventNOA11Y>(); @Output() navigate = new EventEmitter<NgbDatepickerNavigateEventNOA11Y>();
/** /**
* Template da Adoperare * Template da Adoperare
*/ */
template: number = 0; template: number = 0;
mesi: CalendarItemNOA11Y[][] = [
[
{
name: "JAN",
number: 1,
disabled: false,
selected: false,
focused: false,
},
{
name: "FEB",
number: 2,
disabled: false,
selected: false,
focused: false,
},
{
name: "MAR",
number: 3,
disabled: false,
selected: false,
focused: false,
},
{
name: "APR",
number: 4,
disabled: false,
selected: false,
focused: false,
},
],
[
{
name: "MAY",
number: 5,
disabled: false,
selected: false,
focused: false,
},
{
name: "JUN",
number: 6,
disabled: false,
selected: false,
focused: false,
},
{
name: "JUL",
number: 7,
disabled: false,
selected: false,
focused: false,
},
{
name: "AUG",
number: 8,
disabled: false,
selected: false,
focused: false,
},
],
[
{
name: "SEP",
number: 9,
disabled: false,
selected: false,
focused: false,
},
{
name: "OCT",
number: 10,
disabled: false,
selected: false,
focused: false,
},
{
name: "NOV",
number: 11,
disabled: false,
selected: false,
focused: false,
},
{
name: "DEC",
number: 12,
disabled: false,
selected: false,
focused: false,
},
],
];
years: CalendarItemNOA11Y[][] = [ mesi : CalendarItemNOA11Y[][] = [
[ [
{ { name: "JAN", number: 1, disabled: false, selected: false, focused: false },
name: "2018", { name: "FEB", number: 2, disabled: false, selected: false, focused: false },
number: 2018, { name: "MAR", number: 3, disabled: false, selected: false, focused: false },
disabled: false, { name: "APR", number: 4, disabled: false, selected: false, focused: false }
selected: false,
focused: false,
},
{
name: "2019",
number: 2019,
disabled: false,
selected: false,
focused: false,
},
{
name: "2020",
number: 2020,
disabled: false,
selected: false,
focused: false,
},
{
name: "2021",
number: 2021,
disabled: false,
selected: false,
focused: false,
},
], ],
[ [
{ { name: "MAY", number: 5, disabled: false, selected: false, focused: false },
name: "2022", { name: "JUN", number: 6, disabled: false, selected: false, focused: false },
number: 2022, { name: "JUL", number: 7, disabled: false, selected: false, focused: false },
disabled: false, { name: "AUG", number: 8, disabled: false, selected: false, focused: false }
selected: false,
focused: false,
},
{
name: "2023",
number: 2023,
disabled: false,
selected: false,
focused: false,
},
{
name: "2024",
number: 2024,
disabled: false,
selected: false,
focused: false,
},
{
name: "2025",
number: 2025,
disabled: false,
selected: false,
focused: false,
},
], ],
[ [
{ { name: "SEP", number: 9, disabled: false, selected: false, focused: false },
name: "2026", { name: "OCT", number: 10, disabled: false, selected: false, focused: false },
number: 2026, { name: "NOV", number: 11, disabled: false, selected: false, focused: false },
disabled: false, { name: "DEC", number: 12, disabled: false, selected: false, focused: false }
selected: false, ]
focused: false, ]
},
{
name: "2027",
number: 2027,
disabled: false,
selected: false,
focused: false,
},
{
name: "2028",
number: 2028,
disabled: false,
selected: false,
focused: false,
},
{
name: "2029",
number: 2029,
disabled: false,
selected: false,
focused: false,
},
],
];
onChange = (_: any) => {}; years : CalendarItemNOA11Y [][] = [
onTouched = () => {}; [
{ name: "2018", number: 2018, disabled: false, selected: false, focused: false },
{ name: "2019", number: 2019, disabled: false, selected: false, focused: false },
{ name: "2020", number: 2020, disabled: false, selected: false, focused: false },
{ name: "2021", number: 2021, disabled: false, selected: false, focused: false }
],
[
{ name: "2022", number: 2022, disabled: false, selected: false, focused: false },
{ name: "2023", number: 2023, disabled: false, selected: false, focused: false },
{ name: "2024", number: 2024, disabled: false, selected: false, focused: false },
{ name: "2025", number: 2025, disabled: false, selected: false, focused: false }
],
[
{ name: "2026", number: 2026, disabled: false, selected: false, focused: false },
{ name: "2027", number: 2027, disabled: false, selected: false, focused: false },
{ name: "2028", number: 2028, disabled: false, selected: false, focused: false },
{ name: "2029", number: 2029, disabled: false, selected: false, focused: false }
]
]
onChange = (_: any) => { };
onTouched = () => { };
// startDateEnabled: string; // startDateEnabled: string;
// endDateEnabled: string; // endDateEnabled: string;
@ -394,11 +256,9 @@ export class FidRplCalendarNOA11Y
private _keyMapService: NgbDatepickerKeyMapServiceNOA11Y, private _keyMapService: NgbDatepickerKeyMapServiceNOA11Y,
public _service: NgbDatepickerServiceNOA11Y, public _service: NgbDatepickerServiceNOA11Y,
private _calendar: NgbCalendarNOA11Y, private _calendar: NgbCalendarNOA11Y,
public i18n: NgbDatepickerI18nNOA11Y, public i18n: NgbDatepickerI18nNOA11Y, config: NgbDatepickerConfigNOA11Y,
config: NgbDatepickerConfigNOA11Y,
private _cd: ChangeDetectorRef, private _cd: ChangeDetectorRef,
private _elementRef: ElementRef private _elementRef: ElementRef) {
) {
this.dayTemplate = config.dayTemplate; this.dayTemplate = config.dayTemplate;
this.displayMonths = config.displayMonths; this.displayMonths = config.displayMonths;
this.firstDayOfWeek = config.firstDayOfWeek; this.firstDayOfWeek = config.firstDayOfWeek;
@ -419,7 +279,8 @@ export class FidRplCalendarNOA11Y
// alert("finale Start : " + this.startDateEnabled) // alert("finale Start : " + this.startDateEnabled)
// alert("finale End : " + this.endDateEnabled) // alert("finale End : " + this.endDateEnabled)
this._subscription = _service.model$.subscribe((model) => {
this._subscription = _service.model$.subscribe(model => {
const newDate = model.firstDate; const newDate = model.firstDate;
const oldDate = this.model ? this.model.firstDate : null; const oldDate = this.model ? this.model.firstDate : null;
const newSelectedDate = model.selectedDate; const newSelectedDate = model.selectedDate;
@ -431,22 +292,14 @@ export class FidRplCalendarNOA11Y
if (isChangedDate(newSelectedDate, oldSelectedDate)) { if (isChangedDate(newSelectedDate, oldSelectedDate)) {
this.onTouched(); this.onTouched();
this.onChange( this.onChange(
newSelectedDate newSelectedDate ? { year: newSelectedDate.year, month: newSelectedDate.month, day: newSelectedDate.day } :
? { null);
year: newSelectedDate.year,
month: newSelectedDate.month,
day: newSelectedDate.day,
}
: null
);
} }
// emitting navigation event if the first month changes // emitting navigation event if the first month changes
if (!newDate.equals(oldDate)) { if (!newDate.equals(oldDate)) {
this.navigate.emit({ this.navigate.emit({
current: oldDate current: oldDate ? { year: oldDate.year, month: oldDate.month } : null,
? { year: oldDate.year, month: oldDate.month } next: { year: newDate.year, month: newDate.month }
: null,
next: { year: newDate.year, month: newDate.month },
}); });
} }
_cd.markForCheck(); _cd.markForCheck();
@ -454,27 +307,23 @@ export class FidRplCalendarNOA11Y
} }
abilitaMesi(data) { abilitaMesi(data) {
if (
this.startDateEnabled.month <= data && if(this.startDateEnabled.month <= data && data <= this.endDateEnabled.month && (this.startDateEnabled.year <= this.dataTemplate.year && this.dataTemplate.year <= this.endDateEnabled.year) ){
data <= this.endDateEnabled.month && return true
this.startDateEnabled.year <= this.dataTemplate.year &&
this.dataTemplate.year <= this.endDateEnabled.year
) {
return true;
} }
return false; return false
} }
abilitaAnni(data) { abilitaAnni(data) {
if (
this.startDateEnabled.year <= data && if(this.startDateEnabled.year <= data && data <= this.endDateEnabled.year){
data <= this.endDateEnabled.year return true
) {
return true;
} }
return false; return false
} }
setNewTemplate(selectedTemplate: number) { setNewTemplate(selectedTemplate: number) {
@ -483,54 +332,47 @@ export class FidRplCalendarNOA11Y
this.setYear(this.dataTemplate.year, true); this.setYear(this.dataTemplate.year, true);
const prevTemplate = this.template; const prevTemplate = this.template;
this.template = selectedTemplate; this.template = selectedTemplate;
if (prevTemplate === 2 && this.template === 0) { if(prevTemplate === 2 && this.template === 0) {
const model = this._service._model$.getValue(); const model = this._service._model$.getValue();
if (model && model.selectedDate) { if(model && model.selectedDate) {
this.navigateTo({ this.navigateTo({month: model.selectedDate.month, year: model.selectedDate.year});
month: model.selectedDate.month,
year: model.selectedDate.year,
});
} }
} }
} }
setMesi(position: number, selected: boolean) { setMesi(position: number, selected: boolean) {
if (!this.abilitaMesi(position)) return;
let nRow = 0, if (!this.abilitaMesi(position))
nCol = 0; return
if (position == 4) nRow = 0; let nRow = 0, nCol = 0
else if (position == 8) nRow = 1;
else if (position == 12) nRow = 2;
else nRow = Math.trunc(position / 4);
nCol = position - nRow * 4 - 1; if (position == 4)
console.info( nRow = 0
"dataTemplate", else if (position == 8)
this.dataTemplate, nRow = 1
"mese", else if (position == 12)
this.mesi[nRow][nCol], nRow = 2
"nRow", else
nRow, nRow = Math.trunc(position / 4)
"nCol",
nCol nCol = position - (nRow * 4) - 1;
); console.info('dataTemplate', this.dataTemplate, 'mese', this.mesi[nRow][nCol], 'nRow', nRow, 'nCol', nCol);
this.mesi[nRow][nCol].selected = selected; this.mesi[nRow][nCol].selected = selected;
} }
updateYears(startYearValue: number) { updateYears(startYearValue: number) {
let yrs: CalendarItemNOA11Y[][] = []; let yrs : CalendarItemNOA11Y[][] = [];
for (let j = 0; j < 3; j++) { for (let j = 0; j < 3; j++) {
yrs[j] = []; yrs[j] = [];
for (let i = 0; i < 4; i++) { for (let i = 0; i < 4; i++) {
const yr = new CalendarItemNOA11Y(); const yr = new CalendarItemNOA11Y();
yr.number = startYearValue + i + j * 4; yr.number = startYearValue + i + j * 4;
yr.name = yr.number + ""; yr.name = yr.number+"";
yr.disabled = false; yr.disabled = false;
yr.focused = false; yr.focused = false;
yr.selected = false; yr.selected = false;
yrs[j][i] = yr; yrs[j][i]= yr;
// this.years[j][i].number = startYearValue + i + j * 4 // this.years[j][i].number = startYearValue + i + j * 4
// this.years[j][i].name = this.years[j][i].number + ""; // this.years[j][i].name = this.years[j][i].number + "";
} }
@ -538,36 +380,38 @@ export class FidRplCalendarNOA11Y
yrs.forEach((row) => { yrs.forEach((row) => {
row.forEach((y) => { row.forEach((y) => {
y.selected = this.dataTemplate.year === y.number; y.selected = this.dataTemplate.year === y.number;
}); })
}); })
this.years = yrs; this.years = yrs;
} }
setYear(yearValue: number, selected: boolean) { setYear(yearValue: number, selected: boolean) {
if (!this.abilitaAnni(yearValue)) return;
if (!this.abilitaAnni(yearValue))
return
this.years.forEach((row) => { this.years.forEach((row) => {
row.forEach((year) => { row.forEach((year) => {
if (year.number == yearValue) year.selected = selected; if (year.number == yearValue) year.selected = selected
}); })
}); })
} }
/** /**
* Manually focus the calendar * Manually focus the calendar
*/ */
focus() { focus() { this._elementRef.nativeElement.focus(); }
this._elementRef.nativeElement.focus();
}
getHeaderHeight() { getHeaderHeight() {
const h = this.showWeekdays ? 6.25 : 4.25; const h = this.showWeekdays ? 6.25 : 4.25;
return this.displayMonths === 1 || this.navigation !== "select" ? h - 2 : h; return this.displayMonths === 1 || this.navigation !== 'select' ? h - 2 : h;
} }
getHeaderMargin() { getHeaderMargin() {
const m = this.showWeekdays ? 2 : 0; const m = this.showWeekdays ? 2 : 0;
return this.displayMonths !== 1 || this.navigation !== "select" ? m + 2 : m; return this.displayMonths !== 1 || this.navigation !== 'select' ? m + 2 : m;
} }
/** /**
@ -576,15 +420,11 @@ export class FidRplCalendarNOA11Y
* If nothing or invalid date provided calendar will open current month. * If nothing or invalid date provided calendar will open current month.
* Use 'startDate' input as an alternative * Use 'startDate' input as an alternative
*/ */
navigateTo(date?: { year: number; month: number }) { navigateTo(date?: { year: number, month: number }) {
this._service.open( this._service.open(date ? new NgbDate(date.year, date.month, 1) : this._calendar.getToday());
date ? new NgbDate(date.year, date.month, 1) : this._calendar.getToday()
);
} }
ngOnDestroy() { ngOnDestroy() { this._subscription.unsubscribe(); }
this._subscription.unsubscribe();
}
ngOnInit() { ngOnInit() {
if (this.model === undefined) { if (this.model === undefined) {
@ -609,7 +449,7 @@ export class FidRplCalendarNOA11Y
this.startDate.month = mm; this.startDate.month = mm;
this.startDate.year = yyyy; this.startDate.year = yyyy
} }
this.dataTemplate.day = this.startDate.day; this.dataTemplate.day = this.startDate.day;
this.dataTemplate.month = this.startDate.month; this.dataTemplate.month = this.startDate.month;
@ -617,23 +457,22 @@ export class FidRplCalendarNOA11Y
this.dataTemplate.valid = false; this.dataTemplate.valid = false;
let elem: HTMLElement = this._elementRef.nativeElement; let elem: HTMLElement = this._elementRef.nativeElement;
elem.classList.contains("isp-corporate-mode-wrapper") elem.classList.contains('isp-corporate-mode-wrapper') ? this.outsideDays = 'hidden' : this.outsideDays = 'visible';
? (this.outsideDays = "hidden")
: (this.outsideDays = "visible");
} }
} }
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {
if (changes["displayMonths"]) { if (changes['displayMonths']) {
this._service.displayMonths = toInteger(this.displayMonths); this._service.displayMonths = toInteger(this.displayMonths);
} }
if (changes["markDisabled"]) { if (changes['markDisabled']) {
this._service.markDisabled = this.markDisabled; this._service.markDisabled = this.markDisabled;
} }
if (changes["firstDayOfWeek"]) { if (changes['firstDayOfWeek']) {
this._service.firstDayOfWeek = this.firstDayOfWeek; this._service.firstDayOfWeek = this.firstDayOfWeek;
} }
if (changes["taxDeadlines"]) { if (changes['taxDeadlines']) {
this._service.taxDeadlines = this.taxDeadlines; this._service.taxDeadlines = this.taxDeadlines;
} }
} }
@ -643,122 +482,118 @@ export class FidRplCalendarNOA11Y
this.writeValue(date); this.writeValue(date);
} }
onKeyDown(event: KeyboardEvent) { onKeyDown(event: KeyboardEvent) { this._keyMapService.processKey(event); }
this._keyMapService.processKey(event);
}
onNavigateDateSelect(date: NgbDate) { onNavigateDateSelect(date: NgbDate) {
this._service.open(date); this._service.open(date);
} }
onNavigateEvent(event: NavigationEvent) { onNavigateEvent(event: NavigationEvent) {
let bufferData: NgbDate; let bufferData: NgbDate;
this.model.firstDate.month = this.dataTemplate.month; this.model.firstDate.month = this.dataTemplate.month;
this.model.firstDate.year = this.dataTemplate.year; this.model.firstDate.year = this.dataTemplate.year;
if (event == NavigationEvent.PREV && this.template == 0) { if (event == NavigationEvent.PREV && this.template == 0) {
bufferData = this._calendar.getPrev(this.model.firstDate, "m", 1); bufferData = this._calendar.getPrev(this.model.firstDate, 'm', 1)
this._service.open(bufferData);
this.updateDataTemplate(bufferData)
}
else if (NavigationEvent.NEXT && this.template == 0) {
bufferData = this._calendar.getNext(this.model.firstDate, 'm', 1);
this._service.open(bufferData);
this.updateDataTemplate(bufferData)
}
else if (event == NavigationEvent.PREV && this.template == 1) {
bufferData = this._calendar.getPrev(this.model.firstDate, 'm', 12);
this._service.open(bufferData); this._service.open(bufferData);
this.updateDataTemplate(bufferData); this.updateDataTemplate(bufferData);
} else if (NavigationEvent.NEXT && this.template == 0) { }
bufferData = this._calendar.getNext(this.model.firstDate, "m", 1); else if (event == NavigationEvent.NEXT && this.template == 1) {
bufferData = this._calendar.getNext(this.model.firstDate, 'm', 12);
this._service.open(bufferData); this._service.open(bufferData);
this.updateDataTemplate(bufferData); this.updateDataTemplate(bufferData)
} else if (event == NavigationEvent.PREV && this.template == 1) { }
bufferData = this._calendar.getPrev(this.model.firstDate, "m", 12); else if (event == NavigationEvent.PREV && this.template == 2) {
this._service.open(bufferData); bufferData = this._calendar.getPrev(this.model.firstDate, 'm', 144);
this.updateDataTemplate(bufferData);
} else if (event == NavigationEvent.NEXT && this.template == 1) {
bufferData = this._calendar.getNext(this.model.firstDate, "m", 12);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
} else if (event == NavigationEvent.PREV && this.template == 2) {
bufferData = this._calendar.getPrev(this.model.firstDate, "m", 144);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
this.updateYears(this.dataTemplate.year);
} else if (event == NavigationEvent.NEXT && this.template == 2) {
bufferData = this._calendar.getNext(this.model.firstDate, "m", 144);
this._service.open(bufferData); this._service.open(bufferData);
this.updateDataTemplate(bufferData); this.updateDataTemplate(bufferData);
this.updateYears(this.dataTemplate.year); this.updateYears(this.dataTemplate.year);
} }
else if (event == NavigationEvent.NEXT && this.template == 2) {
bufferData = this._calendar.getNext(this.model.firstDate, 'm', 144);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
this.updateYears(this.dataTemplate.year);
}
} }
onChangeTemplate(dataTemplate: NgbDataTemplateStruct) { onChangeTemplate(dataTemplate: NgbDataTemplateStruct) {
this.dataTemplate = dataTemplate; this.dataTemplate = dataTemplate;
this.template = dataTemplate.template; this.template = dataTemplate.template;
this.navigateTo({ month: dataTemplate.month, year: dataTemplate.year }); this.navigateTo({month: dataTemplate.month, year: dataTemplate.year});
} }
updateDataTemplate(date: NgbDate) { updateDataTemplate(date: NgbDate) {
const newTemplate = { ...this.dataTemplate }; const newTemplate = {...this.dataTemplate};
newTemplate.day = date.day; newTemplate.day = date.day;
newTemplate.month = date.month; newTemplate.month = date.month;
newTemplate.year = date.year; newTemplate.year = date.year;
this.dataTemplate = newTemplate; this.dataTemplate = newTemplate;
this.navigateTo({ this.navigateTo({month: this.dataTemplate.month, year: this.dataTemplate.year});
month: this.dataTemplate.month,
year: this.dataTemplate.year,
});
}
registerOnChange(fn: (value: any) => any): void {
this.onChange = fn;
}
registerOnTouched(fn: () => any): void {
this.onTouched = fn;
} }
registerOnChange(fn: (value: any) => any): void { this.onChange = fn; }
setDisabledState(isDisabled: boolean) { registerOnTouched(fn: () => any): void { this.onTouched = fn; }
this._service.disabled = isDisabled;
}
showFocus(focusVisible: boolean) { setDisabledState(isDisabled: boolean) { this._service.disabled = isDisabled; }
this._service.focusVisible = focusVisible;
}
writeValue(value: any) { showFocus(focusVisible: boolean) { this._service.focusVisible = focusVisible; }
this._service.select(value);
} writeValue(value: any) { this._service.select(value); }
private _setDates() { private _setDates() {
const startDate = this._service.toValidDate( const startDate = this._service.toValidDate(this.startDate, this._calendar.getToday());
this.startDate, const minDate = this._service.toValidDate(this.minDate, this._calendar.getPrev(startDate, 'y', 10));
this._calendar.getToday() const maxDate =
); this._service.toValidDate(this.maxDate, this._calendar.getPrev(this._calendar.getNext(startDate, 'y', 11)));
const minDate = this._service.toValidDate(
this.minDate,
this._calendar.getPrev(startDate, "y", 10)
);
const maxDate = this._service.toValidDate(
this.maxDate,
this._calendar.getPrev(this._calendar.getNext(startDate, "y", 11))
);
this.minDate = { this.minDate = { year: minDate.year, month: minDate.month, day: minDate.day };
year: minDate.year, this.maxDate = { year: maxDate.year, month: maxDate.month, day: maxDate.day };
month: minDate.month,
day: minDate.day,
};
this.maxDate = {
year: maxDate.year,
month: maxDate.month,
day: maxDate.day,
};
this._service.minDate = minDate; this._service.minDate = minDate;
this._service.maxDate = maxDate; this._service.maxDate = maxDate;
this.navigateTo(startDate); this.navigateTo(startDate);
} }
public focusOutComponent(event: any) { public focusOutComponent(event: any){
if (!this._elementRef.nativeElement.contains(event.target)) { if(!this._elementRef.nativeElement.contains(event.target)) {
let elem: HTMLElement = this._elementRef.nativeElement; let elem: HTMLElement = this._elementRef.nativeElement;
if (elem.parentElement) { if(elem.parentElement) {
elem.parentElement.removeChild(elem); elem.parentElement.removeChild(elem);
} }
this._subscription.unsubscribe(); this._subscription.unsubscribe();
} }
} }
} }
/**
* The payload of the calendar navigation event
*/
export interface NgbDatepickerNavigateEventNOA11Y {
/**
* Currently displayed month
*/
current: { year: number, month: number };
/**
* Month we're navigating to
*/
next: { year: number, month: number };
}

View File

@ -0,0 +1,95 @@
import {NgbDate} from '../ngb-date';
import {NgbPeriodNOA11Y, NgbCalendarNOA11Y} from '../ngb-calendar';
import {Injectable} from '@angular/core';
import {isNumber} from '../../util/util';
@Injectable()
export abstract class NgbCalendarHijriNOA11Y extends NgbCalendarNOA11Y {
getDaysPerWeek() { return 7; }
getMonths() { return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; }
getWeeksPerMonth() { return 6; }
isValid(date: NgbDate): boolean {
return date && isNumber(date.year) && isNumber(date.month) && isNumber(date.day) &&
!isNaN(this.toGregorian(date).getTime());
}
setDay(date: NgbDate, day: number): NgbDate {
day = +day;
let mDays = this.getDaysInIslamicMonth(date.month, date.year);
if (day <= 0) {
while (day <= 0) {
date = this.setMonth(date, date.month - 1);
mDays = this.getDaysInIslamicMonth(date.month, date.year);
day += mDays;
}
} else if (day > mDays) {
while (day > mDays) {
day -= mDays;
date = this.setMonth(date, date.month + 1);
mDays = this.getDaysInIslamicMonth(date.month, date.year);
}
}
date.day = day;
return date;
}
setMonth(date: NgbDate, month: number): NgbDate {
month = +month;
date.year = date.year + Math.floor((month - 1) / 12);
date.month = Math.floor(((month - 1) % 12 + 12) % 12) + 1;
return date;
}
setYear(date: NgbDate, yearValue: number): NgbDate {
date.year = +yearValue;
return date;
}
abstract getWeekday(date: NgbDate): number;
abstract getNext(date: NgbDate, period?: NgbPeriodNOA11Y, number?: number): NgbDate;
abstract getPrev(date: NgbDate, period?: NgbPeriodNOA11Y, number?: number): NgbDate;
abstract getWeekNumber(week: NgbDate[], firstDayOfWeek: number): number;
abstract getToday(): NgbDate;
/**
* Returns the equivalent Hijri date value for a give input Gregorian date.
* `gDate` is s JS Date to be converted to Hijri.
*/
abstract fromGregorian(gDate: Date): NgbDate;
/**
* Converts the current Hijri date to Gregorian.
*/
abstract toGregorian(hijriDate: NgbDate): Date;
/**
* Returns the number of days in a specific Hijri month.
* `month` is 1 for Muharram, 2 for Safar, etc.
* `year` is any Hijri year.
*/
abstract getDaysInIslamicMonth(month: number, year: number): number;
protected _isIslamicLeapYear(year: number): boolean { return (14 + 11 * year) % 30 < 11; }
/**
* Returns the start of Hijri Month.
* `month` is 0 for Muharram, 1 for Safar, etc.
* `year` is any Hijri year.
*/
protected _getMonthStart(year: number, month: number): number {
return Math.ceil(29.5 * month) + (year - 1) * 354 + Math.floor((3 + 11 * year) / 30.0);
}
/**
* Returns the start of Hijri year.
* `year` is any Hijri year.
*/
protected _getYearStart(year: number): number { return (year - 1) * 354 + Math.floor((3 + 11 * year) / 30.0); }
}

View File

@ -0,0 +1,429 @@
import {NgbCalendarIslamicCivilNOA11Y} from './ngb-calendar-islamic-civil';
import {NgbDate} from '../ngb-date';
describe('ngb-calendar-islamic-civil', () => {
const DATE_TABLE = [
[1420, 1, 1, 1999, 3, 17], [1420, 1, 12, 1999, 3, 28], [1420, 1, 23, 1999, 4, 9],
[1420, 2, 4, 1999, 4, 20], [1420, 2, 15, 1999, 4, 31], [1420, 2, 26, 1999, 5, 11],
[1420, 3, 8, 1999, 5, 22], [1420, 3, 19, 1999, 6, 3], [1420, 3, 30, 1999, 6, 14],
[1420, 4, 11, 1999, 6, 25], [1420, 4, 22, 1999, 7, 5], [1420, 5, 4, 1999, 7, 16],
[1420, 5, 15, 1999, 7, 27], [1420, 5, 26, 1999, 8, 7], [1420, 6, 7, 1999, 8, 18],
[1420, 6, 18, 1999, 8, 29], [1420, 6, 29, 1999, 9, 10], [1420, 7, 11, 1999, 9, 21],
[1420, 7, 22, 1999, 10, 1], [1420, 8, 3, 1999, 10, 12], [1420, 8, 14, 1999, 10, 23],
[1420, 9, 29, 2000, 0, 6], [1420, 10, 10, 2000, 0, 17], [1420, 10, 21, 2000, 0, 28],
[1420, 11, 3, 2000, 1, 8], [1420, 11, 14, 2000, 1, 19], [1420, 11, 25, 2000, 2, 1],
[1420, 12, 6, 2000, 2, 12], [1420, 12, 17, 2000, 2, 23], [1420, 12, 28, 2000, 3, 3],
[1421, 1, 9, 2000, 3, 14], [1421, 1, 20, 2000, 3, 25], [1421, 2, 1, 2000, 4, 6],
[1421, 2, 12, 2000, 4, 17], [1421, 2, 23, 2000, 4, 28], [1421, 3, 5, 2000, 5, 8],
[1421, 3, 16, 2000, 5, 19], [1421, 3, 27, 2000, 5, 30], [1421, 4, 8, 2000, 6, 11],
[1421, 4, 19, 2000, 6, 22], [1421, 5, 1, 2000, 7, 2], [1421, 5, 12, 2000, 7, 13],
[1421, 5, 23, 2000, 7, 24], [1421, 6, 4, 2000, 8, 4], [1421, 6, 15, 2000, 8, 15],
[1421, 6, 26, 2000, 8, 26], [1421, 7, 8, 2000, 9, 7], [1421, 7, 19, 2000, 9, 18],
[1421, 7, 30, 2000, 9, 29], [1421, 8, 11, 2000, 10, 9], [1421, 8, 22, 2000, 10, 20],
[1421, 10, 7, 2001, 0, 3], [1421, 10, 18, 2001, 0, 14], [1421, 10, 7, 2001, 0, 3],
[1421, 10, 18, 2001, 0, 14], [1421, 10, 29, 2001, 0, 25], [1421, 11, 11, 2001, 1, 5],
[1421, 11, 22, 2001, 1, 16], [1421, 12, 3, 2001, 1, 27], [1421, 12, 14, 2001, 2, 10],
[1421, 12, 25, 2001, 2, 21], [1422, 1, 7, 2001, 3, 1], [1422, 1, 18, 2001, 3, 12],
[1422, 1, 29, 2001, 3, 23], [1422, 2, 10, 2001, 4, 4], [1422, 2, 21, 2001, 4, 15],
[1422, 3, 3, 2001, 4, 26], [1422, 3, 14, 2001, 5, 6], [1422, 3, 25, 2001, 5, 17],
[1422, 4, 6, 2001, 5, 28], [1422, 4, 17, 2001, 6, 9], [1422, 4, 28, 2001, 6, 20],
[1422, 5, 10, 2001, 6, 31], [1422, 5, 21, 2001, 7, 11], [1422, 6, 2, 2001, 7, 22],
[1422, 6, 13, 2001, 8, 2], [1422, 6, 24, 2001, 8, 13], [1422, 7, 6, 2001, 8, 24],
[1422, 7, 17, 2001, 9, 5], [1422, 7, 28, 2001, 9, 16], [1422, 8, 9, 2001, 9, 27],
[1422, 8, 20, 2001, 10, 7], [1422, 9, 2, 2001, 10, 18], [1422, 9, 13, 2001, 10, 29],
[1422, 9, 24, 2001, 11, 10], [1422, 10, 5, 2001, 11, 21], [1422, 10, 16, 2002, 0, 1],
[1422, 10, 27, 2002, 0, 12], [1422, 11, 9, 2002, 0, 23], [1422, 11, 20, 2002, 1, 3],
[1422, 12, 1, 2002, 1, 14], [1422, 12, 12, 2002, 1, 25], [1422, 12, 23, 2002, 2, 8],
[1423, 1, 5, 2002, 2, 19], [1423, 1, 16, 2002, 2, 30], [1423, 1, 27, 2002, 3, 10],
[1423, 2, 8, 2002, 3, 21], [1423, 2, 19, 2002, 4, 2], [1423, 3, 1, 2002, 4, 13],
[1423, 3, 12, 2002, 4, 24], [1423, 3, 23, 2002, 5, 4], [1423, 4, 4, 2002, 5, 15],
[1423, 4, 15, 2002, 5, 26], [1423, 4, 26, 2002, 6, 7], [1423, 5, 8, 2002, 6, 18],
[1423, 5, 19, 2002, 6, 29], [1423, 5, 30, 2002, 7, 9], [1423, 6, 11, 2002, 7, 20],
[1423, 6, 22, 2002, 7, 31], [1423, 7, 4, 2002, 8, 11], [1423, 7, 15, 2002, 8, 22],
[1423, 7, 26, 2002, 9, 3], [1423, 8, 7, 2002, 9, 14], [1423, 8, 18, 2002, 9, 25],
[1423, 8, 29, 2002, 10, 5], [1423, 9, 11, 2002, 10, 16], [1423, 9, 22, 2002, 10, 27],
[1423, 10, 3, 2002, 11, 8], [1423, 10, 14, 2002, 11, 19], [1423, 10, 25, 2002, 11, 30],
[1423, 11, 7, 2003, 0, 10], [1423, 11, 18, 2003, 0, 21], [1423, 11, 29, 2003, 1, 1],
[1423, 12, 10, 2003, 1, 12], [1423, 12, 21, 2003, 1, 23], [1424, 1, 2, 2003, 2, 6],
[1424, 1, 13, 2003, 2, 17], [1424, 1, 24, 2003, 2, 28], [1424, 2, 5, 2003, 3, 8],
[1424, 2, 16, 2003, 3, 19], [1424, 2, 27, 2003, 3, 30], [1424, 3, 9, 2003, 4, 11],
[1424, 3, 20, 2003, 4, 22], [1424, 4, 1, 2003, 5, 2], [1424, 4, 12, 2003, 5, 13],
[1424, 4, 23, 2003, 5, 24], [1424, 5, 5, 2003, 6, 5], [1424, 5, 16, 2003, 6, 16],
[1424, 5, 27, 2003, 6, 27], [1424, 6, 8, 2003, 7, 7], [1424, 6, 19, 2003, 7, 18],
[1424, 7, 1, 2003, 7, 29], [1424, 7, 12, 2003, 8, 9], [1424, 7, 23, 2003, 8, 20],
[1424, 8, 4, 2003, 9, 1], [1424, 8, 15, 2003, 9, 12], [1424, 8, 26, 2003, 9, 23],
[1424, 9, 8, 2003, 10, 3], [1424, 9, 19, 2003, 10, 14], [1424, 9, 30, 2003, 10, 25],
[1424, 11, 15, 2004, 0, 8], [1424, 11, 26, 2004, 0, 19], [1424, 12, 7, 2004, 0, 30],
[1424, 12, 18, 2004, 1, 10], [1424, 12, 29, 2004, 1, 21], [1425, 1, 11, 2004, 2, 3],
[1425, 1, 22, 2004, 2, 14], [1425, 2, 3, 2004, 2, 25], [1425, 2, 14, 2004, 3, 5],
[1425, 2, 25, 2004, 3, 16], [1425, 3, 7, 2004, 3, 27], [1425, 3, 18, 2004, 4, 8],
[1425, 3, 29, 2004, 4, 19], [1425, 4, 10, 2004, 4, 30], [1425, 4, 21, 2004, 5, 10],
[1425, 5, 3, 2004, 5, 21], [1425, 5, 14, 2004, 6, 2], [1425, 5, 25, 2004, 6, 13],
[1425, 6, 6, 2004, 6, 24], [1425, 6, 17, 2004, 7, 4], [1425, 6, 28, 2004, 7, 15],
[1425, 7, 10, 2004, 7, 26], [1425, 7, 21, 2004, 8, 6], [1425, 8, 2, 2004, 8, 17],
[1425, 8, 13, 2004, 8, 28], [1425, 8, 24, 2004, 9, 9], [1425, 9, 6, 2004, 9, 20],
[1425, 9, 17, 2004, 9, 31], [1425, 9, 28, 2004, 10, 11], [1425, 10, 9, 2004, 10, 22],
[1425, 11, 24, 2005, 0, 5], [1425, 12, 5, 2005, 0, 16], [1425, 12, 16, 2005, 0, 27],
[1425, 12, 27, 2005, 1, 7], [1426, 1, 9, 2005, 1, 18], [1426, 1, 20, 2005, 2, 1],
[1426, 2, 1, 2005, 2, 12], [1426, 2, 12, 2005, 2, 23], [1426, 2, 23, 2005, 3, 3],
[1426, 3, 5, 2005, 3, 14], [1426, 3, 16, 2005, 3, 25], [1426, 3, 27, 2005, 4, 6],
[1426, 4, 8, 2005, 4, 17], [1426, 4, 19, 2005, 4, 28], [1426, 5, 1, 2005, 5, 8],
[1426, 5, 12, 2005, 5, 19], [1426, 5, 23, 2005, 5, 30], [1426, 6, 4, 2005, 6, 11],
[1426, 6, 15, 2005, 6, 22], [1426, 6, 26, 2005, 7, 2], [1426, 7, 8, 2005, 7, 13],
[1426, 7, 19, 2005, 7, 24], [1426, 7, 30, 2005, 8, 4], [1426, 8, 11, 2005, 8, 15],
[1426, 8, 22, 2005, 8, 26], [1426, 9, 4, 2005, 9, 7], [1426, 9, 15, 2005, 9, 18],
[1426, 9, 26, 2005, 9, 29], [1426, 10, 7, 2005, 10, 9], [1426, 10, 18, 2005, 10, 20],
[1426, 10, 29, 2005, 11, 1], [1426, 11, 11, 2005, 11, 12], [1426, 11, 22, 2005, 11, 23],
[1426, 12, 3, 2006, 0, 3], [1426, 12, 14, 2006, 0, 14], [1426, 12, 25, 2006, 0, 25],
[1427, 1, 6, 2006, 1, 5], [1427, 1, 17, 2006, 1, 16], [1427, 1, 28, 2006, 1, 27],
[1427, 2, 9, 2006, 2, 10], [1427, 2, 20, 2006, 2, 21], [1427, 3, 2, 2006, 3, 1],
[1427, 3, 13, 2006, 3, 12], [1427, 3, 24, 2006, 3, 23], [1427, 4, 5, 2006, 4, 4],
[1427, 4, 16, 2006, 4, 15], [1427, 4, 27, 2006, 4, 26], [1427, 5, 9, 2006, 5, 6],
[1427, 5, 20, 2006, 5, 17], [1427, 6, 1, 2006, 5, 28], [1427, 6, 12, 2006, 6, 9],
[1427, 6, 23, 2006, 6, 20], [1427, 7, 5, 2006, 6, 31], [1427, 7, 16, 2006, 7, 11],
[1427, 7, 27, 2006, 7, 22], [1427, 8, 8, 2006, 8, 2], [1427, 8, 19, 2006, 8, 13],
[1427, 9, 1, 2006, 8, 24], [1427, 9, 12, 2006, 9, 5], [1427, 9, 23, 2006, 9, 16],
[1427, 10, 4, 2006, 9, 27], [1427, 10, 15, 2006, 10, 7], [1427, 10, 26, 2006, 10, 18],
[1427, 11, 8, 2006, 10, 29], [1427, 11, 19, 2006, 11, 10], [1427, 11, 30, 2006, 11, 21],
[1427, 12, 11, 2007, 0, 1], [1427, 12, 22, 2007, 0, 12], [1428, 1, 4, 2007, 0, 23],
[1428, 1, 15, 2007, 1, 3], [1428, 1, 26, 2007, 1, 14], [1428, 2, 7, 2007, 1, 25],
[1428, 2, 18, 2007, 2, 8], [1428, 2, 29, 2007, 2, 19], [1428, 3, 11, 2007, 2, 30],
[1428, 3, 22, 2007, 3, 10], [1428, 4, 3, 2007, 3, 21], [1428, 4, 14, 2007, 4, 2],
[1428, 4, 25, 2007, 4, 13], [1428, 5, 7, 2007, 4, 24], [1428, 5, 18, 2007, 5, 4],
[1428, 5, 29, 2007, 5, 15], [1428, 6, 10, 2007, 5, 26], [1428, 6, 21, 2007, 6, 7],
[1428, 7, 3, 2007, 6, 18], [1428, 7, 14, 2007, 6, 29], [1428, 7, 25, 2007, 7, 9],
[1428, 8, 6, 2007, 7, 20], [1428, 8, 17, 2007, 7, 31], [1428, 8, 28, 2007, 8, 11],
[1428, 9, 10, 2007, 8, 22], [1428, 9, 21, 2007, 9, 3], [1428, 10, 2, 2007, 9, 14],
[1428, 10, 13, 2007, 9, 25], [1428, 10, 24, 2007, 10, 5], [1428, 11, 6, 2007, 10, 16],
[1428, 11, 17, 2007, 10, 27], [1429, 1, 1, 2008, 0, 10], [1429, 1, 12, 2008, 0, 21],
[1429, 1, 23, 2008, 1, 1], [1429, 2, 4, 2008, 1, 12], [1429, 2, 15, 2008, 1, 23],
[1429, 2, 26, 2008, 2, 5], [1429, 3, 8, 2008, 2, 16], [1429, 3, 19, 2008, 2, 27],
[1429, 3, 30, 2008, 3, 7], [1429, 4, 11, 2008, 3, 18], [1429, 4, 22, 2008, 3, 29],
[1429, 5, 4, 2008, 4, 10], [1429, 5, 15, 2008, 4, 21], [1429, 5, 26, 2008, 5, 1],
[1429, 6, 7, 2008, 5, 12], [1429, 6, 18, 2008, 5, 23], [1429, 6, 29, 2008, 6, 4],
[1429, 7, 11, 2008, 6, 15], [1429, 7, 22, 2008, 6, 26], [1429, 8, 3, 2008, 7, 6],
[1429, 8, 14, 2008, 7, 17], [1429, 8, 25, 2008, 7, 28], [1429, 9, 7, 2008, 8, 8],
[1429, 9, 18, 2008, 8, 19], [1429, 9, 29, 2008, 8, 30], [1429, 10, 10, 2008, 9, 11],
[1429, 10, 21, 2008, 9, 22], [1429, 11, 3, 2008, 10, 2], [1429, 11, 14, 2008, 10, 13],
[1429, 11, 25, 2008, 10, 24], [1430, 1, 10, 2009, 0, 7], [1430, 1, 21, 2009, 0, 18],
[1430, 2, 2, 2009, 0, 29], [1430, 2, 13, 2009, 1, 9], [1430, 2, 24, 2009, 1, 20],
[1430, 3, 6, 2009, 2, 3], [1430, 3, 17, 2009, 2, 14], [1430, 3, 28, 2009, 2, 25],
[1430, 4, 9, 2009, 3, 5], [1430, 4, 20, 2009, 3, 16], [1430, 5, 2, 2009, 3, 27],
[1430, 5, 13, 2009, 4, 8], [1430, 5, 24, 2009, 4, 19], [1430, 6, 5, 2009, 4, 30],
[1430, 6, 16, 2009, 5, 10], [1430, 6, 27, 2009, 5, 21], [1430, 7, 9, 2009, 6, 2],
[1430, 7, 20, 2009, 6, 13], [1430, 8, 1, 2009, 6, 24], [1430, 8, 12, 2009, 7, 4],
[1430, 8, 23, 2009, 7, 15], [1430, 9, 5, 2009, 7, 26], [1430, 9, 16, 2009, 8, 6],
[1430, 9, 27, 2009, 8, 17], [1430, 10, 8, 2009, 8, 28], [1430, 10, 19, 2009, 9, 9],
[1430, 11, 1, 2009, 9, 20], [1430, 11, 12, 2009, 9, 31], [1430, 11, 23, 2009, 10, 11],
[1430, 12, 4, 2009, 10, 22], [1430, 12, 15, 2009, 11, 3], [1430, 12, 26, 2009, 11, 14],
[1431, 1, 8, 2009, 11, 25], [1431, 1, 19, 2010, 0, 5], [1431, 1, 30, 2010, 0, 16],
[1431, 2, 11, 2010, 0, 27], [1431, 2, 22, 2010, 1, 7], [1431, 3, 4, 2010, 1, 18],
[1431, 3, 15, 2010, 2, 1], [1431, 3, 26, 2010, 2, 12], [1431, 4, 7, 2010, 2, 23],
[1431, 4, 18, 2010, 3, 3], [1431, 4, 29, 2010, 3, 14], [1431, 5, 11, 2010, 3, 25],
[1431, 5, 22, 2010, 4, 6], [1431, 6, 3, 2010, 4, 17], [1431, 6, 14, 2010, 4, 28],
[1431, 6, 25, 2010, 5, 8], [1431, 7, 7, 2010, 5, 19], [1431, 7, 18, 2010, 5, 30],
[1431, 7, 29, 2010, 6, 11], [1431, 8, 10, 2010, 6, 22], [1431, 8, 21, 2010, 7, 2],
[1431, 9, 3, 2010, 7, 13], [1431, 9, 14, 2010, 7, 24], [1431, 9, 25, 2010, 8, 4],
[1431, 10, 6, 2010, 8, 15], [1431, 10, 17, 2010, 8, 26], [1431, 10, 28, 2010, 9, 7],
[1431, 11, 10, 2010, 9, 18], [1431, 11, 21, 2010, 9, 29], [1431, 12, 2, 2010, 10, 9],
[1431, 12, 13, 2010, 10, 20], [1431, 12, 24, 2010, 11, 1], [1432, 1, 5, 2010, 11, 12],
[1432, 1, 16, 2010, 11, 23], [1432, 1, 27, 2011, 0, 3], [1432, 2, 8, 2011, 0, 14],
[1432, 2, 19, 2011, 0, 25], [1432, 3, 1, 2011, 1, 5], [1432, 3, 12, 2011, 1, 16],
[1432, 3, 23, 2011, 1, 27], [1432, 4, 4, 2011, 2, 10], [1432, 4, 15, 2011, 2, 21],
[1432, 4, 26, 2011, 3, 1], [1432, 5, 8, 2011, 3, 12], [1432, 5, 19, 2011, 3, 23],
[1432, 5, 30, 2011, 4, 4], [1432, 6, 11, 2011, 4, 15], [1432, 6, 22, 2011, 4, 26],
[1432, 7, 4, 2011, 5, 6], [1432, 7, 15, 2011, 5, 17], [1432, 7, 26, 2011, 5, 28],
[1432, 8, 7, 2011, 6, 9], [1432, 8, 18, 2011, 6, 20], [1432, 8, 29, 2011, 6, 31],
[1432, 9, 11, 2011, 7, 11], [1432, 9, 22, 2011, 7, 22], [1432, 10, 3, 2011, 8, 2],
[1432, 10, 14, 2011, 8, 13], [1432, 10, 25, 2011, 8, 24], [1432, 11, 7, 2011, 9, 5],
[1432, 11, 18, 2011, 9, 16], [1432, 11, 29, 2011, 9, 27], [1432, 12, 10, 2011, 10, 7],
[1432, 12, 21, 2011, 10, 18], [1433, 1, 3, 2011, 10, 29], [1433, 2, 6, 2012, 0, 1],
[1433, 2, 17, 2012, 0, 12], [1433, 2, 28, 2012, 0, 23], [1433, 3, 10, 2012, 1, 3],
[1433, 3, 21, 2012, 1, 14], [1433, 4, 2, 2012, 1, 25], [1433, 4, 13, 2012, 2, 7],
[1433, 4, 24, 2012, 2, 18], [1433, 5, 6, 2012, 2, 29], [1433, 5, 17, 2012, 3, 9],
[1433, 5, 28, 2012, 3, 20], [1433, 6, 9, 2012, 4, 1], [1433, 6, 20, 2012, 4, 12],
[1433, 7, 2, 2012, 4, 23], [1433, 7, 13, 2012, 5, 3], [1433, 7, 24, 2012, 5, 14],
[1433, 8, 5, 2012, 5, 25], [1433, 8, 16, 2012, 6, 6], [1433, 8, 27, 2012, 6, 17],
[1433, 9, 9, 2012, 6, 28], [1433, 9, 20, 2012, 7, 8], [1433, 10, 1, 2012, 7, 19],
[1433, 10, 12, 2012, 7, 30], [1433, 10, 23, 2012, 8, 10], [1433, 11, 5, 2012, 8, 21],
[1433, 11, 16, 2012, 9, 2], [1433, 11, 27, 2012, 9, 13], [1433, 12, 8, 2012, 9, 24],
[1433, 12, 19, 2012, 10, 4], [1434, 1, 1, 2012, 10, 15], [1434, 1, 12, 2012, 10, 26],
[1434, 2, 26, 2013, 0, 9], [1434, 3, 8, 2013, 0, 20], [1434, 3, 19, 2013, 0, 31],
[1434, 3, 30, 2013, 1, 11], [1434, 4, 11, 2013, 1, 22], [1434, 4, 22, 2013, 2, 5],
[1434, 5, 4, 2013, 2, 16], [1434, 5, 15, 2013, 2, 27], [1434, 5, 26, 2013, 3, 7],
[1434, 6, 7, 2013, 3, 18], [1434, 6, 18, 2013, 3, 29], [1434, 6, 29, 2013, 4, 10],
[1434, 7, 11, 2013, 4, 21], [1434, 7, 22, 2013, 5, 1], [1434, 8, 3, 2013, 5, 12],
[1434, 8, 14, 2013, 5, 23], [1434, 8, 25, 2013, 6, 4], [1434, 9, 7, 2013, 6, 15],
[1434, 9, 18, 2013, 6, 26], [1434, 9, 29, 2013, 7, 6], [1434, 10, 10, 2013, 7, 17],
[1434, 10, 21, 2013, 7, 28], [1434, 11, 3, 2013, 8, 8], [1434, 11, 14, 2013, 8, 19],
[1434, 11, 25, 2013, 8, 30], [1434, 12, 6, 2013, 9, 11], [1434, 12, 17, 2013, 9, 22],
[1434, 12, 28, 2013, 10, 2], [1435, 1, 9, 2013, 10, 13], [1435, 1, 20, 2013, 10, 24],
[1435, 2, 1, 2013, 11, 5], [1435, 2, 12, 2013, 11, 16], [1435, 2, 23, 2013, 11, 27],
[1435, 3, 5, 2014, 0, 7], [1435, 3, 16, 2014, 0, 18], [1435, 3, 27, 2014, 0, 29],
[1435, 4, 8, 2014, 1, 9], [1435, 4, 19, 2014, 1, 20], [1435, 5, 1, 2014, 2, 3],
[1435, 5, 12, 2014, 2, 14], [1435, 5, 23, 2014, 2, 25], [1435, 6, 4, 2014, 3, 5],
[1435, 6, 15, 2014, 3, 16], [1435, 6, 26, 2014, 3, 27], [1435, 7, 8, 2014, 4, 8],
[1435, 7, 19, 2014, 4, 19], [1435, 7, 30, 2014, 4, 30], [1435, 8, 11, 2014, 5, 10],
[1435, 8, 22, 2014, 5, 21], [1435, 9, 4, 2014, 6, 2], [1435, 9, 15, 2014, 6, 13],
[1435, 9, 26, 2014, 6, 24], [1435, 10, 7, 2014, 7, 4], [1435, 10, 18, 2014, 7, 15],
[1435, 10, 29, 2014, 7, 26], [1435, 11, 11, 2014, 8, 6], [1435, 11, 22, 2014, 8, 17],
[1435, 12, 3, 2014, 8, 28], [1435, 12, 14, 2014, 9, 9], [1435, 12, 25, 2014, 9, 20],
[1436, 1, 7, 2014, 9, 31], [1436, 1, 18, 2014, 10, 11], [1436, 1, 29, 2014, 10, 22],
[1436, 2, 10, 2014, 11, 3], [1436, 2, 21, 2014, 11, 14], [1436, 3, 3, 2014, 11, 25],
[1436, 3, 14, 2015, 0, 5], [1436, 3, 25, 2015, 0, 16], [1436, 4, 6, 2015, 0, 27],
[1436, 4, 17, 2015, 1, 7], [1436, 4, 28, 2015, 1, 18], [1436, 5, 10, 2015, 2, 1],
[1436, 5, 21, 2015, 2, 12], [1436, 6, 2, 2015, 2, 23], [1436, 6, 13, 2015, 3, 3],
[1436, 6, 24, 2015, 3, 14], [1436, 7, 6, 2015, 3, 25], [1436, 7, 17, 2015, 4, 6],
[1436, 7, 28, 2015, 4, 17], [1436, 8, 9, 2015, 4, 28], [1436, 8, 20, 2015, 5, 8],
[1436, 9, 2, 2015, 5, 19], [1436, 9, 13, 2015, 5, 30], [1436, 9, 24, 2015, 6, 11],
[1436, 10, 5, 2015, 6, 22], [1436, 10, 16, 2015, 7, 2], [1436, 10, 27, 2015, 7, 13],
[1436, 11, 9, 2015, 7, 24], [1436, 11, 20, 2015, 8, 4], [1436, 12, 1, 2015, 8, 15],
[1436, 12, 12, 2015, 8, 26], [1436, 12, 23, 2015, 9, 7], [1437, 1, 4, 2015, 9, 18],
[1437, 1, 15, 2015, 9, 29], [1437, 1, 26, 2015, 10, 9], [1437, 2, 7, 2015, 10, 20],
[1437, 3, 22, 2016, 0, 3], [1437, 4, 3, 2016, 0, 14], [1437, 4, 14, 2016, 0, 25],
[1437, 4, 25, 2016, 1, 5], [1437, 5, 7, 2016, 1, 16], [1437, 5, 18, 2016, 1, 27],
[1437, 5, 29, 2016, 2, 9], [1437, 6, 10, 2016, 2, 20], [1437, 6, 21, 2016, 2, 31],
[1437, 7, 3, 2016, 3, 11], [1437, 7, 14, 2016, 3, 22], [1437, 7, 25, 2016, 4, 3],
[1437, 8, 6, 2016, 4, 14], [1437, 8, 17, 2016, 4, 25], [1437, 8, 28, 2016, 5, 5],
[1437, 9, 10, 2016, 5, 16], [1437, 9, 21, 2016, 5, 27], [1437, 10, 2, 2016, 6, 8],
[1437, 10, 13, 2016, 6, 19], [1437, 10, 24, 2016, 6, 30], [1437, 11, 6, 2016, 7, 10],
[1437, 11, 17, 2016, 7, 21], [1437, 11, 28, 2016, 8, 1], [1437, 12, 9, 2016, 8, 12],
[1437, 12, 20, 2016, 8, 23], [1438, 1, 2, 2016, 9, 4], [1438, 1, 13, 2016, 9, 15],
[1438, 1, 24, 2016, 9, 26], [1438, 2, 5, 2016, 10, 6], [1438, 2, 16, 2016, 10, 17],
[1438, 2, 27, 2016, 10, 28], [1438, 4, 12, 2017, 0, 11], [1438, 4, 23, 2017, 0, 22],
[1438, 5, 5, 2017, 1, 2], [1438, 5, 16, 2017, 1, 13], [1438, 5, 27, 2017, 1, 24],
[1438, 6, 8, 2017, 2, 7], [1438, 6, 19, 2017, 2, 18], [1438, 7, 1, 2017, 2, 29],
[1438, 7, 12, 2017, 3, 9], [1438, 7, 23, 2017, 3, 20], [1438, 8, 4, 2017, 4, 1],
[1438, 8, 15, 2017, 4, 12], [1438, 8, 26, 2017, 4, 23], [1438, 9, 8, 2017, 5, 3],
[1438, 9, 19, 2017, 5, 14], [1438, 9, 30, 2017, 5, 25], [1438, 10, 11, 2017, 6, 6],
[1438, 10, 22, 2017, 6, 17], [1438, 11, 4, 2017, 6, 28], [1438, 11, 15, 2017, 7, 8],
[1438, 11, 26, 2017, 7, 19], [1438, 12, 7, 2017, 7, 30], [1438, 12, 18, 2017, 8, 10],
[1438, 12, 29, 2017, 8, 21], [1439, 1, 11, 2017, 9, 2], [1439, 1, 22, 2017, 9, 13],
[1439, 2, 3, 2017, 9, 24], [1439, 2, 14, 2017, 10, 4], [1439, 2, 25, 2017, 10, 15],
[1439, 3, 7, 2017, 10, 26], [1439, 3, 18, 2017, 11, 7], [1439, 3, 29, 2017, 11, 18],
[1439, 4, 10, 2017, 11, 29], [1439, 4, 21, 2018, 0, 9], [1439, 5, 3, 2018, 0, 20],
[1439, 5, 14, 2018, 0, 31], [1439, 5, 25, 2018, 1, 11], [1439, 6, 6, 2018, 1, 22],
[1439, 6, 17, 2018, 2, 5], [1439, 6, 28, 2018, 2, 16], [1439, 7, 10, 2018, 2, 27],
[1439, 7, 21, 2018, 3, 7], [1439, 8, 2, 2018, 3, 18], [1439, 8, 13, 2018, 3, 29],
[1439, 8, 24, 2018, 4, 10], [1439, 9, 6, 2018, 4, 21], [1439, 9, 17, 2018, 5, 1],
[1439, 9, 28, 2018, 5, 12], [1439, 10, 9, 2018, 5, 23], [1439, 10, 20, 2018, 6, 4],
[1439, 11, 2, 2018, 6, 15], [1439, 11, 13, 2018, 6, 26], [1439, 11, 24, 2018, 7, 6],
[1439, 12, 5, 2018, 7, 17], [1439, 12, 16, 2018, 7, 28], [1439, 12, 27, 2018, 8, 8],
[1440, 1, 8, 2018, 8, 19], [1440, 1, 19, 2018, 8, 30], [1440, 1, 30, 2018, 9, 11],
[1440, 2, 11, 2018, 9, 22], [1440, 2, 22, 2018, 10, 2], [1440, 3, 4, 2018, 10, 13],
[1440, 3, 15, 2018, 10, 24], [1440, 3, 26, 2018, 11, 5], [1440, 4, 7, 2018, 11, 16],
[1440, 4, 18, 2018, 11, 27], [1440, 4, 29, 2019, 0, 7], [1440, 5, 11, 2019, 0, 18],
[1440, 5, 22, 2019, 0, 29], [1440, 6, 3, 2019, 1, 9], [1440, 6, 14, 2019, 1, 20],
[1440, 6, 25, 2019, 2, 3], [1440, 7, 7, 2019, 2, 14], [1440, 7, 18, 2019, 2, 25],
[1440, 7, 29, 2019, 3, 5], [1440, 8, 10, 2019, 3, 16], [1440, 8, 21, 2019, 3, 27],
[1440, 9, 3, 2019, 4, 8], [1440, 9, 14, 2019, 4, 19], [1440, 9, 25, 2019, 4, 30],
[1440, 10, 6, 2019, 5, 10], [1440, 10, 17, 2019, 5, 21], [1440, 10, 28, 2019, 6, 2],
[1440, 11, 10, 2019, 6, 13], [1440, 11, 21, 2019, 6, 24], [1440, 12, 2, 2019, 7, 4],
[1440, 12, 13, 2019, 7, 15], [1440, 12, 24, 2019, 7, 26], [1441, 1, 6, 2019, 8, 6],
[1441, 1, 17, 2019, 8, 17], [1441, 1, 28, 2019, 8, 28], [1441, 2, 9, 2019, 9, 9],
[1441, 2, 20, 2019, 9, 20], [1441, 3, 2, 2019, 9, 31], [1441, 3, 13, 2019, 10, 11],
[1441, 3, 24, 2019, 10, 22], [1441, 5, 9, 2020, 0, 5], [1441, 5, 20, 2020, 0, 16],
[1441, 6, 1, 2020, 0, 27], [1441, 6, 12, 2020, 1, 7], [1441, 6, 23, 2020, 1, 18],
[1441, 7, 5, 2020, 1, 29], [1441, 7, 16, 2020, 2, 11], [1441, 7, 27, 2020, 2, 22],
[1441, 8, 8, 2020, 3, 2], [1441, 8, 19, 2020, 3, 13], [1441, 9, 1, 2020, 3, 24],
[1441, 9, 12, 2020, 4, 5], [1441, 9, 23, 2020, 4, 16], [1441, 10, 4, 2020, 4, 27],
[1441, 10, 15, 2020, 5, 7], [1441, 10, 26, 2020, 5, 18], [1441, 11, 8, 2020, 5, 29],
[1441, 11, 19, 2020, 6, 10], [1441, 11, 30, 2020, 6, 21], [1441, 12, 11, 2020, 7, 1],
[1441, 12, 22, 2020, 7, 12], [1442, 1, 4, 2020, 7, 23], [1442, 1, 15, 2020, 8, 3],
[1442, 1, 26, 2020, 8, 14], [1442, 2, 7, 2020, 8, 25], [1442, 2, 18, 2020, 9, 6],
[1442, 2, 29, 2020, 9, 17], [1442, 3, 11, 2020, 9, 28], [1442, 3, 22, 2020, 10, 8],
[1442, 4, 3, 2020, 10, 19], [1442, 4, 14, 2020, 10, 30], [1442, 5, 18, 2021, 0, 2],
[1442, 5, 29, 2021, 0, 13], [1442, 6, 10, 2021, 0, 24], [1442, 6, 21, 2021, 1, 4],
[1442, 7, 3, 2021, 1, 15], [1442, 7, 14, 2021, 1, 26], [1442, 7, 25, 2021, 2, 9],
[1442, 8, 6, 2021, 2, 20], [1442, 8, 17, 2021, 2, 31], [1442, 8, 28, 2021, 3, 11],
[1442, 9, 10, 2021, 3, 22], [1442, 9, 21, 2021, 4, 3], [1442, 10, 2, 2021, 4, 14],
[1442, 10, 13, 2021, 4, 25], [1442, 10, 24, 2021, 5, 5], [1442, 11, 6, 2021, 5, 16],
[1442, 11, 17, 2021, 5, 27], [1442, 11, 28, 2021, 6, 8], [1442, 12, 9, 2021, 6, 19],
[1442, 12, 20, 2021, 6, 30], [1443, 1, 1, 2021, 7, 10], [1443, 1, 12, 2021, 7, 21],
[1443, 1, 23, 2021, 8, 1], [1443, 2, 4, 2021, 8, 12], [1443, 2, 15, 2021, 8, 23],
[1443, 2, 26, 2021, 9, 4], [1443, 3, 8, 2021, 9, 15], [1443, 3, 19, 2021, 9, 26],
[1443, 3, 30, 2021, 10, 6], [1443, 4, 11, 2021, 10, 17], [1443, 4, 22, 2021, 10, 28],
[1443, 6, 7, 2022, 0, 11], [1443, 6, 18, 2022, 0, 22], [1443, 6, 29, 2022, 1, 2],
[1443, 7, 11, 2022, 1, 13], [1443, 7, 22, 2022, 1, 24], [1443, 8, 3, 2022, 2, 7],
[1443, 8, 14, 2022, 2, 18], [1443, 8, 25, 2022, 2, 29], [1443, 9, 7, 2022, 3, 9],
[1443, 9, 18, 2022, 3, 20], [1443, 9, 29, 2022, 4, 1], [1443, 10, 10, 2022, 4, 12],
[1443, 10, 21, 2022, 4, 23], [1443, 11, 3, 2022, 5, 3], [1443, 11, 14, 2022, 5, 14],
[1443, 11, 25, 2022, 5, 25], [1443, 12, 6, 2022, 6, 6], [1443, 12, 17, 2022, 6, 17],
[1443, 12, 28, 2022, 6, 28], [1444, 1, 10, 2022, 7, 8], [1444, 1, 21, 2022, 7, 19],
[1444, 2, 2, 2022, 7, 30], [1444, 2, 13, 2022, 8, 10], [1444, 2, 24, 2022, 8, 21],
[1444, 3, 6, 2022, 9, 2], [1444, 3, 17, 2022, 9, 13], [1444, 3, 28, 2022, 9, 24],
[1444, 4, 9, 2022, 10, 4], [1444, 4, 20, 2022, 10, 15], [1444, 5, 2, 2022, 10, 26],
[1444, 6, 16, 2023, 0, 9], [1444, 6, 27, 2023, 0, 20], [1444, 7, 9, 2023, 0, 31],
[1444, 7, 20, 2023, 1, 11], [1444, 8, 1, 2023, 1, 22], [1444, 8, 12, 2023, 2, 5],
[1444, 8, 23, 2023, 2, 16], [1444, 9, 5, 2023, 2, 27], [1444, 9, 16, 2023, 3, 7],
[1444, 9, 27, 2023, 3, 18], [1444, 10, 8, 2023, 3, 29], [1444, 10, 19, 2023, 4, 10],
[1444, 11, 1, 2023, 4, 21], [1444, 11, 12, 2023, 5, 1], [1444, 11, 23, 2023, 5, 12],
[1444, 12, 4, 2023, 5, 23], [1444, 12, 15, 2023, 6, 4], [1444, 12, 26, 2023, 6, 15],
[1445, 1, 8, 2023, 6, 26], [1445, 1, 19, 2023, 7, 6], [1445, 1, 30, 2023, 7, 17],
[1445, 2, 11, 2023, 7, 28], [1445, 2, 22, 2023, 8, 8], [1445, 3, 4, 2023, 8, 19],
[1445, 3, 15, 2023, 8, 30], [1445, 3, 26, 2023, 9, 11], [1445, 4, 7, 2023, 9, 22],
[1445, 4, 18, 2023, 10, 2], [1445, 4, 29, 2023, 10, 13], [1445, 5, 11, 2023, 10, 24],
[1445, 6, 25, 2024, 0, 7], [1445, 7, 7, 2024, 0, 18], [1445, 7, 18, 2024, 0, 29],
[1445, 7, 29, 2024, 1, 9], [1445, 8, 10, 2024, 1, 20], [1445, 8, 21, 2024, 2, 2],
[1445, 9, 3, 2024, 2, 13], [1445, 9, 14, 2024, 2, 24], [1445, 9, 25, 2024, 3, 4],
[1445, 10, 6, 2024, 3, 15], [1445, 10, 17, 2024, 3, 26], [1445, 10, 28, 2024, 4, 7],
[1445, 11, 10, 2024, 4, 18], [1445, 11, 21, 2024, 4, 29], [1445, 12, 2, 2024, 5, 9],
[1445, 12, 13, 2024, 5, 20], [1445, 12, 24, 2024, 6, 1], [1446, 1, 5, 2024, 6, 12],
[1446, 1, 16, 2024, 6, 23], [1446, 1, 27, 2024, 7, 3], [1446, 2, 8, 2024, 7, 14],
[1446, 2, 19, 2024, 7, 25], [1446, 3, 1, 2024, 8, 5], [1446, 3, 12, 2024, 8, 16],
[1446, 3, 23, 2024, 8, 27], [1446, 4, 4, 2024, 9, 8], [1446, 4, 15, 2024, 9, 19],
[1446, 4, 26, 2024, 9, 30], [1446, 5, 8, 2024, 10, 10], [1446, 5, 19, 2024, 10, 21],
[1446, 7, 4, 2025, 0, 4], [1446, 7, 15, 2025, 0, 15], [1446, 7, 26, 2025, 0, 26],
[1446, 8, 7, 2025, 1, 6], [1446, 8, 18, 2025, 1, 17], [1446, 8, 29, 2025, 1, 28],
[1446, 9, 11, 2025, 2, 11], [1446, 9, 22, 2025, 2, 22], [1446, 10, 3, 2025, 3, 2],
[1446, 10, 14, 2025, 3, 13], [1446, 10, 25, 2025, 3, 24], [1446, 11, 7, 2025, 4, 5],
[1446, 11, 18, 2025, 4, 16], [1446, 11, 29, 2025, 4, 27], [1446, 12, 10, 2025, 5, 7],
[1446, 12, 21, 2025, 5, 18], [1447, 1, 3, 2025, 5, 29], [1447, 1, 14, 2025, 6, 10],
[1447, 1, 25, 2025, 6, 21], [1447, 2, 6, 2025, 7, 1], [1447, 2, 17, 2025, 7, 12],
[1447, 2, 28, 2025, 7, 23], [1447, 3, 10, 2025, 8, 3], [1447, 3, 21, 2025, 8, 14],
[1447, 4, 2, 2025, 8, 25], [1447, 4, 13, 2025, 9, 6], [1447, 4, 24, 2025, 9, 17],
[1447, 5, 6, 2025, 9, 28], [1447, 5, 17, 2025, 10, 8], [1447, 5, 28, 2025, 10, 19],
[1447, 6, 9, 2025, 10, 30], [1447, 7, 13, 2026, 0, 2], [1447, 7, 24, 2026, 0, 13],
[1447, 8, 5, 2026, 0, 24], [1447, 8, 16, 2026, 1, 4], [1447, 8, 27, 2026, 1, 15],
[1447, 9, 9, 2026, 1, 26], [1447, 9, 20, 2026, 2, 9], [1447, 10, 1, 2026, 2, 20],
[1447, 10, 12, 2026, 2, 31], [1447, 10, 23, 2026, 3, 11], [1447, 11, 5, 2026, 3, 22],
[1447, 11, 16, 2026, 4, 3], [1447, 11, 27, 2026, 4, 14], [1447, 12, 8, 2026, 4, 25],
[1447, 12, 19, 2026, 5, 5], [1447, 12, 30, 2026, 5, 16], [1448, 1, 11, 2026, 5, 27],
[1448, 1, 22, 2026, 6, 8], [1448, 2, 3, 2026, 6, 19], [1448, 2, 14, 2026, 6, 30],
[1448, 2, 25, 2026, 7, 10], [1448, 3, 7, 2026, 7, 21], [1448, 3, 18, 2026, 8, 1],
[1420, 8, 22, 1999, 11, 1], [1424, 10, 6, 2003, 11, 1], [1428, 11, 21, 2007, 11, 1],
[1433, 1, 5, 2011, 11, 1]
];
const calendar = new NgbCalendarIslamicCivilNOA11Y();
describe('toGregorian', () => {
DATE_TABLE.forEach(element => {
let iDate = new NgbDate(element[0], element[1], element[2]);
let gDate = new Date(element[3], element[4], element[5]);
it('should convert correctly from Hijri to Gregorian',
() => { expect(calendar.toGregorian(iDate).getTime()).toEqual(gDate.getTime()); });
});
});
describe('fromGregorian', () => {
DATE_TABLE.forEach(element => {
let iDate = new NgbDate(element[0], element[1], element[2]);
const gDate = new Date(element[3], element[4], element[5]);
let iDate2 = calendar.fromGregorian(gDate);
it('should convert correctly from Gregorian to Hijri', () => { expect(iDate2.equals(iDate)).toBeTruthy(); });
});
});
it('should return number of days per week', () => { expect(calendar.getDaysPerWeek()).toBe(7); });
it('should return number of weeks per month', () => { expect(calendar.getWeeksPerMonth()).toBe(6); });
it('should return months of a year', () => {
expect(calendar.getMonths()).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);
});
it('should return day of week', () => {
expect(calendar.getWeekday(new NgbDate(1437, 12, 15))).toEqual(7);
expect(calendar.getWeekday(new NgbDate(1437, 12, 16))).toEqual(1);
expect(calendar.getWeekday(new NgbDate(1437, 12, 17))).toEqual(2);
expect(calendar.getWeekday(new NgbDate(1437, 12, 18))).toEqual(3);
expect(calendar.getWeekday(new NgbDate(1437, 12, 19))).toEqual(4);
expect(calendar.getWeekday(new NgbDate(1437, 12, 20))).toEqual(5);
expect(calendar.getWeekday(new NgbDate(1437, 12, 21))).toEqual(6);
expect(calendar.getWeekday(new NgbDate(1431, 1, 11))).toEqual(1);
expect(calendar.getWeekday(new NgbDate(1431, 7, 22))).toEqual(7);
expect(calendar.getWeekday(new NgbDate(1431, 2, 3))).toEqual(2);
expect(calendar.getWeekday(new NgbDate(1431, 3, 10))).toEqual(3);
expect(calendar.getWeekday(new NgbDate(1431, 4, 23))).toEqual(4);
expect(calendar.getWeekday(new NgbDate(1202, 2, 19))).toEqual(5);
expect(calendar.getWeekday(new NgbDate(1431, 7, 21))).toEqual(6);
});
it('should add days to date', () => {
expect(calendar.getNext(new NgbDate(1431, 1, 30))).toEqual(new NgbDate(1431, 2, 1));
expect(calendar.getNext(new NgbDate(1437, 2, 28))).toEqual(new NgbDate(1437, 2, 29));
expect(calendar.getNext(new NgbDate(1437, 2, 29))).toEqual(new NgbDate(1437, 3, 1));
});
it('should subtract days from date', () => {
expect(calendar.getPrev(new NgbDate(1431, 2, 1))).toEqual(new NgbDate(1431, 1, 30));
expect(calendar.getPrev(new NgbDate(1431, 3, 1))).toEqual(new NgbDate(1431, 2, 29));
expect(calendar.getPrev(new NgbDate(1437, 3, 5))).toEqual(new NgbDate(1437, 3, 4));
});
it('should add months to date', () => {
expect(calendar.getNext(new NgbDate(1437, 8, 22), 'm')).toEqual(new NgbDate(1437, 9, 1));
expect(calendar.getNext(new NgbDate(1437, 8, 1), 'm')).toEqual(new NgbDate(1437, 9, 1));
expect(calendar.getNext(new NgbDate(1437, 12, 22), 'm')).toEqual(new NgbDate(1438, 1, 1));
});
it('should subtract months from date', () => {
expect(calendar.getPrev(new NgbDate(1437, 8, 22), 'm')).toEqual(new NgbDate(1437, 7, 1));
expect(calendar.getPrev(new NgbDate(1437, 9, 1), 'm')).toEqual(new NgbDate(1437, 8, 1));
expect(calendar.getPrev(new NgbDate(1437, 1, 22), 'm')).toEqual(new NgbDate(1436, 12, 1));
});
it('should add years to date', () => {
expect(calendar.getNext(new NgbDate(1437, 2, 22), 'y')).toEqual(new NgbDate(1438, 1, 1));
expect(calendar.getNext(new NgbDate(1438, 12, 22), 'y')).toEqual(new NgbDate(1439, 1, 1));
});
it('should subtract years from date', () => {
expect(calendar.getPrev(new NgbDate(1437, 12, 22), 'y')).toEqual(new NgbDate(1436, 1, 1));
expect(calendar.getPrev(new NgbDate(1438, 2, 22), 'y')).toEqual(new NgbDate(1437, 1, 1));
});
it('should return week number', () => {
let week = [
new NgbDate(1437, 1, 4), new NgbDate(1437, 1, 5), new NgbDate(1437, 1, 6), new NgbDate(1437, 1, 7),
new NgbDate(1437, 1, 8), new NgbDate(1437, 1, 9), new NgbDate(1437, 1, 10)
];
expect(calendar.getWeekNumber(week, 7)).toEqual(2);
week = [
new NgbDate(1437, 12, 15), new NgbDate(1437, 12, 16), new NgbDate(1437, 12, 17), new NgbDate(1437, 12, 18),
new NgbDate(1437, 12, 19), new NgbDate(1437, 12, 20), new NgbDate(1437, 12, 21)
];
expect(calendar.getWeekNumber(week, 7)).toEqual(50);
week = [
new NgbDate(1437, 12, 22), new NgbDate(1437, 12, 23), new NgbDate(1437, 12, 24), new NgbDate(1437, 12, 25),
new NgbDate(1437, 12, 26), new NgbDate(1437, 12, 27), new NgbDate(1437, 12, 28)
];
expect(calendar.getWeekNumber(week, 7)).toEqual(51);
});
describe('setDay', () => {
it('should return correct value of day', () => {
expect(calendar.setDay(new NgbDate(1202, 9, 1), 19).day).toEqual(19);
expect(calendar.setDay(new NgbDate(1431, 1, 1), 1).day).toEqual(1);
expect(calendar.setDay(new NgbDate(1431, 1, 1), 31).day).toEqual(1);
expect(calendar.setDay(new NgbDate(1437, 1, 1), 61).day).toEqual(2);
expect(calendar.setDay(new NgbDate(1431, 2, 1), 0).day).toEqual(30);
expect(calendar.setDay(new NgbDate(1431, 2, 1), -1).day).toEqual(29);
expect(calendar.setDay(new NgbDate(1431, 2, 1), -2).day).toEqual(28);
});
});
describe('setMonth', () => {
it('should return correct value of month', () => {
expect(calendar.setMonth(new NgbDate(1202, 9, 1), 9).month).toEqual(9);
expect(calendar.setMonth(new NgbDate(1431, 1, 30), 1).month).toEqual(1);
expect(calendar.setDay(new NgbDate(1431, 1, 1), 31).month).toEqual(2);
expect(calendar.setDay(new NgbDate(1437, 1, 1), 61).month).toEqual(3);
expect(calendar.setDay(new NgbDate(1431, 2, 1), -1).month).toEqual(1);
expect(calendar.setDay(new NgbDate(1431, 2, 1), -30).month).toEqual(12);
expect(calendar.setMonth(new NgbDate(1431, 1, 1), 0).month).toEqual(12);
});
});
describe('setYear', () => {
it('should return correct value of yar', () => {
expect(calendar.setYear(new NgbDate(1200, 1, 1), 1202).year).toEqual(1202);
expect(calendar.setYear(new NgbDate(1430, 11, 30), 1431).year).toEqual(1431);
expect(calendar.setDay(new NgbDate(1431, 12, 1), 31).year).toEqual(1432);
expect(calendar.setMonth(new NgbDate(1431, 1, 1), 13).year).toEqual(1432);
expect(calendar.setMonth(new NgbDate(1431, 1, 1), 25).year).toEqual(1433);
expect(calendar.setDay(new NgbDate(1431, 1, 1), -1).year).toEqual(1430);
expect(calendar.setMonth(new NgbDate(1431, 1, 1), 0).year).toEqual(1430);
expect(calendar.setMonth(new NgbDate(1431, 1, 1), -13).year).toEqual(1429);
});
});
});

View File

@ -0,0 +1,153 @@
import {NgbCalendarHijriNOA11Y} from './ngb-calendar-hijri';
import {NgbDate} from '../ngb-date';
import {NgbPeriodNOA11Y} from '../ngb-calendar';
import {Injectable} from '@angular/core';
function isGregorianLeapYear(date: Date): boolean {
const year = date.getFullYear();
return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
}
function mod(a: number, b: number): number {
return a - b * Math.floor(a / b);
}
/**
* The civil calendar is one type of Hijri calendars used in islamic countries.
* Uses a fixed cycle of alternating 29- and 30-day months,
* with a leap day added to the last month of 11 out of every 30 years.
* http://cldr.unicode.org/development/development-process/design-proposals/islamic-calendar-types
* All the calculations here are based on the equations from "Calendrical Calculations" By Edward M. Reingold, Nachum
* Dershowitz.
*/
const GREGORIAN_EPOCH = 1721425.5;
const ISLAMIC_EPOCH = 1948439.5;
@Injectable()
export class NgbCalendarIslamicCivilNOA11Y extends NgbCalendarHijriNOA11Y {
/**
* Returns the equivalent islamic(civil) date value for a give input Gregorian date.
* `gdate` is a JS Date to be converted to Hijri.
*/
fromGregorian(gdate: Date): NgbDate {
const date = new Date(gdate);
const gYear = date.getFullYear(), gMonth = date.getMonth(), gDay = date.getDate();
let julianDay = GREGORIAN_EPOCH - 1 + 365 * (gYear - 1) + Math.floor((gYear - 1) / 4) +
-Math.floor((gYear - 1) / 100) + Math.floor((gYear - 1) / 400) +
Math.floor(
(367 * (gMonth + 1) - 362) / 12 + (gMonth + 1 <= 2 ? 0 : isGregorianLeapYear(date) ? -1 : -2) + gDay);
julianDay = Math.floor(julianDay) + 0.5;
const days = julianDay - ISLAMIC_EPOCH;
const hYear = Math.floor((30 * days + 10646) / 10631.0);
let hMonth = Math.ceil((days - 29 - this._getYearStart(hYear)) / 29.5);
hMonth = Math.min(hMonth, 11);
const hDay = Math.ceil(days - this._getMonthStart(hYear, hMonth)) + 1;
return new NgbDate(hYear, hMonth + 1, hDay);
}
/**
* Returns the equivalent JS date value for a give input islamic(civil) date.
* `hijriDate` is an islamic(civil) date to be converted to Gregorian.
*/
toGregorian(hijriDate: NgbDate): Date {
const hYear = hijriDate.year;
const hMonth = hijriDate.month - 1;
const hDate = hijriDate.day;
const julianDay =
hDate + Math.ceil(29.5 * hMonth) + (hYear - 1) * 354 + Math.floor((3 + 11 * hYear) / 30) + ISLAMIC_EPOCH - 1;
const wjd = Math.floor(julianDay - 0.5) + 0.5, depoch = wjd - GREGORIAN_EPOCH,
quadricent = Math.floor(depoch / 146097), dqc = mod(depoch, 146097), cent = Math.floor(dqc / 36524),
dcent = mod(dqc, 36524), quad = Math.floor(dcent / 1461), dquad = mod(dcent, 1461),
yindex = Math.floor(dquad / 365);
let year = quadricent * 400 + cent * 100 + quad * 4 + yindex;
if (!(cent === 4 || yindex === 4)) {
year++;
}
const gYearStart = GREGORIAN_EPOCH + 365 * (year - 1) + Math.floor((year - 1) / 4) - Math.floor((year - 1) / 100) +
Math.floor((year - 1) / 400);
const yearday = wjd - gYearStart;
const tjd = GREGORIAN_EPOCH - 1 + 365 * (year - 1) + Math.floor((year - 1) / 4) - Math.floor((year - 1) / 100) +
Math.floor((year - 1) / 400) + Math.floor(739 / 12 + (isGregorianLeapYear(new Date(year, 3, 1)) ? -1 : -2) + 1);
const leapadj = wjd < tjd ? 0 : isGregorianLeapYear(new Date(year, 3, 1)) ? 1 : 2;
const month = Math.floor(((yearday + leapadj) * 12 + 373) / 367);
const tjd2 = GREGORIAN_EPOCH - 1 + 365 * (year - 1) + Math.floor((year - 1) / 4) - Math.floor((year - 1) / 100) +
Math.floor((year - 1) / 400) +
Math.floor(
(367 * month - 362) / 12 + (month <= 2 ? 0 : isGregorianLeapYear(new Date(year, month - 1, 1)) ? -1 : -2) +
1);
const day = wjd - tjd2 + 1;
return new Date(year, month - 1, day);
}
/**
* Returns the number of days in a specific Hijri month.
* `month` is 1 for Muharram, 2 for Safar, etc.
* `year` is any Hijri year.
*/
getDaysInIslamicMonth(month: number, year: number): number {
year = year + Math.floor(month / 13);
month = ((month - 1) % 12) + 1;
let length = 29 + month % 2;
if (month === 12 && this._isIslamicLeapYear(year)) {
length++;
}
return length;
}
getNext(date: NgbDate, period: NgbPeriodNOA11Y = 'd', number = 1) {
date = NgbDate.from(date);
switch (period) {
case 'y':
date = this.setYear(date, date.year + number);
date.month = 1;
date.day = 1;
return date;
case 'm':
date = this.setMonth(date, date.month + number);
date.day = 1;
return date;
case 'd':
return this.setDay(date, date.day + number);
default:
return date;
}
}
getPrev(date: NgbDate, period: NgbPeriodNOA11Y = 'd', number = 1) { return this.getNext(date, period, -number); }
getWeekday(date: NgbDate) {
const day = this.toGregorian(date).getDay();
// in JS Date Sun=0, in ISO 8601 Sun=7
return day === 0 ? 7 : day;
}
getWeekNumber(week: NgbDate[], firstDayOfWeek: number) {
// in JS Date Sun=0, in ISO 8601 Sun=7
if (firstDayOfWeek === 7) {
firstDayOfWeek = 0;
}
const thursdayIndex = (4 + 7 - firstDayOfWeek) % 7;
const date = week[thursdayIndex];
const jsDate = this.toGregorian(date);
jsDate.setDate(jsDate.getDate() + 4 - (jsDate.getDay() || 7)); // Thursday
const time = jsDate.getTime();
const MuhDate = this.toGregorian(new NgbDate(date.year, 1, 1)); // Compare with Muharram 1
return Math.floor(Math.round((time - MuhDate.getTime()) / 86400000) / 7) + 1;
}
getToday(): NgbDate { return this.fromGregorian(new Date()); }
}

View File

@ -0,0 +1,100 @@
import {NgbDate} from './ngb-date';
import {Injectable} from '@angular/core';
import {isInteger} from '../util/util';
function fromJSDate(jsDate: Date) {
return new NgbDate(jsDate.getFullYear(), jsDate.getMonth() + 1, jsDate.getDate());
}
function toJSDate(date: NgbDate) {
const jsDate = new Date(date.year, date.month - 1, date.day, 12);
// this is done avoid 30 -> 1930 conversion
if (!isNaN(jsDate.getTime())) {
jsDate.setFullYear(date.year);
}
return jsDate;
}
export type NgbPeriodNOA11Y = 'y' | 'm' | 'd';
@Injectable()
export abstract class NgbCalendarNOA11Y {
abstract getDaysPerWeek(): number;
abstract getMonths(): number[];
abstract getWeeksPerMonth(): number;
abstract getWeekday(date: NgbDate): number;
abstract getNext(date: NgbDate, period?: NgbPeriodNOA11Y, number?: number): NgbDate;
abstract getPrev(date: NgbDate, period?: NgbPeriodNOA11Y, number?: number): NgbDate;
abstract getWeekNumber(week: NgbDate[], firstDayOfWeek: number): number;
abstract getToday(): NgbDate;
abstract isValid(date: NgbDate): boolean;
}
@Injectable()
export class NgbCalendarGregorianNOA11Y extends NgbCalendarNOA11Y {
getDaysPerWeek() { return 7; }
getMonths() { return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; }
getWeeksPerMonth() { return 6; }
getNext(date: NgbDate, period: NgbPeriodNOA11Y = 'd', number = 1) {
let jsDate = toJSDate(date);
switch (period) {
case 'y':
return new NgbDate(date.year + number, 1, 1);
case 'm':
jsDate = new Date(date.year, date.month + number - 1, 1, 12);
break;
case 'd':
jsDate.setDate(jsDate.getDate() + number);
break;
default:
return date;
}
return fromJSDate(jsDate);
}
getPrev(date: NgbDate, period: NgbPeriodNOA11Y = 'd', number = 1) { return this.getNext(date, period, -number); }
getWeekday(date: NgbDate) {
let jsDate = toJSDate(date);
let day = jsDate.getDay();
// in JS Date Sun=0, in ISO 8601 Sun=7
return day === 0 ? 7 : day;
}
getWeekNumber(week: NgbDate[], firstDayOfWeek: number) {
// in JS Date Sun=0, in ISO 8601 Sun=7
if (firstDayOfWeek === 7) {
firstDayOfWeek = 0;
}
const thursdayIndex = (4 + 7 - firstDayOfWeek) % 7;
let date = week[thursdayIndex];
const jsDate = toJSDate(date);
jsDate.setDate(jsDate.getDate() + 4 - (jsDate.getDay() || 7)); // Thursday
const time = jsDate.getTime();
jsDate.setMonth(0); // Compare with Jan 1
jsDate.setDate(1);
return Math.floor(Math.round((time - jsDate.getTime()) / 86400000) / 7) + 1;
}
getToday(): NgbDate { return fromJSDate(new Date()); }
isValid(date: NgbDate): boolean {
if (!date || !isInteger(date.year) || !isInteger(date.month) || !isInteger(date.day)) {
return false;
}
const jsDate = toJSDate(date);
return !isNaN(jsDate.getTime()) && jsDate.getFullYear() === date.year && jsDate.getMonth() + 1 === date.month &&
jsDate.getDate() === date.day;
}
}

View File

@ -0,0 +1,26 @@
export interface NgbDataTemplateStruct {
/**
* Il template selezionato
*/
template: number;
/**
* Il numero del giorno
*/
day: number;
/**
* Il numero del mese
*/
month: number;
/**
* Il numero dell'anno
*/
year: number;
/**
* Se i dati sono validi o meno
*/
valid: boolean;
}

View File

@ -0,0 +1,46 @@
import { NbpCalendarPattern, NbpDateSeparator } from '../../nbp-calendar-generic.enum';
import {padNumber, toInteger, isNumber} from '../util/util';
import {NgbDateStruct} from './ngb-date-struct';
/**
* Abstract type serving as a DI token for the service parsing and formatting dates for the NgbInputDatepicker
* directive. A default implementation using the ISO 8601 format is provided, but you can provide another implementation
* to use an alternative format.
*/
export abstract class NgbDateParserFormatterNOA11Y {
/**
* Parses the given value to an NgbDateStruct. Implementations should try their best to provide a result, even
* partial. They must return null if the value can't be parsed.
* @param value the value to parse
*/
abstract parse(value: string, pattern?: NbpCalendarPattern): NgbDateStruct;
/**
* Formats the given date to a string. Implementations should return an empty string if the given date is null,
* and try their best to provide a partial result if the given date is incomplete or invalid.
* @param date the date to format as a string
*/
abstract format(date: NgbDateStruct, pattern?: NbpCalendarPattern, separator?: NbpDateSeparator): string;
}
export class NgbDateISOParserFormatterNOA11Y extends NgbDateParserFormatterNOA11Y {
parse(value: string): NgbDateStruct {
if (value) {
const dateParts = value.trim().split('-');
if (dateParts.length === 1 && isNumber(dateParts[0])) {
return {year: toInteger(dateParts[0]), month: null, day: null};
} else if (dateParts.length === 2 && isNumber(dateParts[0]) && isNumber(dateParts[1])) {
return {year: toInteger(dateParts[0]), month: toInteger(dateParts[1]), day: null};
} else if (dateParts.length === 3 && isNumber(dateParts[0]) && isNumber(dateParts[1]) && isNumber(dateParts[2])) {
return {year: toInteger(dateParts[0]), month: toInteger(dateParts[1]), day: toInteger(dateParts[2])};
}
}
return null;
}
format(date: NgbDateStruct): string {
return date ?
`${date.year}-${isNumber(date.month) ? padNumber(date.month) : ''}-${isNumber(date.day) ? padNumber(date.day) : ''}` :
'';
}
}

View File

@ -0,0 +1,19 @@
/**
* Interface of the model of the NgbDatepicker and NgbInputDatepicker directives
*/
export interface NgbDateStruct {
/**
* The year, for example 2016
*/
year: number;
/**
* The month, with default calendar we use ISO 8601: 1=Jan ... 12=Dec
*/
month: number;
/**
* The day of month, starting at 1
*/
day: number;
}

View File

@ -0,0 +1,46 @@
export class NgbDate {
static from(date: {year: number, month: number, day?: number}) {
return date ? new NgbDate(date.year, date.month, date.day ? date.day : 1) : null;
}
constructor(public year: number, public month: number, public day: number) {}
equals(other: NgbDate) {
return other && this.year === other.year && this.month === other.month && this.day === other.day;
}
before(other: NgbDate) {
if (!other) {
return false;
}
if (this.year === other.year) {
if (this.month === other.month) {
return this.day === other.day ? false : this.day < other.day;
} else {
return this.month < other.month;
}
} else {
return this.year < other.year;
}
}
after(other: NgbDate) {
if (!other) {
return false;
}
if (this.year === other.year) {
if (this.month === other.month) {
return this.day === other.day ? false : this.day > other.day;
} else {
return this.month > other.month;
}
} else {
return this.year > other.year;
}
}
toStruct() { return {year: this.year, month: this.month, day: this.day}; }
toString() { return `${this.year}-${this.month}-${this.day}`; }
}

View File

@ -0,0 +1,14 @@
/**
* Interface of the model of the NgbDatepicker and NgbInputDatepicker directives
*/
export interface NgbMeseStruct {
/**
* Il nome del mese
*/
name: string;
/**
* Il numero del mese
*/
number: number;
}

View File

@ -0,0 +1,14 @@
/**
* Interface of the model of the NgbDatepicker and NgbInputDatepicker directives
*/
export interface NgbYearStruct {
/**
* Il nome del mese
*/
name: string;
/**
* Il numero del mese
*/
number: number;
}

View File

@ -0,0 +1,59 @@
import {
Injector,
TemplateRef,
ViewRef,
ViewContainerRef,
Renderer2,
ComponentRef,
ComponentFactory,
ComponentFactoryResolver
} from '@angular/core';
export class ContentRef {
constructor(public nodes: any[], public viewRef?: ViewRef, public componentRef?: ComponentRef<any>) {}
}
export class PopupService<T> {
private _windowFactory: ComponentFactory<T>;
private _windowRef: ComponentRef<T>;
private _contentRef: ContentRef;
constructor(
type: any, private _injector: Injector, private _viewContainerRef: ViewContainerRef, private _renderer: Renderer2,
componentFactoryResolver: ComponentFactoryResolver) {
this._windowFactory = componentFactoryResolver.resolveComponentFactory<T>(type);
}
open(content?: string | TemplateRef<any>, context?: any): ComponentRef<T> {
if (!this._windowRef) {
this._contentRef = this._getContentRef(content, context);
this._windowRef =
this._viewContainerRef.createComponent(this._windowFactory, 0, this._injector, this._contentRef.nodes);
}
return this._windowRef;
}
close() {
if (this._windowRef) {
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._windowRef.hostView));
this._windowRef = null;
if (this._contentRef.viewRef) {
this._viewContainerRef.remove(this._viewContainerRef.indexOf(this._contentRef.viewRef));
this._contentRef = null;
}
}
}
private _getContentRef(content: string | TemplateRef<any>, context?: any): ContentRef {
if (!content) {
return new ContentRef([]);
} else if (content instanceof TemplateRef) {
const viewRef = this._viewContainerRef.createEmbeddedView(<TemplateRef<T>>content, context);
return new ContentRef([viewRef.rootNodes], viewRef);
} else {
return new ContentRef([[this._renderer.createText(`${content}`)]]);
}
}
}

View File

@ -0,0 +1,192 @@
import {Positioning} from './positioning';
describe('Positioning', () => {
const positioning = new Positioning();
const documentMargin = document.documentElement.style.margin;
const bodyMargin = document.body.style.margin;
const bodyHeight = document.body.style.height;
const bodyWidth = document.body.style.width;
function createElement(height: number, width: number, marginTop: number, marginLeft: number): HTMLElement {
let element = document.createElement('div');
element.style.display = 'inline-block';
element.style.height = height + 'px';
element.style.width = width + 'px';
element.style.marginTop = marginTop + 'px';
element.style.marginLeft = marginLeft + 'px';
return element;
}
let element = createElement(200, 300, 100, 150);
document.body.appendChild(element);
let targetElement = createElement(50, 100, 10, 20);
document.body.appendChild(targetElement);
document.documentElement.style.margin = '0';
document.body.style.margin = '0';
document.body.style.height = '2000px';
document.body.style.width = '2000px';
it('should calculate the element offset', () => {
let position = positioning.offset(element);
expect(position.height).toBe(200);
expect(position.width).toBe(300);
expect(position.top).toBe(100);
expect(position.bottom).toBe(300);
expect(position.left).toBe(150);
expect(position.right).toBe(450);
});
it('should calculate the element offset when scrolled', () => {
document.documentElement.scrollTop = 1000;
document.documentElement.scrollLeft = 1000;
let position = positioning.offset(element);
expect(position.top).toBe(100);
expect(position.bottom).toBe(300);
expect(position.left).toBe(150);
expect(position.right).toBe(450);
document.documentElement.scrollTop = 0;
document.documentElement.scrollLeft = 0;
});
it('should calculate the element position', () => {
let position = positioning.position(element);
expect(position.height).toBe(200);
expect(position.width).toBe(300);
expect(position.top).toBe(100);
expect(position.bottom).toBe(300);
expect(position.left).toBe(150);
expect(position.right).toBe(450);
});
it('should calculate the element position when scrolled', () => {
document.documentElement.scrollTop = 1000;
document.documentElement.scrollLeft = 1000;
let position = positioning.position(element);
expect(position.top).toBe(100);
expect(position.bottom).toBe(300);
expect(position.left).toBe(150);
expect(position.right).toBe(450);
document.documentElement.scrollTop = 0;
document.documentElement.scrollLeft = 0;
});
it('should calculate the element position on positioned ancestor', () => {
let childElement = createElement(100, 150, 50, 75);
element.style.position = 'relative';
element.appendChild(childElement);
let position = positioning.position(childElement);
expect(position.top).toBe(50);
expect(position.bottom).toBe(150);
expect(position.left).toBe(75);
expect(position.right).toBe(225);
element.style.position = '';
element.removeChild(childElement);
});
it('should position the element top-left', () => {
let position = positioning.positionElements(element, targetElement, 'top-left');
expect(position.top).toBe(50);
expect(position.left).toBe(150);
});
it('should position the element top-center', () => {
let position = positioning.positionElements(element, targetElement, 'top');
expect(position.top).toBe(50);
expect(position.left).toBe(250);
});
it('should position the element top-right', () => {
let position = positioning.positionElements(element, targetElement, 'top-right');
expect(position.top).toBe(50);
expect(position.left).toBe(350);
});
it('should position the element bottom-left', () => {
let position = positioning.positionElements(element, targetElement, 'bottom-left');
expect(position.top).toBe(300);
expect(position.left).toBe(150);
});
it('should position the element bottom-center', () => {
let position = positioning.positionElements(element, targetElement, 'bottom');
expect(position.top).toBe(300);
expect(position.left).toBe(250);
});
it('should position the element bottom-right', () => {
let position = positioning.positionElements(element, targetElement, 'bottom-right');
expect(position.top).toBe(300);
expect(position.left).toBe(350);
});
it('should position the element left-top', () => {
let position = positioning.positionElements(element, targetElement, 'left-top');
expect(position.top).toBe(100);
expect(position.left).toBe(50);
});
it('should position the element left-center', () => {
let position = positioning.positionElements(element, targetElement, 'left');
expect(position.top).toBe(175);
expect(position.left).toBe(50);
});
it('should position the element left-bottom', () => {
let position = positioning.positionElements(element, targetElement, 'left-bottom');
expect(position.top).toBe(250);
expect(position.left).toBe(50);
});
it('should position the element right-top', () => {
let position = positioning.positionElements(element, targetElement, 'right-top');
expect(position.top).toBe(100);
expect(position.left).toBe(450);
});
it('should position the element right-center', () => {
let position = positioning.positionElements(element, targetElement, 'right');
expect(position.top).toBe(175);
expect(position.left).toBe(450);
});
it('should position the element right-bottom', () => {
let position = positioning.positionElements(element, targetElement, 'right-bottom');
expect(position.top).toBe(250);
expect(position.left).toBe(450);
});
it('cleanUp', () => {
document.body.removeChild(element);
document.body.removeChild(targetElement);
document.documentElement.style.margin = documentMargin;
document.body.style.margin = bodyMargin;
document.body.style.height = bodyHeight;
document.body.style.width = bodyWidth;
});
});

View File

@ -0,0 +1,88 @@
import {parseTriggers} from './triggers';
describe('triggers', () => {
describe('parseTriggers', () => {
it('should parse single trigger', () => {
const t = parseTriggers('foo');
expect(t.length).toBe(1);
expect(t[0].open).toBe('foo');
expect(t[0].close).toBe('foo');
});
it('should parse open:close form', () => {
const t = parseTriggers('foo:bar');
expect(t.length).toBe(1);
expect(t[0].open).toBe('foo');
expect(t[0].close).toBe('bar');
});
it('should parse multiple triggers', () => {
const t = parseTriggers('foo:bar bar:baz');
expect(t.length).toBe(2);
expect(t[0].open).toBe('foo');
expect(t[0].close).toBe('bar');
expect(t[1].open).toBe('bar');
expect(t[1].close).toBe('baz');
});
it('should parse multiple triggers with mixed forms', () => {
const t = parseTriggers('foo bar:baz');
expect(t.length).toBe(2);
expect(t[0].open).toBe('foo');
expect(t[0].close).toBe('foo');
expect(t[1].open).toBe('bar');
expect(t[1].close).toBe('baz');
});
it('should properly trim excessive white-spaces', () => {
const t = parseTriggers('foo bar \n baz ');
expect(t.length).toBe(3);
expect(t[0].open).toBe('foo');
expect(t[0].close).toBe('foo');
expect(t[1].open).toBe('bar');
expect(t[1].close).toBe('bar');
expect(t[2].open).toBe('baz');
expect(t[2].close).toBe('baz');
});
it('should lookup and translate special aliases', () => {
const t = parseTriggers('hover');
expect(t.length).toBe(1);
expect(t[0].open).toBe('mouseenter');
expect(t[0].close).toBe('mouseleave');
});
it('should detect manual triggers', () => {
const t = parseTriggers('manual');
expect(t[0].isManual).toBeTruthy();
});
it('should ignore empty inputs', () => {
expect(parseTriggers(null).length).toBe(0);
expect(parseTriggers(undefined).length).toBe(0);
expect(parseTriggers('').length).toBe(0);
});
it('should throw when more than one manual trigger detected', () => {
expect(() => {
parseTriggers('manual click manual');
}).toThrow('Triggers parse error: only one manual trigger is allowed');
});
it('should throw when manual trigger is mixed with other triggers', () => {
expect(() => {
parseTriggers('click manual');
}).toThrow(`Triggers parse error: manual trigger can\'t be mixed with other triggers`);
});
});
});

View File

@ -0,0 +1,60 @@
export class Trigger {
constructor(public open: string, public close?: string) {
if (!close) {
this.close = open;
}
}
isManual() { return this.open === 'manual' || this.close === 'manual'; }
}
const DEFAULT_ALIASES = {
'hover': ['mouseenter', 'mouseleave']
};
export function parseTriggers(triggers: string, aliases = DEFAULT_ALIASES): Trigger[] {
const trimmedTriggers = (triggers || '').trim();
if (trimmedTriggers.length === 0) {
return [];
}
const parsedTriggers = trimmedTriggers.split(/\s+/).map(trigger => trigger.split(':')).map((triggerPair) => {
let alias = aliases[triggerPair[0]] || triggerPair;
return new Trigger(alias[0], alias[1]);
});
const manualTriggers = parsedTriggers.filter(triggerPair => triggerPair.isManual());
if (manualTriggers.length > 1) {
throw 'Triggers parse error: only one manual trigger is allowed';
}
if (manualTriggers.length === 1 && parsedTriggers.length > 1) {
throw 'Triggers parse error: manual trigger can\'t be mixed with other triggers';
}
return parsedTriggers;
}
const noopFn = () => {};
export function listenToTriggers(renderer: any, nativeElement: any, triggers: string, openFn, closeFn, toggleFn) {
const parsedTriggers = parseTriggers(triggers);
const listeners = [];
if (parsedTriggers.length === 1 && parsedTriggers[0].isManual()) {
return noopFn;
}
parsedTriggers.forEach((trigger: Trigger) => {
if (trigger.open === trigger.close) {
listeners.push(renderer.listen(nativeElement, trigger.open, toggleFn));
} else {
listeners.push(
renderer.listen(nativeElement, trigger.open, openFn), renderer.listen(nativeElement, trigger.close, closeFn));
}
});
return () => { listeners.forEach(unsubscribeFn => unsubscribeFn()); };
}

View File

@ -0,0 +1,93 @@
import {toInteger, toString, getValueInRange, isInteger, isString} from './util';
describe('util', () => {
describe('toInteger', () => {
it('should be noop for integers', () => {
expect(toInteger(0)).toBe(0);
expect(toInteger(10)).toBe(10);
});
it('should act as Math.floor for numbers', () => {
expect(toInteger(0.1)).toBe(0);
expect(toInteger(0.9)).toBe(0);
});
it('should parse strings', () => {
expect(toInteger('0')).toBe(0);
expect(toInteger('10')).toBe(10);
expect(toInteger('10.1')).toBe(10);
expect(toInteger('10.9')).toBe(10);
});
});
describe('toString', () => {
it('should be noop for strings', () => { expect(toString('foo')).toBe('foo'); });
it('should return empty string for undefined values', () => {
expect(toString(null)).toBe('');
expect(toString(undefined)).toBe('');
});
it('should stringify non-string values', () => {
expect(toString(10)).toBe('10');
expect(toString(false)).toBe('false');
});
});
describe('getValueInRange', () => {
it('should be noop for numbers in range', () => { expect(getValueInRange(5, 10, 0)).toBe(5); });
it('should do corrections in range', () => {
expect(getValueInRange(11, 10, 0)).toBe(10);
expect(getValueInRange(-1, 10, 0)).toBe(0);
});
it('should take 0 as a default min bound', () => {
expect(getValueInRange(11, 10)).toBe(10);
expect(getValueInRange(-1, 10)).toBe(0);
});
});
describe('isInteger', () => {
it('should recognize integers', () => {
expect(isInteger(0)).toBeTruthy();
expect(isInteger(10)).toBeTruthy();
expect(isInteger(-110)).toBeTruthy();
});
it('should recognize non-integers', () => {
expect(isInteger(null)).toBeFalsy();
expect(isString([])).toBeFalsy();
expect(isString(undefined)).toBeFalsy();
expect(isInteger('2048')).toBeFalsy();
expect(isInteger(14.1)).toBeFalsy();
expect(isInteger(-14.1)).toBeFalsy();
});
});
describe('isString', () => {
it('should recognize strings', () => {
expect(isString('string')).toBeTruthy();
expect(isString('')).toBeTruthy();
});
it('should recognize non-strings', () => {
expect(isString(null)).toBeFalsy();
expect(isString(2048)).toBeFalsy();
expect(isString([])).toBeFalsy();
expect(isString(undefined)).toBeFalsy();
});
});
});

View File

@ -1,39 +1,39 @@
export function toInteger(value: any): number { export function toInteger(value: any): number {
return parseInt(`${value}`, 10); return parseInt(`${value}`, 10);
} }
export function toString(value: any): string { export function toString(value: any): string {
return (value !== undefined && value !== null) ? `${value}` : ''; return (value !== undefined && value !== null) ? `${value}` : '';
} }
export function getValueInRange(value: number, max: number, min = 0): number { export function getValueInRange(value: number, max: number, min = 0): number {
return Math.max(Math.min(value, max), min); return Math.max(Math.min(value, max), min);
} }
export function isString(value: any): value is string { export function isString(value: any): value is string {
return typeof value === 'string'; return typeof value === 'string';
} }
export function isNumber(value: any): value is number { export function isNumber(value: any): value is number {
return !isNaN(toInteger(value)); return !isNaN(toInteger(value));
} }
export function isInteger(value: any): value is number { export function isInteger(value: any): value is number {
return typeof value === 'number' && isFinite(value) && Math.floor(value) === value; return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
} }
export function isDefined(value: any): boolean { export function isDefined(value: any): boolean {
return value !== undefined && value !== null; return value !== undefined && value !== null;
} }
export function padNumber(value: number) { export function padNumber(value: number) {
if (isNumber(value)) { if (isNumber(value)) {
return `0${value}`.slice(-2); return `0${value}`.slice(-2);
} else { } else {
return ''; return '';
} }
} }
export function regExpEscape(text) { export function regExpEscape(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&'); return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
} }

View File

@ -1,25 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NgbDatepickerDayView } from '@isp/xdce-widget';
@Component({
selector: '[ngbFidDatepickerDayView]',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'class': 'btn-secondary',
'[class.bg-primary]': 'selected',
'[class.text-white]': 'selected',
'[class.text-muted]': 'isMuted()',
'[class.outside]': 'isOutside()',
'[class.notOutside]': '!isOutside()',
'[class.active]': 'focused',
'[class.is-today]': 'isToday',
'[class.is-holiday]': 'isHoliday',
'[class.is-weekend]': 'isWeekend && !selected',
'[class.is-daypast]': 'isDayPast',
'[class.is-fiscal]': 'isFiscalDay'
},
template: '<ng-container></ng-container>',
})
export class NgbFidDatepickerDayView extends NgbDatepickerDayView {
}

View File

@ -1,667 +0,0 @@
import {
ComponentFactoryResolver,
ComponentRef,
Directive,
ElementRef,
EventEmitter,
Input,
NgZone,
OnChanges,
OnDestroy,
Output,
Renderer2,
SimpleChanges,
TemplateRef,
ViewContainerRef,
forwardRef,
} from "@angular/core";
import {
AbstractControl,
ControlValueAccessor,
NG_VALIDATORS,
NG_VALUE_ACCESSOR,
Validator,
} from "@angular/forms";
import { EventManager } from "@isp/xdce-arch-core-base";
import {
DayTemplateContext,
NbpCalendarPattern,
NbpCalendarPosition,
NbpDateSeparator,
NgbCalendar,
NgbDate,
NgbDateParserFormatter,
NgbDateStruct,
NgbDatepickerNavigateEvent,
NgbDatepickerService,
} from "@isp/xdce-widget";
import { Positioning } from "../util/positioning";
import { FidRplCalendar } from "./datepicker";
const NGB_DATEPICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NgbFidInputDatepicker),
multi: true,
};
const NGB_DATEPICKER_VALIDATOR = {
provide: NG_VALIDATORS,
useExisting: forwardRef(() => NgbFidInputDatepicker),
multi: true,
};
/**
* A directive that makes it possible to have datepickers on input fields.
* Manages integration with the input field itself (data entry) and ngModel (validation etc.).
*/
@Directive({
selector: 'input[fidRplCalendar]',
exportAs: "fidRplCalendar",
host: {
"(input)": "waitForFormat($event.target.value)",
"(change)": "manualDateChange($event.target.value, true)",
"(keyup.esc)": "close()",
"(blur)": "onBlur()",
"(document:click)": "onFocusOut($event)",
},
providers: [
NGB_DATEPICKER_VALUE_ACCESSOR,
NGB_DATEPICKER_VALIDATOR,
NgbDatepickerService,
],
})
export class NgbFidInputDatepicker
implements OnChanges, OnDestroy, ControlValueAccessor, Validator
{
private _cRef: ComponentRef<FidRplCalendar> = null;
private _model: NgbDate;
private _zoneSubscription: any;
opened: boolean;
dataBeforeChange;
@Input() onDateSelectedCallback: (value: any) => void | null;
/**
* Reference for the custom template for the day display
*/
@Input() dayTemplate: TemplateRef<DayTemplateContext>;
/**
* Number of months to display
*/
@Input() displayMonths: number;
/**
* First day of the week. With default calendar we use ISO 8601: 1=Mon ... 7=Sun
*/
@Input() firstDayOfWeek: number;
/**
* Callback to mark a given date as disabled.
* 'Current' contains the month that will be displayed in the view
*/
@Input() markDisabled: (
date: NgbDateStruct,
current: { year: number; month: number }
) => boolean;
/**
* Min date for the navigation. If not provided will be 10 years before today or `startDate`
*/
_minDate: NgbDateStruct;
@Input()
get minDate() {
return this._minDate;
}
set minDate(minDate: NgbDateStruct) {
this._minDate = minDate;
}
/**
* Max date for the navigation. If not provided will be 10 years from today or `startDate`
*/
_maxDate: NgbDateStruct;
@Input()
get maxDate() {
return this._maxDate;
}
set maxDate(maxDate: NgbDateStruct) {
this._maxDate = maxDate;
}
/**
* Navigation type: `select` (default with select boxes for month and year), `arrows`
* (without select boxes, only navigation arrows) or `none` (no navigation at all)
*/
@Input() navigation: "select" | "arrows" | "none";
/**
* The way to display days that don't belong to current month: `visible` (default),
* `hidden` (not displayed) or `collapsed` (not displayed with empty space collapsed)
*/
@Input() outsideDays: "visible" | "collapsed" | "hidden";
/**
* Placement of a datepicker popup. Accepts: "top", "bottom", "left", "right", "bottom-left",
* "bottom-right" etc.
*/
@Input() placement = "bottom-left";
/**
* Whether to display days of the week
*/
@Input() showWeekdays: boolean;
/**
* Whether to display week numbers
*/
@Input() showWeekNumbers: boolean;
/**
* Date to open calendar with.
* With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.
* If nothing or invalid date provided, calendar will open with current month.
* Use 'navigateTo(date)' as an alternative
*/
@Input() startDate: { year: number; month: number };
@Input() disabledWeekend: boolean;
@Input() holidays: Array<NgbDateStruct>;
@Input() taxDeadlines: Array<NgbDateStruct>;
/**
* input for unifiedVg
*/
@Input() isUnifiedVg: boolean;
private _pattern: any = NbpCalendarPattern;
@Input() nbpLabelPattern: NbpCalendarPattern = this._pattern.GGMMAAAA;
private _separator = NbpDateSeparator;
@Input() nbpDateSeparator: NbpDateSeparator = this._separator.DOT;
/**
* An event fired when navigation happens and currently displayed month changes.
* See NgbDatepickerNavigateEvent for the payload info.
*/
@Output() navigate = new EventEmitter<NgbDatepickerNavigateEvent>();
private _onChange = (_: any) => {};
private _onTouched = () => {};
private _validatorChange = () => {};
private _placement: any = NbpCalendarPosition;
private positionService: Positioning;
private get isInModal(): boolean {
let el: HTMLElement = <HTMLElement>this._elRef.nativeElement;
if (!el || !el.parentElement || !el.parentElement.tagName) {
return false;
}
let tagName: string = el.parentElement.tagName;
while (!tagName.match(/modal/i) && !tagName.match(/body/i)) {
el = el.parentElement;
tagName =
el.parentElement && el.parentElement.tagName
? el.parentElement.tagName
: "";
}
return tagName && !!tagName.match(/modal/i);
}
private get isCorporate(): boolean {
return this._cRef.location.nativeElement.classList.contains(
"isp-corporate-mode-wrapper"
);
}
get _isNative(): boolean {
return /(ip(a|o)d|iphone|android)/gi.test(window.navigator.userAgent);
}
constructor(
private _parserFormatter: NgbDateParserFormatter,
private _elRef: ElementRef,
private _vcRef: ViewContainerRef,
private _renderer: Renderer2,
private _cfr: ComponentFactoryResolver,
ngZone: NgZone,
private _service: NgbDatepickerService,
private _calendar: NgbCalendar,
private eventManager: EventManager
) {
this.positionService = new Positioning();
this._zoneSubscription = ngZone.onStable.subscribe(() =>
this.setDatepickerPosition()
);
}
get screenWidth(): number {
return window.innerWidth;
}
setDatepickerPosition() {
if (!this._cRef || !this._elRef) {
return;
}
if (this.screenWidth < this.getCalendarWidth() + 200) {
this.placement = this._placement.BOTTOM_LEFT;
}
const calendar: HTMLElement = this._cRef.location.nativeElement;
const datepickerInput: HTMLElement = this._elRef.nativeElement;
const calendarClone: HTMLElement = <HTMLElement>calendar.cloneNode(true);
this._renderer.removeClass(
calendarClone.querySelector(".isp-main-datepicker"),
"d-none"
);
this._renderer.addClass(calendarClone, "invisible");
window.document.body.appendChild(calendarClone);
const navigation: number = calendarClone.querySelector(
".isp-datepicker-navigation"
)["offsetHeight"];
const routingView: number = calendarClone.querySelector(
".isp-datepicker-routing-view"
)["offsetHeight"];
const position: ClientRect = this.positionService.positionElements(
datepickerInput,
calendarClone,
this.placement
);
this._renderer.removeChild(calendarClone.parentElement, calendarClone);
switch (this.placement) {
case this._placement.TOP:
case this._placement.TOP_RIGHT:
case this._placement.TOP_LEFT:
position.top = this.isCorporate
? -navigation - routingView
: -navigation - routingView - 3;
break;
case this._placement.RIGHT:
case this._placement.LEFT:
position.top = -navigation - routingView / 2;
break;
}
calendar.style.top = `${position.top}px`;
calendar.style.left = `${position.left}px`;
this._renderer.removeClass(
calendar.querySelector(".isp-main-datepicker"),
"d-none"
);
}
registerOnChange(fn: (value: any) => any): void {
this._onChange = fn;
}
registerOnTouched(fn: () => any): void {
this._onTouched = fn;
}
registerOnValidatorChange(fn: () => void): void {
this._validatorChange = fn;
}
setDisabledState(isDisabled: boolean): void {
this._renderer.setProperty(
this._elRef.nativeElement,
"disabled",
isDisabled
);
if (this.isOpen()) {
this._cRef.instance.setDisabledState(isDisabled);
}
}
validate(c: AbstractControl): { [key: string]: any } {
const value = c.value;
if (value === null || value === undefined) {
return null;
}
if (typeof value === "string") {
let newValue: NgbDate;
newValue = new NgbDate(
parseInt(value.substring(0, 4), 10),
parseInt(value.substring(5, 7), 10),
parseInt(value.substring(8, 10), 10)
);
if (!this._calendar.isValid(newValue)) {
return { ngbDate: { invalid: c.value } };
}
if (
this.minDate &&
NgbDate.from(newValue).before(NgbDate.from(this.minDate))
) {
return { ngbDate: { requiredBefore: this.minDate } };
}
if (
this.maxDate &&
NgbDate.from(newValue).after(NgbDate.from(this.maxDate))
) {
return { ngbDate: { requiredAfter: this.maxDate } };
}
} else {
if (!this._calendar.isValid(value)) {
return { ngbDate: { invalid: c.value } };
}
if (
this.minDate &&
NgbDate.from(value).before(NgbDate.from(this.minDate))
) {
return { ngbDate: { requiredBefore: this.minDate } };
}
if (
this.maxDate &&
NgbDate.from(value).after(NgbDate.from(this.maxDate))
) {
return { ngbDate: { requiredAfter: this.maxDate } };
}
}
}
writeValue(value: any) {
const ngbDate = value
? new NgbDate(value.year, value.month, value.day)
: null;
this._model = this._calendar.isValid(value) ? ngbDate : null;
this._writeModelValue(this._model);
}
waitForFormat(value: string, updateView = false) {
this.dataBeforeChange = value;
let actualValue = value;
setTimeout(() => {
if (actualValue === this.dataBeforeChange) {
this.manualDateChange(actualValue, updateView);
}
}, 2000);
}
manualDateChange(value: string, updateView = false) {
let datesplitted = value.split(/[./-]/g);
if (
this.nbpLabelPattern == this._pattern.MMAAAA &&
datesplitted.length < 3 &&
datesplitted.length > 1
) {
value = "01." + value;
}
let [year, month, day] = value.split("-");
if (this.isUnifiedVg && this._isNative) {
if (year && month && day) {
// value = day + '.' + month + '.' + year;
}
}
this._model = this._service.toValidDate(
this._parserFormatter.parse(value, this.nbpLabelPattern),
null
);
this._onChange(
this._model ? this._model.toStruct() : value === "" ? null : value
);
if (updateView && this._model) {
this._writeModelValue(this._model);
}
}
isOpen() {
return !!this._cRef;
}
/**
* Opens the datepicker with the selected date indicated by the ngModel value.
*/
open(mode: boolean, fromkeyboard: boolean) {
if (!this.isOpen()) {
if (this._model && (this.minDate || this.maxDate)) {
if (
(this.minDate &&
NgbDate.from(this._model).before(NgbDate.from(this.minDate))) ||
(this.maxDate &&
NgbDate.from(this._model).after(NgbDate.from(this.maxDate)))
) {
this._model = null;
}
}
const cf = this._cfr.resolveComponentFactory(FidRplCalendar);
this._cRef = this._vcRef.createComponent(cf);
this._applyPopupStyling(this._cRef.location.nativeElement);
this._cRef.instance.writeValue(this._model);
this._applyDatepickerInputs(this._cRef.instance);
this._subscribeForDatepickerOutputs(this._cRef.instance);
this._cRef.instance.disabledWeekend = this.disabledWeekend;
this._cRef.instance.holidays = this.holidays;
this._cRef.instance.taxDeadlines = this.taxDeadlines;
this._cRef.instance.fromkeyboard = fromkeyboard;
if (mode) {
this._renderer.addClass(
this._cRef.location.nativeElement,
"isp-corporate-mode-wrapper"
);
}
this._cRef.instance.ngOnInit();
// date selection event handling
this._cRef.instance.forceClose.subscribe(() => {
if (this.opened) return;
this.close();
if (this.onDateSelectedCallback)
this.onDateSelectedCallback(this.dataBeforeChange);
});
this._cRef.instance.registerOnChange((selectedDate) => {
this.writeValue(selectedDate);
this._onChange(selectedDate);
if (!this.opened) {
this.close();
}
if (this.onDateSelectedCallback)
this.onDateSelectedCallback(selectedDate);
});
// focus handling
this._cRef.instance.focus();
// Escape Key handling - d100f
// const handleKeyUp = (event) => {
// if (event.key === "Escape") {
// this.close();
// document.removeEventListener("keyup", handleKeyUp);
// }
// };
// document.addEventListener("keyup", handleKeyUp);
}
}
/**
* Closes the datepicker popup.
*/
close() {
if (this.isOpen()) {
this._vcRef.remove(this._vcRef.indexOf(this._cRef.hostView));
this._cRef = null;
this.eventManager.emit("DATEPICKER_CLOSE", true);
}
}
/**
* Toggles the datepicker popup (opens when closed and closes when opened).
*/
toggle(mode: boolean, fromkeyboard?: boolean) {
if (this.isOpen()) {
this.close();
} else {
this.open(mode, fromkeyboard);
}
}
addMargin(value: string) {
if (this._cRef) {
this._renderer.setStyle(
this._cRef.location.nativeElement,
"margin-top",
value
);
}
}
onFocusOut($event) {
const parent: HTMLElement = this._elRef.nativeElement.parentElement;
const icon: HTMLElement = parent.querySelector("i");
if (
this.isOpen() &&
!(
event.target === icon ||
this._elRef.nativeElement.contains($event.target) ||
this._cRef.location.nativeElement.contains($event.target)
)
) {
this._cRef.instance.focusOutComponent($event);
console.info("onfocusout close");
this.close();
if (this.eventManager) {
this.eventManager.emit("HANDLER_CALENDAR", {});
}
}
}
/**
* Navigates current view to provided date.
* With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.
* If nothing or invalid date provided calendar will open current month.
* Use 'startDate' input as an alternative
*/
navigateTo(date?: { year: number; month: number }) {
if (this.isOpen()) {
this._cRef.instance.navigateTo(date);
}
}
onBlur() {
this._onTouched();
}
ngOnChanges(changes: SimpleChanges) {
if (changes["minDate"] || changes["maxDate"]) {
this._validatorChange();
}
}
ngOnDestroy() {
this.close();
this._zoneSubscription.unsubscribe();
}
getCalendarHeight() {
if (this._cRef && this._cRef.instance.datepickerRoutingView) {
return this._cRef.instance.datepickerRoutingView.getRoutingViewHeight();
}
return 0;
}
getCalendarWidth() {
if (this._cRef && this._cRef.instance.datepickerRoutingView) {
return this._cRef.instance.datepickerRoutingView.getRoutingViewWidth();
}
return 0;
}
getInputHeight() {
if (this._elRef) {
return this._elRef.nativeElement.offsetHeight;
}
return 0;
}
private _applyDatepickerInputs(datepickerInstance: FidRplCalendar): void {
[
"dayTemplate",
"displayMonths",
"firstDayOfWeek",
"markDisabled",
"minDate",
"maxDate",
"navigation",
"outsideDays",
"showNavigation",
"showWeekdays",
"showWeekNumbers",
].forEach((optionName: string) => {
if ((this as any)[optionName] !== undefined) {
(datepickerInstance as any)[optionName] = (this as any)[optionName];
}
});
datepickerInstance.startDate = this.startDate || this._model;
}
private _applyPopupStyling(nativeElement: any) {
this._renderer.addClass(nativeElement, "dropdown-menu");
this._renderer.setStyle(nativeElement, "padding", "0");
}
private _subscribeForDatepickerOutputs(datepickerInstance: FidRplCalendar) {
datepickerInstance.navigate.subscribe((date: any) =>
this.navigate.emit(date)
);
}
private _writeModelValue(model: NgbDate) {
if (model) {
const { day, month, year } = model;
if (this.nbpLabelPattern == this._pattern.MMAAAA) {
this._renderer.setProperty(
this._elRef.nativeElement,
"value",
this._parserFormatter.format(
{ year, month, day: 0 },
this.nbpLabelPattern,
this.nbpDateSeparator
)
);
} else {
this._renderer.setProperty(
this._elRef.nativeElement,
"value",
this._parserFormatter.format(
{ year, month, day },
this.nbpLabelPattern,
this.nbpDateSeparator
)
);
}
} else {
this._renderer.setProperty(
this._elRef.nativeElement,
"value",
this._parserFormatter.format(
model,
this.nbpLabelPattern,
this.nbpDateSeparator
)
);
}
if (this.isOpen()) {
this._cRef.instance.writeValue(model);
this._onTouched();
}
}
}

View File

@ -1,13 +0,0 @@
import { ChangeDetectionStrategy, Component } from "@angular/core";
import { NgbDatepickerNavigation } from "@isp/xdce-widget";
@Component({
selector: 'ngb-fid-datepicker-navigation',
changeDetection: ChangeDetectionStrategy.OnPush,
host: { 'class': 'd-flex justify-content-between', '[class.collapsed]': '!showSelect' },
template: '<ng-container></ng-container>',
})
export class NgbFidDatepickerNavigation extends NgbDatepickerNavigation {
}

View File

@ -1,22 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NgbDatepickerReplyMonthView } from '@isp/xdce-widget';
@Component({
selector: '[ngbFidDatepickerReplyMonthView]',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'class': 'btn-secondary-month',
'[class.bg-primary]': 'selected',
'[class.text-white]': 'selected',
'[class.text-muted]': 'isMuted()',
'[class.outside]': 'isMuted()',
'[class.focused]': 'mounthFocusVisible',
'[class.active]': 'focused',
'[class.is-current]': 'isCurrent',
'[attr.tabindex]':"focused && mounthFocusVisible ? 0 : -1"
},
template: '<ng-container></ng-container>'
})
export class NgbFidDatepickerReplyMonthView extends NgbDatepickerReplyMonthView {
}

View File

@ -1,22 +0,0 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { NgbDatepickerReplyYearsView } from '@isp/xdce-widget';
@Component({
selector: '[ngbFidDatepickerReplyYearsView]',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
'class': 'btn-secondary-years',
'[class.bg-primary]': 'selected',
'[class.text-white]': 'selected',
'[class.text-muted]': 'isMuted()',
'[class.outside]': 'isMuted()',
'[class.active]': 'focused',
'[class.focused]': 'yearFocusVisible',
'[class.is-current]':'isCurrent',
'[attr.tabindex]':"focused && yearFocusVisible ? 0 : -1"
},
template: '<ng-container></ng-container>',
})
export class NgbFidDatepickerReplyYearsView extends NgbDatepickerReplyYearsView {
}

View File

@ -1,118 +0,0 @@
<div class="isp-datepicker-routing-view" #ispDatepickerRoutingView (keydown.tab)="onKeyDownTab()">
<div [ngSwitch]="currentTemplate">
<!-- giorni -->
<div *ngSwitchCase=0>
<!-- mesi nell'header. -->
<div *ngIf="showWeekdays" class="ngb-dp-week d-flex" role="row" [attr.aria-hidden]="true">
<div *ngIf="showWeekNumbers" class="ngb-dp-weekday"></div>
<div *ngFor="let w of month.weekdays" class="ngb-dp-weekday small text-center text-info font-italic" [attr.aria-hidden]="true">
<span [attr.role]="'columnheader'" [attr.aria-labelledby]="''">
{{ i18n.getWeekdayShortName(w) | translate | uppercase | slice: 0:3 }}
</span>
</div>
</div>
<ng-template ngFor let-week [ngForOf]="month.weeks">
<div *ngIf="!isCollapsed(week) && !isHiddenWeek(week)" class="ngb-dp-week d-flex" role="row">
<div *ngIf="showWeekNumbers" class="ngb-dp-week-number small text-center font-italic text-muted">
<span [attr.role]="'columnheader'" [attr.aria-label]="''">{{ week.number }}</span>
</div>
<div *ngFor="let day of week.days" (click)="doSelect(day, $event)" class="ngb-dp-day"
[class.disabled]="day.context.disabled"
[class.hidden]="isHidden(day)"
[class.tab-focused]="day.context.focused && tabFocusVisible"
[attr.aria-label]="''">
<ng-template [ngIf]="!isHidden(day)">
<div ngbFidDatepickerDayView
[ngClass] = "{'cursor-pointer' : !disabledWeekend && !day.context.disabled}"
[date]="day.context.date"
[currentMonth]="day.context.currentMonth"
[selected]="day.context.selected"
[disabled]="day.context.disabled"
[focused]="day.context.focused"
[startDateEnabled]="startDateEnabled"
[endDateEnabled]="endDateEnabled"
[isToday]="day.context.isToday"
[isWeekend]="day.context.isWeekend"
[isHoliday]="day.context.isHoliday"
[taxDeadlines]="taxDeadlines"
[isFiscalDay]="day.context.isFiscalDay"
[attr.role]="'cell'"
[attr.aria-selected]="day.context.selected"
[attr.tabindex]="isActiveCell(day)"
[labelText]="i18n.getAriaLabelDaysTabularForm(day)"
[attr.aria-label]="i18n.getAriaLabelDays(day)"
[attr.aria-labelledby]="''"
[attr.aria-describedby]="''">
</div>
</ng-template>
</div>
</div>
</ng-template>
</div>
<!-- mesi -->
<div *ngSwitchCase=1>
<div *ngFor="let line of mesi" class="d-flex ngb-dp-mese" role="row">
<ng-container *ngFor="let mese of line">
<div ngbFidDatepickerReplyMonthView
[mese]="mese"
[year]="dataTemplate.year"
[selected]="mese.selected"
[disabled]="mese.disabled"
[focused]="mese.focused"
[mounthFocusVisible]="tabFocusVisible"
[startDateEnabled]="startDateEnabled"
[endDateEnabled]="endDateEnabled"
[attr.role]="'cell'"
type='button'
[labelText]="i18n.getAriaLabelMonthTabularForm(mese.name, dataTemplate.year)"
[attr.aria-label]="i18n.getAriaLabelMonth(mese.name, dataTemplate.year)"
[attr.aria-selected]="mese.selected"
[attr.aria-labelledby]="''"
[attr.aria-describedby]="''"
(click)="doSelectMonth(mese, $event)">
</div>
</ng-container>
</div>
</div>
<!-- anni -->
<div *ngSwitchCase=2>
<div *ngFor="let line of years" class="d-flex ngb-dp-mese" role="row">
<ng-container *ngFor="let year of line">
<div ngbFidDatepickerReplyYearsView [year]="year" [selected]="year.selected" [disabled]="year.disabled"
[focused]="year.focused"
[startDateEnabled]="startDateEnabled"
[endDateEnabled]="endDateEnabled"
[attr.aria-selected]="year.selected"
[attr.role]="'cell'"
type='button'
[attr.aria-label]="i18n.getAriaLabelYear(year.name)"
[attr.aria-labelledby]="''"
[attr.aria-describedby]="''"
[labelText]="i18n.getAriaLabelYearTabularForm(year.name)"
[yearFocusVisible]="tabFocusVisible"
(click)="doSelectYear(year, $event)">
</div>
</ng-container>
</div>
</div>
<!-- default -->
<div *ngSwitchDefault>errore template</div>
</div>
<div>
<button>Oggi</button><button>Cancella</button><button>Chiudi</button>
</div>
</div>

View File

@ -1,158 +0,0 @@
.isp-datepicker-routing-view {
pointer-events: none;
pointer-events: auto;
.d-flex {
display: -webkit-box !important;
display: -ms-flexbox !important;
display: flex !important;
border-bottom-width: 1px;
border-bottom-style: solid;
border-right-width: 1px;
border-right-style: solid;
border-left-width: 1px;
border-left-style: solid;
&:first-child:not(.ngb-dp-mese) {
border-top-width: 1px;
border-top-style: solid;
}
&.ngb-dp-week, &.ngb-dp-mese {
.ngb-dp-day {
width: 2.6875rem;
height: 2.5625rem !important;
cursor: pointer;
position: relative;
box-sizing: border-box;
&.disabled, &.hidden {
cursor: default;
}
&:not(:first-child) {
border-left-width: 1px;
border-left-style: solid;
}
.cursor-pointer {
cursor : pointer !important
}
&[tabindex='0'] {
//pointer-events: none;
&:focus-visible {
box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 4px #FFF599, 0 0 0 6px #000000!important;
border-radius: 4px!important;
border-width: 0px!important;
z-index: 1;
position: relative;
}
}
}
.bg-primary {
&::before {
position: absolute;
top: 0;
right: -0.5rem;
content: '';
display: inline-block;
width: 0;
height: 0;
margin: 0;
padding: 0;
}
}
.btn-secondary {
&:focus {
box-shadow: none;
}
height: inherit;
//font-size: .625rem !important;
}
.btn-secondary, .btn-secondary-month, .btn-secondary-years {
font-weight: 400;
font-size: 0.75rem;
&:focus-visible {
box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 4px #FFF599, 0 0 0 6px #000000!important;
border-radius: 4px!important;
border-width: 0px!important;
z-index: 1;
position: relative;
}
}
div[ngbdatepickerreplymonthview], div[ngbdatepickerreplyyearsview]{
&.btn-secondary-month, &.btn-secondary-years {
border-radius: 0 !important;
box-sizing: border-box;
text-align: center;
min-width: 4.95rem !important;
height: 2.8125rem !important;
line-height: 2.8125rem !important;
vertical-align: middle !important;
border-right-width: 1px;
border-right-style: solid;
border-top-width: 1px;
border-top-style: solid;
border-collapse: collapse;
border-spacing: 0;
&:focus-visible {
box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 4px #FFF599, 0 0 0 6px #000000!important;
border-radius: 4px!important;
border-width: 0px!important;
z-index: 1;
position: relative;
}
// &.active {
// &.focused {
// box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 4px #FFF599, 0 0 0 6px #000000!important;
// border-radius: 4px!important;
// border-width: 0px!important;
// z-index: 1;
// position: relative;
// }
// }
&:last-child {
border-right-style: none;
border-right-width: 0;
}
.ngbdatepickerreplymonthviewdisabled, .ngbDatepickerReplyYearsViewdisabled {
cursor: not-allowed;
opacity: 0.5;
}
.d-flex:first-child & {
border-top-width: 0;
border-top-style: none;
}
}
}
.is-weekend, .is-daypast {
cursor: default;
}
.ngb-dp-weekday, .ngb-dp-week-number {
width: 14.28% !important;
height: 2.375rem !important;
line-height: 2.4375rem;
&.small, & small {
font-size: 80%;
font-weight: 400;
}
&.text-center {
text-align: center !important;
}
&.font-italic {
font-family: 'Arial Bold', 'Arial';
font-weight: 700;
font-style: normal !important;
font-size: .875rem;
text-align: center;
text-transform: uppercase;
}
}
}
}
}
// .tab-focused {
// .active {
// box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 4px #FFF599, 0 0 0 6px #000000!important;
// border-radius: 4px!important;
// border-width: 0px!important;
// z-index: 1;
// position: relative;
// }
// }

View File

@ -1,443 +0,0 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
HostListener,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
TemplateRef,
ViewChild,
} from "@angular/core";
import {
DayTemplateContext,
DayViewModel,
MonthViewModel,
NgbDataTemplateStruct,
NgbDate,
NgbDatepickerI18n,
NgbDatepickerService,
WeekViewModel
} from "@isp/xdce-widget";
import { Subscription } from "rxjs";
@Component({
selector: 'ngb-fid-datepicker-routing-view',
host: { class: "d-block" },
templateUrl: './datepicker-routing-view.html',
styleUrls: ["./datepicker-routing-view.scss"],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class NgbFidDatepickerRoutingView implements OnInit, OnChanges, OnDestroy {
@Input() dayTemplate: TemplateRef<DayTemplateContext>;
@Input() monthTemplate: TemplateRef<DayTemplateContext>;
@Input() yearsTemplate: TemplateRef<DayTemplateContext>;
@Input() currentTemplate: number;
@Input() mesi: any;
@Input() years: any;
@Input() disabledWeekend: boolean;
@Input() date: any;
@Input() dataTemplate: NgbDataTemplateStruct;
@Input() month: MonthViewModel;
@Input() outsideDays: "visible" | "hidden" | "collapsed";
@Input() showWeekdays;
@Input() showWeekNumbers;
@Input() startDateEnabled: any;
@Input() endDateEnabled: any;
@Input() isToday: boolean;
@Input() isWeekend: boolean;
@Input() taxDeadlines: any;
@Output() select = new EventEmitter<NgbDate>();
@Output() forceClose = new EventEmitter();
@Output() changeTemplate = new EventEmitter<NgbDataTemplateStruct>();
@Output() updateYears = new EventEmitter<number>();
@ViewChild("ispDatepickerRoutingView") routingView: ElementRef;
currentYear: number;
currentMonth: number;
currentDay: number;
sub: Subscription;
tabFocusVisible: boolean;
shiftTabFromDayActive: boolean = false;
constructor(
public i18n: NgbDatepickerI18n,
private cdr: ChangeDetectorRef,
private service: NgbDatepickerService,
private _elementRef: ElementRef
) {}
ngOnInit() {
// alert("in select in routing : " + this.startDateEnabled)
// alert("in select in routing : " + this.endDateEnabled)
// this.currentYear = this.date && this.date.year;
// this.currentMonth = this.date && this.date.month;
console.info("routing init", this.currentYear, this.currentMonth);
this.service.isDayFocusView.subscribe((isDayFocusView) => {
this.tabFocusVisible = isDayFocusView;
});
this.dataTemplate.day = this.date && this.date.day;
this.dataTemplate.month = this.date && this.date.month;
this.dataTemplate.year = this.date && this.date.year;
const model = this.service._model$.getValue();
if (model && model.selectedDate) {
this.currentDay = model.selectedDate.day;
this.currentMonth = model.selectedDate.month;
this.currentYear = model.selectedDate.year;
this.selectedDay = model.selectedDate.day;
}
this.sub = this.service.model$.subscribe((modelDate) => {
if (modelDate.focusVisible) {
if (modelDate && modelDate.focusDate) {
this.currentDay = modelDate.focusDate.day;
this.currentMonth = modelDate.focusDate.month;
this.currentYear = modelDate.focusDate.year;
if (model && model.selectedDate)
this.selectedDay = model.selectedDate.day;
}
this.cdr.detectChanges();
}
this.setFocusDate();
});
this.service["subscribeIsDayFocusView"]().subscribe((tabFocusVisible) => {
this.tabFocusVisible = tabFocusVisible;
if (tabFocusVisible) {
this.shiftTabFromDayActive = false;
this.service.focusVisible = tabFocusVisible;
this.setFocusDate();
}
this.cdr.detectChanges();
});
}
private setFocusDate() {
let domElement = this._elementRef.nativeElement;
if (this.currentTemplate == 0 && this.tabFocusVisible) {
setTimeout(() => {
const elementToFocus = domElement.querySelector(
"div.ngb-dp-day > .active"
);
if (!!elementToFocus) elementToFocus.focus();
this.cdr.detectChanges();
}, 0);
}
if (this.currentTemplate == 1 && this.tabFocusVisible) {
setTimeout(() => {
const elementToFocus = domElement.querySelector(
"div.btn-secondary-month.active"
);
if (!!elementToFocus) elementToFocus.focus();
this.cdr.detectChanges();
}, 50);
}
if (this.currentTemplate == 2 && this.tabFocusVisible) {
setTimeout(() => {
const elementToFocus = domElement.querySelector(
"div.btn-secondary-years.active"
);
if (!!elementToFocus) elementToFocus.focus();
this.cdr.detectChanges();
}, 50);
}
}
isActiveCell(day) {
if (this.tabFocusVisible) {
if (!!day.context.focused && day.context.focused) {
return 0;
} else if (
this.service._model$.getValue().selectedDate &&
day.context.selected
) {
//focus all'apertura
//caso del giorno preselezionato
return 0;
} else if (
!this.service._model$.getValue().selectedDate &&
day.context.date.day == this.getToday().day &&
day.context.date.month == this.getToday().month
) {
//focus all'apertura
//quando non è preselezionato nessun giorno il focus parte dal giorno corrente
return 0;
} else {
return -1;
}
} else {
if (this.shiftTabFromDayActive) {
//focus all'apertura
//caso del giorno preselezionato
if (
this.service._model$.getValue().selectedDate &&
day.context.selected
) {
return 0;
//quando non è preselezionato nessun giorno il focus parte dal giorno corrente
} else if (
!this.service._model$.getValue().selectedDate &&
day.context.date.day == this.getToday().day &&
day.context.date.month == this.getToday().month
) {
return 0;
} else {
return -1;
}
} else {
return -1;
}
}
}
onKeyDownTab() {
//console.info("onKeyDownTab datepicker routing view")
this.service.isTabClickedFromDay.next(true);
this.service.emitIsDayFocusView(false);
}
getToday(): NgbDate {
return new NgbDate(
new Date().getFullYear(),
new Date().getMonth() + 1,
new Date().getDate()
);
}
ngOnDestroy(): void {
if (this.sub) {
this.sub.unsubscribe();
}
}
@HostListener("keydown.shift.tab", ["$event"])
onKeyDown(e) {
this.service.emitIsDayFocusView(false);
this.shiftTabFromDayActive = true;
}
selectedDay: number = -1;
ngOnChanges(changes: SimpleChanges) {
console.info(
"routing ngOnChanges",
this.currentYear,
this.currentMonth,
this.currentDay
);
if (changes.years) {
this.years = [...changes.years.currentValue];
}
if (changes.currentTemplate || changes.dataTemplate) {
//this.service.isDayFocusView.next(false);
this.service.emitTemplate(this.currentTemplate);
this.resetMesi();
this.resetAnni();
const model = this.service._model$.getValue();
if (model && model.focusDate && model.firstDate) {
//model.focusDate.month = model.firstDate.month;
//model.focusDate.year = model.firstDate.year;
//this.service._model$.next(model);
}
if (model && model.selectedDate) {
this.currentDay = model.selectedDate.day;
this.currentMonth = model.selectedDate.month;
this.currentYear = model.selectedDate.year;
}
}
if (changes["date"] && changes["date"].currentValue) {
//l'anno in focus non è compreso nel range della maschera => riscostrisco la maschera
//se il primo anno della maschera è superiore all'anno selezionato
if (this.years[0][0].number > this.date.year) {
this.updateYears.emit(this.years[0][0].number - 12);
//se l'ultimo anno della maschera è minore dell'anno selezionato
} else if (this.date.year > this.years[2][3].number) {
this.updateYears.emit(this.years[2][3].number + 1);
}
}
this.cdr.detectChanges();
}
doSelect(day: DayViewModel, $event: any) {
if (!this.abilitaGiorni(day.date)) {
return;
}
setTimeout(() => this.forceClose.emit(), 0);
if (this.dataTemplate.valid) {
// il day si prende quello selezionato e non quello del dataTemplate
// day.date.day = this.dataTemplate.day;
day.date.month = this.dataTemplate.month;
day.date.year = this.dataTemplate.year;
this.currentYear = day.date.year;
this.currentMonth = day.date.month;
this.currentDay = day.date.day;
this.select.emit(NgbDate.from(day.date));
} else {
if (!day.context.disabled && !this.isHidden(day)) {
this.currentYear = day.date.year;
this.currentMonth = day.date.month;
this.currentDay = day.date.day;
this.select.emit(NgbDate.from(day.date));
}
}
$event.stopPropagation();
}
abilitaGiorni(data) {
let buffer = new Date(data.year, data.month - 1, data.day);
let startDate = new Date(
this.startDateEnabled.year,
this.startDateEnabled.month - 1,
this.startDateEnabled.day
);
let endDate = new Date(
this.endDateEnabled.year,
this.endDateEnabled.month - 1,
this.endDateEnabled.day
);
return startDate <= buffer && buffer <= endDate;
}
abilitaMesi(data) {
return (
((this.startDateEnabled.year == this.dataTemplate.year &&
this.startDateEnabled.month <= data.number) ||
(data.number < this.startDateEnabled.month &&
this.startDateEnabled.year < this.dataTemplate.year) ||
(this.startDateEnabled.month <= data.number &&
this.startDateEnabled.year <= this.dataTemplate.year)) &&
((data.number <= this.endDateEnabled.month &&
this.dataTemplate.year <= this.endDateEnabled.year) ||
(data.number > this.endDateEnabled.month &&
this.dataTemplate.year < this.endDateEnabled.year))
);
}
abilitaAnni(data) {
return (
this.startDateEnabled.year <= data.number &&
data.number <= this.endDateEnabled.year
);
}
doSelectMonth(mese: any, $event: any) {
console.info("doSelectMonth", $event);
if (!this.abilitaMesi(mese)) {
return;
}
this.currentTemplate = 0;
this.dataTemplate.template = this.currentTemplate;
// reset giorni
this.month.weeks.forEach((week) => {
week.days.forEach((day) => {
day.context.selected =
day.date.day === this.currentDay &&
day.date.month === this.currentMonth &&
day.date.year === this.currentYear;
day.context.focused =
day.date.day === this.currentDay &&
day.date.month === this.currentMonth &&
day.date.year === this.currentYear;
});
});
this.resetMesi();
this.dataTemplate.month = mese.number;
this.dataTemplate.valid = true;
this.changeTemplate.emit(this.dataTemplate);
$event.stopPropagation();
}
doSelectYear(year: any, $event: any) {
if (!this.abilitaAnni(year)) {
return;
}
this.currentTemplate = 1;
this.dataTemplate.template = this.currentTemplate;
// resetta mesi e anno
this.resetMesi();
this.dataTemplate.year = year.number;
this.dataTemplate.valid = true;
this.changeTemplate.emit(this.dataTemplate);
$event.stopPropagation();
}
isCollapsed(week: WeekViewModel) {
return (
this.outsideDays === "collapsed" &&
week.days[0].date.month !== this.month.number &&
week.days[week.days.length - 1].date.month !== this.month.number
);
}
isHiddenWeek(week: WeekViewModel) {
let counter = 0;
for (let i = 0; i < week.days.length; i++) {
if (this.isHidden(week.days[i])) {
counter++;
}
}
return counter === 7;
}
isHidden(day: DayViewModel) {
return (
this.outsideDays === "hidden" && this.month.number !== day.date.month
);
}
getRoutingViewHeight() {
return this.routingView.nativeElement.offsetHeight;
}
getRoutingViewWidth() {
return this.routingView.nativeElement.offsetWidth;
}
private resetMesi() {
let months: [][] = [];
months = this.mesi.map((row) => {
return row.map((m) => {
const res = { ...m };
res.selected =
res.number === this.currentMonth &&
this.dataTemplate.year === this.currentYear;
res.focused =
res.number === this.currentMonth &&
this.dataTemplate.year === this.currentYear;
return res;
});
});
this.mesi = months;
}
private resetAnni() {
let yrs: [][] = [];
yrs = this.years.map((row) => {
return row.map((y) => {
const res = { ...y };
res.selected = res.number === this.currentYear;
res.focused = res.number === this.currentYear;
return res;
});
});
this.years = yrs;
}
}

View File

@ -1,81 +0,0 @@
<!-- intestazione -->
<div class="isp-main-datepicker d-none" role="dialog" aria-modal="true">
<div class="ngb-dp-header bg-faded pt-1 rounded-top" [style.height.rem]="getHeaderHeight()"
[style.marginBottom.rem]="-getHeaderMargin()">
<!-- componente per la navigazione! Seleziona il template -->
<ngb-fid-datepicker-navigation *ngIf="navigation !== 'none'"
[date]="model.firstDate"
[minDate]="model.minDate"
[maxDate]="model.maxDate"
[months]="model.months.length"
[years]="years"
[template]="template"
[disabled]="model.disabled"
[showWeekNumbers]="showWeekNumbers"
[showSelect]="navigation === 'select'"
[disabledWeekend]="model.disabledWeekend"
[holidays]="model.holidays"
[taxDeadlines]="model.taxDeadlines"
(navigate)="onNavigateEvent($event)"
(select)="onNavigateDateSelect($event)"
(newTemplate)="setNewTemplate($event);$event.event.stopPropagation();"
[attr.label]="''"
[attr.tabindex]="-1"
[dataTemplate]="dataTemplate"
[attr.labelledby]="''"
[attr.describedby]="''">
</ngb-fid-datepicker-navigation>
</div>
<!-- corpo componente -->
<div class="ngb-dp-months d-flex px-1 pb-1">
<ng-template ngFor let-month [ngForOf]="model.months" let-i="index">
<div class="ngb-dp-month d-block ml-3">
<!-- <div *ngIf="navigation !== 'select' || displayMonths > 1" style="min-width:150px"
class="ngb-dp-month-name text-center" (click)="setNewTemplate((template+1)%3);$event.stopPropagation();" aria-label="" [attr.role]=""> -->
<!-- <div [ngSwitch]="template" style="margin-top:1px" class="header-title">
<div role="heading" aria-level="2" *ngSwitchCase=0 [attr.aria-label]="i18n.getAriaLabel(dataTemplate)" id="id-grid-label" [attr.aria-live]="'polite'">
{{ i18n.getMonthFullName(dataTemplate.month) | translate | uppercase }} {{ dataTemplate.year }}
</div>
<div role="heading" aria-level="2" *ngSwitchCase=1 [attr.aria-label]="dataTemplate.year" id="id-grid-label" [attr.aria-live]="'polite'">
{{ dataTemplate.year }}
</div>
<div role="heading" aria-level="2" *ngSwitchCase=2 [attr.aria-label]="this.years[0][0].number+' - '+this.years[2][3].number" id="id-grid-label" [attr.aria-live]="'polite'">
{{ this.years[0][0].number }} - {{ this.years[2][3].number }}
</div>
</div> -->
<!-- </div> -->
<!-- componente routing che usa il template selezionato-->
<ngb-fid-datepicker-routing-view
[mesi]="mesi"
[years]="years"
[disabledWeekend]="disabledWeekend"
[dataTemplate]="dataTemplate"
[date]="model.firstDate"
[currentTemplate]="template"
[month]="month"
[showWeekdays]="showWeekdays"
[showWeekNumbers]="showWeekNumbers"
[startDateEnabled]="startDateEnabled"
[endDateEnabled]="endDateEnabled"
[outsideDays]="(displayMonths === 1 ? outsideDays : 'hidden')"
[taxDeadlines]="taxDeadlines"
(select)="onDateSelect($event)"
(forceClose)="emitForceClose()"
(updateYears)="updateYears($event)"
(changeTemplate)="onChangeTemplate($event)"
[attr.label]="''"
[attr.aria-label]="''"
[attr.aria-live]="polite"
[attr.role]="'table'"
[attr.labelledby]="'id-grid-label'">
</ngb-fid-datepicker-routing-view>
</div>
</ng-template>
</div>
</div>

View File

@ -1,254 +0,0 @@
:host(.isp-corporate-mode-wrapper) {
&.dropdown-menu {
margin-top: 0;
}
.isp-main-datepicker{
.ngb-dp-header {
height: 2.1875rem!important;
margin-bottom: 0 !important;
& ::ng-deep .isp-datepicker-navigation {
height: 2.1875rem !important;
border-top-left-radius: 2px;
border-top-right-radius: 2px;
span {
button.btn-link {
width: 2.1875rem;
height: 2.1875rem;
font-size: 0.9375rem;
&:disabled {
opacity: 1;
cursor: default;
.ispv2-font-chevron-left {
opacity: 0.35 !important;
}
.ispv2-font-chevron-right {
opacity: 0.35 !important;
}
}
}
}
}
}
.ngb-dp-months {
.ngb-dp-month {
.ngb-dp-month-name {
height: 2.1875rem !important;
margin-top: -2.188rem !important;
top: auto;
line-height: 0.875rem !important;
font-size: 0.75rem !important;
text-decoration: underline;
.header-title {
pointer-events: auto;
padding: 3% 15%;
&:active {
scale: 0.95;
transition: transform 0.15s ease-in-out 0s;
}
}
}
& ::ng-deep .isp-datepicker-routing-view {
.d-flex {
&:last-child{
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-left-radius: 1px;
border-bottom-right-radius: 1px;
}
&.ngb-dp-mese:first-child {
border-top-width: 1px;
border-top-style: solid;
}
&.ngb-dp-week, &.ngb-dp-mese {
.ngb-dp-week-number {
height: inherit !important;
line-height: inherit;
width: 2.125rem !important;
font-size: 0.75rem;
font-weight: 700;
}
.ngb-dp-weekday {
height: inherit !important;
line-height: 1.875rem;
width: 2.25rem !important;
font-size: 0.625rem;
}
.ngb-dp-day {
width: 2.25rem !important;
height: 2.25rem !important;
font-size: 0.75rem;
.bg-primary, .btn-secondary {
font-size: 0.75rem;
.ngbdatepickerdayview, .ngbdatepickerdayviewdisabled {
line-height: 2.125rem !important;
}
.ngbdatepickerdayview:hover{
text-decoration: underline !important;
opacity: 1;
}
.ngbdatepickerdayview:active {
text-decoration: underline !important;
cursor: pointer;
transform: scale(0.9);
transition: transform 0.15s ease 0s;
opacity: 1;
}
}
.ngbdatepickerreplymonthview {
cursor: pointer;
}
.ngbdatepickerdayview {
}
.ngbdatepickerdayviewdisabled, .ngbdatepickerreplymonthviewdisabled {
cursor: not-allowed;
}
.ngbDatepickerReplyYearsView {
cursor: pointer;
// &:active, &:hover {
// text-decoration: underline!important;
// }
}
.ngbDatepickerReplyYearsView[disabled] {
cursor: default;
}
.ngbDatepickerReplyYearsViewdisabled {
cursor: not-allowed;
opacity: 0.35;
}
.ngbdatepickerdayviewdisabled{
cursor: not-allowed !important;
}
&.disabled.text-muted {
.ngbdatepickerdayviewdisabled {
opacity: .35;
}
}
}
.is-daypast{
.ngbdatepickerdayview {
opacity: .5;
}
}
}
div[ngbdatepickerreplymonthview], div[ngbdatepickerreplyyearsview]{
position: relative;
.ngbdatepickerreplymonthview:active, .ngbdatepickerreplymonthview:hover, .ngbDatepickerReplyYearsView:hover, .ngbDatepickerReplyYearsView:active {
text-decoration: underline!important;
}
&.btn-secondary-month, &.btn-secondary-years {
min-width: 0rem !important;
width: 3.75rem !important;
height: 2.125rem !important;
line-height: 2.125rem !important;
border-top: none;
font-size: 0.75rem;
&.is-current {
border-top-width: 1px;
border-top-style: solid;
&:hover, &:active {
.ngbdatepickerreplymonthview {
height: calc(100% - 1px);
}
}
}
.ngbdatepickerdayview, .ngbdatepickerreplymonthview {
cursor: pointer;
}
.ngbdatepickerdayviewdisabled, .ngbdatepickerreplymonthviewdisabled {
cursor: not-allowed;
opacity: 0.35;
}
.ngbDatepickerReplyYearsView {
cursor: pointer;
}
.ngbDatepickerReplyYearsView[disabled] {
cursor: default;
}
.ngbDatepickerReplyYearsViewdisabled {
cursor: not-allowed;
opacity: 0.35;
}
}
}
}
}
}
}
}
}
.isp-main-datepicker {
.justify-content-between {
-webkit-box-pack: justify !important;
-ms-flex-pack: justify !important;
justify-content: space-between !important;
}
.d-flex {
display: -webkit-box !important;
display: -ms-flexbox !important;
display: flex !important;
height: 3.125rem !important;
line-height: 1.875rem !important;
}
.collapsed {
margin-bottom: -32px;
}
.ngb-dp-header {
height: 4.625rem !important;
margin-bottom: -24px !important;
border-bottom: none !important;
&.pt-1 {
padding-top: 0 !important;
height: 4.25rem;
margin-bottom: -32px;
}
&.rounded-top {
border-radius: 0 !important;
}
}
.ngb-dp-months {
&.pb-1 {
padding: 0 !important;
}
&.px-1 {
padding-left: 0 !important;
padding-right: 0 !important;
}
.ngb-dp-month {
pointer-events: none;
&:first-child {
margin-left: 0 !important;
}
&.ml-3 {
margin-left: 16px;
}
&.d-block {
display: block !important;
}
.ngb-dp-month-name {
font-family: 'Arial', sans-serif;
font-size: 1rem !important;
font-weight: 700;
text-transform: uppercase;
position: absolute;
text-align: center !important;
top: 0;
height: 3.125rem !important;
line-height: 1.42857143rem !important;
word-wrap: break-word;
word-break: break-word;
left: 0;
right: 0;
margin-left: auto;
margin-right: auto;
display:flex;
justify-content: center;
align-items: center;
cursor: pointer;
}
}
}
}

View File

@ -1,832 +0,0 @@
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
EventEmitter,
forwardRef,
Input,
OnChanges,
OnDestroy,
OnInit,
Output,
SimpleChanges,
TemplateRef,
ViewChild,
} from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
import {
CalendarItem,
DatepickerViewModel,
DayTemplateContext,
EnabledRangeService,
isChangedDate,
NavigationEvent,
NgbCalendar,
NgbDataTemplateStruct,
NgbDate,
NgbDatepickerConfig,
NgbDatepickerI18n,
NgbDatepickerKeyMapService,
NgbDatepickerNavigateEvent,
NgbDatepickerService,
NgbDateStruct
} from "@isp/xdce-widget";
import { Subscription } from "rxjs";
import { toInteger } from "../util/util";
import { NgbFidDatepickerRoutingView } from "./datepicker-routing-view";
const NGB_CALENDAR_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => FidRplCalendar),
multi: true,
};
/**
* A lightweight and highly configurable datepicker directive
*/
@Component({
exportAs: "fidRplCalendar",
selector: 'fid-rpl-calendar',
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
class: "d-inline-block rounded",
"[attr.tabindex]": "-1",
"(focus)": "fromkeyboard ? showFocus(true) : showFocus(false)",
"(keydown.arrowdown)": "showFocus(true)",
"(keydown.arrowup)": "showFocus(true)",
"(keydown.arrowleft)": "showFocus(true)",
"(keydown.arrowright)": "showFocus(true)",
"(keydown)": "onKeyDown($event)",
"(keyup.esc)": "close()",
},
templateUrl: './datepicker.html',
styleUrls: ["./datepicker.scss"],
providers: [
NGB_CALENDAR_VALUE_ACCESSOR,
NgbDatepickerService,
NgbDatepickerKeyMapService,
],
})
export class FidRplCalendar
implements OnDestroy, OnChanges, OnInit, ControlValueAccessor
{
model: DatepickerViewModel;
@ViewChild(forwardRef(() => NgbFidDatepickerRoutingView))
datepickerRoutingView: NgbFidDatepickerRoutingView;
@ViewChild(forwardRef(() => NgbFidDatepickerRoutingView))
datepickerHeader: NgbFidDatepickerRoutingView;
private _subscription: Subscription;
/**
* Reference for the custom template for the day display
*/
@Input() dayTemplate: TemplateRef<DayTemplateContext>;
/**
* Number of months to display
*/
@Input() displayMonths: number;
/**
* First day of the week. With default calendar we use ISO 8601: 'weekday' is 1=Mon ... 7=Sun
*/
@Input() firstDayOfWeek: number;
/**
* Callback to mark a given date as disabled.
* 'Current' contains the month that will be displayed in the view
*/
@Input() markDisabled: (
date: NgbDateStruct,
current: { year: number; month: number }
) => boolean;
/**
* Min date for the navigation. If not provided will be 10 years before today or `startDate`
*/
_minDate: NgbDateStruct;
@Input()
get minDate() {
return this._minDate;
}
set minDate(minDate: NgbDateStruct) {
this._minDate = minDate;
this.startDateEnabled = minDate;
}
/**
* Max date for the navigation. If not provided will be 10 years from today or `startDate`
*/
_maxDate: NgbDateStruct;
@Input()
get maxDate() {
return this._maxDate;
}
set maxDate(maxDate: NgbDateStruct) {
this._maxDate = maxDate;
this.endDateEnabled = maxDate;
}
/**
* Navigation type: `select` (default with select boxes for month and year), `arrows`
* (without select boxes, only navigation arrows) or `none` (no navigation at all)
*/
@Input() navigation: "select" | "arrows" | "none";
/**
* The way to display days that don't belong to current month: `visible` (default),
* `hidden` (not displayed) or `collapsed` (not displayed with empty space collapsed)
*/
@Input() outsideDays: "visible" | "collapsed" | "hidden";
/**
* Whether to display days of the week
*/
@Input() showWeekdays: boolean;
/**
* Whether to display week numbers
*/
@Input() showWeekNumbers: boolean;
/**
* Date to open calendar with.
* With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.
* If nothing or invalid date provided, calendar will open with current month.
* Use 'navigateTo(date)' as an alternative
*/
@Input() startDate: { year: number; month: number; day?: number };
@Input() startDateEnabled: any;
@Input() endDateEnabled: any;
@Input() disabledWeekend: boolean;
@Input() holidays: Array<NgbDateStruct>;
@Input() taxDeadlines: Array<NgbDateStruct>;
// /**
// * Start date Enabled
// */
// @Input() startDateEnabled: { year: number, month: number, day: number };
// /**
// * End date Enabled
// */
// @Input() endDateEnabled: { year: number, month: number, day: number };
/**
* In questa variabile sono memorizzati i dati iniziali che scenderanno l'albero dei template
*/
dataTemplate: NgbDataTemplateStruct = {
template: 0,
day: 0,
month: 0,
year: 0,
valid: false,
};
/**
* An event fired when navigation happens and currently displayed month changes.
* See NgbDatepickerNavigateEvent for the payload info.
*/
@Output() navigate = new EventEmitter<NgbDatepickerNavigateEvent>();
@Output() forceClose = new EventEmitter();
/**
* Template da Adoperare
*/
template: number = 0;
/**
* The field indicates that the datepicker was opened from the keyboard(with the enter key or the space key).
* The field is used to display the focus on the pre-selected day or today when the calendar opens by keyboard.
*/
public fromkeyboard: boolean;
/**
* The field indicates that the focus is on the month, year, day cell. If the field is false it means that the focus is positioned on the header of the calendar table
*/
private tabDayFocusVisible: boolean;
mesi: CalendarItem[][] = [
[
{
name: "JAN",
number: 1,
disabled: false,
selected: false,
focused: false,
},
{
name: "FEB",
number: 2,
disabled: false,
selected: false,
focused: false,
},
{
name: "MAR",
number: 3,
disabled: false,
selected: false,
focused: false,
},
{
name: "APR",
number: 4,
disabled: false,
selected: false,
focused: false,
},
],
[
{
name: "MAY",
number: 5,
disabled: false,
selected: false,
focused: false,
},
{
name: "JUN",
number: 6,
disabled: false,
selected: false,
focused: false,
},
{
name: "JUL",
number: 7,
disabled: false,
selected: false,
focused: false,
},
{
name: "AUG",
number: 8,
disabled: false,
selected: false,
focused: false,
},
],
[
{
name: "SEP",
number: 9,
disabled: false,
selected: false,
focused: false,
},
{
name: "OCT",
number: 10,
disabled: false,
selected: false,
focused: false,
},
{
name: "NOV",
number: 11,
disabled: false,
selected: false,
focused: false,
},
{
name: "DEC",
number: 12,
disabled: false,
selected: false,
focused: false,
},
],
];
years: CalendarItem[][] = [
[
{
name: "2018",
number: 2018,
disabled: false,
selected: false,
focused: false,
},
{
name: "2019",
number: 2019,
disabled: false,
selected: false,
focused: false,
},
{
name: "2020",
number: 2020,
disabled: false,
selected: false,
focused: false,
},
{
name: "2021",
number: 2021,
disabled: false,
selected: false,
focused: false,
},
],
[
{
name: "2022",
number: 2022,
disabled: false,
selected: false,
focused: false,
},
{
name: "2023",
number: 2023,
disabled: false,
selected: false,
focused: false,
},
{
name: "2024",
number: 2024,
disabled: false,
selected: false,
focused: false,
},
{
name: "2025",
number: 2025,
disabled: false,
selected: false,
focused: false,
},
],
[
{
name: "2026",
number: 2026,
disabled: false,
selected: false,
focused: false,
},
{
name: "2027",
number: 2027,
disabled: false,
selected: false,
focused: false,
},
{
name: "2028",
number: 2028,
disabled: false,
selected: false,
focused: false,
},
{
name: "2029",
number: 2029,
disabled: false,
selected: false,
focused: false,
},
],
];
onChange = (_: any) => {};
onTouched = () => {};
get _isNative(): boolean {
return /(ip(a|o)d|iphone|android)/gi.test(window.navigator.userAgent);
}
// startDateEnabled: string;
// endDateEnabled: string;
constructor(
private enabledRange: EnabledRangeService,
private _keyMapService: NgbDatepickerKeyMapService,
public _service: NgbDatepickerService,
private _calendar: NgbCalendar,
public i18n: NgbDatepickerI18n,
config: NgbDatepickerConfig,
private _cd: ChangeDetectorRef,
private _elementRef: ElementRef
) {
this.dayTemplate = config.dayTemplate;
this.displayMonths = config.displayMonths;
this.firstDayOfWeek = config.firstDayOfWeek;
this.markDisabled = config.markDisabled;
this.minDate = config.minDate;
this.maxDate = config.maxDate;
this.navigation = config.navigation;
this.showWeekdays = config.showWeekdays;
this.showWeekNumbers = config.showWeekNumbers;
this.startDate = config.startDate;
this.disabledWeekend = config.disabledWeekend;
this.holidays = config.holidays;
this.taxDeadlines = config.taxDeadlines;
this.startDateEnabled = enabledRange.startDate;
this.endDateEnabled = enabledRange.endDate;
// alert("finale Start : " + this.startDateEnabled)
// alert("finale End : " + this.endDateEnabled)
this._subscription = _service.model$.subscribe((model) => {
const newDate = model.firstDate;
const oldDate = this.model ? this.model.firstDate : null;
const newSelectedDate = model.selectedDate;
const oldSelectedDate = this.model ? this.model.selectedDate : null;
this.model = model;
// handling selection change
if (isChangedDate(newSelectedDate, oldSelectedDate)) {
this.onTouched();
this.onChange(
newSelectedDate
? {
year: newSelectedDate.year,
month: newSelectedDate.month,
day: newSelectedDate.day,
}
: null
);
}
// emitting navigation event if the first month changes
if (!newDate.equals(oldDate)) {
this.navigate.emit({
current: oldDate
? { year: oldDate.year, month: oldDate.month }
: null,
next: { year: newDate.year, month: newDate.month },
});
}
_cd.markForCheck();
});
}
abilitaMesi(data) {
if (
this.startDateEnabled.month <= data &&
data <= this.endDateEnabled.month &&
this.startDateEnabled.year <= this.dataTemplate.year &&
this.dataTemplate.year <= this.endDateEnabled.year
) {
return true;
}
return false;
}
abilitaAnni(data) {
if (
this.startDateEnabled.year <= data &&
data <= this.endDateEnabled.year
) {
return true;
}
return false;
}
emitForceClose() {
setTimeout(() => this.forceClose.emit(), 0);
}
setNewTemplate(obj) {
this.setMesi(this.dataTemplate.month, true);
this.updateYears(this.dataTemplate.year);
this.setYear(this.dataTemplate.year, true);
const prevTemplate = this.template;
this.template = obj.template;
this._service.emitTemplate(this.template);
if (prevTemplate === 2 && this.template === 0) {
const model = this._service._model$.getValue();
if (model && model.selectedDate) {
this.navigateTo({
month: model.selectedDate.month,
year: model.selectedDate.year,
});
}
}
obj.event.stopPropagation();
}
setMesi(position: number, selected: boolean) {
if (!this.abilitaMesi(position)) return;
let nRow = 0,
nCol = 0;
if (position == 4) nRow = 0;
else if (position == 8) nRow = 1;
else if (position == 12) nRow = 2;
else nRow = Math.trunc(position / 4);
nCol = position - nRow * 4 - 1;
console.info(
"dataTemplate",
this.dataTemplate,
"mese",
this.mesi[nRow][nCol],
"nRow",
nRow,
"nCol",
nCol
);
this.mesi[nRow][nCol].selected = selected;
this.mesi[nRow][nCol].focused = true;
}
updateYears(startYearValue: number) {
let yrs: CalendarItem[][] = [];
for (let j = 0; j < 3; j++) {
yrs[j] = [];
for (let i = 0; i < 4; i++) {
const yr = new CalendarItem();
yr.number = startYearValue + i + j * 4;
yr.name = yr.number + "";
yr.disabled = false;
yr.focused = false;
yr.selected = false;
yrs[j][i] = yr;
// this.years[j][i].number = startYearValue + i + j * 4
// this.years[j][i].name = this.years[j][i].number + "";
}
}
yrs.forEach((row) => {
row.forEach((y) => {
y.selected = this.dataTemplate.year === y.number;
y.focused = this.dataTemplate.year === y.number;
});
});
this.years = yrs;
}
setYear(yearValue: number, selected: boolean) {
if (!this.abilitaAnni(yearValue)) return;
this.years.forEach((row) => {
row.forEach((year) => {
if (year.number == yearValue) year.selected = selected;
});
});
}
/**
* Manually focus the calendar
*/
focus() {
this._elementRef.nativeElement.focus();
}
getHeaderHeight() {
const h = this.showWeekdays ? 6.25 : 4.25;
return this.displayMonths === 1 || this.navigation !== "select" ? h - 2 : h;
}
getHeaderMargin() {
const m = this.showWeekdays ? 2 : 0;
return this.displayMonths !== 1 || this.navigation !== "select" ? m + 2 : m;
}
/**
* Navigates current view to provided date.
* With default calendar we use ISO 8601: 'month' is 1=Jan ... 12=Dec.
* If nothing or invalid date provided calendar will open current month.
* Use 'startDate' input as an alternative
*/
navigateTo(date?: { year: number; month: number }) {
this._service.open(
date ? new NgbDate(date.year, date.month, 1) : this._calendar.getToday()
);
}
ngOnDestroy() {
this._subscription.unsubscribe();
}
ngOnInit() {
if (this.model === undefined) {
this._service.displayMonths = toInteger(this.displayMonths);
this._service.markDisabled = this.markDisabled;
this._service.firstDayOfWeek = this.firstDayOfWeek;
this._service.disabledWeekend = this.disabledWeekend;
this._service.holidays = this.holidays;
this._service.taxDeadlines = this.taxDeadlines;
this._setDates();
// inixializzazione dataTemplate alla data selezionata
if (!this.startDate || !this.startDate.month || !this.startDate.year) {
this.startDate = { year: null, month: null, day: null };
let today = new Date();
let dd = today.getDate();
let mm = today.getMonth() + 1; //January is 0!
let yyyy = today.getFullYear();
this.startDate.day = dd;
this.startDate.month = mm;
this.startDate.year = yyyy;
}
this.dataTemplate.day = this.startDate.day;
this.dataTemplate.month = this.startDate.month;
this.dataTemplate.year = this.startDate.year;
this.dataTemplate.valid = false;
let elem: HTMLElement = this._elementRef.nativeElement;
elem.classList.contains("isp-corporate-mode-wrapper")
? (this.outsideDays = "collapsed")
: (this.outsideDays = "visible");
}
this._service["subscribeIsDayFocusView"]().subscribe((tabFocusVisible) => {
this.tabDayFocusVisible = tabFocusVisible;
});
this._service.emitTemplate(this.template);
}
ngOnChanges(changes: SimpleChanges) {
if (changes["displayMonths"]) {
this._service.displayMonths = toInteger(this.displayMonths);
}
if (changes["markDisabled"]) {
this._service.markDisabled = this.markDisabled;
}
if (changes["firstDayOfWeek"]) {
this._service.firstDayOfWeek = this.firstDayOfWeek;
}
if (changes["taxDeadlines"]) {
this._service.taxDeadlines = this.taxDeadlines;
}
}
onDateSelect(date: NgbDate) {
this._service.focus(date);
this.writeValue(date);
}
onKeyDown(event: KeyboardEvent) {
// this.template == 0 => days template
// this.template == 1 => months template
// this.template == 2 => years template
// if I click the enter button in the months template I return to the days template
if (
this.template == 1 &&
(event.key == "Enter" || event.key == " ") &&
this.tabDayFocusVisible
) {
let selectedMounth;
this.datepickerRoutingView.mesi.map((row) => {
row.map((mounth) => {
if (mounth.number == this.datepickerRoutingView.currentMonth) {
selectedMounth = mounth;
return mounth;
}
});
});
this.datepickerRoutingView.doSelectMonth(selectedMounth, event);
}
// if I click the enter button in the years template I return to the months template
else if (
this.template == 2 &&
(event.key == "Enter" || event.key == " ") &&
this.tabDayFocusVisible
) {
let selectedYear;
this.datepickerRoutingView.years.map((row) => {
row.map((year) => {
if (year.number == this.datepickerRoutingView.currentYear) {
selectedYear = year;
}
});
});
this.datepickerRoutingView.doSelectYear(selectedYear, event);
} else {
if (this._keyMapService.processKey(event) === true) {
this.emitForceClose();
}
}
}
onNavigateDateSelect(date: NgbDate) {
this._service.open(date);
}
onNavigateEvent(event: NavigationEvent) {
let bufferData: NgbDate;
this.model.firstDate.month = this.dataTemplate.month;
this.model.firstDate.year = this.dataTemplate.year;
if (event == NavigationEvent.PREV && this.template == 0) {
bufferData = this._calendar.getPrev(this.model.firstDate, "m", 1);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
} else if (NavigationEvent.NEXT && this.template == 0) {
bufferData = this._calendar.getNext(this.model.firstDate, "m", 1);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
} else if (event == NavigationEvent.PREV && this.template == 1) {
bufferData = this._calendar.getPrev(this.model.firstDate, "m", 12);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
} else if (event == NavigationEvent.NEXT && this.template == 1) {
bufferData = this._calendar.getNext(this.model.firstDate, "m", 12);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
} else if (event == NavigationEvent.PREV && this.template == 2) {
bufferData = this._calendar.getPrev(this.model.firstDate, "m", 144);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
this.updateYears(this.dataTemplate.year);
} else if (event == NavigationEvent.NEXT && this.template == 2) {
bufferData = this._calendar.getNext(this.model.firstDate, "m", 144);
this._service.open(bufferData);
this.updateDataTemplate(bufferData);
this.updateYears(this.dataTemplate.year);
}
}
onChangeTemplate(dataTemplate: NgbDataTemplateStruct) {
this.dataTemplate = dataTemplate;
this.template = dataTemplate.template;
this.navigateTo({ month: dataTemplate.month, year: dataTemplate.year });
}
updateDataTemplate(date: NgbDate) {
const newTemplate = { ...this.dataTemplate };
newTemplate.day = date.day;
newTemplate.month = date.month;
newTemplate.year = date.year;
this.dataTemplate = newTemplate;
this.navigateTo({
month: this.dataTemplate.month,
year: this.dataTemplate.year,
});
}
registerOnChange(fn: (value: any) => any): void {
this.onChange = fn;
}
registerOnTouched(fn: () => any): void {
this.onTouched = fn;
}
setDisabledState(isDisabled: boolean) {
this._service.disabled = isDisabled;
}
showFocus(focusVisible: boolean) {
this._service.focusVisible = focusVisible;
}
writeValue(value: any) {
this._service.select(value);
}
private _setDates() {
const startDate = this._service.toValidDate(
this.startDate,
this._calendar.getToday()
);
const minDate = this._service.toValidDate(
this.minDate,
this._calendar.getPrev(startDate, "y", 10)
);
const maxDate = this._service.toValidDate(
this.maxDate,
this._calendar.getPrev(this._calendar.getNext(startDate, "y", 11))
);
this.minDate = {
year: minDate.year,
month: minDate.month,
day: minDate.day,
};
this.maxDate = {
year: maxDate.year,
month: maxDate.month,
day: maxDate.day,
};
this._service.minDate = minDate;
this._service.maxDate = maxDate;
this.navigateTo(startDate);
}
public focusOutComponent(event: any) {
if (!this._elementRef.nativeElement.contains(event.target)) {
let elem: HTMLElement = this._elementRef.nativeElement;
if (elem.parentElement) {
elem.parentElement.removeChild(elem);
}
this._subscription.unsubscribe();
}
}
}

View File

@ -1,151 +0,0 @@
// previous version:
// https://github.com/angular-ui/bootstrap/blob/07c31d0731f7cb068a1932b8e01d2312b796b4ec/src/position/position.js
export class Positioning {
private getStyle(element: HTMLElement, prop: string): string { return window.getComputedStyle(element)[prop]; }
private isStaticPositioned(element: HTMLElement): boolean {
return (this.getStyle(element, 'position') || 'static') === 'static';
}
private offsetParent(element: HTMLElement): HTMLElement {
let offsetParentEl = <HTMLElement>element.offsetParent || document.documentElement;
while (offsetParentEl && offsetParentEl !== document.documentElement && this.isStaticPositioned(offsetParentEl)) {
offsetParentEl = <HTMLElement>offsetParentEl.offsetParent;
}
return offsetParentEl || document.documentElement;
}
position(element: HTMLElement, round = true): ClientRect {
let elPosition: ClientRect;
let parentOffset: ClientRect = {width: 0, height: 0, top: 0, bottom: 0, left: 0, right: 0};
if (this.getStyle(element, 'position') === 'fixed') {
elPosition = element.getBoundingClientRect();
} else {
const offsetParentEl = this.offsetParent(element);
elPosition = this.offset(element, false);
if (offsetParentEl !== document.documentElement) {
parentOffset = this.offset(offsetParentEl, false);
}
parentOffset.top += offsetParentEl.clientTop;
parentOffset.left += offsetParentEl.clientLeft;
}
elPosition.top -= parentOffset.top;
elPosition.bottom -= parentOffset.top;
elPosition.left -= parentOffset.left;
elPosition.right -= parentOffset.left;
if (round) {
elPosition.top = Math.round(elPosition.top);
elPosition.bottom = Math.round(elPosition.bottom);
elPosition.left = Math.round(elPosition.left);
elPosition.right = Math.round(elPosition.right);
}
return elPosition;
}
offset(element: HTMLElement, round = true): ClientRect {
const elBcr = element.getBoundingClientRect();
const viewportOffset = {
top: window.pageYOffset - document.documentElement.clientTop,
left: window.pageXOffset - document.documentElement.clientLeft
};
let elOffset = {
height: elBcr.height || element.offsetHeight,
width: elBcr.width || element.offsetWidth,
top: elBcr.top + viewportOffset.top,
bottom: elBcr.bottom + viewportOffset.top,
left: elBcr.left + viewportOffset.left,
right: elBcr.right + viewportOffset.left
};
if (round) {
elOffset.height = Math.round(elOffset.height);
elOffset.width = Math.round(elOffset.width);
elOffset.top = Math.round(elOffset.top);
elOffset.bottom = Math.round(elOffset.bottom);
elOffset.left = Math.round(elOffset.left);
elOffset.right = Math.round(elOffset.right);
}
return elOffset;
}
positionElements(hostElement: HTMLElement, targetElement: HTMLElement, placement: string, appendToBody?: boolean):
ClientRect {
const hostElPosition = appendToBody ? this.offset(hostElement, false) : this.position(hostElement, false);
const targetElBCR = targetElement.getBoundingClientRect();
const placementPrimary = placement.split('-')[0] || 'top';
const placementSecondary = placement.split('-')[1] || 'center';
let targetElPosition: ClientRect = {
'height': targetElBCR.height || targetElement.offsetHeight,
'width': targetElBCR.width || targetElement.offsetWidth,
'top': 0,
'bottom': targetElBCR.height || targetElement.offsetHeight,
'left': 0,
'right': targetElBCR.width || targetElement.offsetWidth
};
switch (placementPrimary) {
case 'top':
targetElPosition.top = hostElPosition.top - targetElement.offsetHeight;
break;
case 'bottom':
targetElPosition.top = hostElPosition.top + hostElPosition.height;
break;
case 'left':
targetElPosition.left = hostElPosition.left - targetElement.offsetWidth;
break;
case 'right':
targetElPosition.left = hostElPosition.left + hostElPosition.width;
break;
}
switch (placementSecondary) {
case 'top':
targetElPosition.top = hostElPosition.top;
break;
case 'bottom':
targetElPosition.top = hostElPosition.top + hostElPosition.height - targetElement.offsetHeight;
break;
case 'left':
targetElPosition.left = hostElPosition.left;
break;
case 'right':
targetElPosition.left = hostElPosition.left + hostElPosition.width - targetElement.offsetWidth;
break;
case 'center':
if (placementPrimary === 'top' || placementPrimary === 'bottom') {
targetElPosition.left = hostElPosition.left + hostElPosition.width / 2 - targetElement.offsetWidth / 2;
} else {
targetElPosition.top = hostElPosition.top + hostElPosition.height / 2 - targetElement.offsetHeight / 2;
}
break;
}
targetElPosition.top = Math.round(targetElPosition.top);
targetElPosition.bottom = Math.round(targetElPosition.bottom);
targetElPosition.left = Math.round(targetElPosition.left);
targetElPosition.right = Math.round(targetElPosition.right);
return targetElPosition;
}
}
const positionService = new Positioning();
export function positionElements(
hostElement: HTMLElement, targetElement: HTMLElement, placement: string, appendToBody?: boolean): void {
const pos = positionService.positionElements(hostElement, targetElement, placement, appendToBody);
targetElement.style.top = `${pos.top}px`;
targetElement.style.left = `${pos.left}px`;
}

View File

@ -1,39 +0,0 @@
export function toInteger(value: any): number {
return parseInt(`${value}`, 10);
}
export function toString(value: any): string {
return (value !== undefined && value !== null) ? `${value}` : '';
}
export function getValueInRange(value: number, max: number, min = 0): number {
return Math.max(Math.min(value, max), min);
}
export function isString(value: any): value is string {
return typeof value === 'string';
}
export function isNumber(value: any): value is number {
return !isNaN(toInteger(value));
}
export function isInteger(value: any): value is number {
return typeof value === 'number' && isFinite(value) && Math.floor(value) === value;
}
export function isDefined(value: any): boolean {
return value !== undefined && value !== null;
}
export function padNumber(value: number) {
if (isNumber(value)) {
return `0${value}`.slice(-2);
} else {
return '';
}
}
export function regExpEscape(text) {
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}

View File

@ -1,111 +0,0 @@
<div class="isp-calendar-generic" [ngClass]="{ 'isp-default': nbpStyle === _style.DEFAULT || corporateMode,
'isp-primary': nbpStyle === _style.PRIMARY && !corporateMode,
'isp-secondary': nbpStyle === _style.SECONDARY,
'on-dark-background': nbpDarkBackground,
'isp-focused' : (rplCalendar.isOpen() && !opened) || hasFocus,
'isp-highlight': nbpHighlightedDefault,
'opened': opened,
'disabled-background-current-month': isCurrentMonth,
'disabled-background': !isCurrentMonth }" [attr.aria-label]="'CALENDAR'| translate"
[class.enableDefaultView]="enableDefaultViewOnUnifiedVG && unifiedMode"
(keydown.space)="preventScroll($event)"
>
<div class="form-group" [ngClass]="{ 'disabled': disabled,
'tab-focused': tabFocus}">
<div class="input-group">
<input
[ngClass]="{'padding-top-15 d-flex' : unifiedMode, 'calendar-open': rplCalendar.isOpen(),'input-hidden': _nbpOutMode}"
fidRplCalendar
#rplCalendar="fidRplCalendar"
[onDateSelectedCallback]="focusButton()"
[placement]="nbpPlacement"
[nbpLabelPattern]="nbpLabelPattern"
[nbpDateSeparator]="nbpDateSeparator"
[isUnifiedVg]="unifiedMode"
[id]="id"
(click)="nativeClickHandler()"
[name]="name"
[ngModel]="_ngbModel"
[ngModelOptions]="nbpModelOptions"
(ngModelChange)='_ngbModelChanged($event)'
[required]="required"
[disabled]="disabled"
[maxDate]="ngbMaxDate"
[minDate]="ngbMinDate"
(navigate)="_onNavigate($event)"
(blur)="touchExternalInput();"
(touchstart)="handleCalendar($event)"
navigation="arrows"
class="form-control"
[pattern]="pattern"
[placeholder]="placeholder"
[type]="_type"
[disabledWeekend]="_disableWeekend"
[holidays]="_holidays"
[taxDeadlines]="_tax"
[tabindex]="tabindex"
#autoFocusCalendar
[attr.aria-labelledby]="label"
[attr.aria-describedby]="ariaInvalidDate() ? 'error_message'+ id : 'info-text' + id"
[attr.aria-required]="required"
[attr.aria-live]="ariaLive"
[attr.aria-invalid]="ariaInvalidDate() && isNative"
(focus)="onFocusIn()"
(focusout)="onFocusOut()"
(keyup.tab)="_tabFocusOn()"
(keydown.tab)="_tabFocusOff()"
(keyup.shift.tab)="_tabFocusOn()"
(keydown.shift.tab)="_tabFocusOff()"
dateValidator
autocomplete="off"
[attr.aria-label]="ariaLabel"
closeKeyboardOnScroll>
<i class="isp-font-comuni-calendario button-icon"
[ngClass]="{ 'cursor-initial': opened,
'disabled': disabled,
'input-hidden': _nbpOutMode,
'isIt': unifiedMode && isIt }"
#myIconCalendar
*ngIf="!_nbpOutMode && (retailMode || unifiedMode)"
type="'button'"
(ispClick)="handleCalendar($event)"
[attr.aria-hidden]="disabled"
[attr.tabindex]="0"
[attr.aria-live]="'off'"
[attr.role]="'button'"
[attr.aria-label]="'ARIA_CALENDAR_SELECT_DATE_AND_DIALOG'| translate"
(keyup.tab)="_tabFocusOnIcon()"
(keydown.tab)="_tabFocusOffIcon()"
(keydown.space)="manageKeydownSpaceCalendar($event)"
(focusout)="onFocusOutIcon()"
[style.pointerEvents]="enableDefaultViewOnUnifiedVG ? 'all' : null"
>
</i>
<span *ngIf="!_nbpOutMode && unifiedMode" class="calendar-label" aria-hidden="true">{{'CALENDAR' | translate}}</span>
<div class="button-icon button-icon-scale"
#myIconCalendar
*ngIf="!_nbpOutMode && !retailMode && !unifiedMode"
[ngClass]="{ 'cursor-initial': opened,
'disabled': disabled,
'input-hidden': _nbpOutMode}"
type="'button'"
(ispClick)="handleCalendar($event)"
[attr.role]="'button'"
[attr.tabindex]="disabled ? -1 : 0"
[attr.aria-label]="isNative ? 'CALENDAR': 'ARIA_CALENDAR_SELECT_DATE_AND_DIALOG'| translate"
[attr.aria-hidden]="disabled"
[attr.aria-live]="'off'"
(keyup.tab)="_tabFocusOnIcon()"
(keydown.tab)="_tabFocusOffIcon()"
(keydown.space)="manageKeydownSpaceCalendar($event)"
(focusout)="onFocusOutIcon()">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50">
<path class="svg-icon"
d="m7,2c.416,0,.75.334.75.75v1.25h4.5v-1.25c0-.416.334-.75.75-.75s.75.334.75.75v1.25h1.25c1.103,0,2,.897,2,2v10c0,1.103-.897,2-2,2H5c-1.103,0-2-.897-2-2V6c0-1.103.897-2,2-2h1.25v-1.25c0-.416.334-.75.75-.75Zm8.5,6H4.5v8c0,.275.225.5.5.5h10c.275,0,.5-.225.5-.5v-8Zm-9,2h3c.275,0,.5.225.5.5v3c0,.275-.225.5-.5.5h-3c-.275,0-.5-.225-.5-.5v-3c0-.275.225-.5.5-.5Z" />
</svg>
</div>
</div>
<span class="output-mode" *ngIf="_nbpOutMode"
[ngClass]="{'output-mode-light': nbpLightMode}">{{setSpanLabel(_ngbModel)}}</span>
</div>
</div>

View File

@ -1,570 +0,0 @@
:host(.isp-corporate-mode-a11y-wrapper) {
.isp-calendar-generic {
//width: 12.65em;
input::-webkit-input-placeholder {
text-overflow: ellipsis !important;
overflow: hidden;
white-space: nowrap;
max-width: 90%;
}
input::-moz-placeholder {
text-overflow: ellipsis !important;
overflow: hidden;
white-space: nowrap;
max-width: 90%;
}
input:-moz-placeholder {
text-overflow: ellipsis !important;
overflow: hidden;
white-space: nowrap;
max-width: 90%;
}
input:-ms-input-placeholder {
text-overflow: ellipsis !important;
overflow: hidden;
white-space: nowrap;
font-size: 0.75rem;
}
input.input-hidden {
display: none !important;
}
.output-mode {
height: 2.1875rem;
padding: 11px 10px 10px 0px;
line-height: 0.875rem;
font-size: .75rem;
}
&>.form-group {
border-width: 0px;
&.tab-focused {
&:not([disabled]) {
box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 4px #FFF599, 0 0 0 6px #000000 !important;
border-radius: 4px;
border-width: 0px !important;
&>.input-group {
input.form-control {
&:focus,
&:active {
border-width: 1px !important;
}
}
}
}
}
&>.input-group {
display: table;
table-layout: fixed;
input.form-control {
font-size: 0.75rem;
border-radius: 2px !important;
height: 2.25rem;
padding: 11px 25px 10px 10px;
background-clip: border-box;
line-height: 0.875rem;
white-space: nowrap;
display: table-cell;
overflow: hidden;
text-overflow: ellipsis;
/*no-shadow*/
//-webkit-box-shadow: none !important;
//box-shadow: none !important;
&:active:not([disabled]),
&:focus:not([disabled]) {
border-width: 1px;
}
&:not([disabled]) {
&.ng-touched.ng-invalid,
&.ng-dirty.ng-invalid,
&.nbp-show-validation.ng-invalid {
border-width: 2px;
&:focus,
&.calendar-open {
border-width: 2px;
}
}
&.calendar-open {
border-width: 1px;
}
}
&[disabled] {
opacity: 0.35;
}
}
}
}
.button-icon {
&.disabled {
opacity: 0.35;
}
&:active {
scale: 0.95;
transition: transform 0.15s ease 0s;
border: none !important;
}
font-size: 1.25rem;
top:50%;
transform: translateY(-50%);
right: 0.375rem;
}
.button-icon-scale {
display: flex;
justify-content: flex-end;
height: 24px;
width: 24px;
}
.svg-icon {
transform: scale(2.2) translate(1.5px, 1px);
}
}
.ng-invalid.ng-dirty.ng-touched & {
&>.form-group {
&>.input-group {
input.form-control {
&:not([disabled]) {
border-width: 2px;
border-style: solid;
&:focus {
border-width: 2px;
border-style: solid;
}
}
}
}
}
}
}
:host(.isp-isybankm-mode-a11y-wrapper),
:host(.isp-unifiedvg-mode-a11y-wrapper) {
.isp-calendar-generic {
.input-hidden {
display: none !important;
}
.output-mode {
font-size: 1.125rem;
line-height: 1.313rem;
padding: 0 15px;
}
&>.form-group {
border-width: 0px;
&>.input-group {
display: table;
table-layout: fixed;
input.form-control {
font-size: 0.75rem;
border-radius: 2px !important;
height: 2.1875rem;
padding: 11px 40px 10px 14px !important;
background-clip: border-box;
line-height: 0.875rem;
vertical-align: middle;
white-space: nowrap;
display: table-cell !important;
&.input-hidden {
display: none !important;
}
overflow: hidden;
text-overflow: ellipsis !important;
/*no-shadow*/
-webkit-box-shadow: none !important;
box-shadow: none !important;
box-shadow: none !important;
padding: 1px 15px;
border-radius: 4px !important;
&:focus:not([disabled]) {
border-width: 2px !important;
}
}
}
}
.button-icon {
top: .2em;
right: .85em;
pointer-events: none;
&.isIt {
margin-right: 5px;
}
}
.calendar-label {
margin-right: 6px;
position: absolute;
top: 2.80em;
right: 0.45em;
z-index: 3;
line-height: 1em;
font-size: 0.75rem;
letter-spacing: 0px;
opacity: 1;
cursor: pointer;
}
}
}
.error_message_visible {
color: #F51500;
}
.isp-calendar-generic {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
input.input-hidden {
display: none !important;
}
&>.form-group {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-flex: 0;
-ms-flex: 0 0 auto;
flex: 0 0 auto;
-ms-flex-flow: row wrap;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
flex-flow: row wrap;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin-bottom: 0;
border-width: 0px !important;
font-size: 1rem;
&.tab-focused {
&:not([disabled]) {
box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 4px #FFF599, 0 0 0 6px #000000 !important;
border-radius: 4px !important;
border-width: 0px !important;
z-index: 1;
position: relative;
&>.input-group {
input.form-control {
&:focus,
&:active {
border-width: 1px !important;
}
}
}
}
}
border-radius: 2px;
margin:0px;
border: solid;
&>.input-group {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
//flex-wrap: nowrap;
width: 100%;
input.form-control {
font-family: sans-serif;
-webkit-appearance: none;
font-size: 100%;
line-height: 2.25rem;
margin: 0;
display: block;
width: 100%;
overflow: visible;
height: 3.125rem;
padding: 11px 40px 10px 10px;
background-image: none;
background-clip: padding-box;
border-radius: 2px !important;
white-space: nowrap;
display: table-cell;
overflow: hidden;
text-overflow: ellipsis !important;
transition: none !important;
border-width: 1px;
border-style: solid;
padding-left: 10px;
-ms-touch-action: manipulation;
touch-action: manipulation;
&::-ms-clear {
display: none;
width: 0;
height: 0;
}
&:focus:not([disabled]),
&:active:not([disabled]) {
border-width: 2px !important;
border-style: solid;
}
&:not([disabled]).calendar-open {
border-width: 2px;
}
&[disabled] {
border-width: 1px;
border-style: solid;
user-select: none;
}
&::-webkit-clear-button {
display: none;
}
&::-webkit-inner-spin-button {
display: none;
}
&::-webkit-calendar-picker-indicator {
&.disabled {
cursor: default;
pointer-events: none;
}
content: '';
background-color: transparent;
color: transparent;
width: 2rem;
height: 80%;
border-width: none;
cursor: pointer;
position: relative;
vertical-align: middle;
right: 0.375rem;
z-index: 5;
font-size: 1rem;
line-height: 1rem;
}
}
& ::ng-deep .dropdown-menu {
border: none;
}
}
}
.output-mode {
height: 2.1875rem;
padding: 8px 10px 10px 10px;
line-height: 0.875rem;
font-size: 1rem;
}
.input-group-addon {
padding: 10px 12px;
margin-bottom: 0;
font-size: 1rem;
font-weight: 400;
line-height: 1.25;
text-align: center;
border-top-style: solid;
border-top-width: 1px;
border-right-style: solid;
border-right-width: 1px;
border-bottom-style: solid;
border-bottom-width: 1px;
border-left-style: none !important;
border-left-width: 0 !important;
&:not(:first-child) {
border-left: 0;
}
img {
width: 1.25rem;
height: 1rem;
cursor: pointer;
}
}
.button-icon {
&.cursor-initial {
cursor: initial !important;
}
&.disabled {
opacity: 0.35;
}
&:focus-visible:not(.disabled) {
box-shadow: 0 0 0 2px #FFFFFF, 0 0 0 4px #FFF599, 0 0 0 6px #000000 !important;
border-radius: 4px !important;
border-width: 0px !important;
z-index: 1;
//position: relative;
}
margin: 0px;
border: solid;
border-width: 0px;
cursor: pointer;
position: absolute;
top: 0.45em;
right: 0.475em;
z-index: 3;
font-size: 1.6em;
line-height: 1em;
&.disabled {
cursor: not-allowed;
pointer-events: none;
}
}
//--- esempio di un template custom -----
//--- le classi successive servono nel caso del template #tpl indicato nel selettore-----
.day {
border-radius: 0 !important;
box-sizing: border-box;
text-align: center;
width: inherit !important;
height: inherit !important;
line-height: 2.6rem !important;
vertical-align: middle;
border-left-width: 1px;
border-left-style: solid;
border-right-width: 1px;
border-right-style: solid;
border-bottom-width: 1px;
border-bottom-style: solid;
border-collapse: separate;
border-spacing: 0;
&:hover {
cursor: pointer;
}
}
.icon {
width: 2rem;
height: 2rem;
}
//--- fine template custom -----
}
//fix jira 565
:host(:not(.isp-corporate-mode-a11y-wrapper)).ng-invalid.ng-dirty.ng-touched {
.isp-calendar-generic {
&>.form-group {
&>.input-group {
input.form-control {
&:not([disabled]) {
border-width: 2px;
border-style: solid;
&:focus {
border-width: 2px;
border-style: solid;
}
}
}
}
}
}
}
:host(:not(.isp-corporate-mode-a11y-wrapper)) {
.isp-calendar-generic {
&>.form-group {
&>.input-group {
input.form-control {
font-size: 1rem;
height: 3.125rem;
:host(:not(.isp-unifiedvg-mode-a11y-wrapper)) {
padding: 6px 10px 6px 10px;
}
}
}
}
}
}
.d-inline-block {
display: inline-block !important;
&.dropdown-menu {
position: absolute;
left: 0;
display: none;
float: left;
min-width: 10rem;
margin: 2px 0 0;
font-size: 1rem;
text-align: left;
list-style: none;
background-clip: padding-box;
padding: 0;
top: 1.5rem;
border-radius: 0 !important;
border: none !important;
&.rounded {
border-radius: 4px;
}
}
}
.padding-top-15 {
padding-top: 15px;
}
.padding-top-15:placeholder-shown {
padding-top: 0px;
}
:host(.isp-retail-mode-a11y-wrapper) {
input[type="date"]::-webkit-inner-spin-button,
input[type="date"]::-webkit-calendar-picker-indicator {
display: none;
-webkit-appearance: none;
}
}

View File

@ -1,66 +0,0 @@
<div class="isp-calendar-generic "
[ngClass]="{ 'isp-default': nbpStyle === _style.DEFAULT,
'isp-primary': nbpStyle === _style.PRIMARY,
'isp-secondary': nbpStyle === _style.SECONDARY,
'on-dark-background': nbpDarkBackground,
'isp-focused' : (rplCalendar.isOpen() && !opened) || hasFocus,
'isp-highlight': nbpHighlightedDefault,
'opened': opened }"
[tabIndex]="0"
[attr.aria-label]="'CALENDARIO'"
[class.enableDefaultView]="enableDefaultViewOnUnifiedVG && unifiedMode">
<div class="form-group">
<div class="input-group">
<input
[ngClass] ="{'padding-top-15 d-flex' : unifiedMode, 'calendar-open': rplCalendar.isOpen(),'input-hidden': _nbpOutMode}"
fidRplCalendarNOA11Y
#rplCalendar="fidRplCalendarNOA11Y"
[placement]="nbpPlacement"
[nbpLabelPattern]="nbpLabelPattern"
[nbpDateSeparator]="nbpDateSeparator"
[isUnifiedVg]="unifiedMode"
[id]="id"
(click)="nativeClickHandler()"
[name]="name"
[ngModel]="_ngbModel"
[ngModelOptions]="nbpModelOptions"
(ngModelChange)='_ngbModelChanged($event)'
[required]="required"
[disabled]="disabled"
[maxDate]="ngbMaxDate"
[minDate]="ngbMinDate"
(navigate)="_onNavigate($event)"
(blur) = "touchExternalInput();"
(touchstart) ="handleCalendar($event)"
navigation="arrows"
class="form-control"
[pattern]="pattern"
[placeholder]="placeholder"
[type]="_type"
[disabledWeekend]="_disableWeekend"
[holidays]="_holidays"
[taxDeadlines]="_tax"
[tabindex]="tabindex"
#autoFocusCalendar
[attr.aria-labelledby]="label"
[attr.aria-describedby]="' '"
[attr.aria-label]="ariaLabel"
(focus)="onFocusIn()"
(focusout)="onFocusOut()"
dateValidator
autocomplete="off"
closeKeyboardOnScroll>
<i class="isp-font-comuni-calendario button-icon"
[ngClass]="{ 'cursor-initial': opened,
'disabled': disabled,
'input-hidden': _nbpOutMode }"
*ngIf="!_nbpOutMode"
(ispClick)="handleCalendar($event)"
[attr.tabindex]="-1"
[attr.aria-hidden]="true"
[style.pointerEvents]="enableDefaultViewOnUnifiedVG ? 'all' : null">
</i>
</div>
<span class="output-mode" *ngIf="_nbpOutMode" [ngClass]="{'output-mode-light': nbpLightMode}">{{setSpanLabel(_ngbModel)}}</span>
</div>
</div>

View File

@ -1,368 +0,0 @@
:host(.isp-corporate-mode-wrapper) {
.isp-calendar-generic {
//width: 12.65em;
input::-webkit-input-placeholder {
text-overflow: ellipsis !important;
overflow: hidden;
white-space: nowrap;
max-width: 90%;
}
input::-moz-placeholder {
text-overflow: ellipsis !important;
overflow: hidden;
white-space: nowrap;
max-width: 90%;
}
input:-moz-placeholder {
text-overflow: ellipsis !important;
overflow: hidden;
white-space: nowrap;
max-width: 90%;
}
input:-ms-input-placeholder {
text-overflow: ellipsis !important;
overflow: hidden;
white-space: nowrap;
font-size: 0.75rem;
}
input.input-hidden {
display: none!important;
}
.output-mode {
height: 2.1875rem;
padding: 0.6875rem 0.625rem 0.625rem 0.625rem;
line-height: 0.875rem;
font-size: .75rem;
}
& > .form-group {
& > .input-group {
input.form-control {
font-size: 0.75rem;
border-radius: 0.125rem !important;
height: 2.1875rem;
padding: 0.6875rem 0.625rem 0.625rem 0.625rem;
background-clip: border-box;
line-height:0.875rem;
/*no-shadow*/
-webkit-box-shadow: none !important;
box-shadow: none !important;
&:not([disabled]) {
&.ng-touched.ng-invalid, &.ng-dirty.ng-invalid, &.nbp-show-validation.ng-invalid {
border-width: 0.0625rem;
&:focus,&.calendar-open {
border-width: 0.0625rem;
}
}
&.calendar-open {
border-width: 0.0625rem;
}
}
&[disabled] {
opacity: 0.5;
}
}
}
}
.button-icon {
&.disabled {
opacity: 0.5;
}
font-size: 1.25rem;
top:50%;
transform: translateY(-50%);
right: 0.625rem;
}
}
.ng-invalid.ng-dirty.ng-touched & {
& > .form-group {
& > .input-group {
input.form-control {
&:not([disabled]) {
border-width: 0.0625rem;
border-style: solid;
&:focus {
border-width: 0.0625rem;
border-style: solid;
}
}
}
}
}
}
}
:host(.isp-unifiedvg-mode-wrapper) {
.isp-calendar-generic {
.input-hidden {
display: none!important;
}
.output-mode {
font-size: 1.125rem;
line-height: 1.313rem;
padding: 0 0.9375rem;
}
& > .form-group {
& > .input-group {
input.form-control {
box-shadow: none!important;
padding: .0625rem .9375rem;
border-radius: .25rem!important;
&:focus:not([disabled]){
border-width: 0.125rem !important;
}
}
}
}
.button-icon {
top: .47em;
right: .60em;
pointer-events: none;
}
}
}
.error_message_visible {
color: #F51500;
}
.isp-calendar-generic {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
-webkit-box-pack: center;
-ms-flex-pack: center;
justify-content: center;
& > .form-group {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-flex: 0;
-ms-flex: 0 0 auto;
flex: 0 0 auto;
-ms-flex-flow: row wrap;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
flex-flow: row wrap;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
margin-bottom: 0;
font-size: 1rem;
& > .input-group {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
//flex-wrap: nowrap;
width: 100%;
input.form-control {
font-family: sans-serif;
-webkit-appearance: none;
font-size: 100%;
line-height: 2.25rem;
margin: 0;
display: block;
width: 100%;
overflow: visible;
height: 3.125rem;
background-image: none;
background-clip: padding-box;
border-radius: .125rem !important;
transition: none !important;
border-width: 0.0625rem;
border-style: solid;
padding-left: .625rem;
-ms-touch-action: manipulation;
touch-action: manipulation;
&::-ms-clear {
display: none;
width: 0;
height: 0;
}
&:focus:not([disabled]), &:active:not([disabled]) {
border-width: 0.0625rem;
border-style: solid;
}
&[disabled] {
border-width: 0.0625rem;
border-style: solid;
user-select: none;
}
&::-webkit-clear-button {
display: none;
}
&::-webkit-inner-spin-button{
display: none;
}
&::-webkit-calendar-picker-indicator{
&.disabled {
cursor: default;
pointer-events: none;
}
content: '';
background-color: transparent;
color: transparent;
width: 2rem;
height: 80%;
border-width: none;
cursor: pointer;
position: relative;
vertical-align: middle;
right: 0.375rem;
z-index: 5;
font-size: 1rem;
line-height: 1rem;
}
}
& ::ng-deep .dropdown-menu {
border: none;
}
}
}
.input-group-addon {
padding: 0.625rem 0.75rem;
margin-bottom: 0;
font-size: 1rem;
font-weight: 400;
line-height: 1.25;
text-align: center;
border-top-style: solid;
border-top-width: 0.0625rem;
border-right-style: solid;
border-right-width: 0.0625rem;
border-bottom-style: solid;
border-bottom-width: 0.0625rem;
border-left-style: none !important;
border-left-width: 0 !important;
&:not(:first-child) {
border-left: 0;
}
img {
width: 1.25rem;
height: 1rem;
cursor: pointer;
}
}
.button-icon {
&.cursor-initial{
cursor: initial !important;
}
&.disabled {
opacity: 0.5;
}
cursor: pointer;
position: absolute;
top: 0.45em;
right: 0.6em;
z-index: 3;
font-size: 1.6em;
line-height: 1em;
&.disabled {
cursor: not-allowed;
pointer-events: none;
}
}
//--- esempio di un template custom -----
//--- le classi successive servono nel caso del template #tpl indicato nel selettore-----
.day {
border-radius: 0 !important;
box-sizing: border-box;
text-align: center;
width: inherit !important;
height: inherit !important;
line-height: 2.6rem !important;
vertical-align: middle;
border-left-width: 1px;
border-left-style: solid;
border-right-width: 0.0625rem;
border-right-style: solid;
border-bottom-width: 0.0625rem;
border-bottom-style: solid;
border-collapse: separate;
border-spacing: 0;
&:hover {
cursor: pointer;
}
}
.icon {
width: 2rem;
height: 2rem;
}
//--- fine template custom -----
}
//fix jira 565
:host(:not(.isp-corporate-mode-wrapper)).ng-invalid.ng-dirty.ng-touched{
.isp-calendar-generic {
& > .form-group {
& > .input-group {
input.form-control {
&:not([disabled]) {
border-width: 0.125rem;
border-style: solid;
&:focus {
border-width: 0.125rem;
border-style: solid;
}
}
}
}
}
}
}
:host(:not(.isp-corporate-mode-wrapper)){
.isp-calendar-generic {
& > .form-group {
& > .input-group {
input.form-control {
font-size: 1rem;
height: 3.125rem;
:host(:not(.isp-unifiedvg-mode-wrapper)) {
padding: 0.375rem 0.75rem 0.375rem 0.625rem;
}
}
}
}
}
}
.d-inline-block {
display: inline-block !important;
&.dropdown-menu {
position: absolute;
left: 0;
display: none;
float: left;
min-width: 10rem;
margin: .125rem 0 0;
font-size: 1rem;
text-align: left;
list-style: none;
background-clip: padding-box;
padding: 0;
top: 1.5rem;
border-radius: 0 !important;
border: none !important;
&.rounded {
border-radius: .25rem;
}
}
}
.padding-top-15 {
padding-top:15px;
}
.padding-top-15:placeholder-shown {
padding-top:0px;
}

View File

@ -0,0 +1,23 @@
export enum NbpCalendarPattern {
GGMMAAAA = 'gg/mm/aaaa',
MMAAAA = 'mm/aaaa',
MMGGAAAA = 'mm/gg/aaaa',
AAAAMMGG = 'aaaa/mm/gg'
}
export enum NbpCalendarPosition {
LEFT = 'left',
RIGHT = 'right',
TOP = 'top',
TOP_LEFT = 'top-left',
TOP_RIGHT = 'top-right',
BOTTOM = 'bottom',
BOTTOM_LEFT = 'bottom-left',
BOTTOM_RIGHT = 'bottom-right'
}
export enum NbpDateSeparator {
DOT = '.',
SLASH = '/',
HYPHEN = '-'
}

View File

@ -0,0 +1,8 @@
import {Injectable} from '@angular/core';
@Injectable()
export class EnabledRangeService {
startDate: any = {};
endDate: any = {};
}

View File

@ -0,0 +1,33 @@
<div class="nbp-fid-calendar-container">
<div class="input-group">
<input #inputElement
type="text"
class="form-control"
[placeholder]="placeholder"
[disabled]="disabled"
[required]="required"
#datepickerInput="rplFidCalendarNOA11Y"
rplFidCalendarNOA11Y
[nbpLabelPattern]="datePattern"
[nbpDateSeparator]="dateSeparator"
[minDate]="minDate"
[maxDate]="maxDate"
[startDate]="startDate"
[placement]="placementPosition"
[showWeekNumbers]="showWeekNumbers"
[showWeekdays]="showWeekdays"
[showNavigation]="showNavigation"
[outsideDays]="outsideDays"
[displayMonths]="displayMonths"
(dateSelect)="onDateSelect($event)"
(navigate)="onDateChange($event)">
<div class="input-group-append">
<button class="btn btn-outline-secondary calendar-button"
type="button"
[disabled]="disabled"
(click)="toggle()">
<i class="fa fa-calendar"></i>
</button>
</div>
</div>
</div>

View File

@ -0,0 +1,91 @@
.nbp-fid-calendar-container {
width: 100%;
position: relative;
.input-group {
width: 100%;
.form-control {
height: 38px;
border-radius: 4px 0 0 4px;
&:focus {
box-shadow: none;
border-color: #80bdff;
}
&:disabled {
background-color: #e9ecef;
cursor: not-allowed;
}
}
.input-group-append {
.calendar-button {
height: 38px;
border-radius: 0 4px 4px 0;
background-color: #f8f9fa;
border-color: #ced4da;
color: #495057;
cursor: pointer;
&:hover:not(:disabled) {
background-color: #e9ecef;
}
&:disabled {
cursor: not-allowed;
opacity: 0.65;
}
i {
font-size: 16px;
}
}
}
}
}
// Personalizzazione del dropdown del datepicker
::ng-deep {
.dropdown-menu {
padding: 10px !important;
border-radius: 4px;
box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
.btn-light {
background-color: #f8f9fa;
border-color: #f8f9fa;
&:hover:not(:disabled) {
background-color: #e9ecef;
border-color: #e9ecef;
}
&.active {
background-color: #007bff;
border-color: #007bff;
color: white;
}
}
.ngb-dp-header {
background-color: #f8f9fa;
border-radius: 4px;
.ngb-dp-navigation-select {
select {
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
border-radius: 3px;
}
}
}
.ngb-dp-day {
&.disabled {
opacity: 0.5;
}
}
}
}

View File

@ -1,571 +1,95 @@
import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, OnInit } from '@angular/core';
import { NgbInputDatepickerNOA11Y } from './@ng-bootstrap-noa11y/datepicker/datepicker-input';
import { AfterViewInit, ChangeDetectorRef, Component, ElementRef, EventEmitter, HostBinding, Inject, Injector, Input, Optional, Output, SimpleChanges, Type, forwardRef } from '@angular/core'; import { NbpCalendarPattern, NbpCalendarPosition, NbpDateSeparator } from './nbp-calendar-generic.enum';
import { NG_ASYNC_VALIDATORS, NG_VALIDATORS, NG_VALUE_ACCESSOR } from '@angular/forms'; import { NgbDateStruct } from './@ng-bootstrap-noa11y/datepicker/ngb-date-struct';
import { EventManager } from '@isp/xdce-arch-core-base';
import { AsyncValidatorArray, FormTouchService, NbpFormContainerComponent, NbpInputElementBase, NbpInputElementBaseComponentA11YWrapper, NbpStyle, ValidatorArray } from '@isp/xdce-widget/base';
import { APPLICATION_CONTEXT_MANAGER, ApplicationContextManagerInterface, EventManager } from '@isp/xdce-arch-core-base';
import { EnabledRangeService, NbpCalendarPattern, NbpDateSeparator, NgbDateStruct } from '@isp/xdce-widget';
import { NbpCalendarGenericComponentA11Y } from './nbp-calendar-generic.component.a11y';
import { NbpCalendarGenericComponentNOA11Y } from './nbp-calendar-generic.component.noa11y';
export const NBP_CALENDAR_CONTROL_VALUE_ACCESSOR: any = {
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => NbpFidCalendarGeneric), // un riferimento al futuro componente corrente
multi: true
};
export const NBP_INPUT_CALENDAR_ELEMENT_BASE: any = {
provide: NbpInputElementBase,
useExisting: forwardRef(() => NbpFidCalendarGeneric), // un riferimento al futuro componente corrente
multi: true
};
@Component({ @Component({
selector : "nbp-fid-calendar-generic", selector: 'nbp-fid-calendar-generic',
template: "<ng-container #componentContainer></ng-container>", templateUrl: './nbp-fid-calendar-generic.component.html',
providers: [ styleUrls: ['./nbp-fid-calendar-generic.component.scss']
NBP_CALENDAR_CONTROL_VALUE_ACCESSOR,
NBP_INPUT_CALENDAR_ELEMENT_BASE,
]
}) })
export class NbpFidCalendarGeneric extends NbpInputElementBaseComponentA11YWrapper<NbpCalendarGenericComponentA11Y, NbpCalendarGenericComponentNOA11Y, any> implements AfterViewInit { export class NbpFidCalendarGenericComponent implements OnInit {
@ViewChild('datepickerInput') datepickerInput: NgbInputDatepickerNOA11Y;
@ViewChild('inputElement') inputElement: ElementRef;
constructor(enabledRange: EnabledRangeService, @Input() placeholder: string = '';
eventManager: EventManager, @Input() disabled: boolean = false;
@Optional() @Inject(NG_VALIDATORS) validatori: ValidatorArray, @Input() required: boolean = false;
@Optional() @Inject(NG_ASYNC_VALIDATORS) asyncValidatori: AsyncValidatorArray, @Input() datePattern: NbpCalendarPattern = NbpCalendarPattern.GGMMAAAA;
@Optional() parentFormContainer: NbpFormContainerComponent, @Input() dateSeparator: NbpDateSeparator = NbpDateSeparator.SLASH;
element: ElementRef, @Input() placementPosition: NbpCalendarPosition = NbpCalendarPosition.BOTTOM;
inj: Injector, @Input() minDate: NgbDateStruct;
@Optional() formTouchService: FormTouchService, @Input() maxDate: NgbDateStruct;
private changeDetectorRef: ChangeDetectorRef, @Input() startDate: NgbDateStruct;
@Inject(APPLICATION_CONTEXT_MANAGER) applicationContext: ApplicationContextManagerInterface) { @Input() showWeekNumbers: boolean = false;
super(validatori, asyncValidatori, inj); @Input() showWeekdays: boolean = true;
} @Input() showNavigation: boolean = true;
ngAfterViewInit(): void { @Input() outsideDays: 'visible' | 'collapsed' | 'hidden' = 'visible';
this.model.valueChanges.subscribe(() => this.changeDetectorRef.detectChanges()); @Input() displayMonths: number = 1;
}
get A11Ycomponent(): Type<NbpCalendarGenericComponentA11Y> {
return NbpCalendarGenericComponentA11Y;
}
get noA11Ycomponent(): Type<NbpCalendarGenericComponentNOA11Y> {
return NbpCalendarGenericComponentNOA11Y;
}
protected modelFromContentChild: boolean = false;
ngOnInit(): void {
super.ngOnInit();
this.model = this.component.model;
}
private _keepDateOnDisabled: boolean = undefined;
@Input()
set keepDateOnDisabled(value: boolean) {
this._keepDateOnDisabled = value;
if (this.component) {
this.component.keepDateOnDisabled = value;
}
}
get keepDateOnDisabled(): boolean {
return this._keepDateOnDisabled;
}
private _nbpModelOptions: {
name?: string,
standalone?: boolean,
updateOn?: 'change'|'blur'|'submit'
} = undefined;
@Input()
set nbpModelOptions(value: {
name?: string,
standalone?: boolean,
updateOn?: 'change'|'blur'|'submit'
}) {
this._nbpModelOptions = value;
if (this.component) {
this.component.nbpModelOptions = value;
}
}
get nbpModelOptions(): {
name?: string,
standalone?: boolean,
updateOn?: 'change'|'blur'|'submit'
} {
return this._nbpModelOptions;
}
private _nbpHighlightedDefault: boolean = undefined;
@Input()
set nbpHighlightedDefault(value: boolean) {
this._nbpHighlightedDefault = value;
if (this.component) {
this.component.nbpHighlightedDefault = value;
}
}
get nbpHighlightedDefault(): boolean {
return this._nbpHighlightedDefault;
}
private _pattern: RegExp = undefined;
@Input()
set pattern(value: RegExp) {
this._pattern = value;
if (this.component) {
this.component.pattern = value;
}
}
get pattern(): RegExp {
return this._pattern;
}
private _name: string = undefined;
@Input()
@HostBinding('attr.name')
set name(value: string) {
this._name = value;
if (this.component) {
this.component.name = value;
}
}
get name(): string {
return this._name;
}
private _nbpDarkBackground: boolean = undefined;
@Input()
set nbpDarkBackground(value: boolean) {
this._nbpDarkBackground = value;
if (this.component) {
this.component.nbpDarkBackground = value;
}
}
get nbpDarkBackground(): boolean {
return this._nbpDarkBackground;
}
private _nbpOutput: boolean = undefined;
@Input()
set nbpOutput(value: boolean) {
this._nbpOutput = value;
if (this.component) {
this.component.nbpOutput = value;
}
}
get nbpOutput(): boolean {
return this._nbpOutput;
}
private _id: string = undefined;
@Input()
set id(value: string) {
this._id = value;
if (this.component) {
this.component.id = value;
}
}
get id(): string {
if(this.component && this._id == undefined){
this._id = this.component.getIdAutonegerato();
}
return this._id;
}
private _nbpShowValidation: boolean= undefined; @Output() dateSelected = new EventEmitter<NgbDateStruct>();
@Input() @Output() dateChanged = new EventEmitter<NgbDateStruct>();
set nbpShowValidation(value: boolean) { @Output() datepickerClosed = new EventEmitter<void>();
this._nbpShowValidation = value;
if (this.component) {
this.component.nbpShowValidation = value;
}
}
get nbpShowValidation(): boolean {
return this._nbpShowValidation;
}
constructor(private eventManager: EventManager) { }
private _placeholder: string = undefined; ngOnInit() {
@Input() // Sottoscrizione all'evento di chiusura del datepicker
set placeholder(value: string) { this.eventManager.subscribeToEvent('DATEPICKER_CLOSE', () => {
this._placeholder = value; this.datepickerClosed.emit();
if (this.component) { });
this.component.placeholder = value;
}
} }
get placeholder(): string {
return this._placeholder;
}
private _nbpErrorMessage: string = undefined; /**
@Input() * Apre il datepicker
set nbpErrorMessage(value: string) { */
this._nbpErrorMessage = value; open() {
if (this.component) { if (this.datepickerInput && !this.disabled) {
this.component.nbpErrorMessage = value; this.datepickerInput.open(true);
}
} }
get nbpErrorMessage(): string {
return this._nbpErrorMessage;
} }
/**
private _showErrorLabel: boolean = undefined; * Chiude il datepicker
@Input() */
set showErrorLabel(value: boolean) { close() {
this._showErrorLabel = value; if (this.datepickerInput) {
if (this.component) { this.datepickerInput.close();
this.component.showErrorLabel = value;
}
} }
get showErrorLabel(): boolean {
return this._showErrorLabel;
} }
/**
private _maxDate: Date = undefined; * Alterna l'apertura e la chiusura del datepicker
@Input() */
set maxDate(value: Date) { toggle() {
this._maxDate = value; if (this.datepickerInput && !this.disabled) {
if (this.component) { this.datepickerInput.toggle(true);
this.component.maxDate = value;
} }
} }
get maxDate(): Date {
return this._maxDate;
}
private _minDate: Date = undefined; /**
@Input() * Gestisce l'evento di selezione della data
set minDate(value: Date) { * @param date La data selezionata
this._minDate = value; */
if (this.component) { onDateSelect(date: NgbDateStruct) {
this.component.minDate = value; this.dateSelected.emit(date);
}
} }
get minDate(): Date {
return this._minDate;
}
private _startDateEnabled: NgbDateStruct = undefined; /**
@Input() * Gestisce l'evento di modifica della data
set startDateEnabled(value: NgbDateStruct) { * @param date La nuova data
this._startDateEnabled = value; */
if (this.component) { onDateChange(date: NgbDateStruct) {
this.component.startDateEnabled = value; this.dateChanged.emit(date);
}
} }
get startDateEnabled(): NgbDateStruct {
return this._startDateEnabled;
}
private _endDateEnabled: NgbDateStruct = undefined; /**
@Input() * Imposta il focus sull'input
set endDateEnabled(value: NgbDateStruct) { */
this._endDateEnabled = value; focus() {
if (this.component) { if (this.inputElement) {
this.component.endDateEnabled = value; this.inputElement.nativeElement.focus();
} }
} }
get endDateEnabled(): NgbDateStruct {
return this._endDateEnabled;
}
private _disabled: boolean = undefined;
@Input()
set disabled(value: boolean) {
this._disabled = value;
if (this.component) {
this.component.disabled = value;
}
}
get disabled(): boolean {
return this._disabled;
}
private _required: boolean = undefined;
@Input()
set required(value: boolean) {
this._required = value;
if (this.component) {
this.component.required = value;
}
}
get required(): boolean {
return this._required;
}
private _nbpStyle: NbpStyle = undefined;
@Input()
set nbpStyle(value: NbpStyle) {
this._nbpStyle = value;
if (this.component) {
this.component.nbpStyle = value;
}
}
get nbpStyle(): NbpStyle {
return this._nbpStyle;
}
private __type: string = undefined;
@Input()
set _type(value: string) {
this.__type = value;
if (this.component) {
this.component._type = value;
}
}
get _type(): string {
return this.__type;
}
private _disabledWeekend: boolean = undefined;
@Input()
set disabledWeekend(value: boolean) {
this._disabledWeekend = value;
if (this.component) {
this.component.disabledWeekend = value;
}
}
get disabledWeekend(): boolean {
return this._disabledWeekend;
}
private _holidays: Array<NgbDateStruct> = undefined;
@Input()
set holidays(value: Array<NgbDateStruct>) {
this._holidays = value;
if (this.component) {
this.component.holidays = value;
}
}
get holidays(): Array<NgbDateStruct> {
return this._holidays;
}
private _taxDeadlines: Array<NgbDateStruct> = undefined;
@Input()
set taxDeadlines(value: Array<NgbDateStruct>) {
this._taxDeadlines = value;
if (this.component) {
this.component.taxDeadlines = value;
}
}
get taxDeadlines(): Array<NgbDateStruct> {
return this._taxDeadlines;
}
private _firstFocus: boolean = undefined;
@Input()
set firstFocus(value: boolean) {
this._firstFocus = value;
if (this.component) {
this.component.firstFocus = value;
}
}
get firstFocus(): boolean {
return this._firstFocus;
}
private _focusOn: boolean = undefined;
@Input()
set focusOn(value: boolean) {
this._focusOn = value;
if (this.component) {
this.component.focusOn = value;
}
}
get focusOn(): boolean {
return this._focusOn;
}
private _tabindex: undefined = undefined;
@Input()
set tabindex(value: undefined) {
this._tabindex = value;
if (this.component) {
this.component.tabindex = value;
}
}
get tabindex(): undefined {
return this._tabindex;
}
private _label: string = undefined;
@Input()
set label(value: string) {
this._label = value;
if (this.component) {
this.component.label = value;
}
}
get label(): string {
return this._label;
}
private _ariaLabel: string = undefined;
@Input()
set ariaLabel(value: string) {
this._ariaLabel = value;
if (this.component) {
this.component.ariaLabel = value;
}
}
get ariaLabel(): string {
return this._ariaLabel;
}
private _nbpLightMode: boolean = undefined;
@Input()
set nbpLightMode(value: boolean) {
this._nbpLightMode = value;
if (this.component) {
this.component.nbpLightMode = value;
}
}
get nbpLightMode(): boolean {
return this._nbpLightMode;
}
private _nbpLabelPattern: NbpCalendarPattern = undefined;
@Input()
set nbpLabelPattern(value: NbpCalendarPattern) {
this._nbpLabelPattern = value;
if (this.component) {
this.component.nbpLabelPattern = value;
}
}
get nbpLabelPattern(): NbpCalendarPattern {
return this._nbpLabelPattern;
}
private _nbpDateSeparator: NbpDateSeparator = undefined;
@Input()
set nbpDateSeparator(value: NbpDateSeparator) {
this._nbpDateSeparator = value;
if (this.component) {
this.component.nbpDateSeparator = value;
}
}
get nbpDateSeparator(): NbpDateSeparator {
return this._nbpDateSeparator;
}
private _opened: boolean = undefined;
@Input()
set opened(value: boolean) {
this._opened = value;
if (this.component) {
this.component.opened = value;
}
}
get opened(): boolean {
return this._opened;
}
private _nbpPlacement: string = undefined;
@Input()
set nbpPlacement(value: string) {
this._nbpPlacement = value;
if (this.component) {
this.component.nbpPlacement = value;
}
}
get nbpPlacement(): string {
return this._nbpPlacement;
}
private _enableDefaultViewOnUnifiedVG: boolean = undefined;
@Input()
set enableDefaultViewOnUnifiedVG(value: boolean) {
this._enableDefaultViewOnUnifiedVG = value;
if (this.component) {
this.component.enableDefaultViewOnUnifiedVG = value;
}
}
get enableDefaultViewOnUnifiedVG(): boolean {
return this._enableDefaultViewOnUnifiedVG;
}
private _enableDynamicPosition: boolean = undefined;
@Input()
set enableDynamicPosition(value: boolean) {
this._enableDynamicPosition = value;
if (this.component) {
this.component.enableDynamicPosition = value;
}
}
get enableDynamicPosition(): boolean {
return this._enableDynamicPosition;
}
@Output() nbpOnNavigate = new EventEmitter<{ current: any, next: any }>();
@Output() modelChange = new EventEmitter<any>();
@Output() focus = new EventEmitter<boolean>();
get rplCalendar() {
return this.component.rplCalendar;
}
_ngbModelChanged(event: NgbDateStruct) {
return this.component ? this.component._ngbModelChanged(event): undefined;
}
getCalendarWidth() {
return this.component.getCalendarWidth();
}
getCalendarHeight() {
return this.component.getCalendarHeight();
}
public handleCalendar($event) {
return this.component.handleCalendar($event);
}
public setAriaLabel(date: any) {
return this.component.setAriaLabel(date);
}
public setSpanLabel(date){
return this.component.setSpanLabel(date);
}
public focusOutComponent(event: any){
return this.component.focusOutComponent(event);
}
} }

View File

@ -53,30 +53,36 @@
<p class="new-part">Calendar generic (nbp-input-container + nbp-calendar-generic)</p> <p class="new-part">Calendar generic (nbp-input-container + nbp-calendar-generic)</p>
<div> <div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'"> <nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-fid-calendar-generic [id]="'calendarDefault'" [name]="'calendarDefault'" [nbpStyle]="_nbpStyle.DEFAULT" <nbp-calendar-generic [id]="'calendarDefault'" [name]="'calendarDefault'" [nbpStyle]="_nbpStyle.DEFAULT"
[nbpPlacement]="_nbpCalendarPosition.BOTTOM_LEFT" [nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA" [nbpPlacement]="_nbpCalendarPosition.BOTTOM_LEFT" [nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA"
[(ngModel)]="calendarModel"> [(ngModel)]="calendarModel">
</nbp-fid-calendar-generic> </nbp-calendar-generic>
</nbp-input-container> </nbp-input-container>
</div> </div>
<div> <div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'"> <nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-fid-calendar-generic [id]="'calendarConstrainedDateInterval'" [name]="'calendarConstrainedDateInterval'" <nbp-calendar-generic [id]="'calendarConstrainedDateInterval'" [name]="'calendarConstrainedDateInterval'"
[nbpStyle]="_nbpStyle.DEFAULT" [nbpPlacement]="_nbpCalendarPosition.BOTTOM_RIGHT" [nbpStyle]="_nbpStyle.DEFAULT" [nbpPlacement]="_nbpCalendarPosition.BOTTOM_RIGHT"
[nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA" [(ngModel)]="calendarModel" [nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA" [(ngModel)]="calendarModel"
[startDateEnabled]="startDate" [endDateEnabled]="endDate"> [startDateEnabled]="startDate" [endDateEnabled]="endDate">
</nbp-fid-calendar-generic> </nbp-calendar-generic>
</nbp-input-container> </nbp-input-container>
</div> </div>
<div> <div>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'"> <nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-fid-calendar-generic [id]="'calendarConstrainedDateInterval'" [name]="'calendarConstrainedDateInterval'" <nbp-calendar-generic [id]="'calendarConstrainedDateInterval'" [name]="'calendarConstrainedDateInterval'"
[nbpStyle]="_nbpStyle.DEFAULT" [nbpPlacement]="_nbpCalendarPosition.BOTTOM_RIGHT" [disabled]="true" [nbpStyle]="_nbpStyle.DEFAULT" [nbpPlacement]="_nbpCalendarPosition.BOTTOM_RIGHT" [disabled]="true"
[nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA" [(ngModel)]="calendarModel" [nbpLabelPattern]="_nbpCalendarPattern.GGMMAAAA" [(ngModel)]="calendarModel"
[startDateEnabled]="startDate" [endDateEnabled]="endDate"> [startDateEnabled]="startDate" [endDateEnabled]="endDate">
</nbp-fid-calendar-generic> </nbp-calendar-generic>
</nbp-input-container> </nbp-input-container>
</div> </div>
<div>
<nbp-fid-calendar-generic [placeholder]="'Seleziona data'" [datePattern]="_nbpCalendarPattern.GGMMAAAA"
[dateSeparator]="_nbpDateSeparator.SLASH" [placementPosition]="_nbpCalendarPosition.BOTTOM"
(dateSelected)="onDateSelect($event)">
</nbp-fid-calendar-generic>
</div>
<p class="new-part">Combo (nbp-input-container + nbp-combo)</p> <p class="new-part">Combo (nbp-input-container + nbp-combo)</p>
<div> <div>
@ -87,7 +93,8 @@
</nbp-input-container> </nbp-input-container>
<nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'"> <nbp-input-container [nbpStyle]="_nbpStyle.DEFAULT" [nbpLabel]="'Default'">
<nbp-combo [id]="'comboDefault'" [name]="'comboDefault'" [nbpStyle]="_nbpStyle.DEFAULT" <nbp-combo [id]="'comboDefault'" [name]="'comboDefault'" [nbpStyle]="_nbpStyle.DEFAULT"
[nbpDataSource]="comboDatasource" [(ngModel)]="comboSelectedValue" [nbpShowEmptyValue]="true" [disabled]="true"> [nbpDataSource]="comboDatasource" [(ngModel)]="comboSelectedValue" [nbpShowEmptyValue]="true"
[disabled]="true">
</nbp-combo> </nbp-combo>
</nbp-input-container> </nbp-input-container>
</div> </div>
@ -149,8 +156,7 @@
[nbpDataSource]="tableDs" [nbpAutoBind]="true" [nbpSelectionType]="tableSelectionType" [nbpDataSource]="tableDs" [nbpAutoBind]="true" [nbpSelectionType]="tableSelectionType"
[nbpLayoutAuto]="true"> [nbpLayoutAuto]="true">
<nbp-table-column nbpId='headerField' nbpTitle='Header field' nbpField='headerField' <nbp-table-column nbpId='headerField' nbpTitle='Header field' nbpField='headerField' [nbpVisible]='true'>
[nbpVisible]='true'>
</nbp-table-column> </nbp-table-column>
<nbp-table-column nbpId='headerField2' nbpTitle='Header field 2' nbpField='headerField2' <nbp-table-column nbpId='headerField2' nbpTitle='Header field 2' nbpField='headerField2'
@ -171,12 +177,12 @@
[nbpDataSource]="campiStandardData" ariaLabel="multi selection table" [nbpAutoBind]="true" [nbpDataSource]="campiStandardData" ariaLabel="multi selection table" [nbpAutoBind]="true"
[nbpSelectionType]="multi"> [nbpSelectionType]="multi">
<nbp-table-column nbpId='headerField' nbpTitle='Header field' nbpField='headerField' <nbp-table-column nbpId='headerField' nbpTitle='Header field' nbpField='headerField' [nbpSortable]='true'
[nbpSortable]='true' [nbpVisible]='true'> [nbpVisible]='true'>
</nbp-table-column> </nbp-table-column>
<nbp-table-column nbpId='headerField2' nbpTitle='Header field 2' nbpField='headerField2' <nbp-table-column nbpId='headerField2' nbpTitle='Header field 2' nbpField='headerField2' [nbpSortable]='true'
[nbpSortable]='true' [nbpVisible]='true'> [nbpVisible]='true'>
</nbp-table-column> </nbp-table-column>
</nbp-table> </nbp-table>