Skip to content
Snippets Groups Projects
cloze.component.ts 10.4 KiB
Newer Older
rhenck's avatar
rhenck committed
  Component, EventEmitter, Input, Output, QueryList, ViewChildren
} from '@angular/core';
import { CompoundElementComponent } from 'common/directives/compound-element.directive';
import { ElementComponent } from 'common/directives/element-component.directive';
import { ClozeElement } from 'common/models/elements/compound-elements/cloze/cloze';
rhenck's avatar
rhenck committed
import { ClozeChildOverlay } from './cloze-child-overlay.component';
rhenck's avatar
rhenck committed

rhenck's avatar
rhenck committed
// TODO background color implementieren
rhenck's avatar
rhenck committed
@Component({
  selector: 'aspect-cloze',
rhenck's avatar
rhenck committed
  template: `
    <div [style.width.%]="100"
         [style.height]="'auto'"
         [style.column-count]="elementModel.columnCount">
      <ng-container *ngFor="let part of elementModel.document?.content">
        <ul *ngIf="part.type === 'bulletList'"
            [style.font-size]="part.attrs.fontSize"
            [style.list-style]="part.attrs.listStyle">
rhenck's avatar
rhenck committed
          <li *ngFor="let listItem of part.content">
            <ng-container *ngFor="let listItemPart of $any(listItem).content"
                          [ngTemplateOutlet]="paragraphs"
                          [ngTemplateOutletContext]="{ $implicit: listItemPart }"></ng-container>
          </li>
        </ul>
        <ol *ngIf="part.type === 'orderedList'"
            [style.font-size]="part.attrs.fontSize"
            [style.list-style]="part.attrs.listStyle">
rhenck's avatar
rhenck committed
          <li *ngFor="let listItem of part.content">
            <ng-container *ngFor="let listItemPart of $any(listItem).content"
                          [ngTemplateOutlet]="paragraphs"
                          [ngTemplateOutletContext]="{ $implicit: listItemPart }"></ng-container>
          </li>
        </ol>
rhenck's avatar
rhenck committed
        <blockquote *ngIf="part.type === 'blockquote'">
          <ng-container *ngFor="let blockquotePart of $any(part).content"
                        [ngTemplateOutlet]="paragraphs"
                        [ngTemplateOutletContext]="{ $implicit: blockquotePart }"></ng-container>
        </blockquote>
        <ng-container *ngIf="part.type === 'paragraph' || part.type === 'heading'"
rhenck's avatar
rhenck committed
                      [ngTemplateOutlet]="paragraphs"
                      [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
rhenck's avatar
rhenck committed
        <img *ngIf="part.type === 'blockImage'"
             imageFullscreen [imgSrc]="$any(part.attrs.src) | safeResourceUrl"
rhenck's avatar
rhenck committed
             [src]="part.attrs.src" [alt]="$any(part.attrs.alt)">
rhenck's avatar
rhenck committed
      </ng-container>
    </div>

    <ng-template #paragraphs let-part>
      <p *ngIf="part.type === 'paragraph'"
         [style.line-height.%]="elementModel.styling.lineHeight"
         [style.color]="elementModel.styling.fontColor"
         [style.font-size.px]="elementModel.styling.fontSize"
         [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
         [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
         [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''"
         [style.margin-bottom]="part.attrs?.margin + 'px'"
         [style.margin-left]="part.attrs?.hangingIndent ? '' :
           ($any(part.attrs?.indentSize) * $any(part.attrs?.indent)) + 'px'"
         [style.text-align]="part.attrs?.textAlign"
         [style.text-indent]="part.attrs?.hangingIndent ?
           ($any(part.attrs?.indentSize) * $any(part.attrs?.indent)) + 'px' : ''">
          <ng-container [ngTemplateOutlet]="paragraphChildren"
                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
rhenck's avatar
rhenck committed
      </p>
      <h1 *ngIf="part.type === 'heading' && part.attrs.level === 1"
          [style.display]="'inline'"
          [style.line-height.%]="elementModel.styling.lineHeight"
          [style.color]="elementModel.styling.fontColor"
          [style.font-size.px]="elementModel.styling.fontSize"
          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
          <ng-container [ngTemplateOutlet]="paragraphChildren"
                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
rhenck's avatar
rhenck committed
      </h1>
      <h2 *ngIf="part.type === 'heading' && part.attrs.level === 2"
          [style.display]="'inline'"
          [style.line-height.%]="elementModel.styling.lineHeight"
          [style.color]="elementModel.styling.fontColor"
          [style.font-size.px]="elementModel.styling.fontSize"
          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
          <ng-container [ngTemplateOutlet]="paragraphChildren"
                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
rhenck's avatar
rhenck committed
      </h2>
      <h3 *ngIf="part.type === 'heading' && part.attrs.level === 3"
          [style.display]="'inline'"
          [style.line-height.%]="elementModel.styling.lineHeight"
          [style.color]="elementModel.styling.fontColor"
          [style.font-size.px]="elementModel.styling.fontSize"
          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
          <ng-container [ngTemplateOutlet]="paragraphChildren"
                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
rhenck's avatar
rhenck committed
      </h3>
      <h4 *ngIf="part.type === 'heading' && part.attrs.level === 4"
          [style.display]="'inline'"
          [style.line-height.%]="elementModel.styling.lineHeight"
          [style.color]="elementModel.styling.fontColor"
          [style.font-size.px]="elementModel.styling.fontSize"
          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
          <ng-container [ngTemplateOutlet]="paragraphChildren"
                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
rhenck's avatar
rhenck committed
      </h4>
      <h5 *ngIf="part.type === 'heading' && part.attrs.level === 5"
          [style.display]="'inline'"
          [style.line-height.%]="elementModel.styling.lineHeight"
          [style.color]="elementModel.styling.fontColor"
          [style.font-size.px]="elementModel.styling.fontSize"
          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
          <ng-container [ngTemplateOutlet]="paragraphChildren"
                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
rhenck's avatar
rhenck committed
      </h5>
      <h6 *ngIf="part.type === 'heading' && part.attrs.level === 6"
          [style.display]="'inline'"
          [style.line-height.%]="elementModel.styling.lineHeight"
          [style.color]="elementModel.styling.fontColor"
          [style.font-size.px]="elementModel.styling.fontSize"
          [style.font-weight]="elementModel.styling.bold ? 'bold' : ''"
          [style.font-style]="elementModel.styling.italic ? 'italic' : ''"
          [style.text-decoration]="elementModel.styling.underline ? 'underline' : ''">
          <ng-container [ngTemplateOutlet]="paragraphChildren"
                        [ngTemplateOutletContext]="{ $implicit: part }"></ng-container>
rhenck's avatar
rhenck committed
      </h6>
    </ng-template>

    <ng-template #paragraphChildren let-part>
      <ng-container *ngFor="let subPart of part.content">
        <ng-container *ngIf="$any(subPart).type === 'text' &&
                             (!(subPart.marks | markList | arrayIncludes:'superscript')) &&
                             (!(subPart.marks | markList | arrayIncludes:'subscript')) &&
                             (!(subPart.marks | markList | arrayIncludes:'strike'))">
          <span [ngStyle]="subPart.marks | styleMarks">{{subPart.text}}</span>
rhenck's avatar
rhenck committed
        </ng-container>
        <ng-container *ngIf="$any(subPart).type === 'text' && ((subPart.marks | markList) | arrayIncludes:'superscript')">
          <sup [ngStyle]="subPart.marks | styleMarks">{{subPart.text}}</sup>
        </ng-container>
        <ng-container *ngIf="$any(subPart).type === 'text' && ((subPart.marks | markList) | arrayIncludes:'subscript')">
          <sub [ngStyle]="subPart.marks | styleMarks">{{subPart.text}}</sub>
        </ng-container>
        <ng-container *ngIf="$any(subPart).type === 'text' && ((subPart.marks | markList) | arrayIncludes:'strike')">
          <s [ngStyle]="subPart.marks | styleMarks">{{subPart.text}}</s>
        </ng-container>
rhenck's avatar
rhenck committed
        <ng-container *ngIf="$any(subPart).type === 'inlineImage'">
rhenck's avatar
rhenck committed
          <img [src]="subPart.attrs.src" [alt]="subPart.attrs.alt"
               imageFullscreen [imgSrc]="subPart.attrs.src"
rhenck's avatar
rhenck committed
               [style.display]="'inline-block'"
               [style.height]="'1em'"
               [style.vertical-align]="'middle'">
        </ng-container>
        <aspect-compound-child-overlay
          *ngIf="ClozeElement.validChildElements | arrayIncludes:subPart.type"
          [style.display]="'inline-block'"
rhenck's avatar
rhenck committed
          [parentForm]="parentForm"
          [element]="$any(subPart).attrs.model"
          [style.vertical-align]="subPart.attrs.model.type === 'toggle-button' &&
                                    subPart.attrs.model.verticalOrientation === true ?
                                      'middle' : 'baseline'"
rhenck's avatar
rhenck committed
          [editorMode]="editorMode"
          (elementSelected)="childElementSelected.emit($event)">
        </aspect-compound-child-overlay>
rhenck's avatar
rhenck committed
      </ng-container>
rhenck's avatar
rhenck committed
    </ng-template>
rhenck's avatar
rhenck committed
    'p {margin: 0}',
rhenck's avatar
rhenck committed
    ':host ::ng-deep p strong {letter-spacing: 0.04em; font-weight: 600;}', // bold less bold
rhenck's avatar
rhenck committed
    '::ng-deep p:empty::after {content: \'\'; display: inline-block;}', // render empty p
    'p span {font-size: inherit}',
    'sup, sub {line-height: 0;}',
    '.droplist-child {vertical-align: middle;}'
rhenck's avatar
rhenck committed
})
export class ClozeComponent extends CompoundElementComponent {
rhenck's avatar
rhenck committed
  @Input() elementModel!: ClozeElement;
rhenck's avatar
rhenck committed
  @Output() childElementSelected = new EventEmitter<ClozeChildOverlay>();
  @ViewChildren(ClozeChildOverlay) compoundChildren!: QueryList<ClozeChildOverlay>;
rhenck's avatar
rhenck committed

  protected readonly ClozeElement = ClozeElement;
  editorMode: boolean = false;

  getFormElementChildrenComponents(): ElementComponent[] {
rhenck's avatar
rhenck committed
    return this.compoundChildren.map((child: ClozeChildOverlay) => child.childComponent);
rhenck's avatar
rhenck committed
  }
}