<commit_before>import {
  BehaviorSubject
} from 'rxjs/BehaviorSubject';

import {
  Component,
  Directive,
  Attribute,
  Input,
  Output,
  ElementRef,
  AfterViewInit,
  OnChanges,
  ContentChild,
  SimpleChanges,
  EventEmitter,
  QueryList,
  ViewContainerRef
} from '@angular/core';

import { AngularDropdownControlDirective }
  from './angular-dropdown-control.directive';
import { AngularDropdownContentComponent }
  from './angular-dropdown-content.component';

import { calculatePosition, calculateInPlacePosition } from './utils';

export interface AngularDropdownPositionChanges {
  vPosition: 'above' | 'below';
  hPosition: 'right' | 'center' | 'left';
}

let id = 1;
function generateDropdownId() {
  return id++;
}

export type VerticalPosition = 'auto' | 'above' | 'below';
export type HorizontalPosition = 'auto' | 'right' | 'center' | 'left';

export interface DropdownContentPosition {
  readonly hPosition: HorizontalPosition | null;
  readonly vPosition: VerticalPosition | null;
  readonly top: string | null;
  readonly left: string | null;
  readonly bottom: string | null;
  readonly right: string | null;
}

const EmptyDropdownContentPosition = Object.freeze({
  vPosition: null,
  hPosition: null,
  top: null,
  left: null,
  bottom: null,
  right: null
});

@Directive({
  selector: 'ng-dropdown,[ngDropdown],[ng-dropdown]',
  host: {
    '[class.render-in-place]': 'renderInPlace',
    '[class.ng-dropdown]': 'true',
  }
})
export class AngularDropdownDirective implements OnChanges {
  id?: string;

  @Input()
  renderInPlace: boolean = false;

  @ContentChild(AngularDropdownControlDirective)
  control: AngularDropdownControlDirective | null = null;

  previousVerticalPosition: VerticalPosition | null = null;
  previousHorizontalPosition: HorizontalPosition | null = null;
  matchTriggerWidth: boolean = false;

  isOpen$ = new BehaviorSubject(false);
  position$ = new BehaviorSubject<Readonly<DropdownContentPosition>>(EmptyDropdownContentPosition);

  get dropdownId() {
    return `ng-dropdown-content-${this.uniqueId}`
  }

  @Input()
  calculatePosition: Function = calculatePosition;
  @Input()
  calculateInPlacePosition: Function = calculateInPlacePosition;

  @Input()
  disabled: boolean = false;

  @Input()
  beforeOpen: (() => boolean) | null= null;

  @Input()
  beforeClose: (() => boolean) | null = null;

  @Input()
  public verticalPosition: VerticalPosition = 'auto';
  @Input()
  public horizontalPosition: HorizontalPosition = 'auto';

  @Output('open')
  onOpen = new EventEmitter<void>();

  @Output('close')
  onClose = new EventEmitter<void>();

  get triggerElement(): HTMLElement {
    return this.control!.element.nativeElement;
  }

  get dropdownElement(): HTMLElement {
    return document.getElementById(this.dropdownId)!;
  }

  @ContentChild(AngularDropdownContentComponent)
  private dropdownContent?: AngularDropdownContentComponent;

  private uniqueId: number | string | null = null;
  private width: number | null = null;

  constructor(@Attribute('id') id?: string) {
    this.initializeId(id);
    this.createDefaultWormholeOutlet();
  }

  ngOnChanges({ disabled }: SimpleChanges): void {
    if (disabled &&
        disabled.firstChange === false &&
        disabled.currentValue === true &&
        disabled.previousValue !== true) {
      this.disable();
    }
  }

  open(): void {
    if (this.disabled || this.isOpen$.getValue()) {
      return;
    }

    if (this.beforeOpen && this.beforeOpen() === false) {
      return;
    }

    this.isOpen$.next(true);
    this.onOpen.emit();
  }

  close(skipFocus = false): void {
    if (this.disabled || !this.isOpen$.getValue()) {
      return;
    }

    if (this.beforeClose && this.beforeClose() === false) {
      return;
    }

    Object.assign(this, {
      hPosition: null,
      vPosition: null,
      top: null,
      right: null,
      bottom: null,
      left: null,
      width: null,
      previousVerticalPosition: null,
      previousHorizontalPosition: null
    });
    this.isOpen$.next(false);
    this.onClose.emit();

    if (!skipFocus) {
      if (this.triggerElement instanceof HTMLElement &&
          this.triggerElement.tabIndex > -1) {<commit_msg>beforeOpen boolean observable<commit_after>import {
  BehaviorSubject
} from 'rxjs/BehaviorSubject';

import {
  Component,
  Directive,
  Attribute,
  Input,
  Output,
  ElementRef,
  AfterViewInit,
  OnChanges,
  ContentChild,
  SimpleChanges,
  EventEmitter,
  QueryList,
  ViewContainerRef
} from '@angular/core';

import { AngularDropdownControlDirective }
  from './angular-dropdown-control.directive';
import { AngularDropdownContentComponent }
  from './angular-dropdown-content.component';

import { calculatePosition, calculateInPlacePosition } from './utils';
import { Observable } from 'rxjs/Observable';

export interface AngularDropdownPositionChanges {
  vPosition: 'above' | 'below';
  hPosition: 'right' | 'center' | 'left';
}

let id = 1;
function generateDropdownId() {
  return id++;
}

export type VerticalPosition = 'auto' | 'above' | 'below';
export type HorizontalPosition = 'auto' | 'right' | 'center' | 'left';

export interface DropdownContentPosition {
  readonly hPosition: HorizontalPosition | null;
  readonly vPosition: VerticalPosition | null;
  readonly top: string | null;
  readonly left: string | null;
  readonly bottom: string | null;
  readonly right: string | null;
}

const EmptyDropdownContentPosition = Object.freeze({
  vPosition: null,
  hPosition: null,
  top: null,
  left: null,
  bottom: null,
  right: null
});

@Directive({
  selector: 'ng-dropdown,[ngDropdown],[ng-dropdown]',
  host: {
    '[class.render-in-place]': 'renderInPlace',
    '[class.ng-dropdown]': 'true',
  }
})
export class AngularDropdownDirective implements OnChanges {
  id?: string;

  @Input()
  renderInPlace: boolean = false;

  @ContentChild(AngularDropdownControlDirective)
  control: AngularDropdownControlDirective | null = null;

  previousVerticalPosition: VerticalPosition | null = null;
  previousHorizontalPosition: HorizontalPosition | null = null;
  matchTriggerWidth: boolean = false;

  isOpen$ = new BehaviorSubject(false);
  position$ = new BehaviorSubject<Readonly<DropdownContentPosition>>(EmptyDropdownContentPosition);

  get dropdownId() {
    return `ng-dropdown-content-${this.uniqueId}`
  }

  @Input()
  calculatePosition: Function = calculatePosition;
  @Input()
  calculateInPlacePosition: Function = calculateInPlacePosition;

  @Input()
  disabled: boolean = false;

  @Input()
  beforeOpen: (() => boolean) | (() => Observable<boolean>)  | null= null;

  @Input()
  beforeClose: (() => boolean) | null = null;

  @Input()
  public verticalPosition: VerticalPosition = 'auto';
  @Input()
  public horizontalPosition: HorizontalPosition = 'auto';

  @Output('open')
  onOpen = new EventEmitter<void>();

  @Output('close')
  onClose = new EventEmitter<void>();

  get triggerElement(): HTMLElement {
    return this.control!.element.nativeElement;
  }

  get dropdownElement(): HTMLElement {
    return document.getElementById(this.dropdownId)!;
  }

  @ContentChild(AngularDropdownContentComponent)
  private dropdownContent?: AngularDropdownContentComponent;

  private uniqueId: number | string | null = null;
  private width: number | null = null;

  constructor(@Attribute('id') id?: string) {
    this.initializeId(id);
    this.createDefaultWormholeOutlet();
  }

  ngOnChanges({ disabled }: SimpleChanges): void {
    if (disabled &&
        disabled.firstChange === false &&
        disabled.currentValue === true &&
        disabled.previousValue !== true) {
      this.disable();
    }
  }

  open(): void {
    if (this.disabled || this.isOpen$.getValue()) {
      return;
    }

    let open$: Observable<boolean> = Observable.of(true);

    if (this.beforeOpen) {
      const result = this.beforeOpen();
      if (result instanceof Observable) {
        open$ = result;
      } else {
        open$ = Observable.of(result);
      }

    }

    open$.subscribe( (open) => {
      if (open) {
        this.isOpen$.next(true);
        this.onOpen.emit();
      }
    });

  }

  close(skipFocus = false): void {
    if (this.disabled || !this.isOpen$.getValue()) {
      return;
    }

    if (this.beforeClose && this.beforeClose() === false) {
      return;
    }

    Object.assign(this, {
      hPosition: null,
      vPosition: null,
      top: null,
      right: null,
      bottom: null,
      left: null,
      width: null,
      previousVerticalPosition: null,
      previousHorizontalPosition: null
    });
    this.isOpen$.next(false);
    this.onClose.emit();

    if (!skipFocus) {
      if (this.triggerElement instanceof HTMLElement &&
          this.triggerElement.tabIndex > -1) {
{'fraction_non_alphanumeric': 0.12816419612314708, 'fraction_numerical': 0.00045610034207525655, 'mean_word_length': 3.733405288720993, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 21, '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': '6174502', 'n_tokens_mistral': 2661, 'n_tokens_neox': 2568, 'n_words': 598}