All files / app/formly location-picker.ts

36.17% Statements 17/47
4.16% Branches 1/24
50% Functions 4/8
38.46% Lines 15/39

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 123    12x             12x                           2x     2x       2x                                                                                                             12x                             12x   12x             2x 2x     2x       2x 2x 2x 2x    
import { AbstractControl } from '@angular/forms';
import { FormlyFieldConfig } from '@ngx-formly/core';
import { Subject } from 'rxjs';
 
/**
 * Shared map picker state for all location inputs in a plugin form.
 * The map is shown above the location input that opened it, and any
 * location in the host can be edited from it. Only one map is open at a time.
 */
export class LocationPicker {
  /**
   * The location input the map is shown above.
   */
  owner?: AbstractControl;
  /**
   * The location set by clicking the map.
   */
  active?: AbstractControl;
  /**
   * A list added while the map is open. Right clicking the map adds points
   * to it until another location is selected.
   */
  target?: AbstractControl;
  readonly changes = new Subject<void>();
 
  constructor(
    readonly host: FormlyFieldConfig,
  ) { }
 
  get open() {
    return !!this.owner;
  }
 
  /**
   * Toggle the map for this control. If the map is already open for another
   * control, close it and open it here instead.
   */
  toggle(control: AbstractControl) {
    if (this.owner === control) {
      this.close();
      return;
    }
    if (openPicker && openPicker !== this) openPicker.close();
    openPicker = this;
    this.owner = this.active = control;
    this.target = undefined;
    this.changes.next();
  }
 
  close() {
    if (openPicker === this) openPicker = undefined;
    this.target = undefined;
    if (!this.owner && !this.active) return;
    this.owner = this.active = undefined;
    this.changes.next();
  }
 
  select(control?: AbstractControl) {
    if (!this.owner) return;
    control ||= this.owner;
    this.target = undefined;
    if (this.active === control) return;
    this.active = control;
    this.changes.next();
  }
 
  /**
   * A location input was removed. Removing the location the map is shown
   * above closes the map.
   */
  removed(control: AbstractControl) {
    if (this.owner === control) {
      this.close();
    } else if (this.active === control) {
      this.select(this.owner);
    }
  }
}
 
let openPicker: LocationPicker | undefined;
 
/**
 * Lists of locations kept closed as a linear ring (RFC 7946 3.1.6). The last
 * position is a hidden copy of the first.
 */
export const closedRings = new WeakSet<AbstractControl>();
 
export interface LocationList {
  /**
   * Number of nested lists down to the locations: 1 for a line, ring or
   * multi point, 2 for a polygon, and so on.
   */
  depth: number;
  add(index?: number, initialModel?: any): void;
}
 
/**
 * Lists of locations (lines, rings and multi points) and lists of those
 * lists by form control, so points can be added from the map.
 */
export const locationLists = new WeakMap<AbstractControl, LocationList>();
 
const pickers = new WeakMap<FormlyFieldConfig, LocationPicker>();
 
/**
 * The outermost list containing this location. All locations in the host
 * are shown on the map.
 */
export function locationMapHost(field: FormlyFieldConfig): FormlyFieldConfig {
  let host = field;
  for (let f = field.parent; f; f = f.parent) {
    if (f.type === 'list') host = f;
  }
  return host;
}
 
export function locationPicker(field: FormlyFieldConfig) {
  const host = locationMapHost(field);
  let picker = pickers.get(host);
  Eif (!picker) pickers.set(host, picker = new LocationPicker(host));
  return picker;
}