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 @@
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();
}
}