File

src/app/sys-check/unit-check/unit-check.component.ts

Implements

OnInit OnDestroy

Metadata

selector iqb-unit-check
styleUrls ./unit-check.component.css
templateUrl ./unit-check.component.html

Index

Properties
Methods
HostListeners

Constructor

constructor(ds: SysCheckDataService, bs: BackendService, mds: MainDataService)
Parameters :
Name Type Optional
ds SysCheckDataService No
bs BackendService No
mds MainDataService No

HostListeners

window:resize
window:resize()

Methods

gotoPage
gotoPage(action: string, index: number)
Parameters :
Name Type Optional Default value
action string No
index number No 0
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
setPageList
setPageList(validPages: string[], currentPage: string)
Parameters :
Name Type Optional
validPages string[] No
currentPage string No
Returns : void

Properties

Private iFrameHostElement
Type : HTMLElement
Private iFrameItemplayer
Type : HTMLIFrameElement
Default value : null
Private itemplayerSessionId
Type : string
Default value : ''
Public pageList
Type : PageData[]
Default value : []
Private pendingUnitDef
Type : string
Default value : ''
Private postMessageSubscription
Type : Subscription
Default value : null
Private postMessageTarget
Type : Window
Default value : null
Private taskSubscription
Type : Subscription
Default value : null
import {
  Component, OnInit, HostListener, OnDestroy
} from '@angular/core';
import { Subscription } from 'rxjs';
import { MainDataService } from '../../maindata.service';
import { BackendService } from '../backend.service';
import { SysCheckDataService } from '../sys-check-data.service';

declare let srcDoc: any;

@Component({
  selector: 'iqb-unit-check',
  templateUrl: './unit-check.component.html',
  styleUrls: ['./unit-check.component.css']
})
export class UnitCheckComponent implements OnInit, OnDestroy {
  public pageList: PageData[] = [];
  private iFrameHostElement: HTMLElement;
  private iFrameItemplayer: HTMLIFrameElement = null;
  private postMessageSubscription: Subscription = null;
  private taskSubscription: Subscription = null;
  private postMessageTarget: Window = null;
  private itemplayerSessionId = '';
  private pendingUnitDef = '';

  constructor(
    private ds: SysCheckDataService,
    private bs: BackendService,
    private mds: MainDataService
  ) {
  }

  @HostListener('window:resize')
  public onResize(): any {
    if (this.iFrameItemplayer && this.iFrameHostElement) {
      const divHeight = this.iFrameHostElement.clientHeight;
      this.iFrameItemplayer.setAttribute('height', String(divHeight - 5));
      // TODO: Why minus 5px?
    }
  }

  ngOnInit(): void {
    setTimeout(() => {
      this.ds.setNewCurrentStep('u');
      if (this.ds.unitAndPlayerContainer) {
        this.iFrameHostElement = <HTMLElement>document.querySelector('#iFrameHost');
        this.postMessageSubscription = this.mds.postMessage$.subscribe((m: MessageEvent) => {
          const msgData = m.data;
          const msgType = msgData.type;

          if ((msgType !== undefined) && (msgType !== null)) {
            switch (msgType) {
              case 'vopReadyNotification':
                this.iFrameItemplayer.setAttribute('height', String(Math.trunc(this.iFrameHostElement.clientHeight)));
                this.postMessageTarget = m.source as Window;
                if (typeof this.postMessageTarget !== 'undefined') {
                  this.itemplayerSessionId = Math.floor(Math.random() * 20000000 + 10000000).toString();
                  this.postMessageTarget.postMessage({
                    type: 'vopStartCommand',
                    sessionId: this.itemplayerSessionId,
                    unitDefinition: this.pendingUnitDef,
                    playerConfig: {
                      logPolicy: 'disabled',
                      stateReportPolicy: 'none'
                    }
                  }, '*');
                }
                break;

              case 'vopStateChangedNotification':
                if (msgData.playerState) {
                  const { playerState } = msgData;
                  this.setPageList(Object.keys(playerState.validPages), playerState.currentPage);
                }
                break;

              default:
                console.log(`processMessagePost ignored message: ${msgType}`);
                break;
            }
          }
        });

        while (this.iFrameHostElement.hasChildNodes()) {
          this.iFrameHostElement.removeChild(this.iFrameHostElement.lastChild);
        }
        this.pendingUnitDef = this.ds.unitAndPlayerContainer.def;
        this.iFrameItemplayer = <HTMLIFrameElement>document.createElement('iframe');
        this.iFrameItemplayer.setAttribute('sandbox', 'allow-forms allow-scripts allow-same-origin');
        this.iFrameItemplayer.setAttribute('class', 'unitHost');
        this.iFrameItemplayer.setAttribute('height', String(this.iFrameHostElement.clientHeight - 5));
        this.iFrameHostElement.appendChild(this.iFrameItemplayer);
        srcDoc.set(this.iFrameItemplayer, this.ds.unitAndPlayerContainer.player);
      }
    });
  }

  setPageList(validPages: string[], currentPage: string) {
    if ((validPages instanceof Array)) {
      const newPageList: PageData[] = [];
      if (validPages.length > 1) {
        for (let i = 0; i < validPages.length; i++) {
          if (i === 0) {
            newPageList.push({
              index: -1,
              id: '#previous',
              disabled: validPages[i] === currentPage,
              type: '#previous'
            });
          }

          newPageList.push({
            index: i + 1,
            id: validPages[i],
            disabled: validPages[i] === currentPage,
            type: '#goto'
          });

          if (i === validPages.length - 1) {
            newPageList.push({
              index: -1,
              id: '#next',
              disabled: validPages[i] === currentPage,
              type: '#next'
            });
          }
        }
      }
      this.pageList = newPageList;
    } else if ((this.pageList.length > 1) && (currentPage !== undefined)) {
      let currentPageIndex = 0;
      for (let i = 0; i < this.pageList.length; i++) {
        if (this.pageList[i].type === '#goto') {
          if (this.pageList[i].id === currentPage) {
            this.pageList[i].disabled = true;
            currentPageIndex = i;
          } else {
            this.pageList[i].disabled = false;
          }
        }
      }
      if (currentPageIndex === 1) {
        this.pageList[0].disabled = true;
        this.pageList[this.pageList.length - 1].disabled = false;
      } else {
        this.pageList[0].disabled = false;
        this.pageList[this.pageList.length - 1].disabled = currentPageIndex === this.pageList.length - 2;
      }
    }
  }

  gotoPage(action: string, index = 0): void {
    let nextPageId = '';
    // currentpage is detected by disabled-attribute of page
    if (action === '#next') {
      let currentPageIndex = 0;
      for (let i = 0; i < this.pageList.length; i++) {
        if ((this.pageList[i].index > 0) && (this.pageList[i].disabled)) {
          currentPageIndex = i;
          break;
        }
      }
      if ((currentPageIndex > 0) && (currentPageIndex < this.pageList.length - 2)) {
        nextPageId = this.pageList[currentPageIndex + 1].id;
      }
    } else if (action === '#previous') {
      let currentPageIndex = 0;
      for (let i = 0; i < this.pageList.length; i++) {
        if ((this.pageList[i].index > 0) && (this.pageList[i].disabled)) {
          currentPageIndex = i;
          break;
        }
      }
      if (currentPageIndex > 1) {
        nextPageId = this.pageList[currentPageIndex - 1].id;
      }
    } else if (action === '#goto') {
      if ((index > 0) && (index < this.pageList.length - 1)) {
        nextPageId = this.pageList[index].id;
      }
    } else if (index === 0) {
      // call from player
      nextPageId = action;
    }

    if (nextPageId.length > 0) {
      if (typeof this.postMessageTarget !== 'undefined') {
        this.postMessageTarget.postMessage({
          type: 'vopPageNavigationCommand',
          sessionId: this.itemplayerSessionId,
          target: nextPageId
        }, '*');
      }
    }
  }

  ngOnDestroy(): void {
    if (this.taskSubscription !== null) {
      this.taskSubscription.unsubscribe();
    }
    if (this.postMessageSubscription !== null) {
      this.postMessageSubscription.unsubscribe();
    }
  }
}

export interface PageData {
  index: number;
  id: string;
  type: '#next' | '#previous' | '#goto';
  disabled: boolean;
}
<div class="unit-check-body" fxLayout="row" fxLayoutAlign="start stretch">
  <div id="unit-title" fxLayout="column" fxLayoutAlign="center center">
    <p>{{'Bitte prüfen Sie die folgenden Aufgaben-Elemente'| customtext:'syscheck_unitPrompt' | async}}</p>
  </div>

  <div id="iFrameHost">
  </div>

  <div id="pageNav" fxLayout="row" fxLayoutAlign="end center" fxLayoutGap="10px">
    <div fxLayout="row" fxLayoutAlign="space-between center" *ngIf="pageList.length > 1">
      <div id="pageNavPrompt">
        Wähle hier andere Seiten dieser Aufgabe:
      </div>

      <div *ngFor="let p of pageList">
        <button *ngIf="p.type === '#previous'" (click)="gotoPage(p.type)" [disabled]="p.disabled" fxLayout="row" fxLayoutAlign="center center">
          <i class="material-icons">chevron_left</i>
        </button>
        <button *ngIf="p.type === '#next'" (click)="gotoPage(p.type)" [disabled]="p.disabled" fxLayout="row" fxLayoutAlign="center center">
          <i class="material-icons">chevron_right</i>
        </button>
        <div *ngIf="p.type === '#goto'" fxLayout="column">
          <div class="pageNavEnabled" *ngIf="!p.disabled"></div>
          <div class="pageNavDisabled" *ngIf="p.disabled"></div>
          <button (click)="gotoPage(p.type, p.index)" [disabled]="p.disabled">{{ p.index }}</button>
          <div class="pageNavEnabled" *ngIf="!p.disabled"></div>
          <div class="pageNavDisabled" *ngIf="p.disabled"></div>
        </div>
      </div>
    </div>
  </div>
</div>

./unit-check.component.css

.unit-check-body {
  overflow-x: auto;
  position: absolute;
  width: 100%;
  top: 10px;
  bottom: 0;
}

#iFrameHost {
  position: absolute;
  width: 100%;
  top: var(--tc-unit-title-height);
  bottom: var(--tc-unit-page-nav-height);
  padding: 0;
  background-color: white;
}

#unit-title {
  position: absolute;
  width: 100%;
  /* top: set by .tc-body */
  height: 39px;
  padding: 0;
  font-size: 1.5em;
  background-color: white;
  border-bottom: solid 1px black;
}

#pageNav {
  position: absolute;
  width: 100%;
  height: 45px;
  bottom: 0;
  padding: 0 30px;
  font-size: 1.2em;
}

#pageNavPrompt {
  padding: 2px 8px;
  color: white;
}

#pageNav button {
  font-size: 1.1em;
}

#pageNav button i {
  font-size: 1.2em;
}

.pageNavDisabled {
  height: 5px;
  background-color: orangered;
}

.pageNavEnabled {
  height: 5px;
  background-color: darkgrey;
}
Legend
Html element
Component
Html element with directive

result-matching ""

    No results matching ""