File
Implements
Metadata
selector |
iqb-unit-check |
styleUrls |
./unit-check.component.css |
templateUrl |
./unit-check.component.html |
Index
Properties
|
|
Methods
|
|
HostListeners
|
|
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
|
|
ngOnDestroy
|
ngOnDestroy()
|
|
|
setPageList
|
setPageList(validPages: string[], currentPage: string)
|
|
Parameters :
Name |
Type |
Optional |
validPages |
string[]
|
No
|
currentPage |
string
|
No
|
|
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-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 with directive