Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F87426694
interacted.directive.ts
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Oct 12, 15:18
Size
5 KB
Mime Type
text/x-java
Expires
Mon, Oct 14, 15:18 (2 d)
Engine
blob
Format
Raw Data
Handle
21595937
Attached To
rNIETZSCHEBETAAPP Nietzsche-Beta-App
interacted.directive.ts
View Options
import { Directive, HostListener, Input, ElementRef, OnInit} from '@angular/core';
import { PageViewService } from './page-view.service';
import { Interactable, Word, Line } from './models';
/**
* This directive informs the {@link /injectables/PageViewService.html|PageViewService} about
* mouse events on interactable objects and scrolls interactable objects in view if they are
* invisible.
**/
@Directive({
selector: '[interactedObject]'
})
export class InteractedDirective implements OnInit {
/**
* the object of this rect
**/
@Input('interactedObject') interactedObject: Interactable;
/**
* the identification string of this Interactable's textfield (e.g. 'first textfield' or 'second textfield')
**/
@Input() identity: string = 'first textfield';
/**
* the scrollable HTML-container of this Interactable's textfield.
**/
@Input() container: HTMLElement;
/**
* The time (in milliseconds) the timer should wait before
* the element is scrolled in view.
**/
delay: number = 500;
/**
* The ID of the timeout set by {@link /directives/InteractedDirective.html#timeoutScroll|timeoutScroll}.
**/
timeoutID: number = -1;
/**
* Whether or not the element should scroll into view when the timer expires.
**/
doScroll: boolean = false;
constructor(private pageViewService: PageViewService, private el: ElementRef) {}
/**
* Subscribe to on/offHovered and onClicked methods of the {@link /injectables/PageViewService.html|PageViewService}
* and scroll hovered object in view if it is invisible.
**/
ngOnInit(){
this.interactedObject.textfield_identity = this.identity;
this.pageViewService.onClickedWord.subscribe(
(clickedWord: Word) => { this.scrollIntoViewIfNeeded(clickedWord, 'Word', 0)
});
this.pageViewService.onHoveredWord.subscribe(
(hoveredWord: Word) => { this.scrollIntoViewIfNeeded(hoveredWord, 'Word')
});
this.pageViewService.offHoveredWord.subscribe(
(hoveredWord: Word) => {
this.clearTimeout()
});
this.pageViewService.offHoveredLine.subscribe(
(hoveredLine: Line) => { this.clearTimeout()
});
this.pageViewService.onHoveredLine.subscribe(
(hoveredLine: Line) => { this.scrollIntoViewIfNeeded(hoveredLine, 'Line')
});
this.pageViewService.onClickedLine.subscribe(
(clickedLine: Line) => { this.scrollIntoViewIfNeeded(clickedLine, 'Line', 0)
});
}
/**
* Clear timeout and prevent element from scrolling into view.
**/
private clearTimeout(){
if(this.timeoutID != -1){
this.doScroll = false;
clearTimeout(this.timeoutID);
this.timeoutID = -1;
}
}
/**
* Scroll interactable object in view if it is invisible.
* @param hoveredItem interactable object that is hovered
* @param hoveredType string representation of object's type (i.e. 'Word' | 'Line')
**/
private scrollIntoViewIfNeeded(hoveredItem: Interactable, hoveredType: String, delay: number= this.delay){
if (hoveredType == 'Word' && this.interactedObject.datatype == 'Word' && this.identity != hoveredItem.textfield_identity){
let hoveredWord = <Word>hoveredItem
let currentWord = <Word>this.interactedObject
if (currentWord.id == hoveredWord.id && currentWord.is_top_object && this.isElementInvisible()){
this.timeoutScroll(delay);
}
} else if (hoveredType =='Line' && this.interactedObject.datatype == 'Line'){
let hoveredLine = <Line>hoveredItem
let currentLine = <Line>this.interactedObject
if (currentLine !== hoveredLine && currentLine.id == hoveredLine.id && this.isElementInvisible()){
this.timeoutScroll(delay)
}
}
}
/**
* Scroll element in view if timeout has not been canceled during its countdown.
**/
private timeoutScroll(delay: number) {
let behavior = (delay == 0) ? "instant" : "smooth";
this.doScroll = true;
this.timeoutID = window.setTimeout(()=>{
if (this.doScroll){
this.el.nativeElement.scrollIntoView({ 'behavior': behavior});
}
}, delay);
}
/**
* Return whether interactable object is invisible, i.e. whether it is outside of
* its scrollable container's viewport.
**/
private isElementInvisible(): boolean {
if (this.container == null || this.container == undefined || this.container.getAttribute('class') == 'inline'){
return false;
}
let myRect: DOMRect = <DOMRect>this.el.nativeElement.getBoundingClientRect();
let containerRect: DOMRect = <DOMRect>this.container.getBoundingClientRect();
return myRect.top < containerRect.top
|| myRect.bottom > containerRect.bottom
|| myRect.left < containerRect.left
|| myRect.right > containerRect.right;
}
/**
* informs the {@link /injectables/PageViewService.html|PageViewService} about
* click events on {@link #interactedObject|interactedObject}.
**/
@HostListener('click', ['$event']) onMouseClick( e: MouseEvent) {
this.pageViewService.onClickService(this.interactedObject, { visible: true, layerX: e.layerX, layerY: e.layerY, clientX: e.clientX, clientY: e.clientY });
}
/**
* informs the {@link /injectables/PageViewService.html|PageViewService} about
* mouse enter events on {@link #interactedObject|interactedObject}.
**/
@HostListener('mouseenter', ['$event']) onMouseEnter( e: MouseEvent) {
this.pageViewService.onHoverService(this.interactedObject, { visible: true, layerX: e.layerX, layerY: e.layerY, clientX: e.clientX, clientY: e.clientY });
}
/**
* informs the {@link /injectables/PageViewService.html|PageViewService} about
* mouse leave events on {@link #interactedObject|interactedObject}.
**/
@HostListener('mouseleave') onMouseLeave() {
this.pageViewService.offHoverService(this.interactedObject);
}
}
Event Timeline
Log In to Comment