improving lightbox
bug fixes with new image loading and fullscreen mode
This commit is contained in:
parent
52544ae956
commit
f1d8364a2e
@ -30,6 +30,7 @@ import {Config} from "./config/Config";
|
|||||||
import {GalleryMapComponent} from "./gallery/map/map.gallery.component";
|
import {GalleryMapComponent} from "./gallery/map/map.gallery.component";
|
||||||
import {GalleryMapLightboxComponent} from "./gallery/map/lightbox/lightbox.map.gallery.component";
|
import {GalleryMapLightboxComponent} from "./gallery/map/lightbox/lightbox.map.gallery.component";
|
||||||
import {ThumbnailManagerService} from "./gallery/thumnailManager.service";
|
import {ThumbnailManagerService} from "./gallery/thumnailManager.service";
|
||||||
|
import {OverlayService} from "./gallery/overlay.service";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -68,7 +69,8 @@ import {ThumbnailManagerService} from "./gallery/thumnailManager.service";
|
|||||||
AuthenticationService,
|
AuthenticationService,
|
||||||
ThumbnailLoaderService,
|
ThumbnailLoaderService,
|
||||||
ThumbnailManagerService,
|
ThumbnailManagerService,
|
||||||
FullScreenService],
|
FullScreenService,
|
||||||
|
OverlayService],
|
||||||
|
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
import {Injectable} from "@angular/core";
|
import {Injectable} from "@angular/core";
|
||||||
|
import {Event} from "../../../common/event/Event";
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FullScreenService {
|
export class FullScreenService {
|
||||||
|
|
||||||
|
|
||||||
|
OnFullScreenChange = new Event<boolean>();
|
||||||
|
|
||||||
public isFullScreenEnabled(): boolean {
|
public isFullScreenEnabled(): boolean {
|
||||||
return !!(document.fullscreenElement || document['mozFullScreenElement'] || document.webkitFullscreenElement);
|
return !!(document.fullscreenElement || document['mozFullScreenElement'] || document.webkitFullscreenElement);
|
||||||
}
|
}
|
||||||
@ -22,6 +25,7 @@ export class FullScreenService {
|
|||||||
} else if (element.msRequestFullscreen) {
|
} else if (element.msRequestFullscreen) {
|
||||||
element.msRequestFullscreen();
|
element.msRequestFullscreen();
|
||||||
}
|
}
|
||||||
|
this.OnFullScreenChange.trigger(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public exitFullScreen() {
|
public exitFullScreen() {
|
||||||
@ -36,6 +40,7 @@ export class FullScreenService {
|
|||||||
} else if (document.webkitExitFullscreen) {
|
} else if (document.webkitExitFullscreen) {
|
||||||
document.webkitExitFullscreen();
|
document.webkitExitFullscreen();
|
||||||
}
|
}
|
||||||
|
this.OnFullScreenChange.trigger(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,14 @@
|
|||||||
import {
|
import {
|
||||||
Component,
|
|
||||||
Input,
|
|
||||||
ElementRef,
|
|
||||||
OnChanges,
|
|
||||||
ViewChild,
|
|
||||||
ViewChildren,
|
|
||||||
QueryList,
|
|
||||||
AfterViewInit,
|
AfterViewInit,
|
||||||
HostListener
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
ElementRef,
|
||||||
|
HostListener,
|
||||||
|
Input,
|
||||||
|
OnChanges,
|
||||||
|
QueryList,
|
||||||
|
ViewChild,
|
||||||
|
ViewChildren
|
||||||
} from "@angular/core";
|
} from "@angular/core";
|
||||||
import {PhotoDTO} from "../../../../common/entities/PhotoDTO";
|
import {PhotoDTO} from "../../../../common/entities/PhotoDTO";
|
||||||
import {GridRowBuilder} from "./GridRowBuilder";
|
import {GridRowBuilder} from "./GridRowBuilder";
|
||||||
@ -15,31 +16,33 @@ import {GalleryLightboxComponent} from "../lightbox/lightbox.gallery.component";
|
|||||||
import {GridPhoto} from "./GridPhoto";
|
import {GridPhoto} from "./GridPhoto";
|
||||||
import {GalleryPhotoComponent} from "./photo/photo.grid.gallery.component";
|
import {GalleryPhotoComponent} from "./photo/photo.grid.gallery.component";
|
||||||
import {Config} from "../../config/Config";
|
import {Config} from "../../config/Config";
|
||||||
|
import {OverlayService} from "../overlay.service";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'gallery-grid',
|
selector: 'gallery-grid',
|
||||||
templateUrl: 'app/gallery/grid/grid.gallery.component.html',
|
templateUrl: 'app/gallery/grid/grid.gallery.component.html',
|
||||||
styleUrls: ['app/gallery/grid/grid.gallery.component.css'],
|
styleUrls: ['app/gallery/grid/grid.gallery.component.css'],
|
||||||
})
|
})
|
||||||
export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
export class GalleryGridComponent implements OnChanges, AfterViewInit {
|
||||||
|
|
||||||
@ViewChild('gridContainer') gridContainer:ElementRef;
|
@ViewChild('gridContainer') gridContainer: ElementRef;
|
||||||
@ViewChildren(GalleryPhotoComponent) gridPhotoQL:QueryList<GalleryPhotoComponent>;
|
@ViewChildren(GalleryPhotoComponent) gridPhotoQL: QueryList<GalleryPhotoComponent>;
|
||||||
|
|
||||||
@Input() photos: Array<PhotoDTO>;
|
@Input() photos: Array<PhotoDTO>;
|
||||||
@Input() lightbox:GalleryLightboxComponent;
|
@Input() lightbox: GalleryLightboxComponent;
|
||||||
|
|
||||||
photosToRender:Array<GridPhoto> = [];
|
photosToRender: Array<GridPhoto> = [];
|
||||||
containerWidth:number = 0;
|
containerWidth: number = 0;
|
||||||
|
|
||||||
private IMAGE_MARGIN = 2;
|
private IMAGE_MARGIN = 2;
|
||||||
private TARGET_COL_COUNT = 5;
|
private TARGET_COL_COUNT = 5;
|
||||||
private MIN_ROW_COUNT = 2;
|
private MIN_ROW_COUNT = 2;
|
||||||
private MAX_ROW_COUNT = 5;
|
private MAX_ROW_COUNT = 5;
|
||||||
|
|
||||||
onScrollFired = false;
|
private onScrollFired = false;
|
||||||
|
private scrollbarWidth = 0;
|
||||||
|
|
||||||
constructor() {
|
constructor(private overlayService: OverlayService, private changeDetector: ChangeDetectorRef) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges() {
|
ngOnChanges() {
|
||||||
@ -61,16 +64,17 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
}
|
}
|
||||||
this.updateContainerWidth();
|
this.updateContainerWidth();
|
||||||
this.sortPhotos();
|
this.sortPhotos();
|
||||||
|
//render the same amount of images on resize
|
||||||
|
let renderedIndex = this.renderedPhotoIndex;
|
||||||
this.clearRenderedPhotos();
|
this.clearRenderedPhotos();
|
||||||
setImmediate(() => {
|
this.renderPhotos(renderedIndex);
|
||||||
this.renderPhotos();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isAfterViewInit:boolean = false;
|
|
||||||
|
isAfterViewInit: boolean = false;
|
||||||
|
|
||||||
ngAfterViewInit() {
|
ngAfterViewInit() {
|
||||||
this.lightbox.gridPhotoQL = this.gridPhotoQL;
|
this.lightbox.setGridPhotoQL(this.gridPhotoQL);
|
||||||
|
|
||||||
//TODO: implement scroll detection
|
//TODO: implement scroll detection
|
||||||
|
|
||||||
@ -96,6 +100,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
private clearRenderedPhotos() {
|
private clearRenderedPhotos() {
|
||||||
this.photosToRender = [];
|
this.photosToRender = [];
|
||||||
this.renderedPhotoIndex = 0;
|
this.renderedPhotoIndex = 0;
|
||||||
|
this.changeDetector.detectChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private mergeNewPhotos() {
|
private mergeNewPhotos() {
|
||||||
@ -123,9 +128,9 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private renderedPhotoIndex:number = 0;
|
private renderedPhotoIndex: number = 0;
|
||||||
|
|
||||||
private renderPhotos() {
|
private renderPhotos(numberOfPhotos: number = 0) {
|
||||||
if (this.containerWidth == 0 || this.renderedPhotoIndex >= this.photos.length || !this.shouldRenderMore()) {
|
if (this.containerWidth == 0 || this.renderedPhotoIndex >= this.photos.length || !this.shouldRenderMore()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -133,7 +138,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
|
|
||||||
let renderedContentHeight = 0;
|
let renderedContentHeight = 0;
|
||||||
|
|
||||||
while (this.renderedPhotoIndex < this.photos.length && this.shouldRenderMore(renderedContentHeight) === true) {
|
while (this.renderedPhotoIndex < this.photos.length && (this.shouldRenderMore(renderedContentHeight) === true || this.renderedPhotoIndex < numberOfPhotos)) {
|
||||||
let ret = this.renderARow();
|
let ret = this.renderARow();
|
||||||
if (ret === null) {
|
if (ret === null) {
|
||||||
throw new Error("Gridphotos rendering failed");
|
throw new Error("Gridphotos rendering failed");
|
||||||
@ -149,7 +154,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
* @param offset Add height to the client height (conent is not yet added to the dom, but calculate with it)
|
* @param offset Add height to the client height (conent is not yet added to the dom, but calculate with it)
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
private shouldRenderMore(offset:number = 0):boolean {
|
private shouldRenderMore(offset: number = 0): boolean {
|
||||||
return Config.Client.enableOnScrollRendering === false ||
|
return Config.Client.enableOnScrollRendering === false ||
|
||||||
window.scrollY >= (document.body.clientHeight + offset - window.innerHeight) * 0.7
|
window.scrollY >= (document.body.clientHeight + offset - window.innerHeight) * 0.7
|
||||||
|| (document.body.clientHeight + offset) * 0.85 < window.innerHeight;
|
|| (document.body.clientHeight + offset) * 0.85 < window.innerHeight;
|
||||||
@ -164,7 +169,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
this.renderPhotos();
|
this.renderPhotos();
|
||||||
|
|
||||||
if (Config.Client.enableOnScrollThumbnailPrioritising === true) {
|
if (Config.Client.enableOnScrollThumbnailPrioritising === true) {
|
||||||
this.gridPhotoQL.toArray().forEach((pc:GalleryPhotoComponent) => {
|
this.gridPhotoQL.toArray().forEach((pc: GalleryPhotoComponent) => {
|
||||||
pc.onScroll();
|
pc.onScroll();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -174,15 +179,16 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public renderARow():number {
|
public renderARow(): number {
|
||||||
if (this.renderedPhotoIndex >= this.photos.length) {
|
if (this.renderedPhotoIndex >= this.photos.length) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let maxRowHeight = window.innerHeight / this.MIN_ROW_COUNT;
|
let maxRowHeight = window.innerHeight / this.MIN_ROW_COUNT;
|
||||||
let minRowHeight = window.innerHeight / this.MAX_ROW_COUNT;
|
let minRowHeight = window.innerHeight / this.MAX_ROW_COUNT;
|
||||||
|
|
||||||
let photoRowBuilder = new GridRowBuilder(this.photos, this.renderedPhotoIndex, this.IMAGE_MARGIN, this.containerWidth);
|
let photoRowBuilder = new GridRowBuilder(this.photos, this.renderedPhotoIndex, this.IMAGE_MARGIN, this.containerWidth - this.overlayService.getPhantomScrollbarWidth());
|
||||||
photoRowBuilder.addPhotos(this.TARGET_COL_COUNT);
|
photoRowBuilder.addPhotos(this.TARGET_COL_COUNT);
|
||||||
photoRowBuilder.adjustRowHeightBetween(minRowHeight, maxRowHeight);
|
photoRowBuilder.adjustRowHeightBetween(minRowHeight, maxRowHeight);
|
||||||
|
|
||||||
@ -198,7 +204,7 @@ export class GalleryGridComponent implements OnChanges,AfterViewInit {
|
|||||||
return rowHeight;
|
return rowHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
private updateContainerWidth():number {
|
private updateContainerWidth(): number {
|
||||||
if (!this.gridContainer) {
|
if (!this.gridContainer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -37,9 +37,11 @@
|
|||||||
<span class="glyphicon glyphicon-remove highlight" (click)="hide()" title="close"></span>
|
<span class="glyphicon glyphicon-remove highlight" (click)="hide()" title="close"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="navigation-arrow highlight" *ngIf="navigation.hasPrev" id="leftArrow" (click)="prevImage()"><span
|
<div class="navigation-arrow highlight" *ngIf="navigation.hasPrev" title="key: left arrow" id="leftArrow"
|
||||||
|
(click)="prevImage()"><span
|
||||||
class="glyphicon glyphicon-chevron-left"></span></div>
|
class="glyphicon glyphicon-chevron-left"></span></div>
|
||||||
<div class="navigation-arrow highlight" *ngIf="navigation.hasNext" id="rightArrow" (click)="nextImage()"><span
|
<div class="navigation-arrow highlight" *ngIf="navigation.hasNext" title="key: right arrow" id="rightArrow"
|
||||||
|
(click)="nextImage()"><span
|
||||||
class="glyphicon glyphicon-chevron-right"></span></div>
|
class="glyphicon glyphicon-chevron-right"></span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,8 +1,19 @@
|
|||||||
import {Component, QueryList, Output, EventEmitter, HostListener, ElementRef, ViewChild} from "@angular/core";
|
import {
|
||||||
|
ChangeDetectorRef,
|
||||||
|
Component,
|
||||||
|
ElementRef,
|
||||||
|
EventEmitter,
|
||||||
|
HostListener,
|
||||||
|
Output,
|
||||||
|
QueryList,
|
||||||
|
ViewChild
|
||||||
|
} from "@angular/core";
|
||||||
import {PhotoDTO} from "../../../../common/entities/PhotoDTO";
|
import {PhotoDTO} from "../../../../common/entities/PhotoDTO";
|
||||||
import {GalleryPhotoComponent} from "../grid/photo/photo.grid.gallery.component";
|
import {GalleryPhotoComponent} from "../grid/photo/photo.grid.gallery.component";
|
||||||
import {Dimension} from "../../model/IRenderable";
|
import {Dimension} from "../../model/IRenderable";
|
||||||
import {FullScreenService} from "../fullscreen.service";
|
import {FullScreenService} from "../fullscreen.service";
|
||||||
|
import {OverlayService} from "../overlay.service";
|
||||||
|
import {Subscription} from "rxjs";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'gallery-lightbox',
|
selector: 'gallery-lightbox',
|
||||||
@ -19,62 +30,80 @@ export class GalleryLightboxComponent {
|
|||||||
public blackCanvasOpacity: any = 0;
|
public blackCanvasOpacity: any = 0;
|
||||||
|
|
||||||
private activePhoto: GalleryPhotoComponent;
|
private activePhoto: GalleryPhotoComponent;
|
||||||
public gridPhotoQL: QueryList<GalleryPhotoComponent>;
|
private gridPhotoQL: QueryList<GalleryPhotoComponent>;
|
||||||
|
|
||||||
private visible = false;
|
private visible = false;
|
||||||
|
private changeSubscription: Subscription = null;
|
||||||
|
|
||||||
@ViewChild("root") elementRef: ElementRef;
|
@ViewChild("root") elementRef: ElementRef;
|
||||||
|
|
||||||
|
|
||||||
constructor(private fullScreenService: FullScreenService) {
|
constructor(private fullScreenService: FullScreenService, private changeDetector: ChangeDetectorRef, private overlayService: OverlayService) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//noinspection JSUnusedGlobalSymbols
|
||||||
|
@HostListener('window:resize', ['$event'])
|
||||||
|
onResize() {
|
||||||
|
if (this.activePhoto) {
|
||||||
|
this.disableAnimation();
|
||||||
|
this.lightboxDimension.width = this.getScreenWidth();
|
||||||
|
this.lightboxDimension.height = this.getScreenHeight();
|
||||||
|
this.updateActivePhoto(this.activePhotoId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public nextImage() {
|
public nextImage() {
|
||||||
|
|
||||||
this.disableAnimation();
|
this.disableAnimation();
|
||||||
let pcList = this.gridPhotoQL.toArray();
|
if (this.activePhotoId + 1 < this.gridPhotoQL.length) {
|
||||||
for (let i = 0; i < pcList.length; i++) {
|
this.showPhoto(this.activePhotoId + 1);
|
||||||
if (pcList[i] === this.activePhoto) {
|
if (this.activePhotoId + 3 >= this.gridPhotoQL.length) {
|
||||||
if (i + 1 < pcList.length) {
|
this.onLastElement.emit({}); //trigger to render more photos if there are
|
||||||
this.showPhoto(pcList[i + 1]);
|
|
||||||
|
|
||||||
if (i + 3 === pcList.length) {
|
|
||||||
this.onLastElement.emit({}); //trigger to render more photos if there are
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
console.warn("can't find photo to show next");
|
||||||
}
|
}
|
||||||
|
|
||||||
public prevImage() {
|
public prevImage() {
|
||||||
this.disableAnimation();
|
this.disableAnimation();
|
||||||
let pcList = this.gridPhotoQL.toArray();
|
if (this.activePhotoId > 0) {
|
||||||
for (let i = 0; i < pcList.length; i++) {
|
this.showPhoto(this.activePhotoId - 1);
|
||||||
if (pcList[i] === this.activePhoto) {
|
return;
|
||||||
if (i > 0) {
|
|
||||||
this.showPhoto(pcList[i - 1]);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
console.warn("can't find photo to show prev");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private showPhoto(photoComponent: GalleryPhotoComponent) {
|
activePhotoId: number = null;
|
||||||
|
|
||||||
|
private showPhoto(photoIndex: number) {
|
||||||
|
this.activePhoto = null;
|
||||||
|
this.changeDetector.detectChanges();
|
||||||
|
this.updateActivePhoto(photoIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private updateActivePhoto(photoIndex: number) {
|
||||||
let pcList = this.gridPhotoQL.toArray();
|
let pcList = this.gridPhotoQL.toArray();
|
||||||
|
|
||||||
let index = pcList.indexOf(photoComponent);
|
|
||||||
if (index == -1) {
|
if (photoIndex < 0 || photoIndex > this.gridPhotoQL.length) {
|
||||||
throw new Error("Can't find the photo");
|
throw new Error("Can't find the photo");
|
||||||
}
|
}
|
||||||
|
this.activePhotoId = photoIndex;
|
||||||
|
this.activePhoto = pcList[photoIndex];
|
||||||
|
|
||||||
|
this.photoDimension = this.calcLightBoxPhotoDimension(this.activePhoto.gridPhoto.photo);
|
||||||
|
this.navigation.hasPrev = photoIndex > 0;
|
||||||
|
this.navigation.hasNext = photoIndex + 1 < pcList.length;
|
||||||
|
|
||||||
|
let to = this.activePhoto.getDimension();
|
||||||
|
|
||||||
|
//if target image out of screen -> scroll to there
|
||||||
|
if (this.getBodyScrollTop() > to.top || this.getBodyScrollTop() + this.getScreenHeight() < to.top) {
|
||||||
|
this.setBodyScrollTop(to.top);
|
||||||
|
}
|
||||||
|
|
||||||
this.photoDimension = this.calcLightBoxPhotoDimension(photoComponent.gridPhoto.photo);
|
|
||||||
this.navigation.hasPrev = index > 0;
|
|
||||||
this.navigation.hasNext = index + 1 < pcList.length;
|
|
||||||
this.activePhoto = photoComponent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public show(photo: PhotoDTO) {
|
public show(photo: PhotoDTO) {
|
||||||
@ -90,8 +119,8 @@ export class GalleryLightboxComponent {
|
|||||||
this.blackCanvasOpacity = 0;
|
this.blackCanvasOpacity = 0;
|
||||||
this.photoDimension = selectedPhoto.getDimension();
|
this.photoDimension = selectedPhoto.getDimension();
|
||||||
|
|
||||||
document.getElementsByTagName('body')[0].style.overflow = 'hidden';
|
//disable scroll
|
||||||
|
this.overlayService.showOverlay();
|
||||||
setImmediate(() => {
|
setImmediate(() => {
|
||||||
this.lightboxDimension = <Dimension>{
|
this.lightboxDimension = <Dimension>{
|
||||||
top: 0,
|
top: 0,
|
||||||
@ -100,19 +129,13 @@ export class GalleryLightboxComponent {
|
|||||||
height: this.getScreenHeight()
|
height: this.getScreenHeight()
|
||||||
};
|
};
|
||||||
this.blackCanvasOpacity = 1.0;
|
this.blackCanvasOpacity = 1.0;
|
||||||
this.showPhoto(selectedPhoto);
|
this.showPhoto(this.gridPhotoQL.toArray().indexOf(selectedPhoto));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public hide() {
|
public hide() {
|
||||||
this.enableAnimation();
|
this.enableAnimation();
|
||||||
this.fullScreenService.exitFullScreen();
|
this.fullScreenService.exitFullScreen();
|
||||||
let to = this.activePhoto.getDimension();
|
|
||||||
|
|
||||||
//iff target image out of screen -> scroll to there
|
|
||||||
if (this.getBodyScrollTop() > to.top || this.getBodyScrollTop() + this.getScreenHeight() < to.top) {
|
|
||||||
this.setBodyScrollTop(to.top);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.lightboxDimension = this.activePhoto.getDimension();
|
this.lightboxDimension = this.activePhoto.getDimension();
|
||||||
this.lightboxDimension.top -= this.getBodyScrollTop();
|
this.lightboxDimension.top -= this.getBodyScrollTop();
|
||||||
@ -121,13 +144,24 @@ export class GalleryLightboxComponent {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
this.activePhoto = null;
|
this.activePhoto = null;
|
||||||
document.getElementsByTagName('body')[0].style.overflow = 'scroll';
|
this.overlayService.hideOverlay();
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setGridPhotoQL(value: QueryList<GalleryPhotoComponent>) {
|
||||||
|
if (this.changeSubscription != null) {
|
||||||
|
this.changeSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
this.gridPhotoQL = value;
|
||||||
|
this.changeSubscription = this.gridPhotoQL.changes.subscribe(() => {
|
||||||
|
if (this.activePhotoId != null && this.gridPhotoQL.length > this.activePhotoId) {
|
||||||
|
this.updateActivePhoto(this.activePhotoId);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private findPhotoComponent(photo: any) {
|
private findPhotoComponent(photo: any) {
|
||||||
let galleryPhotoComponents = this.gridPhotoQL.toArray();
|
let galleryPhotoComponents = this.gridPhotoQL.toArray();
|
||||||
for (let i = 0; i < galleryPhotoComponents.length; i++) {
|
for (let i = 0; i < galleryPhotoComponents.length; i++) {
|
||||||
@ -138,15 +172,26 @@ export class GalleryLightboxComponent {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//noinspection JSUnusedGlobalSymbols
|
||||||
@HostListener('window:keydown', ['$event'])
|
@HostListener('window:keydown', ['$event'])
|
||||||
onKeyPress(e: KeyboardEvent) {
|
onKeyPress(e: KeyboardEvent) {
|
||||||
|
if (this.visible != true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
let event: KeyboardEvent = window.event ? <any>window.event : e;
|
let event: KeyboardEvent = window.event ? <any>window.event : e;
|
||||||
switch (event.keyCode) {
|
switch (event.keyCode) {
|
||||||
case 37:
|
case 37:
|
||||||
this.prevImage();
|
if (this.activePhotoId > 0) {
|
||||||
|
this.prevImage();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 39:
|
case 39:
|
||||||
this.nextImage();
|
if (this.activePhotoId < this.gridPhotoQL.length - 1) {
|
||||||
|
this.nextImage();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 27: //escape
|
||||||
|
this.hide();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,12 +4,13 @@
|
|||||||
[style.height.%]="imageSize.height"
|
[style.height.%]="imageSize.height"
|
||||||
[src]="thumbnailPath()"/>
|
[src]="thumbnailPath()"/>
|
||||||
|
|
||||||
<img *ngIf="gridPhoto"
|
<img *ngIf="gridPhoto !== null"
|
||||||
[style.width.%]="imageSize.width"
|
[style.width.%]="imageSize.width"
|
||||||
[style.height.%]="imageSize.height"
|
[style.height.%]="imageSize.height"
|
||||||
[src]="gridPhoto.getPhotoPath()"
|
[src]="gridPhoto.getPhotoPath()"
|
||||||
(load)="onImageLoad()"
|
(load)="onImageLoad()"
|
||||||
(error)="onImageError()"/>
|
(error)="onImageError()"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import {Component, OnChanges, Input, ViewChild, ElementRef} from "@angular/core";
|
import {Component, Input, OnChanges} from "@angular/core";
|
||||||
import {GridPhoto} from "../../grid/GridPhoto";
|
import {GridPhoto} from "../../grid/GridPhoto";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -8,12 +8,11 @@ import {GridPhoto} from "../../grid/GridPhoto";
|
|||||||
})
|
})
|
||||||
export class GalleryLightboxPhotoComponent implements OnChanges {
|
export class GalleryLightboxPhotoComponent implements OnChanges {
|
||||||
|
|
||||||
@Input() gridPhoto:GridPhoto;
|
@Input() gridPhoto: GridPhoto;
|
||||||
|
|
||||||
public imageSize = {width: "auto", height: "100"};
|
public imageSize = {width: "auto", height: "100"};
|
||||||
@ViewChild('imgContainer') nativeElement:ElementRef;
|
|
||||||
|
|
||||||
imageLoaded:boolean = false;
|
imageLoaded: boolean = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
}
|
}
|
||||||
@ -48,12 +47,12 @@ export class GalleryLightboxPhotoComponent implements OnChanges {
|
|||||||
console.error("cant load image");
|
console.error("cant load image");
|
||||||
}
|
}
|
||||||
|
|
||||||
public showThumbnail():boolean {
|
public showThumbnail(): boolean {
|
||||||
return this.gridPhoto && !this.imageLoaded &&
|
return this.gridPhoto && !this.imageLoaded &&
|
||||||
(this.gridPhoto.isThumbnailAvailable() || this.gridPhoto.isReplacementThumbnailAvailable());
|
(this.gridPhoto.isThumbnailAvailable() || this.gridPhoto.isReplacementThumbnailAvailable());
|
||||||
}
|
}
|
||||||
|
|
||||||
public thumbnailPath():string {
|
public thumbnailPath(): string {
|
||||||
if (this.gridPhoto.isThumbnailAvailable() === true)
|
if (this.gridPhoto.isThumbnailAvailable() === true)
|
||||||
return this.gridPhoto.getThumbnailPath();
|
return this.gridPhoto.getThumbnailPath();
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import {Component, Input, OnChanges, ElementRef, ViewChild} from "@angular/core";
|
import {Component, ElementRef, HostListener, Input, OnChanges, ViewChild} from "@angular/core";
|
||||||
import {PhotoDTO} from "../../../../../common/entities/PhotoDTO";
|
import {PhotoDTO} from "../../../../../common/entities/PhotoDTO";
|
||||||
import {Dimension} from "../../../model/IRenderable";
|
import {Dimension} from "../../../model/IRenderable";
|
||||||
import {FullScreenService} from "../../fullscreen.service";
|
import {FullScreenService} from "../../fullscreen.service";
|
||||||
import {SebmGoogleMap} from "angular2-google-maps/core";
|
import {SebmGoogleMap} from "angular2-google-maps/core";
|
||||||
import {ThumbnailManagerService, IconThumbnail} from "../../thumnailManager.service";
|
import {IconThumbnail, ThumbnailManagerService} from "../../thumnailManager.service";
|
||||||
import {IconPhoto} from "../../IconPhoto";
|
import {IconPhoto} from "../../IconPhoto";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -138,6 +138,20 @@ export class GalleryMapLightboxComponent implements OnChanges {
|
|||||||
return window.innerHeight;
|
return window.innerHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//noinspection JSUnusedGlobalSymbols
|
||||||
|
@HostListener('window:keydown', ['$event'])
|
||||||
|
onKeyPress(e: KeyboardEvent) {
|
||||||
|
if (this.visible != true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let event: KeyboardEvent = window.event ? <any>window.event : e;
|
||||||
|
switch (event.keyCode) {
|
||||||
|
case 27: //escape
|
||||||
|
this.hide();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
60
frontend/app/gallery/overlay.service.ts
Normal file
60
frontend/app/gallery/overlay.service.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import {Injectable} from "@angular/core";
|
||||||
|
import {Event} from "../../../common/event/Event";
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class OverlayService {
|
||||||
|
|
||||||
|
OnOverlayChange = new Event<boolean>();
|
||||||
|
private scrollWidth: number = null;
|
||||||
|
|
||||||
|
public showOverlay() {
|
||||||
|
|
||||||
|
//disable scrolling
|
||||||
|
document.getElementsByTagName('body')[0].style.overflow = 'hidden';
|
||||||
|
this.OnOverlayChange.trigger(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public hideOverlay() {
|
||||||
|
|
||||||
|
document.getElementsByTagName('body')[0].style.overflowY = 'scroll';
|
||||||
|
this.OnOverlayChange.trigger(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
getScrollbarWidth() {
|
||||||
|
if (this.scrollWidth == null) {
|
||||||
|
|
||||||
|
|
||||||
|
let outer = document.createElement("div");
|
||||||
|
outer.style.visibility = "hidden";
|
||||||
|
outer.style.width = "100px";
|
||||||
|
outer.style.msOverflowStyle = "scrollbar"; // needed for WinJS apps
|
||||||
|
|
||||||
|
document.body.appendChild(outer);
|
||||||
|
|
||||||
|
let widthNoScroll = outer.offsetWidth;
|
||||||
|
// force scrollbars
|
||||||
|
outer.style.overflow = "scroll";
|
||||||
|
|
||||||
|
// add innerdiv
|
||||||
|
let inner = document.createElement("div");
|
||||||
|
inner.style.width = "100%";
|
||||||
|
outer.appendChild(inner);
|
||||||
|
|
||||||
|
let widthWithScroll = inner.offsetWidth;
|
||||||
|
|
||||||
|
// remove divs
|
||||||
|
outer.parentNode.removeChild(outer);
|
||||||
|
this.scrollWidth = widthNoScroll - widthWithScroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.scrollWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
getPhantomScrollbarWidth() {
|
||||||
|
if (document.getElementsByTagName('body')[0].style.overflow == 'hidden') {
|
||||||
|
return this.getScrollbarWidth();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user