diff --git a/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.html b/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.html index 956a9ce..7b3b66b 100644 --- a/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.html +++ b/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.html @@ -1,10 +1,10 @@
- +
diff --git a/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.ts b/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.ts index a29351e..cfdf26d 100644 --- a/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.ts +++ b/nietzsche-beta-app/src/app/page-view-wrapper-component/page-view-wrapper.component.ts @@ -1,48 +1,49 @@ -import {AfterViewInit, Component, HostListener, OnInit} from '@angular/core'; +import {AfterViewInit, Component, HostListener, Input, OnInit} from '@angular/core'; import {ActivatedRoute, Params} from '@angular/router'; @Component({ selector: 'app-page-view-wrapper-component', templateUrl: './page-view-wrapper.component.html', styleUrls: ['./page-view-wrapper.component.scss'] }) export class PageViewWrapperComponent implements OnInit, AfterViewInit { + @Input() showAllLines: boolean = false; fullscreen: boolean; innerHeight: number; constructor(private activatedRoute: ActivatedRoute) { } ngOnInit() { this.innerHeight = window.innerHeight; this.activatedRoute.queryParams.subscribe( (queryParams: Params) => this.fullscreen = (queryParams.fullscreen === 'true') ); } @HostListener('window:resize', ['$event']) onResize(event) { this.ngOnInit(); } ngAfterViewInit() { window.setTimeout(() => this.logHeights(), 500); } logHeights() { console.log('Window inner height', window.innerHeight); console.log('Window outer height', window.outerHeight); const elemIds = ['wrapper', 'navigator', 'content', 'tooltip-container', 'page']; elemIds.forEach(id => { const el = document.getElementById(id); if (el) { console.log('--------------------'); console.log(id); console.log(el); // including the element's border const height = el.offsetHeight; // not including the element's border const cHeight = el.clientHeight; console.log('height with border: ', height); console.log('height without border: ', cHeight); } }); } } diff --git a/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.html b/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.html index 87c3d86..9bb13ea 100644 --- a/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.html +++ b/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.html @@ -1,27 +1,27 @@ - {{line.number}} diff --git a/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.ts b/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.ts index 3b538d2..2f95a8b 100644 --- a/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.ts +++ b/nietzsche-beta-app/src/app/page-view/margin-field/margin-field.component.ts @@ -1,198 +1,205 @@ import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core'; import { externalAssignStyle, Continuation, Identifier, Line, LineStub, TextField, Word} from '../models'; import { PageViewService } from '../page-view.service'; import { HIGHTLIGHT_CASES } from '../highlight_status'; /** * This component displays an Array of lines. **/ @Component({ selector: 'margin-field', templateUrl: './margin-field.component.html', styleUrls: ['./margin-field.component.css'] }) export class MarginFieldComponent implements OnInit, OnChanges { /** * scrollable HTML-container of this textfield **/ @Input() container: HTMLElement; /** * the hovered status for a line **/ HOVERED_STATUS: string = HIGHTLIGHT_CASES.LINE_HOVERED SELECTED_STATUS: string = HIGHTLIGHT_CASES.SELECTED_LINE /** * the currently hovered line * */ hoveredLine?: Line; /** * the currently hovered reference line * */ hoveredReferenceLine?: LineStub; /** * the currently hovered word * */ hoveredWord?: Word; /** * an Array of lines that will be displayed. **/ @Input() lines: Line[]; /** * the height of a line rect. **/ line_height: number = 8; /** * the length of the line rect. **/ line_length: number = 10; /** * x coordinate of the line rect. **/ line_x: number = 5; /** * the height of the margin field. **/ margin_height: number = 973.91998; /** * geometrical top position of the margin field. **/ margin_top: number = 0; /** * the width of the margin field. **/ margin_width: number = 30; /** * specifies reference type that should be displayed **/ @Input() showReference: string = "to" + /** + * show all lines or even lines only (default) + **/ + @Input() linesWithWords: Line[] = []; /** * The area of the image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. * The height of the text_field determines {@link #margin_height|margin_height}, while its top position * determines {@link #margin_top|margin_top}. **/ @Input() text_field: TextField; /** * The viewbox of this svg component. **/ viewBox: string = ''; /** * initial maximum height of margin field. **/ @Input() max_height: number = -1; /** * initial maximum width of margin field. **/ @Input() max_width: number = -1; /** * identifiers of selected lines that should be highlighted. **/ @Input() selectedLines: Identifier[] = []; /** * global zoom factor **/ @Input() zoomFactor: number = 1; /** * An optional function that can be passed to this component in order to return a (svg-)style object * to the line rects. This function allows the user to extend the style of this component. * E.g. by returning { fill: blue } the function overwrites the default behaviour and sets * the default highlight color to blue. **/ @Input('assignStyle') extAssignStyle?: externalAssignStyle; /** * local zoom factor **/ local_zoom: number = 1; /** * @param lineservice an information source about (un-)hovered and clicked Lines/Words. **/ constructor( private lineservice: PageViewService) { } /** * Initialize geometrical information and subscribe to {@link /injectables/PageViewService.html|PageViewService}. **/ ngOnInit() { if (this.max_height == -1 && this.max_width == -1){ this.max_height = screen.availHeight; } this.viewBox = 0 + ' ' + this.margin_top + ' ' + this.margin_width + ' ' + this.margin_height; if (this.text_field != null) { this.updateViewBox() } this.lineservice.onHoveredLine.subscribe( (changedLine: Line) => { this.hoveredLine = changedLine;} ); this.lineservice.onHoveredContinuation.subscribe( (changedContinuation: Continuation) => { this.hoveredReferenceLine = changedContinuation.reference.line;} ); this.lineservice.offHoveredContinuation.subscribe( (changedContinuation: Continuation) => { this.hoveredReferenceLine = null} ); this.lineservice.offHoveredLine.subscribe( (changedLine: Line) => { this.hoveredLine = null; } ); this.lineservice.onHoveredWord.subscribe( (changedWord: Word) => { this.hoveredWord = changedWord;} ); this.lineservice.offHoveredWord.subscribe( (changedWord: Word) => { this.hoveredWord = null; } ); } /** * Update viewBox if there is a change. **/ ngOnChanges(changes: SimpleChanges) { if (this.text_field != null) { this.updateViewBox() } } /** * Update viewBox: set * {@link #margin_height|margin_height}, * {@link #margin_top|margin_top}, * {@link #viewBox|viewBox} * and {@link #local_zoom|local_zoom} according to * {@link #text_field|text_field}. **/ private updateViewBox(){ this.lines.forEach(line =>line.datatype = "Line"); if (this.showReference == 'to'){ this.margin_width = (this.lines.some(line =>line.continuesTo != null || line.continuesTo != undefined)) ? this.line_length*2+30 : 30; } else { let hasReference = this.lines.some(line =>line.continuesFrom != null || line.continuesFrom != undefined) this.margin_width = (this.showReference == 'from' && hasReference) ? this.line_length*2+30 : 30; this.line_x = (this.showReference == 'from' && hasReference) ? 2*this.line_length : 5; } this.margin_height = this.text_field.height; this.margin_top = this.text_field.top; this.viewBox = 0 + ' ' + this.margin_top + ' ' + this.margin_width + ' ' + this.margin_height; this.local_zoom = (this.max_height != -1 && this.max_width == -1) ? this.max_height/this.text_field.height : this.max_width/this.text_field.width; if (this.max_width == -1 && this.text_field.height < this.text_field.width){ this.local_zoom = (window.innerWidth/2-100)/this.text_field.width; } } /** * Get the hover status of a line, i.e. whether it is hovered * ({@link /miscellaneous/enumerations.html#HIGHTLIGHT_CASES|HIGHTLIGHT_CASES.LINE_HOVERED}) * or not ({@link /miscellaneous/enumerations.html#HIGHTLIGHT_CASES|HIGHTLIGHT_CASES.DEFAULT}). **/ private getHoverStatus(line: Line): string { if ( (this.hoveredLine != undefined && this.hoveredLine != null && line.id == this.hoveredLine.id) || (this.hoveredReferenceLine != undefined && this.hoveredReferenceLine != null && line.id == this.hoveredReferenceLine.id) || (this.hoveredWord != undefined && this.hoveredWord != null && line.id == this.hoveredWord.line)) { return HIGHTLIGHT_CASES.LINE_HOVERED; } else if (this.selectedLines.length > 0 && this.selectedLines.indexOf(line.id) > -1) { return HIGHTLIGHT_CASES.SELECTED_LINE } else { return HIGHTLIGHT_CASES.DEFAULT; } } /** * Assign a style to the rects of a line. **/ private assignStyle(line: Line, hoveredWord: Word, hoveredLine: Line, hoverStatus: string): Object { return (this.extAssignStyle != null) ? this.extAssignStyle(line, hoveredWord, hoveredLine, hoverStatus) : {}; } + private hasWordsOnLine(line: Line) : boolean { + return this.linesWithWords.length > 0 && this.linesWithWords.indexOf(line) > -1; + } } diff --git a/nietzsche-beta-app/src/app/page-view/page-view.component.html b/nietzsche-beta-app/src/app/page-view/page-view.component.html index 0beeafb..2632442 100644 --- a/nietzsche-beta-app/src/app/page-view/page-view.component.html +++ b/nietzsche-beta-app/src/app/page-view/page-view.component.html @@ -1,50 +1,50 @@
diff --git a/nietzsche-beta-app/src/app/page-view/page-view.component.ts b/nietzsche-beta-app/src/app/page-view/page-view.component.ts index 9639e50..ce63547 100644 --- a/nietzsche-beta-app/src/app/page-view/page-view.component.ts +++ b/nietzsche-beta-app/src/app/page-view/page-view.component.ts @@ -1,173 +1,183 @@ import { Component, Input, OnInit, OnChanges} from '@angular/core'; import { externalAssignClass, externalAssignStyle, Configuration, Identifier, Image, Line, TextField, TextByForeignHand, Word} from './models'; /** * This component displays one or two {@link /components/TextFieldComponent.html|TextFieldComponent(s)} * and its or their {@link /components/MarginFieldComponent.html|MarginFieldComponent(s)}. **/ @Component({ selector: 'page-view', templateUrl: './page-view.component.html', styleUrls: ['./page-view.component.css'] }) export class PageViewComponent implements OnInit, OnChanges { @Input() configuration: Configuration; /** * the search text of words that should be highlighted as {@link /miscellaneous/enumerations.html#HIGHTLIGHT_CASES|HIGHTLIGHT_CASES.SEARCHED_WORD}. **/ @Input() findText: string; /** * first texts written by foreign hand **/ @Input() first_foreign_texts: TextByForeignHand[] = []; /** * the first image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ @Input() first_image: Image; /** * the Array of lines of the first image that will be displayed by {@link /components/MarginFieldComponent.html|MarginFieldComponent}. **/ @Input() first_lines: Line[]; + first_unevenlines: Line[] = []; /** * Identification of first textfield. **/ first_textfield_id: string = 'first textfield' /** * the Array of words of the first image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ @Input() first_words: Word[]; /** * the (initial) maximum height of the image(s). **/ @Input() max_height: number = -1; /** * the (initial) maximum width of the image(s). **/ @Input() max_width: number = -1; /** * should primary Url be used for image. Use secondary Url if false. **/ @Input() preferPrimaryUrl: boolean = true; /** * second texts written by foreign hand **/ @Input() second_foreign_texts: TextByForeignHand[] = []; /** * the second image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ @Input() second_image: Image; /** * the Array of lines of the second image that will be displayed by {@link /components/MarginFieldComponent.html|MarginFieldComponent}. **/ @Input() second_lines: Line[]; + second_unevenlines: Line[] = []; /** * Identification of second textfield. **/ second_textfield_id: string = 'second textfield' /** * the Array of words of the second image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ @Input() second_words: Word[]; /** * An optional function that will be passed to {@link /components/TextFieldComponent.html|TextFieldComponent} * in order to return a further highlight class * to the word rects when the internal function would return 'textfield unhighlighted'. **/ @Input('assignClass') assignClass?: externalAssignClass; /** * An optional function that will be passed to {@link /components/TextFieldComponent.html|TextFieldComponent} * and {@link /components/MarginFieldComponent.html|MarginFieldComponent} * in order to return a (svg-)style object * to the word and line rects. This function allows the user to extend the style of this component. * E.g. by returning { fill: blue } the function overwrites the default behaviour and sets * the default highlight color to blue. **/ @Input('assignStyle') assignStyle?: externalAssignStyle; /** * global zoom factor. **/ @Input() zoomFactor: number = 1; /** * identifiers of selected words that should be highlighted. **/ @Input() selectedWords: Identifier[] = []; /** * identifiers of selected lines that should be highlighted. **/ @Input() selectedLines: Identifier[] = []; @Input('startLine') startLineId: Identifier; @Input('endLine') endLineId: Identifier; + @Input() showAllLines: boolean = false; @Input() dontShowReference: boolean; showReferenceLeft: string = 'from'; showReferenceRight: string = 'to'; constructor() {} /** * sets {@link /components/PageViewComponent.html#max_height|max_height} if it is unset. **/ ngOnInit() { if (this.max_height == -1 && this.max_width == -1){ this.max_height = screen.availHeight; } this.checkImages(); } ngOnChanges(){ + if (this.showAllLines){ + this.dontShowReference = false; + let allLinesFirst = new Set(this.first_words.map(word =>word.line)); + let allLinesSecond = new Set(this.second_words.map(word =>word.line)); + this.first_unevenlines = this.first_lines.filter(line => (line.number % 2 == 1 && allLinesFirst.has(line.id))); + this.second_unevenlines = this.second_lines.filter(line => (line.number % 2 == 1 && allLinesSecond.has(line.id))); + } if (this.dontShowReference != undefined && this.dontShowReference != null && this.dontShowReference){ this.showReferenceLeft = ''; this.showReferenceRight = ''; } else { this.showReferenceLeft = 'from'; this.showReferenceRight = 'to'; } this.checkImages(); if (this.first_image != null && this.first_image != undefined && this.first_image.transform != null){ this.updateLines(this.first_words, this.first_lines) } if (this.second_image != null && this.second_image != undefined && this.second_image.transform != null){ this.updateLines(this.second_words, this.second_lines) } } private checkImages(){ if (this.first_image != null && this.first_image != undefined && this.startLineId != null && this.startLineId != undefined){ if(this.first_lines != null && this.first_lines != undefined && this.first_lines.length > 0){ this.first_image = this.updateTextField(this.first_image, this.first_lines); } if(this.second_lines != null && this.second_lines != undefined && this.second_lines.length > 0){ this.second_image = this.updateTextField(this.second_image, this.second_lines); } } } private updateLines(words: Word[], lines: Line[]) { for (var i = 0; i < lines.length; i++){ if (words.filter(word =>word.line == lines[i].id).length > 0){ lines[i].top = words.filter(word =>word.line == lines[i].id).map(word =>Number(word.top)).sort(function(a,b){ return a-b; })[0] lines[i].bottom = words.filter(word =>word.line == lines[i].id).map(word =>Number(word.top)+Number(word.height)).sort(function(a,b){ return b-a; })[0] } } } private updateTextField(image: Image, lines: Line[]): Image { let endLineId = (this.endLineId != null && this.endLineId != undefined) ? this.endLineId : this.startLineId; let startLines = lines.filter(line =>line.id == this.startLineId) let endLines = lines.filter(line =>line.id == endLineId) if (startLines.length > 0 && endLines.length > 0){ let top = (startLines[0].top > 10) ? startLines[0].top-10 : startLines[0].top; let height = (endLines[0].bottom-top)+10; let text_field: TextField = { top: top, left: image.text_field.left, width: image.text_field.width, height: height } return { x: image.x, y: image.y, width: image.width, height: image.height, filename: image.filename, URL: image.URL, secondaryURL: image.secondaryURL, text_field: text_field, transform: image.transform, copyright: image.copyright } } return image; } /** * Returns whether the two images can be displayed as columns. **/ private hasColumnStyle(): boolean { if (this.zoomFactor <= 1 || this.first_image == null || this.second_image == null){ return true } let newLeftWidth = this.max_height/this.first_image.text_field.height*this.zoomFactor*this.first_image.text_field.width; let newRightWidth = this.max_height/this.second_image.text_field.height*this.zoomFactor*this.second_image.text_field.width; return newLeftWidth + newRightWidth < screen.availWidth; } } diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-page-view.component.html b/nietzsche-beta-app/src/app/tln-edition/tln-page-view.component.html index 8fd3cb8..a889aa6 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-page-view.component.html +++ b/nietzsche-beta-app/src/app/tln-edition/tln-page-view.component.html @@ -1,12 +1,12 @@
diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-page-view.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-page-view.component.ts index d75ff0c..d5cf849 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-page-view.component.ts +++ b/nietzsche-beta-app/src/app/tln-edition/tln-page-view.component.ts @@ -1,243 +1,244 @@ import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core'; import { Router, ActivatedRoute, Params } from '@angular/router'; import { TlnQueryServiceInterface } from './models'; import { TlnQueryService } from './tln-query.service'; import { TlnPage} from './datatypes/page'; import { FaksimileImage } from './datatypes/faksimile_image'; import { SVGImage, SVGImageClip } from './datatypes/svg_image'; import { TlnImage } from './datatypes/image'; import { TlnLine, FaksimileLine } from './datatypes/line'; import { TlnWord, FaksimileWord } from './datatypes/word'; import { TlnTextByForeignHand, FaksimileTextByForeignHand } from './datatypes/foreign_text'; import { externalAssignClass, externalAssignStyle, Configuration, Identifier, Image, Line, Word } from './models'; import { ConfigurableComponent } from './services'; import { ComplexKeyIriMapping, DataHandler } from './data_handler'; import { DEFAULT_VIEW_OPTION, VIEW_OPTIONS, TLN_FULLSCREEN_PARAM, TLN_FIND_PARAM, TLN_PAGE_PARAM, TLN_SELECTED_LINES_PARAM, TLN_SELECTED_WORDS_PARAM, TLN_VIEW_OPTION_PARAM, TLN_MULTI_INSTANCE_ZOOM_PARAM, TLN_ZOOM_PARAM } from './constants'; import { Mapping, RouteReader } from './route-reader'; /** * Given a page IRI, this component will request all relevant information and * display the data with {@link /components/PageViewComponent.html|PageViewComponent}. **/ @Component({ selector: 'tln-page-view', templateUrl: './tln-page-view.component.html', styleUrls: ['./tln-page-view.component.css'] }) export class TlnPageViewComponent extends RouteReader implements OnInit, OnChanges { @Input() configuration: Configuration = { '*': { 'useExtendedTooltip': true }}; /** * IRI of the current page, the component will ignore page iri's from params if set. **/ @Input('page') current_iri: string; /** * the search text of words that should be highlighted as {@link /miscellaneous/enumerations.html#HIGHTLIGHT_CASES|HIGHTLIGHT_CASES.SEARCHED_WORD}. **/ @Input() findText: string; /** * whether or not to ignore the params **/ private ignoreParams: boolean = false; /** * OPTIONAL pass a queryService with method * {@link /interfaces/TlnQueryServiceInterface.html#getData|getData} * to TlnPageViewComponent. **/ @Input() queryService: TlnQueryServiceInterface; /** * global zoom factor. **/ @Input() zoomFactor: number = 1; /** * identifiers of selected words that should be highlighted. **/ @Input() selectedWords: Identifier[] = []; /** * identifiers of selected lines that should be highlighted. **/ @Input() selectedLines: Identifier[] = []; /** * the (initial) maximum height of the image. **/ @Input() max_height: number = -1; /** * the (initial) maximum width of the image, if both height and width are specified prefer width. **/ @Input() max_width: number = -1; dontShowReference: boolean = false; + @Input() showAllLines: boolean = false; @Input() startLine: Identifier; @Input() endLine: Identifier; /** * should primary Url be used for image. Use secondary Url if false. **/ @Input() preferPrimaryUrl: boolean = true; /** * selected view option, i.e. one of the following * {@link /miscellaneous/enumerations.html#VIEW_OPTIONS|VIEW_OPTIONS}. * */ @Input() selectedViewOption: string = DEFAULT_VIEW_OPTION; /** * An optional function that will be passed to {@link /components/TextFieldComponent.html|TextFieldComponent} * in order to return a further highlight class * to the word rects when the internal function would return 'textfield unhighlighted'. **/ @Input('assignClass') assignClass?: externalAssignClass; /** * An optional function that will be passed to {@link /components/TextFieldComponent.html|TextFieldComponent} * and {@link /components/MarginFieldComponent.html|MarginFieldComponent} * in order to return a (svg-)style object * to the word and line rects. This function allows the user to extend the style of this component. * E.g. by returning { fill: blue } the function overwrites the default behaviour and sets * the default highlight color to blue. **/ @Input('assignStyle') assignStyle?: externalAssignStyle; /** * the data handler of this component that retrieves * data and instantiates it according to their proper * datatypes. **/ dataHandler: DataHandler = new DataHandler(this); /** * whether or not to show page view in fullscreen mode. **/ fullscreen: boolean = false; /** * texts written by foreign hand **/ foreignTexts: TlnTextByForeignHand[] = []; /** * the (first) image to be displayed by * {@link /components/PageViewComponent.html|PageViewComponent}. **/ image: Image; /** * the Array of lines of the first image that will be displayed by {@link /components/MarginFieldComponent.html|MarginFieldComponent}. **/ lines: Line[] = []; /** * texts written by foreign hand **/ second_foreignTexts: FaksimileTextByForeignHand[] = []; /** * the second image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ second_image: Image; /** * the Array of lines of the second image that will be displayed by {@link /components/MarginFieldComponent.html|MarginFieldComponent}. **/ second_lines: Line[] = []; /** * the Array of words of the second image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ second_words: Word[] = []; /** * the Array of words of the first image that will be displayed by {@link /components/TextFieldComponent.html|TextFieldComponent}. **/ words: Word[] = []; @Input() multiInstanceMode: boolean = false; protected mapping: Mapping = { findText: { param: TLN_FIND_PARAM, type: "string" }, fullscreen: { param: TLN_FULLSCREEN_PARAM, type: "boolean" }, selectedViewOption: { param: TLN_VIEW_OPTION_PARAM, type: "string" }, selectedLines: { param: TLN_SELECTED_LINES_PARAM, type: "string" }, selectedWords: { param: TLN_SELECTED_WORDS_PARAM, type: "string" }, current_iri: { param: TLN_PAGE_PARAM, type: "string" }, zoomFactor: { param: TLN_ZOOM_PARAM, type: "number" } } /** * @param localQueryService internal query service that will be used if no external queryService is passed * to input. **/ constructor(private localQueryService: TlnQueryService, protected router: Router, protected activatedRoute: ActivatedRoute){ super(router, activatedRoute); } ngOnInit() { if (this.multiInstanceMode){ this.mapping['current_iri']['ignore'] = (this.current_iri != null); this.mapping['selectedViewOption']['ignore'] = true; this.mapping['zoomFactor']['param'] = TLN_MULTI_INSTANCE_ZOOM_PARAM; this.dontShowReference = true; //this.configuration['*']['useExtendedTooltip'] = false; } super.ngOnInit(); let tlnQueryService = (this.queryService != null) ? this.queryService : this.localQueryService; let queryConfiguration: Configuration = { '*': { 'tlnQueryService': tlnQueryService }} this.configuration = ConfigurableComponent.updateConfiguration(this.configuration, queryConfiguration) this.dataHandler.addHandler('image', { 'handler': SVGImage }); this.dataHandler.addHandler('words', { 'handler': TlnWord }); this.dataHandler.addHandler('foreignTexts', { 'handler': TlnTextByForeignHand}); this.dataHandler.addHandler('lines', { 'handler': TlnLine }); this.dataHandler.addHandler('second_image',{ 'handler': FaksimileImage }); this.dataHandler.addHandler('second_words',{ 'handler': FaksimileWord }); this.dataHandler.addHandler('second_lines',{ 'handler': FaksimileLine }); this.dataHandler.addHandler('second_foreignTexts', { 'handler': FaksimileTextByForeignHand}); this.dataHandler.addHandler('page_content',[ 'image', 'lines', 'words', 'foreignTexts' ]); this.dataHandler.addHandler('second_page_content', [ 'second_image', 'second_lines', 'second_words', 'second_foreignTexts' ] ); this.dataHandler.setQueryService(tlnQueryService); this.updatePageData(); } ngOnChanges(change: SimpleChanges) { if (this.dataHandler.ready && (change.current_iri != undefined && change.current_iri != null && !change.current_iri.firstChange) || (change.selectedViewOption != undefined && change.selectedViewOption != null && !change.selectedViewOption.firstChange)) { this.updatePageData(); } } protected readParams(params: Params){ let old_page_iri = this.current_iri; let old_selectedViewOption = this.selectedViewOption; let old_fullscreen = this.fullscreen super.readParams(params); if (this.dataHandler.ready && (old_page_iri != this.current_iri || old_selectedViewOption != this.selectedViewOption)){ this.updatePageData(); } if (old_fullscreen != this.fullscreen && !this.multiInstanceMode){ //this.dontShowReference = !this.fullscreen; //this.configuration['*']['useExtendedTooltip'] = this.fullscreen; } } /** * This function updates the page data by setting the handlers for the current * {@link #selectedViewOption|selectedViewOption} and by retrieving the data. **/ private updatePageData(){ this.dataHandler['image']['handler'] = (this.selectedViewOption != VIEW_OPTIONS.FAKSIMILE && this.selectedViewOption != VIEW_OPTIONS.SYNOPSIS_B) ? SVGImage : FaksimileImage ; this.dataHandler['words']['handler'] = (this.selectedViewOption != VIEW_OPTIONS.FAKSIMILE && this.selectedViewOption != VIEW_OPTIONS.SYNOPSIS_B) ? TlnWord : FaksimileWord ; this.dataHandler['lines']['handler'] = (this.selectedViewOption != VIEW_OPTIONS.FAKSIMILE && this.selectedViewOption != VIEW_OPTIONS.SYNOPSIS_B) ? TlnLine : FaksimileLine ; this.dataHandler['foreignTexts']['handler'] = (this.selectedViewOption != VIEW_OPTIONS.FAKSIMILE && this.selectedViewOption != VIEW_OPTIONS.SYNOPSIS_B) ? TlnTextByForeignHand : FaksimileTextByForeignHand ; if (this.dataHandler['page_content'][this.dataHandler['page_content'].length-1] == 'second_page_content'){ this.dataHandler['page_content'].pop(); this.second_image = null; this.second_foreignTexts = []; this.second_words = []; this.second_lines = []; } if (this.selectedViewOption == VIEW_OPTIONS.SYNOPSIS || this.selectedViewOption == VIEW_OPTIONS.SYNOPSIS_B){ this.dataHandler['second_image']['handler'] = (this.selectedViewOption == VIEW_OPTIONS.SYNOPSIS_B) ? SVGImage : FaksimileImage ; this.dataHandler['second_words']['handler'] = (this.selectedViewOption == VIEW_OPTIONS.SYNOPSIS_B) ? TlnWord : FaksimileWord ; this.dataHandler['second_lines']['handler'] = (this.selectedViewOption == VIEW_OPTIONS.SYNOPSIS_B) ? TlnLine : FaksimileLine ; this.dataHandler['second_foreignTexts']['handler'] = (this.selectedViewOption == VIEW_OPTIONS.SYNOPSIS_B) ? TlnTextByForeignHand : FaksimileTextByForeignHand ; this.dataHandler['page_content'].push('second_page_content'); } if (this.current_iri != null){ this.dataHandler.resetData('page_content'); if (this.startLine != null && this.startLine != undefined){ this.dataHandler['image']['handler'] = SVGImageClip ; let endLine = (this.endLine != null && this.endLine != undefined) ? this.endLine : this.startLine; let complex: ComplexKeyIriMapping = { idIndex: 0, mapping: [ { key: 'page', iri: this.current_iri}, { key: 'startLine', iri: this.startLine}, {key: 'endLine', iri: endLine} ] } this.dataHandler['page_content'] = this.dataHandler['page_content'].filter(key =>key != 'image') this.dataHandler.getData4Keys('image', complex); } else if (this.dataHandler['page_content'].indexOf('image') == -1){ this.dataHandler['page_content'].splice(0, 0, 'image') } this.dataHandler.getData('page_content', this.current_iri); } } } diff --git a/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.ts b/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.ts index 56faeb8..3cb6d76 100644 --- a/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.ts +++ b/nietzsche-beta-app/src/app/tln-edition/tln-viewer-navigation/tln-viewer-navigation.component.ts @@ -1,164 +1,164 @@ import { Component, OnInit, OnDestroy, HostListener, Input, ElementRef } from '@angular/core'; import { Router, ActivatedRoute, Params } from '@angular/router'; import {MatBottomSheet, MatBottomSheetRef} from '@angular/material/bottom-sheet'; import { TlnQueryServiceInterface, Reference, ManuscriptUnity, NavigationPage } from '../models'; import { TlnManuscriptUnity, TlnNavigationPage} from '../datatypes/navigation'; import { DEFAULT_VIEW_OPTION, TLN_VIEWER_ROUTE, TLN_FULLSCREEN_PARAM, TLN_FIND_PARAM, TLN_NAV_BAR_OPEN_STATE_PARAM, TLN_PAGE_PARAM, TLN_MANUSCRIPT_PARAM, TLN_SELECTED_LINES_PARAM, TLN_SELECTED_WORDS_PARAM, TLN_VIEW_OPTION_PARAM, TLN_ZOOM_PARAM, VIEW_OPTIONS, ONTOLOTY_PREFIX } from '../constants'; import { IsReconstructedKonvolut } from '../datatypes/basic_datatype'; import { TlnLine} from '../datatypes/line'; import { TlnWord} from '../datatypes/word'; import { TlnTextGeneticOrder} from '../datatypes/text_version'; import { Mapping } from '../route-reader'; import { RouteUpdater } from '../route-updater'; import { ComplexKeyIriMapping, DataHandler, KeyIriMapping } from '../data_handler'; import { PageViewService, TlnQueryService } from '../services'; import { TlnInformationComponent, ParentInformation } from '../tln-information/tln-information.component'; import { PageInformation } from '../tln-information/page-information'; @Component({ selector: 'tln-viewer-navigation', templateUrl: './tln-viewer-navigation.component.html', styleUrls: ['./tln-viewer-navigation.component.css'] }) export class TlnViewerNavigation extends RouteUpdater implements OnDestroy { /** * OPTIONAL pass a queryService with method * {@link /interfaces/TlnQueryServiceInterface.html#getData|getData} * to TlnPageViewComponent. **/ @Input() queryService: TlnQueryServiceInterface; /** * whether or not to show page view in fullscreen mode. **/ fullscreen: boolean = false; findText: string; current_iri: string; current_manuscript_iri: string; manuscript_unity: ManuscriptUnity; current_page: NavigationPage; pageInformation: PageInformation; previous_page: NavigationPage; next_page: NavigationPage; navBarOpenState: boolean; showArchivalManuscriptUnity: boolean = false; dataHandler: DataHandler = new DataHandler(this); geneticOrders: TlnTextGeneticOrder[] = []; selectedLines: string[] = []; selectedWords: string[] = []; private readonly increment: number = 0.333; private readonly decrement: number = this.increment*-1; - protected currentRoute: string = TLN_VIEWER_ROUTE; + //protected currentRoute: string = TLN_VIEWER_ROUTE; protected mapping: Mapping = { findText: { param: TLN_FIND_PARAM, type: "string" }, current_iri: { param: TLN_PAGE_PARAM, type: "string" }, navBarOpenState: { param: TLN_NAV_BAR_OPEN_STATE_PARAM, type: "boolean" }, current_manuscript_iri: { param: TLN_MANUSCRIPT_PARAM, type: "string" }, fullscreen: { param: TLN_FULLSCREEN_PARAM, type: "boolean" }, selectedViewOption: { param: TLN_VIEW_OPTION_PARAM, type: "string" }, selectedWords: { param: TLN_SELECTED_WORDS_PARAM, type: "string" }, selectedLines: { param: TLN_SELECTED_LINES_PARAM, type: "string" } } routerParams: Params; selectedViewOption: string = DEFAULT_VIEW_OPTION updating: boolean = false; viewOptions: string[] = [ VIEW_OPTIONS.TRANSKRIPTION, VIEW_OPTIONS.FAKSIMILE, VIEW_OPTIONS.SYNOPSIS, VIEW_OPTIONS.SYNOPSIS_B ]; subscriptions: any[] = []; constructor(el: ElementRef, private bottomSheet: MatBottomSheet, private pageViewService: PageViewService, private localQueryService: TlnQueryService, protected router: Router, protected activatedRoute: ActivatedRoute ) { super(router, activatedRoute); } ngOnInit() { let tlnQueryService = (this.queryService != null) ? this.queryService : this.localQueryService; this.dataHandler.addHandler('manuscript_unity', { 'handler': TlnManuscriptUnity, 'next_key': 'navigation_page'}); this.dataHandler.addHandler('navigation_page', ['current_page', 'geneticOrders'] ); this.dataHandler.addHandler('current_page', { 'handler': TlnNavigationPage }); this.dataHandler.addHandler('geneticOrders', { 'handler': TlnTextGeneticOrder}); this.dataHandler.setQueryService(tlnQueryService); this.subscriptions.push(this.dataHandler.start_processing.subscribe( (started: boolean) =>{ this.updating = true; })); this.subscriptions.push(this.dataHandler.processing_finished.subscribe( (finished: boolean) =>{ this.updating = false; })); super.ngOnInit(); this.subscriptions.push(this.pageViewService.reference.subscribe( (newReference: Reference) => { this.updatePageToReference(newReference) })); this.subscriptions.push(this.pageViewService.onClickedLine.subscribe( (clickedLine: TlnLine) => { let index = this.selectedLines.indexOf(clickedLine.id) if (index > -1){ this.selectedLines.splice(index, 1); } else { this.selectedLines.push(clickedLine.id); } this.updateParams(); })); this.subscriptions.push(this.pageViewService.onClickedWord.subscribe( (clickedWord: TlnWord) => { this.clickWord(clickedWord) })); } ngOnDestroy() { this.subscriptions.forEach(subscription => subscription.unsubscribe()); } private clearFindText() { this.findText = ''; this.updateParams(); } private clickWord(clickedWord: TlnWord){ let wordIndex = this.selectedWords.indexOf(clickedWord.id) let lineIndex = this.selectedLines.indexOf(clickedWord.line) if (wordIndex > -1){ this.selectedWords.splice(wordIndex, 1); } else if (lineIndex > -1){ this.selectedLines.splice(lineIndex, 1); } else { this.selectedWords.push(clickedWord.id); } this.updateParams(); } private getPageTitle(page?: NavigationPage, numPages?: number): string { if (page == null){ return ''; } let indexPrefix = (numPages != null) ? page.index + '/' + numPages : page.index; return indexPrefix + ': ' + page.title + ' ' + page.number; } protected readParams(params: Params){ super.readParams(params); if (this.dataHandler.ready && (this.current_page == null || this.current_page.id != this.current_iri)){ this.dataHandler.resetData('navigation_page') if(this.current_manuscript_iri != null){ //this.dataHandler.debug = true; /*this.dataHandler.conditionalAddHandler(IsReconstructedKonvolut.getQuery(this.current_manuscript_iri), 'current_page',{ handler: TlnNavigationPage}, { handler: TlnNavigationPage});*/ this.dataHandler.getData('manuscript_unity', this.current_manuscript_iri, this.current_iri); } else { this.dataHandler.getData('current_page', this.current_iri); } } } private setCurrentIri(pageIri: string, manuscriptIir?: string){ this.dataHandler.stop_processing.emit(true); this.current_iri = pageIri; this.updateParams(); } private showInformation() { let parentData: ParentInformation = { geneticOrders: this.geneticOrders, page: this.current_page, manuscript_iri: this.current_manuscript_iri, parentActivatedRoute: this.activatedRoute.parent } this.bottomSheet.open(TlnInformationComponent, { data: parentData }); } private updatePageToReference(reference: Reference){ this.current_iri = reference.page.id; this.selectedLines = [ reference.line.id ] this.updateParams(); } }