File

projects/rebirth-ng/src/lib/time-picker/time-picker.component.ts

Implements

OnInit ControlValueAccessor

Metadata

exportAs timePicker
providers { : , : (() => ), : true }
selector re-time-picker
styleUrls time-picker.component.scss
templateUrl ./time-picker.component.html

Index

Properties
Methods
Inputs

Constructor

constructor(changeDetectorRef: ChangeDetectorRef)
Parameters :
Name Type Optional
changeDetectorRef ChangeDetectorRef no

Inputs

maxTime

Type: TimePickerModel

Default value: new TimePickerModel(23, 59, 59)

minTime

Type: TimePickerModel

Default value: new TimePickerModel(0, 0, 0)

showSeconds

Default value: true

Methods

getCurrentTimestamp
getCurrentTimestamp(time: )
Parameters :
Name Optional
time no
Returns : number
getDateByTime
getDateByTime(time: TimePickerModel)
Parameters :
Name Type Optional
time TimePickerModel no
Returns : any
Private getTimePickerModel
getTimePickerModel()
Returns : TimePickerModel
getValue
getValue(value: , defaultValue: )
Parameters :
Name Optional
value no
defaultValue no
Returns : any
handleKeyEvent
handleKeyEvent(event: , type: )
Parameters :
Name Optional
event no
type no
Returns : void
initConditionDate
initConditionDate()
Returns : void
isSafetyKeyPress
isSafetyKeyPress(keyType: any, target: string, key: string)
Parameters :
Name Type Optional
keyType any no
target string no
key string no
Returns : boolean
isSupportedKeyPress
isSupportedKeyPress(event: )
Parameters :
Name Optional
event no
Returns : boolean
modifyTimeByKey
modifyTimeByKey(value: number, key: string)
Parameters :
Name Type Optional
value number no
key string no
Returns : void
modifyTimeByKeyPress
modifyTimeByKeyPress(key: string, type: string, step: number)
Parameters :
Name Type Optional
key string no
type string no
step number no
Returns : void
modifyTimeByKeyPressEvent
modifyTimeByKeyPressEvent(type: string, keyEventType: string)
Parameters :
Name Type Optional
type string no
keyEventType string no
Returns : void
ngOnInit
ngOnInit()
Returns : void
onModelChange
onModelChange()
Returns : void
onTimeChange
onTimeChange(key: string)
Parameters :
Name Type Optional
key string no
Returns : void
registerOnChange
registerOnChange(fn: )
Parameters :
Name Optional
fn no
Returns : void
registerOnTouched
registerOnTouched(fn: )
Parameters :
Name Optional
fn no
Returns : void
setDisabledState
setDisabledState(disabled: )
Parameters :
Name Optional
disabled no
Returns : void
updateTimeByMargin
updateTimeByMargin(key: string, marginDate: )
Parameters :
Name Type Optional
key string no
marginDate no
Returns : void
writeValue
writeValue(value: TimePickerModel)
Parameters :
Name Type Optional
value TimePickerModel no
Returns : void

Properties

disabled
disabled: boolean
Type : boolean
hour
hour: string
Type : string
Default value : '00'
maxDate
maxDate: Date
Type : Date
minDate
minDate: Date
Type : Date
minute
minute: string
Type : string
Default value : '00'
Private onChange
onChange:
Default value : (_: TimePickerModel) => null
Private onTouched
onTouched:
Default value : () => null
second
second: string
Type : string
Default value : '00'
timeUnit
timeUnit:
Default value : TIME_UNIT
import { ChangeDetectorRef, Component, forwardRef, Input, OnInit } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { keyBoardHelper } from '../utils/keyboard-utils';

function fillLeft(num: number) {
  return (num || 0) < 10 ? `0${num}` : `${num}`;
}

const ARROW_DOWN = 'ArrowDown';
const ARROW_UP = 'ArrowUp';
const supportKeyType = [ARROW_UP, ARROW_DOWN];

export class TimePickerModel {

  constructor(public  hour: number, public  minute: number, public second?: number) {

  }

  toString() {
    return `${fillLeft(this.hour)}:${fillLeft(this.minute)}:${fillLeft(this.second)}`;
  }
}

const BACKSPACE_KEY_CODE = 8;
const ENTER_KEY_CODE = 13;
const TAB_KEY_CODE = 9;
const SUPPORTED_KEY_CODE = [
  BACKSPACE_KEY_CODE,
  ENTER_KEY_CODE,
  TAB_KEY_CODE
];

export const TIME_UNIT = {
  HOUR: 'hour',
  MINUTE: 'minute',
  SECOND: 'second',
};

export const MAX_TIME_RANGE = {
  hour: 23,
  minute: 59,
  second: 59,
};

@Component({
  selector: 're-time-picker',
  styleUrls: ['./time-picker.component.scss'],
  templateUrl: './time-picker.component.html',
  exportAs: 'timePicker',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => TimePickerComponent),
      multi: true
    }
  ]
})
export class TimePickerComponent implements OnInit, ControlValueAccessor {
  @Input() showSeconds = true;
  @Input() minTime = new TimePickerModel(0, 0, 0);
  @Input() maxTime = new TimePickerModel(23, 59, 59);

  hour = '00';
  minute = '00';
  second = '00';

  timeUnit = TIME_UNIT;
  minDate: Date;
  maxDate: Date;

  disabled: boolean;
  private onChange = (_: TimePickerModel) => null;
  private onTouched = () => null;

  constructor(private changeDetectorRef: ChangeDetectorRef) {
  }

  ngOnInit(): void {
    this.initConditionDate();
  }

  initConditionDate() {
    this.minDate = this.getDateByTime(this.minTime);
    this.maxDate = this.getDateByTime(this.maxTime);
  }

  getDateByTime(time: TimePickerModel) {
    return new Date((new Date()).setHours(time.hour || 0, time.minute || 0, time.second || 0));
  }

  getValue(value, defaultValue) {
    if (value || value === 0) {
      return value;
    }
    return defaultValue;
  }

  getCurrentTimestamp(time): number {
    const hour = this.getValue(time.hour, parseInt(this.hour, 10));
    const minute = this.getValue(time.minute, parseInt(this.minute, 10));
    const second = this.getValue(time.second, parseInt(this.second, 10));

    return (new Date()).setHours(hour, minute, second);
  }

  writeValue(value: TimePickerModel) {
    if (value) {
      this.hour = fillLeft(value.hour || 0);
      this.minute = fillLeft(value.minute || 0);
      this.second = fillLeft(value.second || 0);
      this.changeDetectorRef.markForCheck();
    }
  }

  registerOnChange(fn) {
    this.onChange = fn;
  }

  registerOnTouched(fn) {
    this.onTouched = fn;
  }

  setDisabledState(disabled) {
    this.disabled = disabled;
    this.changeDetectorRef.markForCheck();
  }

  updateTimeByMargin(key: string, marginDate) {
    switch (key) {
      case TIME_UNIT.HOUR:
        this.hour = fillLeft(marginDate[TIME_UNIT.HOUR]);
        this.minute = fillLeft(marginDate[TIME_UNIT.MINUTE]);
        if (marginDate[TIME_UNIT.SECOND]) {
          this.second = fillLeft(marginDate[TIME_UNIT.SECOND]);
        }
        break;
      case TIME_UNIT.MINUTE:
        this.minute = fillLeft(marginDate[TIME_UNIT.MINUTE]);
        if (marginDate[TIME_UNIT.SECOND]) {
          this.second = fillLeft(marginDate[TIME_UNIT.SECOND]);
        }
        break;
      case TIME_UNIT.SECOND:
        this.second = fillLeft(marginDate[TIME_UNIT.SECOND]);
        break;
    }
  }

  modifyTimeByKey(value: number, key: string) {
    if (isNaN(value)) {
      if (this.getCurrentTimestamp({ [key]: 0 }) < this.minDate.getTime()) {
        this.updateTimeByMargin(key, this.minTime);
      } else if (this.getCurrentTimestamp({ [key]: 0 }) > this.maxDate.getTime()) {
        this.updateTimeByMargin(key, this.maxTime);
      } else {
        this.updateTimeByMargin(key, this.minTime);
      }
    } else if (value < 0) {
      this[key] = fillLeft(0) || fillLeft(this.minTime[key]);
    } else if (value > MAX_TIME_RANGE[key] || this.getCurrentTimestamp({ [key]: value }) > this.maxDate.getTime()) {
      this.updateTimeByMargin(key, this.maxTime);
    } else if (this.getCurrentTimestamp({ [key]: value }) < this.minDate.getTime()) {
      this.updateTimeByMargin(key, this.minTime);
    } else {
      this[key] = fillLeft(value);
    }
  }

  onTimeChange(key: string) {
    this.onTouched();
    this.modifyTimeByKey(parseInt(this[key], 10), key);
    this.onModelChange();
  }

  onModelChange() {
    this.onChange(this.getTimePickerModel());
  }

  private getTimePickerModel() {
    const model = new TimePickerModel(parseInt(this.hour, 10), parseInt(this.minute, 10));
    if (this.showSeconds) {
      model.second = parseInt(this.second, 10);
    }
    return model;
  }

  isSafetyKeyPress(keyType: any, target: string, key: string) {
    const parsedTarget = parseInt(target, 10);
    return !(keyType === ARROW_DOWN && parsedTarget < 1) &&
      (
        (keyType === ARROW_DOWN && key === TIME_UNIT.HOUR && parsedTarget <= MAX_TIME_RANGE.hour) ||
        (keyType === ARROW_DOWN && (key === TIME_UNIT.MINUTE || key === TIME_UNIT.SECOND) && parsedTarget <= MAX_TIME_RANGE.minute) ||
        (keyType === ARROW_UP && key === TIME_UNIT.HOUR && parsedTarget < MAX_TIME_RANGE.hour) ||
        (keyType === ARROW_UP && (key === TIME_UNIT.MINUTE || key === TIME_UNIT.SECOND) && parsedTarget < MAX_TIME_RANGE.minute)
      );
  }

  isSupportedKeyPress(event): boolean {
    return SUPPORTED_KEY_CODE.indexOf(event.keyCode) > -1 ||
      keyBoardHelper.numberKeyBoard(event) ||
      keyBoardHelper.smallKeyBoard(event) ||
      keyBoardHelper.arrowKeyBoard(event);
  }

  handleKeyEvent(event, type) {
    if (!this.isSupportedKeyPress(event)) {
      event.preventDefault();
      return;
    }
    const keyEventType = event.code;
    if (supportKeyType.indexOf(keyEventType) === -1) {
      return;
    }
    this.modifyTimeByKeyPressEvent(type, keyEventType);
  }

  modifyTimeByKeyPress(key: string, type: string, step: number) {
    if (this.isSafetyKeyPress(type, this[key], key)) {
      this[key] = fillLeft(parseInt(this[key], 10) + step);
    }
  }

  modifyTimeByKeyPressEvent(type: string, keyEventType: string) {
    let step = 1;
    if (keyEventType === ARROW_DOWN) {
      step = -1;
    }
    switch (type) {
      case this.timeUnit.HOUR:
        this.modifyTimeByKeyPress(TIME_UNIT.HOUR, keyEventType, step);
        break;
      case this.timeUnit.MINUTE:
        this.modifyTimeByKeyPress(TIME_UNIT.MINUTE, keyEventType, step);
        break;
      case this.timeUnit.SECOND:
        this.modifyTimeByKeyPress(TIME_UNIT.SECOND, keyEventType, step);
        break;
    }
  }
}

<form class="form-inline time-picker">
  <div class="form-group">
    <input type="text"
           #hours
           [disabled]="disabled"
           name="hours"
           class="form-control"
           maxlength="2"
           max="23"
           min="0"
           autocomplete="off"
           [(ngModel)]="hour"
           (keydown)="handleKeyEvent($event, timeUnit.HOUR)"
           (blur)="onTimeChange(timeUnit.HOUR)">
  </div>
  <span>:</span>
  <div class="form-group">
    <input type="text"
           #minutes
           [disabled]="disabled"
           name="minutes"
           class="form-control"
           maxlength="2"
           max="59"
           min="0"
           autocomplete="off"
           [(ngModel)]="minute"
           (keydown)="handleKeyEvent($event, timeUnit.MINUTE)"
           (blur)="onTimeChange(timeUnit.MINUTE)">
  </div>
  <ng-container *ngIf="showSeconds">
    <span>:</span>
    <div class="form-group">
      <input type="text"
             #seconds
             [disabled]="disabled"
             name="seconds"
             class="form-control"
             max="59"
             min="0"
             maxlength="2"
             autocomplete="off"
             [(ngModel)]="second"
             (keydown)="handleKeyEvent($event, timeUnit.SECOND)"
             (blur)="onTimeChange(timeUnit.SECOND)">
    </div>
  </ng-container>
</form>
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""