<commit_before>﻿import {
  AfterViewInit,
  Component,
  ElementRef,
  EventEmitter,
  HostBinding,
  Input,
  OnDestroy,
  Output,
  Provider,
  Renderer2,
  ViewChild,
  ViewEncapsulation,
  forwardRef
} from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { MDCTextfieldAdapter } from './textfield-adapter';

const { MDCTextfieldFoundation } = require('@material/textfield');
const MDC_TEXTFIELD_STYLES = require('@material/textfield/mdc-textfield.scss');

export const MD_TEXTFIELD_CONTROL_VALUE_ACCESSOR: Provider = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => TextfieldComponent),
  multi: true
};

type UnlistenerMap = WeakMap<EventListener, Function>;

@Component({
  selector: 'mdc-textfield',
  templateUrl: './textfield.html',
  styles: [String(MDC_TEXTFIELD_STYLES)],
  encapsulation: ViewEncapsulation.None,
  providers: [MD_TEXTFIELD_CONTROL_VALUE_ACCESSOR]
})
export class TextfieldComponent implements AfterViewInit, OnDestroy {
  @Input() id: string;
  @Input() type: string = 'text';
  @Input() value: string;
  @Input() disabled: 'disabled';
  @Input() required: 'required';
  @Input() labelId: string;
  @Input() label: string;
  @Input() placeholder: string;
  @Input() tabindex: number;
  @Input() rows: number;
  @Input() cols: number;
  @Input() maxlength: number;
  @Input() fullwidth: boolean;
  @Input() multiline: boolean;
  @Output() focus: EventEmitter<FocusEvent> = new EventEmitter<FocusEvent>();
  @Output() blur: EventEmitter<FocusEvent> = new EventEmitter<FocusEvent>();
  @Output() input: EventEmitter<Event> = new EventEmitter<Event>();
  @Output() keydown: EventEmitter<KeyboardEvent> = new EventEmitter<KeyboardEvent>();
  @HostBinding('class') className: string = 'mdc-textfield';
  @HostBinding('class.mdc-textfield--multiline') get classMultiline(): string {
    return this.multiline ? 'mdc-textfield--multiline' : '';
  }
  @HostBinding('class.mdc-textfield--fullwidth') get classFullwidth(): string {
    return this.fullwidth ? 'mdc-textfield--fullwidth' : '';
  }
  @ViewChild('input') public inputEl: ElementRef;

  onTouched: () => any = () => { };

  private _controlValueAccessorChangeFn: (value: any) => void = (value) => { };
  private _unlisteners: Map<string, UnlistenerMap> = new Map<string, UnlistenerMap>();

  private _mdcAdapter: MDCTextfieldAdapter = {
    addClass: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      renderer.addClass(root.nativeElement, className);
    },
    removeClass: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      renderer.removeClass(root.nativeElement, className);
    },
    addClassToLabel: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (this.label) {
        renderer.addClass(root.nativeElement.lastChild, className);
      }
    },
    removeClassFromLabel: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (this.label) {
        renderer.removeClass(root.nativeElement.lastChild, className);
      }
    },
    addClassToHelptext: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (root.nativeElement.attributes.getNamedItem('aria-controls')) {
        if (root.nativeElement.nextElementSibling) {
          renderer.addClass(root.nativeElement.nextElementSibling, className);
        }
      }
    },
    removeClassFromHelptext: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (root.nativeElement.attributes.getNamedItem('aria-controls')) {
        renderer.removeClass(root.nativeElement.nextElementSibling, className);
      }
    },
    registerInputFocusHandler: (handler: EventListener) => {
      if (this._root) {
        this.listen_('focus', handler, this.inputEl);
      }
    },
    deregisterInputFocusHandler: (handler: EventListener) => {
      this.unlisten_('focus', handler);
    },
    registerInputBlurHandler: (handler: EventListener) => {
      if (this._root) {
        this.listen_('blur', handler, this.inputEl);
      }
    },
    deregisterInputBlurHandler: (handler: EventListener) => {
      this.unlisten_('blur', handler);
    },
    registerInputInputHandler: (handler: EventListener) => {
      if (this._root) {
        this.listen_('input', handler, this.inputEl);
      }
    },
    deregisterInputInputHandler: (handler: EventListener) => {
      this.unlisten_('input', handler);
    },
    registerInputKeydownHandler: (handler: EventListener) => {
      if (this._root) {
        this.listen_('keydown', handler, this.inputEl);
      }
    },
    deregisterInputKeydownHandler: (handler: EventListener) => {
      this.unlisten_('keydown', handler);
    },
    setHelptextAttr: (name: string, value: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (root.nativeElement.attributes.getNamedItem('aria-controls')) {
        root.nativeElement.nextElementSibling ? renderer.setAttribute(root.nativeElement.nextElementSibling, name, value) : null;
      }
    },
    removeHelptextAttr: (name: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (root.nativeElement.attributes.getNamedItem('aria-controls')) {
        return root.nativeElement.nextElementSibling ? renderer.removeAttribute(root.nativeElement.nextElementSibling, name) : null;
      }
    },
    helptextHasClass: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (root.nativeElement.attributes.getNamedItem('aria-controls')) {
        return root.nativeElement.nextElementSibling ? root.nativeElement.nextElementSibling.classList.contains(className) : false;
      }
    },
    getNativeInput: () => {
      return {
        checkValidity: () => this.inputEl.nativeElement.checkValidity(),
        value: this.value,
        disabled: this.disabled,
        badInput: this.inputEl.nativeElement.validity.badInput
      };
    }
  };

  private _foundation: {
    init: Function,
    destroy: Function
  } = new MDCTextfieldFoundation(this._mdcAdapter);

  constructor(private _renderer: Renderer2, private _root: ElementRef) { }

  ngAfterViewInit() {
    this._foundation.init();
  }
  ngOnDestroy() {<commit_msg>feat(textfield): Add disabled @Input using Foundation API<commit_after>﻿import {
  AfterViewInit,
  Component,
  ElementRef,
  EventEmitter,
  HostBinding,
  Input,
  OnDestroy,
  Output,
  Provider,
  Renderer2,
  ViewChild,
  ViewEncapsulation,
  forwardRef
} from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';
import { MDCTextfieldAdapter } from './textfield-adapter';

const { MDCTextfieldFoundation } = require('@material/textfield');
const MDC_TEXTFIELD_STYLES = require('@material/textfield/mdc-textfield.scss');

export const MD_TEXTFIELD_CONTROL_VALUE_ACCESSOR: Provider = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => TextfieldComponent),
  multi: true
};

type UnlistenerMap = WeakMap<EventListener, Function>;

@Component({
  selector: 'mdc-textfield',
  templateUrl: './textfield.html',
  styles: [String(MDC_TEXTFIELD_STYLES)],
  encapsulation: ViewEncapsulation.None,
  providers: [MD_TEXTFIELD_CONTROL_VALUE_ACCESSOR]
})
export class TextfieldComponent implements AfterViewInit, OnDestroy {
  private disabled_: boolean;

  @Input() id: string;
  @Input() type: string = 'text';
  @Input() value: string;
  @Input()
  get disabled(): boolean {
    return this.disabled_;
  }
  set disabled(value: boolean) {
    this.disabled_ = value;
    if (this.inputEl) {
      this._foundation.setDisabled(value);
    }
  }
  @Input() required: boolean;
  @Input() labelId: string;
  @Input() label: string;
  @Input() placeholder: string;
  @Input() tabindex: number;
  @Input() rows: number;
  @Input() cols: number;
  @Input() maxlength: number;
  @Input() fullwidth: boolean;
  @Input() multiline: boolean;
  @Output() focus: EventEmitter<FocusEvent> = new EventEmitter<FocusEvent>();
  @Output() blur: EventEmitter<FocusEvent> = new EventEmitter<FocusEvent>();
  @Output() input: EventEmitter<Event> = new EventEmitter<Event>();
  @Output() keydown: EventEmitter<KeyboardEvent> = new EventEmitter<KeyboardEvent>();
  @HostBinding('class') className: string = 'mdc-textfield';
  @HostBinding('class.mdc-textfield--multiline') get classMultiline(): string {
    return this.multiline ? 'mdc-textfield--multiline' : '';
  }
  @HostBinding('class.mdc-textfield--fullwidth') get classFullwidth(): string {
    return this.fullwidth ? 'mdc-textfield--fullwidth' : '';
  }
  @ViewChild('input') public inputEl: ElementRef;

  onTouched: () => any = () => { };

  private _controlValueAccessorChangeFn: (value: any) => void = (value) => { };
  private _unlisteners: Map<string, UnlistenerMap> = new Map<string, UnlistenerMap>();

  private _mdcAdapter: MDCTextfieldAdapter = {
    addClass: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      renderer.addClass(root.nativeElement, className);
    },
    removeClass: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      renderer.removeClass(root.nativeElement, className);
    },
    addClassToLabel: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (this.label) {
        renderer.addClass(root.nativeElement.lastChild, className);
      }
    },
    removeClassFromLabel: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (this.label) {
        renderer.removeClass(root.nativeElement.lastChild, className);
      }
    },
    addClassToHelptext: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (root.nativeElement.attributes.getNamedItem('aria-controls')) {
        if (root.nativeElement.nextElementSibling) {
          renderer.addClass(root.nativeElement.nextElementSibling, className);
        }
      }
    },
    removeClassFromHelptext: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (root.nativeElement.attributes.getNamedItem('aria-controls')) {
        renderer.removeClass(root.nativeElement.nextElementSibling, className);
      }
    },
    registerInputFocusHandler: (handler: EventListener) => {
      if (this._root) {
        this.listen_('focus', handler, this.inputEl);
      }
    },
    deregisterInputFocusHandler: (handler: EventListener) => {
      this.unlisten_('focus', handler);
    },
    registerInputBlurHandler: (handler: EventListener) => {
      if (this._root) {
        this.listen_('blur', handler, this.inputEl);
      }
    },
    deregisterInputBlurHandler: (handler: EventListener) => {
      this.unlisten_('blur', handler);
    },
    registerInputInputHandler: (handler: EventListener) => {
      if (this._root) {
        this.listen_('input', handler, this.inputEl);
      }
    },
    deregisterInputInputHandler: (handler: EventListener) => {
      this.unlisten_('input', handler);
    },
    registerInputKeydownHandler: (handler: EventListener) => {
      if (this._root) {
        this.listen_('keydown', handler, this.inputEl);
      }
    },
    deregisterInputKeydownHandler: (handler: EventListener) => {
      this.unlisten_('keydown', handler);
    },
    setHelptextAttr: (name: string, value: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (root.nativeElement.attributes.getNamedItem('aria-controls')) {
        root.nativeElement.nextElementSibling ? renderer.setAttribute(root.nativeElement.nextElementSibling, name, value) : null;
      }
    },
    removeHelptextAttr: (name: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (root.nativeElement.attributes.getNamedItem('aria-controls')) {
        return root.nativeElement.nextElementSibling ? renderer.removeAttribute(root.nativeElement.nextElementSibling, name) : null;
      }
    },
    helptextHasClass: (className: string) => {
      const { _renderer: renderer, _root: root } = this;
      if (root.nativeElement.attributes.getNamedItem('aria-controls')) {
        return root.nativeElement.nextElementSibling ? root.nativeElement.nextElementSibling.classList.contains(className) : false;
      }
    },
    getNativeInput: () => {
      return {
        checkValidity: () => this.inputEl.nativeElement.checkValidity(),
        value: this.value,
        disabled: (_) => this.disabled_ = _,
        badInput: this.inputEl.nativeElement.validity.badInput
      };
    }
  };

  private _foundation: {
    init: Function,
    destroy: Function,
    isDisabled: Function,
    setDisabled: Function
  } = new MDCTextfieldFoundation(this._mdcAdapter);

  constructor(private _renderer: Renderer2, private _root: ElementRef) { }

  ngAfterViewInit() {
    this._foundation.init();
  }
  ngOnDestroy() {
{'fraction_non_alphanumeric': 0.13558537714021288, 'fraction_numerical': 0.00030849915162733303, 'mean_word_length': 3.777818717759764, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 74, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6621753', 'n_tokens_mistral': 3940, 'n_tokens_neox': 3963, 'n_words': 764}