# All files / src/app/shared/directives dimless-binary.directive.ts

87.18% Statements 34/39
69.23% Branches 18/26
80% Functions 4/5
86.11% Lines 31/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    12392x

    92x

    92x

    92x
    92x

    92x

    92x

    92x

    92x

    92x

    92x

    23x
    23x
    23x
    23x

    23x

    92x
    21x

    92x

    2x

    21x
    21x
    21x

    16x
    16x

    5x
    5x

    92x

    21x

    184x

    92x
     import {
      Directive,
      ElementRef,
      EventEmitter,
      HostListener,
      Input,
      OnInit,
      Output
    } from '@angular/core';
    import { NgControl } from '@angular/forms';

    import * as _ from 'lodash';

    import { DimlessBinaryPipe } from '../pipes/dimless-binary.pipe';
    import { FormatterService } from '../services/formatter.service';

    @Directive({
      selector: '[cdDimlessBinary]'
    })
    export class DimlessBinaryDirective implements OnInit {
      @Output()
      ngModelChange: EventEmitter<any> = new EventEmitter();

      /**
       * Minimum size in bytes.
       * If user enter a value lower than <minBytes>,
       * the model will automatically be update to <minBytes>.
       *
       * If <roundPower> is used, this value should be a power of <roundPower>.
       *
       * Example:
       *   Given minBytes=4096 (4KiB), if user type 1KiB, then model will be updated to 4KiB
       */
      @Input()
      minBytes: number;

      /**
       * Maximum size in bytes.
       * If user enter a value greater than <maxBytes>,
       * the model will automatically be update to <maxBytes>.
       *
       * If <roundPower> is used, this value should be a power of <roundPower>.
       *
       * Example:
       *   Given maxBytes=3145728 (3MiB), if user type 4MiB, then model will be updated to 3MiB
       */
      @Input()
      maxBytes: number;

      /**
       * Value will be rounded up the nearest power of <roundPower>
       *
       * Example:
       *   Given roundPower=2, if user type 7KiB, then model will be updated to 8KiB
       *   Given roundPower=2, if user type 5KiB, then model will be updated to 4KiB
       */
      @Input()
      roundPower: number;

      /**
       * Default unit that should be used when user do not type a unit.
       * By default, "MiB" will be used.
       *
       * Example:
       *   Given defaultUnit=null, if user type 7, then model will be updated to 7MiB
       *   Given defaultUnit=k, if user type 7, then model will be updated to 7KiB
       */
      @Input()
      defaultUnit: string;

      private el: HTMLInputElement;

      constructor(
        private elementRef: ElementRef,
        private control: NgControl,
        private dimlessBinaryPipe: DimlessBinaryPipe,
        private formatter: FormatterService
      ) {
        this.el = this.elementRef.nativeElement;
      }

      ngOnInit() {
        this.setValue(this.el.value);
      }

      setValue(value) {
        if (/^[\d.]+$/.test(value)) {
          value += this.defaultUnit || 'm';
        }
        const size = this.formatter.toBytes(value);
        const roundedSize = this.round(size);
        this.el.value = this.dimlessBinaryPipe.transform(roundedSize);
        if (size !== null) {
          this.ngModelChange.emit(this.el.value);
          this.control.control.setValue(this.el.value);
        } else {
          this.ngModelChange.emit(null);
          this.control.control.setValue(null);
        }
      }

      round(size) {
        if (size !== null && size !== 0) {
          if (!_.isUndefined(this.minBytes) && size < this.minBytes) {
            return this.minBytes;
          }
          if (!_.isUndefined(this.maxBytes) && size > this.maxBytes) {
            return this.maxBytes;
          }
          if (!_.isUndefined(this.roundPower)) {
            const power = Math.round(Math.log(size) / Math.log(this.roundPower));
            return Math.pow(this.roundPower, power);
          }
        }
        return size;
      }

      @HostListener('blur', ['$event.target.value'])
      onBlur(value) {
        this.setValue(value);
      }
    }