File

src/app/shared/components/visibility-menu/visibility-menu.component.ts

Description

Menu for displaying visibility options

Metadata

Index

Properties
Methods
Inputs
Outputs
HostBindings

Constructor

constructor(ga: GoogleAnalyticsService)

Creates an instance of visibility menu component.

Parameters :
Name Type Optional Description
ga GoogleAnalyticsService No

Analytics service

Inputs

items
Type : VisibilityItem[]

Items to be displayed in the visibility menu

selection
Type : VisibilityItem | undefined

The currently selected item

Outputs

hover
Type : EventEmitter

Emits the currently hovered item

itemsChange
Type : EventEmitter

Emits whenever there is a change to one or more items.

HostBindings

class
Type : "ccf-visibility-menu"
Default value : 'ccf-visibility-menu'

HTML class name

Methods

getId
getId(_index: number, item: VisibilityItem)

Returns the id of an item

Parameters :
Name Type Optional Description
_index number No
item VisibilityItem No

The item to get an id for

Returns : string | number

id Id of the item

mouseOut
mouseOut()

Clears current selection and emits undefined in response to mouse out

Returns : void
mouseOver
mouseOver(item: VisibilityItem)

Changes current selection to hovered over item and emits the item

Parameters :
Name Type Optional Description
item VisibilityItem No

Menu item

Returns : void
resetItem
resetItem()

Resets item to opacity 20 and visible

Returns : void
setAllOpacity
setAllOpacity(value: number)

Sets all items to the same opacity and makes them visible

Parameters :
Name Type Optional Description
value number No

Updated opacity value

Returns : void
toggleVisibility
toggleVisibility(item: VisibilityItem)

Toggles visibility of an item; opacity is reverted to the previous value if visibility toggled back on

Parameters :
Name Type Optional Description
item VisibilityItem No

Menu item

Returns : void
updateOpacity
updateOpacity(value: number | undefined)

Updates opacity of the currently selected item (if one is selected) and emits the new items

Parameters :
Name Type Optional Description
value number | undefined No

Updated opacity value

Returns : void

Properties

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

HTML class name

import { ChangeDetectionStrategy, Component, EventEmitter, HostBinding, Input, Output } from '@angular/core';
import { GoogleAnalyticsService } from 'ngx-google-analytics';

import { VisibilityItem } from '../../../core/models/visibility-item';

/**
 * Menu for displaying visibility options
 */
@Component({
  selector: 'ccf-visibility-menu',
  templateUrl: './visibility-menu.component.html',
  styleUrls: ['./visibility-menu.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class VisibilityMenuComponent {
  /**
   * HTML class name
   */
  @HostBinding('class') readonly clsName = 'ccf-visibility-menu';

  /**
   * Items to be displayed in the visibility menu
   */
  @Input() items!: VisibilityItem[];

  /**
   * The currently selected item
   */
  @Input() selection: VisibilityItem | undefined;

  /**
   * Emits the currently hovered item
   */
  @Output() readonly hover = new EventEmitter<VisibilityItem | undefined>();

  /**
   * Emits whenever there is a change to one or more items.
   */
  @Output() readonly itemsChange = new EventEmitter<VisibilityItem[]>();

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

  /**
   * Toggles visibility of an item; opacity is reverted to the previous value if visibility toggled back on
   *
   * @param item Menu item
   */
  toggleVisibility(item: VisibilityItem): void {
    item = { ...item, visible: !item.visible };
    if (this.selection && item.id === this.selection.id) {
      this.selection = { ...this.selection, visible: item.visible };
    }

    this.ga.event('visibility_toggled', 'visibility_menu', '' + item.id, +item.visible);
    this.updateOpacity(item.opacity);
  }

  /**
   * Changes current selection to hovered over item and emits the item
   *
   * @param item Menu item
   */
  mouseOver(item: VisibilityItem): void {
    this.selection = item === this.selection ? undefined : item;
    this.hover.emit(item);
  }

  /**
   * Clears current selection and emits undefined in response to mouse out
   *
   * @param item Menu item
   */
  mouseOut(): void {
    this.selection = undefined;
    this.hover.emit(undefined);
  }

  /**
   * Updates opacity of the currently selected item (if one is selected) and emits the new items
   *
   * @param value Updated opacity value
   */
  updateOpacity(value: number | undefined): void {
    if (!this.selection) {
      return;
    }
    const updatedSelection = { ...this.selection, opacity: value };
    this.selection = updatedSelection;
    if (updatedSelection.id === 'all') {
      this.setAllOpacity(updatedSelection.opacity as number);
    } else {
      this.items = this.items.map((item) => (item.id === updatedSelection.id ? updatedSelection : item));
      this.ga.event('opacity_update', 'visibility_menu', '' + updatedSelection.id, updatedSelection.opacity);
    }
    this.itemsChange.emit(this.items);
  }

  /**
   * Resets item to opacity 20 and visible
   */
  resetItem(): void {
    if (this.selection) {
      const updatedSelection = { ...this.selection, opacity: 20, visible: true };
      this.selection = updatedSelection;
      if (this.selection.id === 'all') {
        this.setAllOpacity(updatedSelection.opacity);
      } else {
        this.items = this.items.map((item) => (item.id === updatedSelection.id ? updatedSelection : item));
        this.ga.event('item_reset', 'visibility_menu', '' + updatedSelection.id);
      }
      this.itemsChange.emit(this.items);
    }
  }

  /**
   * Sets all items to the same opacity and makes them visible
   *
   * @param value Updated opacity value
   */
  setAllOpacity(value: number): void {
    this.items = this.items.map((i) => ({ ...i, opacity: value, visible: true }));
    this.ga.event('all_items_opacity_update', 'visibility_menu', undefined, value);
    this.itemsChange.emit(this.items);
  }

  /**
   * Returns the id of an item
   *
   * @param index Index of item in items array
   * @param item The item to get an id for
   * @returns id Id of the item
   */
  getId(_index: number, item: VisibilityItem): string | number {
    return item.id;
  }
}
<mat-icon
  class="icon reset"
  matRipple
  [matRippleCentered]="true"
  [matRippleUnbounded]="true"
  (click)="setAllOpacity(20)"
  *ngIf="items.length"
  >refresh</mat-icon
>

<div
  class="item-entry"
  [class.selected]="selection ? getId(0, selection) === getId(0, item) : false"
  (mouseenter)="mouseOver(item)"
  (mouseleave)="mouseOut()"
  *ngFor="let item of items; trackBy: getId"
>
  <mat-icon class="opacity-icon" [class.fade]="!item.visible" svgIcon="app:opacity"></mat-icon>
  <div class="item-name" [class.hidden]="item.id === selection?.id" title="{{ item.name }}">{{ item.name }}</div>

  <div class="slider" [class.visible]="item.id === selection?.id" [class.hidden]="item.id !== selection?.id">
    <ccf-opacity-slider
      [opacity]="selection ? selection?.opacity ?? 20 : 20"
      (opacityChange)="updateOpacity($event)"
      (opacityReset)="resetItem()"
      (visibilityToggle)="toggleVisibility(item)"
    >
    </ccf-opacity-slider>
  </div>
</div>

./visibility-menu.component.scss

:host {
  display: flex;
  flex-direction: column;
  margin-right: 0;
  margin-left: 0;
  max-height: 40vh;
  overflow-y: auto;
  scrollbar-width: thin;

  .icon {
    border-radius: 0.25rem;
  }

  .reset {
    transform: scaleX(-1);
    cursor: pointer;
    transition: 0.6s;
    position: absolute;
    top: 3rem;

    &:hover {
      border-radius: 2px;
    }
  }

  .item-entry {
    display: flex;
    height: 2.25rem;
    align-items: center;
    flex-shrink: 0;
    position: relative;

    .opacity {
      cursor: pointer;
    }

    .opacity-icon {
      z-index: 1;
      transition: 0.6s;

      &:hover {
        border-radius: 2px;
      }
    }

    .item-name {
      user-select: none;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
      margin-left: 0.5rem;
      opacity: 1;
      transition-duration: 0.4s;
      transition-timing-function: ease-in-out;
      transition-property: opacity;
      max-width: calc(100% - 2.5rem);

      &.hidden {
        opacity: 0;
      }
    }

    .slider {
      width: calc(100% - 2rem);
      transition-duration: 0.3s;
      transition-timing-function: ease-in-out;
      transition-property: opacity;
      left: 2rem;
      position: absolute;
      opacity: 1;

      &.hidden {
        opacity: 0;
        transition-duration: 0.1s;
        transition-timing-function: ease-in-out;
        transition-property: opacity;
      }
    }
  }
}
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""