File

app/dxa/dxa-entity/views/shortcuts-views/shortcuts-main/shortcuts-main.component.ts

Implements

OnInit OnDestroy

Metadata

selector div[shortcuts-main]
styleUrls ./shortcuts-main.component.scss
templateUrl ./shortcuts-main.component.html

Index

Properties
Methods
Inputs
HostBindings

Constructor

constructor(label: LabelService, util: UtilService, constants: ConstantsService, changeDetector: ChangeDetectorRef, resizer: ResizeContentService, idGenerator: IdGeneratorService, document)
Parameters :
Name Type Optional
label LabelService No
util UtilService No
constants ConstantsService No
changeDetector ChangeDetectorRef No
resizer ResizeContentService No
idGenerator IdGeneratorService No
document No

Inputs

entity

HostBindings

class

Methods

actOnResize
actOnResize()
Returns : void
inDesktopView
inDesktopView(width: number)
Parameters :
Name Type Optional
width number No
Returns : boolean
ngOnChanges
ngOnChanges()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
Private parseJson
parseJson(entity)
Parameters :
Name Optional
entity No
Returns : ShortCutsData
Private parseShortcut
parseShortcut(jsonShortcut)
Parameters :
Name Optional
jsonShortcut No
Returns : Shortcut
scroll
scroll(target, index)
Parameters :
Name Optional
target No
index No
Returns : void
Private setLabel
setLabel(data: ShortCutsData)
Parameters :
Name Type Optional
data ShortCutsData No
Returns : void
Private setSelectedShortcut
setSelectedShortcut(index)
Parameters :
Name Optional
index No
Returns : void
setup
setup()
Returns : void
toggleMobileMenu
toggleMobileMenu()
Returns : void

Properties

Private componentId
Default value : this.idGenerator.getId()
data
Type : ShortCutsData
desktopView
Type : boolean
Private Readonly labelKey
Type : string
Default value : 'shortcutsJumpToSection'
previousWidth
Type : number
Private subscriptions
Type : Subscription[]
Default value : []
import { Component, OnInit, Input, OnDestroy, Inject, ChangeDetectorRef, HostBinding } from '@angular/core';
import { Subscription } from 'rxjs';
import { ConstantsService } from 'src/app/shared/constants/constants.service';
import { LabelService } from 'src/app/core/services/label-service/label-service.service';
import { UtilService } from 'src/app/core/services/util-service/util.service';
import { DOCUMENT } from '@angular/common';
import { ResizeContentService } from 'src/app/core/services/resize-service/resize-content.service';
import { IdGeneratorService } from 'src/app/core/services/id-generator.service';

interface ShortCutsData {
	mobileMenuOpen: boolean;
	jumpToSectionLabel: string;
	shortcuts: Shortcut[];
}

interface Shortcut {
	title: string;
	target: string;
	selected: boolean;
}

@Component({
	selector: 'div[shortcuts-main]',
	templateUrl: './shortcuts-main.component.html',
	styleUrls: ['./shortcuts-main.component.scss']
})
export class ShortcutsMainComponent implements OnInit, OnDestroy {

	data: ShortCutsData;
	private readonly labelKey = 'shortcutsJumpToSection';
	private subscriptions: Subscription[] = [];
	desktopView: boolean;
	previousWidth: number;
	private componentId = this.idGenerator.getId();

	@Input() entity;

	@HostBinding('class') get class() { return 'bg-off-white'; }

	constructor(
		private label: LabelService,
		private util: UtilService,
		private constants: ConstantsService,
		private changeDetector: ChangeDetectorRef,
		private resizer: ResizeContentService,
		private idGenerator: IdGeneratorService,
		@Inject(DOCUMENT) private document) { }

	ngOnInit() {
		this.setup();
	}

	setup() {
		if (this.entity) {
			this.data = this.parseJson(this.entity);
			this.setLabel(this.data);

			const width = (window.innerWidth || this.document.documentElement.clientWidth);
			this.desktopView = this.inDesktopView(width);

			this.previousWidth = (window.innerWidth || this.document.documentElement.clientWidth);
			this.resizer.registerCallback(this.componentId, () => this.actOnResize());
		}
	}

	ngOnChanges() {
		this.data = this.parseJson(this.entity);
		this.setLabel(this.data);
	}

	actOnResize(): void {
		const currentWidth = window.innerWidth || this.document.documentElement.clientWidth;
		this.desktopView = this.inDesktopView(currentWidth);

		const inMobile = currentWidth <= this.constants.BOOTSTRAP_BREAKPOINTS.MD;
		const previousWasTablet = this.previousWidth > this.constants.BOOTSTRAP_BREAKPOINTS.MD;

		// Close if it is not in the mobile view or the broswer is transitioning from non-mobile to mobile
		if ((!inMobile) || (previousWasTablet && inMobile)) {
			this.data.mobileMenuOpen = false;
		}

		this.previousWidth = currentWidth;
		this.changeDetector.detectChanges();
	}

	ngOnDestroy(): void {
		this.resizer.destroyCallback(this.componentId);
	}


	// called from the template
	toggleMobileMenu(): void {
		this.data.mobileMenuOpen = !this.data.mobileMenuOpen;
	}

	// called from the template
	scroll(target, index): void {
		// Target is the tcm id from tridion, appending component prefix to match what is set by dxa-entity
		target = `${this.constants.COMPONENT_ID_PREFIX}-${target}`;
		const scrollTarget = document.getElementById(target);
		if (scrollTarget) {
			this.setSelectedShortcut(index);
			scrollTarget.scrollIntoView({behavior: 'smooth'});
			if (!this.desktopView) {
				this.toggleMobileMenu();
			}
		}
	}

	// set the shortcut that was clicked to selected, all others to false
	private setSelectedShortcut(index): void {
		this.data.shortcuts.forEach( shortcut => shortcut.selected = false);
		this.data.shortcuts[index].selected = true;
	}

	private setLabel(data: ShortCutsData): void {
		this.subscriptions.push(this.label.getValue(this.labelKey).subscribe(label => data.jumpToSectionLabel = label));
	}

	private parseJson(entity): ShortCutsData {

		const shortcuts: Shortcut[] = (this.util.extract(entity, 'ShortcutLink') || []).map(e => this.parseShortcut(e));

		const parsed: ShortCutsData = {
			mobileMenuOpen: false,
			jumpToSectionLabel: '',
			shortcuts: shortcuts
		};
		return parsed;
	}


	private parseShortcut(jsonShortcut): Shortcut {

		const title = this.util.extract(jsonShortcut, 'Title');
		const target = this.util.extract(jsonShortcut, 'LinkedComponentId');

		const parsed = {
			title: title,
			target: target,
			selected: false
		};

		return parsed;
	}

	inDesktopView(width: number): boolean {
		return width > this.constants.BOOTSTRAP_BREAKPOINTS.MD;
	}

}
<div class="container">
  <div class="content" *ngIf="data">
    <div class="mobile-menu">
      <div class="menu-option" (click)="toggleMobileMenu()">
        <div class="shortcut-label">
          {{data.jumpToSectionLabel | uppercase}}
        </div>
        <i *ngIf="!data.mobileMenuOpen" class="icon-chevronDown"></i>
        <i *ngIf="data.mobileMenuOpen" class="icon-chevronUp"></i>
      </div>
    </div>
    <div *ngIf="desktopView || data.mobileMenuOpen" class="shortcuts">
      <div [ngClass]="{'shortcut': true,
                      'shortcut-open': data.mobileMenuOpen,
                      'shortcut-selected': shortcut.selected }" 
                      *ngFor="let shortcut of data.shortcuts; let i = index"
                      (click)="scroll(shortcut.target,i)">
        <a>
          {{shortcut.title | uppercase }}
        </a>
      </div>
    </div>
  </div>
</div>

./shortcuts-main.component.scss

@import "src/app/styles/helpers";

.content {
    >.mobile-menu {
        @include media-breakpoint-up(md) {
            display: none;
        }

        >.menu-option {
            margin-bottom: calc-rem(3);
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: calc-rem(28) 0;
            padding-right: calc-rem(32);
            width: 100%;
            color: $cool-grey;
            cursor: pointer;
            
            >.shortcut-label {
                @include font-scale(14, uppercase);
                letter-spacing: calc-rem(0.4);
            }

            i {
                // add a margin here since the actual icon is bigger than the div so the overflows the box
                // unless we add this margin
                margin-right: calc-rem(20);
                @include font-size(7);
            }
        }
    }
    .shortcuts {
        display: flex;
        flex-wrap: wrap;

        .shortcut {
            @include media-breakpoint-down(sm) {
                justify-content: left;
                width: 100%
            }

            display: flex;
            justify-content: left;
            align-items: center;
            padding: calc-rem(28) calc-rem(32);
            @include font-scale(14, uppercase);
            letter-spacing: calc-rem(0.4);
            color: $cool-grey;
            cursor: pointer;

            &-open {
                padding-left: 0;
                padding-bottom: 0;

                &:last-of-type {
                    padding-bottom: calc-rem(28);
                } 
            }
        }
        .shortcut-selected {
            @include media-breakpoint-up(md) {
                background-color: darken($off-white, 5%);
            }

            @include media-breakpoint-down(sm) {
                font-weight: bold;
                width: 100%
            }
        }
    }
}

.close {
    &:focus {
        outline: none;
    }
}

::ng-deep .modal.modal-60-percent {
    .modal-dialog {
        @include media-breakpoint-up(sm) {
            max-width: 60%;
        }
        
        @include media-breakpoint-down(sm) {
            max-width: 60%;
            margin: auto;
        }
    }
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""