Newer
Older
CompoundElement,
FontElement,
FontProperties,
InputElement,
InputElementValue,
LikertColumn,
LikertRow,
PositionedElement, PositionProperties,
UIElement
} from '../../models/uI-element';
import { TextFieldElement } from '../text-field/text-field-element';
import { TextAreaElement } from '../text-area/text-area-element';
import { CheckboxElement } from '../checkbox/checkbox-element';
import { DropdownElement } from '../dropdown/dropdown-element';
import { DropListElement } from '../drop-list/drop-list';
import { initFontElement, initPositionedElement } from '../../util/unit-interface-initializer';
import { TextFieldSimpleElement } from '../textfield-simple/text-field-simple-element';
import { DropListSimpleElement } from '../drop-list-simple/drop-list-simple';
// TODO styles like em dont continue after inserted components
export class ClozeElement extends CompoundElement implements PositionedElement, FontElement {
text: string = '<p>Lorem ipsum dolor \\z sdfsdf \\i sdfsdf</p>';
parts: {
type: string;
value: string | UIElement;
style?: string;
}[][] = [];
childElements: InputElement[] = [];
constructor(serializedElement: UIElement) {
super(serializedElement);
Object.assign(this, serializedElement);
this.positionProps = initPositionedElement(serializedElement);
this.fontProps = initFontElement(serializedElement);
}
setProperty(property: string, value: InputElementValue | string[] | LikertColumn[] | LikertRow[]): void {
super.setProperty(property, value);
if (property === 'text') {
this.createParts(value as string);
}
}
private createParts(htmlText: string): void {
const elementList = ClozeElement.readElementArray(htmlText);
elementList.forEach((element: HTMLParagraphElement | HTMLHeadingElement, i: number) => {
this.parseParagraphs(element, i);
private static readElementArray(htmlText: string): (HTMLParagraphElement | HTMLHeadingElement)[] {
const el = document.createElement('html');
el.innerHTML = htmlText;
return Array.from(el.children[1].children) as (HTMLParagraphElement | HTMLHeadingElement)[];
private parseParagraphs(element: HTMLParagraphElement | HTMLHeadingElement, partIndex: number): void {
this.parts[partIndex] = []; // init array to be able to push
let [nextSpecialElementIndex, nextElementType] = ClozeElement.getNextSpecialElement(element.innerHTML);
let indexOffset = 0;
while (nextSpecialElementIndex !== -1) {
nextSpecialElementIndex += indexOffset;
this.parts[partIndex].push({
type: element.localName,
value: element.innerHTML.substring(indexOffset, nextSpecialElementIndex),
style: element.style.cssText
});
const newElement = ClozeElement.createElement(nextElementType);
this.childElements.push(newElement);
this.parts[partIndex].push({ type: nextElementType, value: newElement });
indexOffset = nextSpecialElementIndex + 2; // + 2 to get rid of the marker, i.e. '\b'
[nextSpecialElementIndex, nextElementType] =
ClozeElement.getNextSpecialElement(element.innerHTML.substring(indexOffset));
this.parts[partIndex].push({
type: element.localName,
value: element.innerHTML.substring(indexOffset),
style: element.style.cssText
});
}
private static getNextSpecialElement(p: string): [number, string] {
const x = [];
if (p.indexOf('\\d') > 0) {
x.push(p.indexOf('\\d'));
}
if (p.indexOf('\\i') > 0) {
x.push(p.indexOf('\\i'));
}
if (p.indexOf('\\z') > 0) {
x.push(p.indexOf('\\z'));
}
const y = Math.min(...x);
let nextElementType = '';
switch (p[y + 1]) {
case 'd': nextElementType = 'dropdown'; break;
case 'i': nextElementType = 'text-field'; break;
case 'z': nextElementType = 'drop-list'; break;
default: return [-1, 'unknown'];
}
return [y, nextElementType];
}
private static createElement(elementType: string): InputElement {
const elementModel: UIElement = { type: elementType } as UIElement;
let newElement: InputElement;
newElement = new TextFieldSimpleElement(elementModel);
(newElement as TextFieldElement).label = '';
break;
case 'text-area':
newElement = new TextAreaElement(elementModel);
break;
case 'checkbox':
newElement = new CheckboxElement(elementModel);
break;
case 'dropdown':
newElement = new DropdownElement(elementModel);
break;
case 'drop-list':
newElement = new DropListElement(elementModel);
newElement.height = 30;
newElement.width = 100;