File

src/app/modules/content/stage-nav/stage-nav.component.ts

Description

Component that allows the user to change the viewing angle and rendering mode of the stage.

Metadata

Index

Properties
Methods
Inputs
Outputs
HostBindings
HostListeners
Accessors

Constructor

constructor(ga: GoogleAnalyticsService)

Creates an instance of stage nav component.

Parameters :
Name Type Optional Description
ga GoogleAnalyticsService No

Analytics service

Inputs

side
Type : Side
Default value : 'anterior'

Input that allows changing the current side from outside the component

useDropdownMenu
Type : boolean

Whether to use a drop down menu instead of a options bar

view3D
Type : boolean
Default value : false

Input that allows toggling of 3D view on / off from outside the component

Outputs

sideChange
Type : EventEmitter

Output that emits whenever the current side selection changes

view3DChange
Type : EventEmitter

Output that emits whenever the 3D view is toggled on / off

HostBindings

class
Type : "ccf-stage-nav"
Default value : 'ccf-stage-nav'

HTML class name

HostListeners

document:click
Arguments : '$event.target'
document:click(target: HTMLElement)

Listens to document click event Closes the popup only if user clicks outside the popup

Parameters :
Name Optional Description
target No

The element on which the event was fired

Methods

handleClick
handleClick(target: HTMLElement)
Decorators :
@HostListener('document:click', ['$event.target'])

Listens to document click event Closes the popup only if user clicks outside the popup

Parameters :
Name Type Optional Description
target HTMLElement No

The element on which the event was fired

Returns : void
updateSide
updateSide(selection: Side)

Handles the updating of the side selection and calling the event emitter

Parameters :
Name Type Optional Description
selection Side No

the new selected side

Returns : void
updateView
updateView(selection: boolean)

Handles updating of the boolean that keeps track of current view and calling the event emitter.

Parameters :
Name Type Optional Description
selection boolean No

3D (true) or Register (false)

Returns : void

Properties

Readonly clsName
Type : string
Default value : 'ccf-stage-nav'
Decorators :
@HostBinding('class')

HTML class name

isDropdownActive
Default value : false

Whether this component shows a dropdown menu or an options bar

isDropdownHidden
Default value : true

Whether the dropdown menu is hidden

labelRef
Type : ElementRef<HTMLElement>
Decorators :
@ViewChild('label', {static: true})

Label for dropdown

optionsRef
Type : ElementRef<HTMLElement>
Decorators :
@ViewChild('options', {static: true})

Options dropdown

Accessors

useDropdownMenu
setuseDropdownMenu(value: boolean)

Whether to use a drop down menu instead of a options bar

Parameters :
Name Type Optional
value boolean No
Returns : void
import {
  ChangeDetectionStrategy,
  Component,
  ElementRef,
  EventEmitter,
  HostBinding,
  HostListener,
  Input,
  Output,
  ViewChild,
} from '@angular/core';
import { GoogleAnalyticsService } from 'ngx-google-analytics';

/** Valid values for side. */
export type Side = 'left' | 'right' | 'anterior' | 'posterior' | '3D';

/** Component that allows the user to change the viewing angle and rendering mode of the stage. */
@Component({
  selector: 'ccf-stage-nav',
  templateUrl: './stage-nav.component.html',
  styleUrls: ['./stage-nav.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class StageNavComponent {
  /** HTML class name */
  @HostBinding('class') readonly clsName = 'ccf-stage-nav';

  /** Whether to use a drop down menu instead of a options bar */
  @Input()
  set useDropdownMenu(value: boolean) {
    this.isDropdownActive = value;
    this.isDropdownHidden = true;
  }

  /** Input that allows changing the current side from outside the component */
  @Input() side: Side = 'anterior';

  /** Input that allows toggling of 3D view on / off from outside the component */
  @Input() view3D = false;

  /** Output that emits whenever the current side selection changes */
  @Output() readonly sideChange = new EventEmitter<Side>();

  /** Output that emits whenever the 3D view is toggled on / off */
  @Output() readonly view3DChange = new EventEmitter<boolean>();

  /** Label for dropdown */
  @ViewChild('label', { static: true }) labelRef!: ElementRef<HTMLElement>;

  /** Options dropdown */
  @ViewChild('options', { static: true }) optionsRef!: ElementRef<HTMLElement>;

  /** Whether this component shows a dropdown menu or an options bar */
  isDropdownActive = false;

  /** Whether the dropdown menu is hidden */
  isDropdownHidden = true;

  /** Simple helper for accessing the native label element */
  private get labelEl(): HTMLElement {
    return this.labelRef.nativeElement;
  }

  /** Simple helper for accessing the native options element */
  private get optionsEl(): HTMLElement {
    return this.optionsRef.nativeElement;
  }

  /**
   * Creates an instance of stage nav component.
   *
   * @param ga Analytics service
   */
  constructor(private readonly ga: GoogleAnalyticsService) {}

  /**
   * Listens to document click event
   * Closes the popup only if user clicks outside the popup
   *
   * @param target The element on which the event was fired
   */
  @HostListener('document:click', ['$event.target'])
  handleClick(target: HTMLElement): void {
    const { isDropdownHidden, labelEl, optionsEl } = this;

    if (labelEl.contains(target)) {
      this.isDropdownHidden = !isDropdownHidden;
    } else if (!optionsEl.contains(target)) {
      this.isDropdownHidden = true;
    }
  }

  /**
   * Handles the updating of the side selection and calling the event emitter
   *
   * @param selection the new selected side
   */
  updateSide(selection: Side): void {
    this.ga.event('side_update', 'stage_nav', selection);

    if (selection === '3D') {
      this.updateView(true);
    } else {
      this.updateView(false);
      this.side = selection;
      this.sideChange.emit(this.side);
    }
  }

  /**
   * Handles updating of the boolean that keeps track of current view
   * and calling the event emitter.
   *
   * @param selection 3D (true) or Register (false)
   */
  updateView(selection: boolean): void {
    this.view3D = selection;
    this.ga.event('view_update', 'stage_nav', selection ? '3D' : 'Register');
    this.view3DChange.emit(this.view3D);
  }
}
<div class="dropdown-label" [class.dropdown]="isDropdownActive" #label>
  <mat-label>Options</mat-label>
  <mat-icon>arrow_drop_down</mat-icon>
</div>

<div
  class="stage-options"
  [class.dropdowncontainer]="isDropdownActive"
  [class.hidden]="isDropdownActive && isDropdownHidden"
  #options
>
  <mat-radio-group class="input-group" [value]="side" (change)="updateSide($event.value)">
    <mat-radio-button value="left" class="nav-input">Left</mat-radio-button>
    <mat-radio-button value="right" class="nav-input">Right</mat-radio-button>
    <mat-radio-button value="anterior" class="nav-input" checked>Anterior</mat-radio-button>
    <mat-radio-button value="posterior" class="nav-input">Posterior</mat-radio-button>
  </mat-radio-group>

  <ccf-labeled-slide-toggle
    matTooltip="Change view."
    class="view-slider"
    [labels]="['Register', '3D\u00A0Preview']"
    [value]="view3D ? '3D\u00A0Preview' : 'Register'"
    (valueChange)="updateView($event !== 'Register')"
  >
  </ccf-labeled-slide-toggle>
</div>

./stage-nav.component.scss

:host {
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;

  .dropdown-label {
    display: none;
    align-items: center;

    mat-label,
    mat-icon {
      line-height: 1.5rem;
    }

    &.dropdown {
      display: flex;
      cursor: pointer;
      align-items: start;
    }
  }

  .stage-options {
    display: flex;
    align-items: center;

    .input-group {
      .nav-input {
        margin-right: 1rem;
        margin-bottom: 1.5rem;
      }

      mat-radio-button {
        ::ng-deep .mdc-label {
          font-size: 1.25rem;
        }
      }
    }

    .view-slider {
      white-space: nowrap;
      display: flex;

      ::ng-deep .slider {
        display: flex;
      }

      ::ng-deep .slide-label {
        font-size: 1.25rem;
      }
    }

    &.dropdowncontainer {
      display: flex;
      flex-direction: column;
      border-radius: 0.25rem;
      position: absolute;
      top: 3.5rem;
      z-index: 11;
      transition: opacity 0.25s;

      :first-child {
        margin-top: 0.5rem;
      }

      :last-child {
        margin-bottom: 0.5rem;
      }

      .input-group {
        margin-left: 0.875rem;
        margin-right: 0;
        display: flex;
        flex-wrap: wrap;

        .nav-input {
          display: flex;
          margin: 0;
          margin-right: 0.875rem;
          height: 2.5rem;

          ::ng-deep .mdc-label {
            padding-left: 0;
          }
        }
      }

      .view-slider {
        display: flex;
        align-items: center;
        height: 3rem;
        margin: 0 0.5rem;
      }

      mat-divider {
        visibility: visible;
        border-top: 2px solid;
      }
    }

    &.hidden {
      visibility: hidden;
      opacity: 0;
      transition:
        visibility 0.25s,
        opacity 0.25s;

      mat-divider {
        visibility: hidden;
      }
    }
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""